React Native SDK
Install the DEUNA React Native SDK and integrate widgets, native wallets, redirects, and fraud-device flows.
On this page
Use the DEUNA React Native SDK to share Payment Widget, Payment Vault, Click to Pay, next-action, voucher, and native-wallet integrations across iOS and Android.
Install#
Install the SDK and its WebView peer dependency.
npm install @deuna/react-native-sdk react-native-webviewyarn add @deuna/react-native-sdk react-native-webviewpnpm add @deuna/react-native-sdk react-native-webviewReact Native CLI
Autolinking registers the native modules. Install iOS pods after adding or upgrading the package:
npx pod-installThe 2.1 and later releases include native Apple Pay, Google Pay, and fraud modules. Review the repository’s native setup notes for the current Xcode and Android dependency-compatibility blocks required by a bare React Native project.
Expo
Add the config plugin. Supply only the wallet entitlements and fraud providers your application uses.
{
"expo": {
"plugins": [
[
"@deuna/react-native-sdk",
{
"merchantIdentifiers": ["merchant.com.example"],
"googlePay": true,
"fraudProviders": []
}
]
]
}
}Regenerate the native projects after changing the plugin configuration:
npx expo prebuildBecause the SDK contains native modules, test it in a development build rather than Expo Go.
Initialize and mount the renderer#
Create one SDK instance and retain it across renders. Mount exactly one DeunaWidget for that instance. The component renders both modal and embedded WebView flows; calling an initializer only configures its controller.
import {useMemo} from 'react';
import {DeunaSDK, DeunaWidget} from '@deuna/react-native-sdk';
export function CheckoutScreen() {
const deunaSDK = useMemo(
() =>
DeunaSDK.initialize({
publicApiKey: 'YOUR_PUBLIC_API_KEY',
environment: 'sandbox',
}),
[]
);
return (
<>
<CheckoutContent deunaSDK={deunaSDK} />
<DeunaWidget instance={deunaSDK} />
</>
);
}Open Payment Widget#
Use Mode.MODAL for an SDK-owned modal. The previously mounted DeunaWidget reacts to the initialized controller.
import {Mode} from '@deuna/react-native-sdk';
await deunaSDK.initPaymentWidget({
orderToken,
mode: Mode.MODAL,
language: 'en',
callbacks: {
onSuccess: async (order) => {
await deunaSDK.close();
navigation.navigate('PaymentSuccess', {order});
},
onError: (error) => showRetry(error),
onClosed: (action) => navigation.goBack(),
onPaymentProcessing: () => disablePayButton(),
onEventDispatch: (event, payload) => {
analytics.track(event, payload);
},
},
});Use the callback to update the interface. Confirm and fulfill the final order from a verified webhook rather than trusting application state alone.
Embed a widget#
Initialize with Mode.EMBEDDED and render DeunaWidget inside the screen layout instead of mounting it beside the screen.
await deunaSDK.initPaymentWidget({
orderToken,
mode: Mode.EMBEDDED,
callbacks,
});<View style={{flex: 1}}>
<DeunaWidget instance={deunaSDK} />
</View>Do not render the same SDK instance in both locations. Unmounting DeunaWidget disposes its active controller.
If your application owns the pay button, set hidePayButton: true, then call isValid() and submit() from the button action.
const handlePay = async () => {
if (!(await deunaSDK.isValid())) return;
const result = await deunaSDK.submit();
if (result.status === 'error') showRetry(result);
};Available experiences#
| Experience | Method | Important input |
|---|---|---|
| Payment Widget | initPaymentWidget(...) | orderToken, callbacks, optional mode |
| Payment Vault | initElements(...) | callbacks; types may be omitted |
| Click to Pay | initElements(...) | types: [{name: 'click_to_pay'}] |
| Next Action | initNextAction(...) | order token, callbacks, and mode |
| Voucher | initVoucherWidget(...) | order token, callbacks, and mode |
The SDK also exposes setCustomStyle(...), refetchOrder(), getWidgetState(), isValid(), submit(), and close() for the active controller.
Payment Vault and Click to Pay#
Payment Vault is the default Elements experience. Pass either an authenticated userToken or userInfo for the customer.
await deunaSDK.initElements({
orderToken,
userInfo: {email: 'ada@example.com'},
types: [{name: 'vault'}],
mode: Mode.MODAL,
callbacks: {
onSuccess: (credential) => useSavedCredential(credential),
onError: (error) => showRetry(error),
onClosed: (action) => showPaymentMethods(action),
},
});Use {name: 'click_to_pay'} for Click to Pay.
Native Apple Pay and Google Pay#
Check merchant configuration and device support before rendering a wallet button. The returned values are apple_pay and google_pay.
const userInfo = {email: 'ada@example.com'};
const wallets = await deunaSDK.getWalletsAvailable({
orderToken,
userInfo,
});
setShowApplePay(wallets.includes('apple_pay'));
setShowGooglePay(wallets.includes('google_pay'));After availability succeeds, launch the native sheet from the button press. For Apple Pay, keep this call directly in the user gesture.
const launchWallet = (provider: 'apple_pay' | 'google_pay') => {
const type = provider === 'apple_pay' ? 'APPLE_PAY' : 'GOOGLE_PAY';
deunaSDK.initElements({
orderToken,
userInfo,
types: [{name: type}],
callbacks: {
onSuccess: (credential) => useSavedCredential(credential),
onError: (error) => showRetry(error),
onClosed: () => showPaymentMethods(),
},
});
};Apple Pay requires the iOS entitlement and merchant identifier. Google Pay requires merchant enablement and an eligible Android device. See Apple Pay and Google Pay.
Continue a pending action#
Use the same order token when DEUNA reports that the payment requires a supported 3DS challenge or redirect.
await deunaSDK.initNextAction({
orderToken,
mode: Mode.MODAL,
callbacks: {
onSuccess: (order) => showConfirmation(order),
onError: (error) => showRetry(error),
onClosed: () => showPaymentMethods(),
},
});Open a voucher#
await deunaSDK.initVoucherWidget({
orderToken,
mode: Mode.MODAL,
callbacks: {
onSuccess: (order) => showVoucherInstructions(order),
onError: (error) => showRetry(error),
onClosed: () => showPaymentMethods(),
onDownloadFile: (file) => saveVoucher(file),
},
});Handle external redirects#
The default adapter opens external URLs with React Native Linking. Payment methods that require Chrome Custom Tabs or SFSafariViewController need an InAppBrowserAdapter supplied during initialization.
const deunaSDK = DeunaSDK.initialize({
publicApiKey: 'YOUR_PUBLIC_API_KEY',
environment: 'sandbox',
inAppBrowserAdapter: myInAppBrowserAdapter,
});The adapter must implement openUrl(url) and resolve after the external browser closes. See the repository’s adapter migration examples.
Fraud-device data#
Pre-initialize linked providers before the customer reaches payment, then generate the combined identifier when your order or risk flow needs it.
await deunaSDK.initializeFraudProviders({
MERCADOPAGO: {},
});
const fraudId = await deunaSDK.generateFraudId({
MERCADOPAGO: {},
});Expo projects must also list the lower-case provider name in the config plugin, for example fraudProviders: ['mercadopago'], and rerun expo prebuild. Bare projects must link the matching native dependency. See Integrate device fingerprint.
Callback and lifecycle reference#
| Callback or method | Use it for |
|---|---|
onSuccess | Update the interface after the experience succeeds. |
onError | Read type and metadata and present retry behavior. |
onClosed | Distinguish customer and SDK-controlled closure. |
onEventDispatch | Observe supported payment or Elements lifecycle events. |
onCardBinDetected | React to card BIN detection. |
onInstallmentSelected | React to an installment-plan selection. |
onPaymentProcessing | Prevent duplicate payment actions. |
onDownloadFile | Handle voucher files returned as a URL or base64 data. |
close() | Close the active controller and external-view state. |
Official examples and source#
See ModalScreen.tsx, EmbeddedScreen.tsx, and WalletsScreen.tsx for complete runnable flows.