The xMoney React Native SDK exposes native Payment Sheet, Payment Element, Apple Pay, and Google Pay controls through one TypeScript API. Card fields remain inside native SDK views; PAN and CVV do not cross the JavaScript bridge.
Current release: 1.0.0.
- React Native 0.76 or later
- React Native New Architecture
- iOS 15 or later
- Android
minSdk23 - A publishable xMoney key and a backend that signs orders
Expo is supported through the config plugin and a native development or production build. Expo Go is not supported.
Store the xMoney private key on your backend. The app should receive only the publishable key, order payload, and checksum.
npm install @xmoney/react-native@1.0.0Install iOS pods, then rebuild the app:
cd ios
pod installAndroid autolinking registers the native module. Rebuild the Android app after installation.
If the package has been installed without rebuilding the native app, the SDK throws XMoneyPaymentError with code NOT_LINKED.
Add the config plugin to app.json, then create a new native build:
{
"plugins": [
[
"@xmoney/react-native",
{
"merchantIdentifier": "merchant.com.example",
"enableGooglePay": true
}
]
]
}merchantIdentifier configures the iOS Apple Pay capability. enableGooglePay configures the Android application metadata.
Your backend creates and signs the order. Build an intent from the returned values:
const intent = {
orderPayload: payloadFromYourServer,
orderChecksum: checksumFromYourServer,
};See Create the order on your backend for the shared server responsibilities.
Payment Sheet owns the complete checkout UI and Pay button.
import { usePaymentSheet } from '@xmoney/react-native';
function CheckoutButton() {
const { init, present, loading } = usePaymentSheet();
const pay = async () => {
await init({
publicKey: 'pk_test_...',
paymentMethods: {
applePay: { enabled: true },
googlePay: { enabled: true },
},
card: {
savedCards: { enabled: true },
},
});
const result = await present(intent, (event) => {
if (event.type === 'ready') {
hideCheckoutLoader();
}
});
handlePaymentResult(result);
};
return <Button title="Pay" onPress={pay} disabled={loading} />;
}Idle close, drag, or scrim dismissal returns { status: 'canceled' } without consuming the order. Once payment or 3DS starts, terminal results consume the signed order.
Payment Element places the native payment form inside your React Native layout.
import { PaymentElement } from '@xmoney/react-native';
<PaymentElement
configuration={{
publicKey: 'pk_test_...',
paymentMethods: {
applePay: { enabled: true },
googlePay: { enabled: true },
},
}}
intent={intent}
onEvent={(event) => {
if (event.type === 'ready') {
hideCheckoutLoader();
}
}}
onResult={handlePaymentResult}
/>;Payment Element adds no outer page padding or background. Keep it mounted while it binds an order, and provide the surrounding layout in your app.
To use your own Pay button, hide the SDK button and call confirm() after ready:
import {
PaymentElement,
type PaymentElementRef,
} from '@xmoney/react-native';
const elementRef = useRef<PaymentElementRef>(null);
<PaymentElement
ref={elementRef}
configuration={{
publicKey: 'pk_test_...',
card: {
submitButton: { visible: false },
},
}}
intent={intent}
onResult={handlePaymentResult}
/>;
<Button
title="Pay"
onPress={() => elementRef.current?.confirm()}
/>;Use the availability event's isInteractionEnabled value to disable the merchant button while the order updates or payment is processing.
Apple Pay is available only on iOS; Google Pay is available only on Android. Unsupported wallet button components render nothing.
import {
ApplePayButton,
GooglePayButton,
} from '@xmoney/react-native';
<ApplePayButton
configuration={{ publicKey: 'pk_test_...' }}
intent={intent}
appearance={{ color: 'black', type: 'buy' }}
onResult={handlePaymentResult}
/>;
<GooglePayButton
configuration={{ publicKey: 'pk_test_...' }}
intent={intent}
appearance={{ color: 'black', type: 'buy' }}
onResult={handlePaymentResult}
/>;For imperative flows, use ApplePay.init, getState, and present, or the corresponding GooglePay methods. Check isAvailable and isReady before showing custom wallet UI.
A wallet dismissal before authorization returns canceled and does not consume the intent.
See Apple Pay and Google Pay for activation requirements.
function handlePaymentResult(result: PaymentResult) {
switch (result.status) {
case 'complete':
confirmOrderOnBackend(result.transaction);
break;
case 'failed':
showPaymentError(result.error.message);
break;
case 'canceled':
showCheckout();
break;
}
}Use the result to update the app, then confirm final payment status on your backend before fulfillment.
When the amount, currency, or cart changes, request a new signed order and rebind the mounted element:
await elementRef.current?.updateOrder(nextIntent);Changing the intent prop also updates the order. Keep the component mounted; use isInteractionEnabled for loading and button state.
For live styling changes, call updateAppearance, updateStyle, updateLocale, or updateWalletAppearance on the ref. Changing core configuration may remount the native view.
PaymentConfig controls saved cards, card validation, field grouping, submit-button intent, locale, light/dark style, colors, and radii.
const configuration = {
publicKey: 'pk_test_...',
card: {
savedCards: {
enabled: true,
optInVisible: true,
},
validationMode: 'onTouched',
inputs: {
grouping: 'condensed',
},
},
options: {
locale: 'en-US',
style: 'automatic',
},
};Supported UI languages are English (en), Greek (el), Romanian (ro), Bulgarian (bg), Hungarian (hu), and Polish (pl). Region tags such as pl-PL are supported.
For cardholder name verification, provide a callback in the card configuration:
card: {
cardHolderVerification: {
name: {
firstName: 'John',
lastName: 'Doe',
},
onCardHolderVerification: (result) =>
result.status === 'Matched',
},
},The site must have cardholder name verification enabled.
- Review the native SDK shared model.
- Use test cards in the test environment.
- Explore the complete React Native SDK samples.