Card vault - React

The Card vault integrates features like wallets and tokenization without processing the payment.

The Card Vault is a component of DEUNA Payment solutions and contains different types of widgets that allow you to:

  • Store credit and debit cards securely in the Vault.
  • Make Click To Pay payments with the Click To Pay widget.

Initialize the widget

Before integrating the Payment widget, complete the First steps - Web.

1. Display the widget

Display the widget on your application in two ways:

  • On a modal
  • Embedded

Display on a modal

Follow the following steps to show the DEUNA Vault Widget in a Modal:

  1. Create an instance of the DeunaSDK class.
  2. Add the DeunaWidget component to your view.
  3. Call the initElements function.
import { DeunaSDK, DeunaWidget } from "@deuna/react-native-sdk";

const YourScreen = () => {
  const onShowWidget = () => {
    deunaSDK.initElements({
      userToken: "<DEUNA user token>", // optional
      userInfo: {
        firstName: "Esteban",
        lastName: "Posada",
        email: "[email protected]",
      }, // optional
      callbacks: {
        onSuccess: async (data) => {
          await deunaSDK.close(); // Close the widget
          console.log("Success", data);
          // Handle success
        },
        onError: async (error) => {
          console.error("Error:", error);
          await deunaSDK.close(); // Close the widget
          // Handle error
        },
        onClosed: (action) => {
          console.log("Widget closed with action:", action);
          // Handle close action
        },
        onEventDispatch: (type, response) => {
          console.log("Event:", type, response);
          // Handle specific events
        },
      },
      widgetExperience: {
        userExperience: {
          showSavedCardFlow: false, // optional
          defaultCardFlow: false, // optional
        },
      },
    });

    return (
      <View>
        <DeunaWidget instance={deunaSDK} />
        <Button
          onPress={onShowPaymentWidget}
          title="Show Widget"
        ></Button>
      </View>
    );
  };
};

Display embedded widget

To show the DEUNA widget in embedded form you will need to pass the parameter mode: Mode.EMBEDDED when you call the initElements function.

📘

To correctly visualize the DEUNA widget in embedded form, the DeunaWidget component must be inside a component that delimits its dimensions.

import {
  DeunaSDK,
  DeunaWidget,
  Mode, // AGREGAR ESTA LINEA
} from "@deuna/react-native-sdk";

const YourScreen = () => {
  const onShowWidget = () => {
    deunaSDK.initElements({
      userToken: "<DEUNA user token>", // optional
      mode: Mode.EMBEDDED,
      userInfo: {
        firstName: "Esteban",
        lastName: "Posada",
        email: "[email protected]",
      }, // optional
      callbacks: {
        onSuccess: async (data) => {
          await deunaSDK.close(); // Close the widget
          console.log("Success", data);
          // Handle success
        },
        onError: async (error) => {
          console.error("Error:", error);
          await deunaSDK.close(); // Close the widget
          // Handle error
        },
        onClosed: (action) => {
          console.log("Widget closed with action:", action);
          // Handle close action
        },
        onEventDispatch: (type, response) => {
          console.log("Event:", type, response);
          // Handle specific events
        },
      },
    });

    return (
      <View>
        {/* Delimita las dimensiones del Widget */}
        <View style={{ flex: 1, width: "100%" }}>
          <DeunaWidget instance={deunaSDK} />
        </View>
        <Button onPress={onShowWidget} title="Show Payment Widget"></Button>
      </View>
    );
  };
};

Parameters

ParameterDescription
callbacksCallbacks that will be called in case of success, error, or when the widget is closed.
userToken (Optional)The bearer token of the DEUNA user. When this is sent, all actions within the widget will be done on this DEUNA user.

For this userToken to be used and the saved cards to be shown to the customer, the email associated with that userToken must be the same one sent when creating the order in billing_address.email in case an orderToken is passed. If the two emails don't match, the flow will be used without displaying the cards for security reasons.

https://docs.deuna.com/reference/users-register
https://docs.deuna.com/reference/request-otp
https://docs.deuna.com/reference/login-with-otp
orderToken(Optional)The orderToken is a unique token generated for the payment order. This token is generated through the DEUNA API and you must implement the corresponding endpoint in your backend to obtain this information.

IMPORTANT: User information that is available in the following can be extracted: billing_address to use within the widget.
userInfo(Optional)User information to be passed to the widget, possible information available to pass are: email, firstName, lastName . These fields are NOT required if a userToken is used.
styleFile (Optional)UUID provided by DEUNA. This applies if you want to configure a file custom styles custom (Change colors, texts, logo, etc). If a valid value is provided for styleFile The vault widget will use the UI settings provided by the theme configuration that matches the provided UUID.
types(Opcional)A list of the widget types that the initElements function should render.

Allowed values are: vault and click_to_pay .

Example: [ { "name": "click_to_pay" } ]

If this parameter is not passed, the DEUNA Vault Widget will be displayed by default to store credit and debit cards.
language(Opcional)This parameter allows you to specify the language in which the widget interface will be displayed. It must be provided as a valid language code (for example, "es" for Spanish, "en" for English, "pt" for Portuguese).

Behavior:

- If provided: The widget will use the language specified in this parameter, regardless of the merchant's settings.
- If not provided: The widget will use the language configured by the merchant.
widgetExperience(Opcional)Overrides merchant settings. The following are currently supported by the widget:

userExperience.showSavedCardFlow: Shows card saving toggle.
userExperience.defaultCardFlow: Displays toggle to save card as default.
hidePayButton (Opcional)If set to true, the widget's payment button will be hidden, allowing for completely manual payment management. This means the user will need to explicitly call the methods isValid() and submit() to process the transaction.

