@plexy/react-native 2.x.npm install @plexy/react-nativemerchantIdentifier there only for native Apple Pay entitlements. The runtime checkout configuration uses applepay.merchantID.{
"expo": {
"plugins": [
[
"@plexy/react-native",
{
"merchantIdentifier": "merchant.money.plexy.example"
}
]
]
}
}PlexyCheckout is a provider component. It receives the SDK config, a session or paymentMethods, and lifecycle callbacks. usePlexyCheckout() must be called only from a child rendered inside PlexyCheckout.<PlexyCheckout config={checkoutConfig} session={session} onComplete={onComplete} onError={onError}>
<PayButton />
</PlexyCheckout>PayButton, call start('dropin') to open Drop-in. You can also start a specific payment method with its type, for example start('scheme') or start('googlepay'), when that method is present in the session payment methods.import type { Configuration } from '@plexy/react-native';
function buildCheckoutConfig(returnUrl: string): Configuration {
return {
environment: 'live-apse',
clientKey: process.env.EXPO_PUBLIC_PLEXY_CLIENT_KEY!,
returnUrl,
countryCode: 'KZ',
locale: 'ru-KZ',
amount: { value: 10000, currency: 'KZT' },
analytics: { enabled: false },
card: {
holderNameRequired: false,
},
};
}locale controls checkout language and regional formatting, for example ru-KZ, kk-KZ, or en-US. It is not a currency setting. Currency is configured only in amount.currency, for example KZT.live-apse. For test transactions, use the test clientKey in the app and the matching test x-api-key on your backend. For production, use the live APSE key pair. The backend still calls https://api.plexypay.com/v2/sessions; do not send live-apse in the /v2/sessions request body.id and sessionData to the app. The app passes both values to PlexyCheckout.import React, { useCallback, useMemo, useState } from 'react';
import { ActivityIndicator, Alert, Button, Text, View } from 'react-native';
import {
PlexyCheckout,
PlexyDropIn,
ResultCode,
usePlexyCheckout,
} from '@plexy/react-native';
import type {
Configuration,
PlexyComponent,
PlexyError,
SessionConfiguration,
SessionsResult,
} from '@plexy/react-native';
type CheckoutState = {
session: SessionConfiguration;
returnUrl: string;
};
function buildCheckoutConfig(returnUrl: string): Configuration {
return {
environment: 'live-apse',
clientKey: process.env.EXPO_PUBLIC_PLEXY_CLIENT_KEY!,
returnUrl,
countryCode: 'KZ',
locale: 'ru-KZ',
amount: { value: 10000, currency: 'KZT' },
analytics: { enabled: false },
dropin: {
showRemovePaymentMethodButton: true,
},
card: {
holderNameRequired: false,
showStorePaymentField: true,
},
};
}
async function createSessionOnBackend(returnUrl: string): Promise<SessionConfiguration> {
const response = await fetch('https://your-backend.example.com/api/sessions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: { value: 10000, currency: 'KZT' },
countryCode: 'KZ',
returnUrl,
}),
});
if (!response.ok) {
throw new Error(`Session request failed: ${response.status}`);
}
const data = await response.json();
return { id: data.id, sessionData: data.sessionData };
}
function PayButton() {
const { start, isReady } = usePlexyCheckout();
return (
<Button
title="Pay 100 KZT"
disabled={!isReady}
onPress={() => start('dropin')}
/>
);
}
export function CheckoutScreen() {
const [checkoutState, setCheckoutState] = useState<CheckoutState | null>(null);
const [loading, setLoading] = useState(false);
const prepareCheckout = useCallback(async () => {
setLoading(true);
try {
const returnUrl = await PlexyDropIn.getReturnURL();
const session = await createSessionOnBackend(returnUrl);
setCheckoutState({ session, returnUrl });
} catch (error) {
Alert.alert('Checkout error', String(error));
} finally {
setLoading(false);
}
}, []);
const config = useMemo(
() => checkoutState ? buildCheckoutConfig(checkoutState.returnUrl) : null,
[checkoutState]
);
const onComplete = useCallback(
(result: SessionsResult, component: PlexyComponent) => {
const authorised = result.resultCode === ResultCode.authorised;
component.hide(authorised);
if (authorised) {
Alert.alert('Payment authorised');
} else {
Alert.alert('Payment result', result.resultCode);
}
// Always confirm the final status on your backend through a webhook
// or by checking the session/payment status before fulfilling the order.
},
[]
);
const onError = useCallback(
(error: PlexyError, component: PlexyComponent) => {
component.hide(false);
Alert.alert('Payment error', error.message);
},
[]
);
if (!checkoutState || !config) {
return (
<View>
{loading ? <ActivityIndicator /> : null}
<Button title="Start checkout" onPress={prepareCheckout} disabled={loading} />
</View>
);
}
return (
<PlexyCheckout
config={config}
session={checkoutState.session}
onComplete={onComplete}
onError={onError}
>
<View>
<Text>Order total: 100 KZT</Text>
<PayButton />
</View>
</PlexyCheckout>
);
}merchantAccount, authenticates with x-api-key, and calls Plexy.const returnUrl = await PlexyDropIn.getReturnURL();
const session = await createSessionOnBackend(returnUrl);{
"id": "CS123...",
"sessionData": "..."
}const session: SessionConfiguration = {
id: response.id,
sessionData: response.sessionData,
};dropin key:const config: Configuration = {
environment: 'live-apse',
clientKey: process.env.EXPO_PUBLIC_PLEXY_CLIENT_KEY!,
returnUrl,
countryCode: 'KZ',
locale: 'ru-KZ',
amount: { value: 10000, currency: 'KZT' },
dropin: {
showRemovePaymentMethodButton: true,
skipListWhenSinglePaymentMethod: true,
},
};card key:const config: Configuration = {
environment: 'live-apse',
clientKey: process.env.EXPO_PUBLIC_PLEXY_CLIENT_KEY!,
returnUrl,
countryCode: 'KZ',
locale: 'ru-KZ',
amount: { value: 10000, currency: 'KZT' },
card: {
holderNameRequired: false,
showStorePaymentField: true,
addressVisibility: 'none',
},
};card: {
holderNameRequired: false,
}googlepay key:const GOOGLE_PAY_ENVIRONMENT_PRODUCTION = 1;
const GOOGLE_PAY_ENVIRONMENT_TEST = 3;
const config: Configuration = {
environment: 'live-apse',
clientKey: process.env.EXPO_PUBLIC_PLEXY_CLIENT_KEY!,
returnUrl,
countryCode: 'KZ',
locale: 'ru-KZ',
amount: { value: 10000, currency: 'KZT' },
googlepay: {
merchantAccount: 'YOUR_MERCHANT_ACCOUNT',
countryCode: 'KZ',
amount: { value: 10000, currency: 'KZT' },
googlePayEnvironment: GOOGLE_PAY_ENVIRONMENT_PRODUCTION,
},
};googlepay: {
merchantAccount: 'YOUR_MERCHANT_ACCOUNT',
countryCode: 'KZ',
amount: { value: 10000, currency: 'KZT' },
googlePayEnvironment: GOOGLE_PAY_ENVIRONMENT_TEST,
}googlepay.merchantAccount is the Plexy merchant account that is used as Google Pay's gatewayMerchantId in the tokenization request. It is not the Google Pay merchantId. Keep it aligned with the merchantAccount your backend uses when creating the session.TEST / PRODUCTION environment. This is separate from the Plexy SDK environment. Keep the Plexy SDK environment on live-apse.applepay key and the merchantID field:const config: Configuration = {
environment: 'live-apse',
clientKey: process.env.EXPO_PUBLIC_PLEXY_CLIENT_KEY!,
returnUrl,
countryCode: 'KZ',
locale: 'ru-KZ',
amount: { value: 10000, currency: 'KZT' },
applepay: {
merchantID: 'merchant.money.plexy.example',
merchantName: 'Your Store',
summaryItems: [{ label: 'Order', amount: '100.00' }],
},
};merchantIdentifier in runtime checkout configuration. merchantIdentifier belongs to native entitlement setup, for example in the Expo config plugin. The runtime field is merchantID.paymentMethods instead of session and implement onSubmit / onAdditionalDetails. The callbacks should forward SDK data to your backend, where you call /v2/payments and /v2/payments/details.<PlexyCheckout
config={config}
paymentMethods={paymentMethodsResponse}
onSubmit={(data, component) => {
// Send data to your backend POST /v2/payments endpoint.
}}
onAdditionalDetails={(data, component) => {
// Send data to your backend POST /v2/payments/details endpoint.
}}
onError={onError}
>
<PayButton />
</PlexyCheckout>function CardButton() {
const { start, isReady } = usePlexyCheckout();
return (
<Button
title="Pay by card"
disabled={!isReady}
onPress={() => start('scheme')}
/>
);
}PlexyDropIn.getReturnURL() to get the return URL that should be sent to your backend when creating a session or payment:const returnUrl = await PlexyDropIn.getReturnURL();PlexyDropIn.handleReturnURL(url) API in @plexy/react-native 2.x. Do not add that call to your JavaScript code.PlexyCheckout:const onComplete = (result: SessionsResult, component: PlexyComponent) => {
const authorised = result.resultCode === ResultCode.authorised;
component.hide(authorised);
};
const onError = (error: PlexyError, component: PlexyComponent) => {
component.hide(false);
console.error(error.errorCode, error.message);
};<PlexyCheckout
config={config}
paymentMethods={paymentMethodsResponse}
onSubmit={handleSubmit}
onAdditionalDetails={handleAdditionalDetails}
onError={onError}
>
<PayButton />
</PlexyCheckout>usePlexyCheckout() outside of PlexyCheckout children.onResult; use onComplete.PlexyProvider, useCheckout, or startCheckout; these are not the @plexy/react-native 2.x API.googlePay or applePay; use googlepay and applepay.merchantIdentifier in runtime Apple Pay config; use applepay.merchantID.locale to a currency such as KZT; use locale: 'ru-KZ' and amount.currency: 'KZT'.clientKey; x-api-key stays on your backend.