react-native-fincra-checkout
v1.0.1
Published
Production-ready React Native SDK for Fincra Checkout — WebView and Inline JavaScript modes with full TypeScript support.
Maintainers
Readme
react-native-fincra-checkout
A production-ready, 100% TypeScript React Native SDK for Fincra Checkout, with full feature and architectural parity with the official flutter_fincra_checkout package.
Features
- ✅ Two checkout modes: WebView (recommended) and Inline JavaScript
- ✅ Imperative API:
await FincraCheckout.openWebView({...})from anywhere - ✅ Declarative API:
<FincraWebViewCheckout />and<FincraInlineCheckout /> - ✅ Strongly-typed result: Discriminated union —
success | error | cancelled - ✅ URL interception: Redirect URL prefix match + query-param fallback
- ✅ 15-second init timeout for the Inline mode
- ✅ Modern SafeAreaView via
react-native-safe-area-context - ✅ Built-in Error Recovery & Offline Retry UI with custom
renderErrorprop support - ✅ Android back button support
- ✅ Cancellation confirmation dialog (optional)
- ✅ XSS-safe HTML generation (all inputs JSON-encoded)
Installation
npm install react-native-fincra-checkout react-native-webview react-native-safe-area-context
# or
yarn add react-native-fincra-checkout react-native-webview react-native-safe-area-contextiOS — link native modules
cd ios && pod installAndroid — no extra steps needed
react-native-webview auto-links on Android.
⚠️ Security Notice
Never store your Fincra Secret Key in your mobile app bundle.
- For WebView Checkout: Generate the
checkoutUrlserver-side using your secret key via the Fincra API, then pass the URL to the SDK.- For Inline Checkout: Only your public key (
pk_...) is used. This is safe to bundle.Storing secret keys in client code exposes them to reverse engineering and can lead to fraudulent transactions.
Setup — Add the Host Component
Add <FincraCheckoutHost /> once at your app root. This enables the imperative FincraCheckout.open*() API:
// App.tsx
import { FincraCheckoutHost } from 'react-native-fincra-checkout';
export default function App() {
return (
<>
<NavigationContainer>
<RootNavigator />
</NavigationContainer>
{/* ← Add this once at the end of your root component */}
<FincraCheckoutHost />
</>
);
}Note: The host renders nothing until a checkout is opened. It must be inside a rendered component tree (not a provider).
WebView vs. Inline — Comparison
| Feature | WebView Checkout | Inline JS Checkout | |---|---|---| | Trigger | Backend-generated URL | Public key + params | | Key required | Secret key (server-side only) | Public key (client-safe) | | Payment flow | Full Fincra-hosted page | Embedded Fincra JS widget | | URL interception | ✅ Redirect URL or query params | ❌ N/A (JS bridge events) | | Init timeout | ❌ N/A | ✅ 15 seconds | | Recommended for | Production (most secure) | Frontend-only prototypes |
Usage
A. Imperative API (Promise / async-await)
WebView Mode — recommended
import { FincraCheckout } from 'react-native-fincra-checkout';
async function handlePayment() {
const result = await FincraCheckout.openWebView({
// Generated by your backend using Fincra API + secret key
checkoutUrl: 'https://checkout.fincra.com/pay/abc123',
// Your backend redirect URL — intercepted by the SDK
redirectUrl: 'https://api.yourapp.com/payment/callback',
headerTitle: 'Complete Payment',
showCancelConfirmationDialog: true,
});
switch (result.type) {
case 'success':
console.log('Payment successful:', result.response.reference);
break;
case 'error':
console.error('Payment failed:', result.error.message);
break;
case 'cancelled':
console.log('User cancelled the payment');
break;
}
}Inline Mode
import { FincraCheckout } from 'react-native-fincra-checkout';
async function handleInlinePayment() {
const result = await FincraCheckout.openInline({
publicKey: 'pk_live_xxxxxxxxxxxx',
amount: 5000, // in smallest currency unit (e.g., kobo for NGN)
currency: 'NGN',
customerEmail: '[email protected]',
customerName: 'Jane Doe',
customerPhoneNumber: '08012345678',
feeBearer: 'customer',
reference: 'ORDER-001', // optional — Fincra generates one if omitted
paymentMethods: ['card', 'bank_transfer'], // optional
});
if (result.type === 'success') {
const { reference, transactionId, status } = result.response;
console.log({ reference, transactionId, status });
}
}B. Declarative Component API
Embed checkout views directly inside your own modals, bottom sheets, or navigation screens:
<FincraWebViewCheckout />
import { FincraWebViewCheckout } from 'react-native-fincra-checkout';
function PaymentScreen() {
return (
<FincraWebViewCheckout
checkoutUrl="https://checkout.fincra.com/pay/abc123"
redirectUrl="https://api.yourapp.com/payment/callback"
headerTitle="Secure Payment"
headerBackgroundColor="#0066FF"
headerTintColor="#FFFFFF"
showCancelConfirmationDialog
onSuccess={(response) => {
console.log('Success:', response.reference);
navigation.navigate('PaymentSuccess');
}}
onFailed={(error) => {
console.error('Error:', error.message);
}}
onCancelled={() => {
navigation.goBack();
}}
/>
);
}<FincraInlineCheckout />
import { FincraInlineCheckout } from 'react-native-fincra-checkout';
function InlinePaymentScreen() {
return (
<FincraInlineCheckout
publicKey="pk_live_xxxxxxxxxxxx"
amount={10000}
currency="NGN"
customerEmail="[email protected]"
customerName="John Doe"
customerPhoneNumber="08099887766"
feeBearer="business"
onSuccess={(response) => console.log(response)}
onFailed={(error) => console.error(error)}
onCancelled={() => navigation.goBack()}
/>
);
}TypeScript Types
import type {
FincraCheckoutResult,
FincraPaymentResponse,
FincraPaymentError,
WebViewCheckoutConfig,
InlineCheckoutConfig,
FincraCurrency,
FeeBearer,
} from 'react-native-fincra-checkout';
// Discriminated union result
const result: FincraCheckoutResult =
| { type: 'success'; response: FincraPaymentResponse }
| { type: 'error'; error: FincraPaymentError }
| { type: 'cancelled' };Supported Currencies
NGN · USD · GBP · EUR · GHS · KES · ZAR · UGX · XAF · XOF
Props Reference
Shared (BaseCheckoutProps)
| Prop | Type | Default | Description |
|---|---|---|---|
| onSuccess | (response) => void | — | Called on successful payment |
| onFailed | (error) => void | — | Called on payment error |
| onCancelled | () => void | — | Called when user cancels |
| headerTitle | string | 'Secure Checkout' | Navigation bar title |
| headerBackgroundColor | string | '#FFFFFF' | Nav bar background color |
| headerTintColor | string | '#000000' | Nav bar text/icon color |
| showCancelConfirmationDialog | boolean | false | Show Alert before closing |
| loadingComponent | ReactNode | ActivityIndicator | Custom loading spinner |
| closeIcon | ReactNode | ✕ text | Custom close button content |
WebViewCheckoutConfig
| Prop | Type | Required | Description |
|---|---|---|---|
| checkoutUrl | string | ✅ | Backend-generated Fincra checkout URL |
| redirectUrl | string | — | Redirect URL to intercept for completion |
InlineCheckoutConfig
| Prop | Type | Required | Description |
|---|---|---|---|
| publicKey | string | ✅ | Your Fincra public key (pk_...) |
| amount | number | ✅ | Amount in smallest currency unit |
| currency | FincraCurrency | ✅ | Payment currency |
| customerEmail | string | ✅ | Customer email |
| customerName | string | ✅ | Customer full name |
| customerPhoneNumber | string | ✅ | Customer phone number |
| feeBearer | FeeBearer | ✅ | 'business' or 'customer' |
| reference | string | — | Custom transaction reference |
| paymentMethods | string[] | — | Restrict to specific methods |
How URL Interception Works
The WebView mode intercepts navigation requests:
- If
redirectUrlis set: Any URL starting withredirectUrltriggers completion (prefix match — mirrors Flutter'surl.startsWith(redirectUrl)). - Fallback (no
redirectUrl): Completion is detected when bothstatus(orpayment_status) andreferencequery params are present.
Response parameters are normalized:
customerReference→reference(preferred)merchantReference→reference(fallback)transactionReference→transactionId
Running Tests
npm testTests cover UrlHandler (URL detection, param extraction, reference normalization) and JsBridge (event parsing, data coercion, malformed input handling) — no device or emulator required.
Changelog
See CHANGELOG.md for a list of release notes and changes.
License
MIT © Fincra