Click To Pay Widget

Using the types parameter of the initElements function you can make a payment with Click To Pay.

📘

The userInfo parameter is mandatory to be able to show the ClickToPay widget.

deunaSDK.initElements({
  // In web context, we don't need the 'context' parameter
  userInfo: {
    firstName: "Esteban",
    lastName: "Posada",
    email: "[email protected]"
  }, // Required for Click to Pay
  types: [
    {
      name: "click_to_pay" // Shows Click to Pay widget
    }
  ],
  callbacks: {
    onSuccess: async (data) => {
      await deunaSDK.close();
      console.log('Success', data);
      // Handle successful payment
    },
    onEventDispatch: (eventType, data) => {
      console.log('Event:', eventType, data);
      // Handle specific events
    },
    onError: (error) => {
      console.error('Error:', error);
      // Handle payment error
    },
    onClosed: (action) => {
      console.log('Widget closed:', action);
      // Handle widget close
    }
  }
}); 

2. Listen to widget events

It's crucial to adequately handle the Widget events to offer a fluid experience to users. Define the necessary callbacks to update your application interface.

Callbacks

CallbackModalEmbeddedTrigger
onSuccessExecuted when a card is successfully saved or when a Click to Pay payment is successful. This callback contains a JSON parameter.
onErrorExecuted when an error occurs while saving the card. This callback contains a JSON parameter that identifies the type of error that occurred.
onClosed
(Opcional)
Runs when the payment widget is closed.

This callback contains a string parameter whose values can be one of the following:

- userAction: When the widget was manually closed by the user (by pressing the close button X) without the operation being completed.

- systemAction: When the widget is closed due to the execution of the close function.
onCardBinDetected (Opcional)Runs when the payment widget detects the BIN of an entered credit or debit card or when the user deletes the entered card number.

This callback contains a parameter of type JSON with the bin information and card brand entered.

The JSON type parameter will be null when the user deletes the text entered in the card number field.
onEventDispatch (Opcional)It is run on all events that the widget can produce.
This callback contains a string parameter and the data (JSON) associated with that event.

3. Close the widget

The close function liberates the Payment widget resources closes the widget if it was shown in a modal.

It's very important to liberate the widget resources when you no longer need them to avoid memory loss.

The following example code shows how to close the widget when a card is tokenized successfully.

deunaSDK.initPaymentWidget({
  .
  .
  .
  callbacks: {
    onSuccess: async(data) => {
      await deunaSDK.close(); // Close Payment widget
      // Example: Redirect to success page
    },
  }
});

When the DEUNA widget is shown in a Modal, the resources of it are liberated when the Modal is closed.

However if the widget is shown in embedded form and the user abandons your view it's necessary to liberate the widget resources.

import { DeunaSDK, DeunaWidget, Mode } from "@deuna/react-native-sdk";

const YourScreen = () => {
  useEffect(() => {
    return () => {
      deunaSDK.close(); // Release the widget resources
    };
  }, []);

  const onShowWidget = () => {
    deunaSDK.initElements({
      userToken: "<DEUNA user token>", // optional
      mode: Mode.EMBEDDED,
      userInfo: {...}, // optional
      callbacks: {...},
    });

    return (
      <View>
        {/* Delimits widget dimensions */}
        <View style={{ flex: 1, width: "100%" }}>
          <DeunaWidget instance={deunaSDK} />
        </View>
        <Button onPress={onShowWidget} title="Show Widget"></Button>
      </View>
    );
  };
};

Optional functionalities

Besides the mandatory steps to operate the widget, you have the following customization options.

Customize the widget appearance

Use the setCustomStyle function to customize the widget appearance.

await DeunaSDK.setCustomStyle({...});

📘

For more information, refer to Customizing styles.

Example

deunaSDK.initElements({
  orderToken: "<DEUNA order token>",
  userToken: "<DEUNA user token>", // optional
  callbacks: {
    onCardBinDetected: (cardBinMetadata: any) => {
      deunaSDK.setCustomStyle({
        theme: {
          colors: {
            primaryTextColor: "#023047",
            backgroundSecondary: "#8ECAE6",
            backgroundPrimary: "#F2F2F2",
            buttonPrimaryFill: "#FFB703",
            buttonPrimaryHover: "#FFB703",
            buttonPrimaryText: "#000000",
            buttonPrimaryActive: "#FFB703"
          }
        },
        HeaderPattern: {
          overrides: {
            Logo: {
              props: {
                url: "https://images-staging.getduna.com/ema/fc78ef09-ffc7-4d04-aec3-4c2a2023b336/test2.png"
              }
            }
          }
        }
      });
    },
    onSuccess: async(order: any) => {
      await deunaSDK.close();
      // Your success handling
    }
    // ... other callbacks
  }
});

Hide the payment button (embedded)

When the widget is shown in embedded form the hidePayButton property can be used to hide the pay button of the DeunaWidget.

deunaSDK.initElements({
  ...
  mode: Mode.EMBEDDED, // AGREGAR ESTA LINEA
  hidePayButton: true, // AGREGAR ESTA LINEA
  callbacks: {...},
});

You can use the following functions to validate and execute the payment.

MethodDescriptionResponse
.isValid()Validates if input information is correct and if the payment can be processed.true if valis, false otherwise.
.submit()Executes payment process, equivalent to clicking on "pay".{ status: "success", message: "Payment processed successfully" } o { status: "error", message: "The submit flow is not available" }

Considerations

  • It's recommended to use isValid() before calling submit() to avoid errors in the payment process.
  • If the payment flow is not yet available, submit() will always return an error with the message "The submit flow is not available"