valuepay-react-native
v2.0.0
Published
Official react-native package for the value payment solution provider service
Readme
valuepay-react-native
Official React Native SDK for the Valuepay Payment Gateway. Provides a secure, drop-in payment modal for accepting payments in your React Native application.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- API Reference
- Payment Channels
- Supported Currencies
- Payment Flow
- Advanced Usage
- Migration from v1.0.x
- Security
- Contributing
- Support
- License
Features
- Secure WebView-based payment modal with HTTPS-only communication
- Supports 6 payment channels: Card, USSD, Bank Transfer, Mobile Money, QR Code, OPay
- 13 supported currencies across Africa and internationally
- Full TypeScript support with strict type definitions
- Built-in payment validation with detailed error reporting
- Tree-shakeable ESM output
- Compatible with iOS, Android, and Expo projects
- Minimal dependencies
Requirements
| Dependency | Version | |---|---| | React Native | >= 0.73.0 | | React | >= 18.0.0 | | react-native-webview | >= 13.13.5 |
Installation
Install the package and its peer dependency:
# npm
npm install valuepay-react-native react-native-webview
# yarn
yarn add valuepay-react-native react-native-webviewiOS
Install CocoaPods dependencies after adding the package:
cd ios && pod installExpo
If using Expo, install the compatible WebView package:
npx expo install react-native-webviewQuick Start
import { useState } from 'react';
import { Button, View, StyleSheet, Alert } from 'react-native';
import {
ValuepayReactNative,
validatePaymentProp,
PaymentProp,
ReturnObject,
} from 'valuepay-react-native';
const App = () => {
const [isPaymentVisible, setPaymentVisible] = useState(false);
const paymentDetails: PaymentProp = {
publicKey: 'YOUR_PUBLIC_KEY', // from https://developer.valuepayng.com/
transactionRef: 'TX_' + Date.now().toString(),
amount: 5000, // amount in kobo (5000 kobo = 50 NGN)
currency: 'NGN',
customer: {
email: '[email protected]',
},
onSuccess: (response: ReturnObject) => {
console.log('Payment successful:', response);
setPaymentVisible(false);
// Verify payment on your backend using response.transaction_id
},
};
const handlePay = () => {
if (validatePaymentProp(paymentDetails)) {
setPaymentVisible(true);
} else {
Alert.alert('Error', 'Invalid payment configuration');
}
};
return (
<View style={styles.container}>
<Button title="Pay Now" onPress={handlePay} />
{isPaymentVisible && (
<ValuepayReactNative
payment={paymentDetails}
isVisible={isPaymentVisible}
/>
)}
</View>
);
};
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
});
export default App;API Reference
ValuepayReactNative
The main payment modal component.
<ValuepayReactNative payment={paymentDetails} isVisible={isPaymentVisible} />| Prop | Type | Required | Description |
|---|---|---|---|
| payment | PaymentProp | Yes | Payment configuration object |
| isVisible | boolean | Yes | Controls modal visibility |
Note: Conditionally render the component (
{isVisible && <ValuepayReactNative ... />}) for optimal performance. The component unmounts and cleans up when hidden.
PaymentProp
Configuration object for payment details. Passed to the payment prop of ValuepayReactNative.
Required Fields
| Field | Type | Description |
|---|---|---|
| publicKey | string | Your Valuepay public key from developer.valuepayng.com |
| transactionRef | string | Unique transaction reference. Must be unique per payment attempt |
| amount | number | Payment amount in the smallest currency unit (e.g. kobo for NGN). Must be greater than 0 |
| customer | Customer | Customer information (see below) |
| onSuccess | (response: ReturnObject) => void | Called when payment completes successfully |
Optional Fields
| Field | Type | Default | Description |
|---|---|---|---|
| currency | currencyTypes | 'NGN' | Payment currency. See Supported Currencies |
| channels | PaymentChannel[] | All enabled | Payment methods to display. See Payment Channels |
| type | string | 'default' | Checkout type |
| redirectUrl | string | 'https://example.com' | URL the checkout page redirects to after payment |
| callback | (response: ReturnObject) => void | - | Called on payment failure or unknown status |
| onCancelled | (response: ReturnObject) => void | - | Called when the user cancels payment |
| onAborted | (response: ReturnObject) => void | - | Called on payment error or abort |
| onClosed | (response: ReturnObject) => void | - | Called when the payment modal is closed |
| customisedCheckout | Customizations | - | Checkout branding options (see below) |
| metaData | Record<string, unknown> | - | Custom key-value metadata attached to the transaction |
Customer Object
| Field | Type | Required | Description |
|---|---|---|---|
| email | string | Yes | Customer's email address |
| fullName | string | No | Customer's full name |
| phone | string | No | Customer's phone number (E.164 format recommended) |
Customizations Object
| Field | Type | Required | Description |
|---|---|---|---|
| title | string | No | Checkout page title |
| description | string | No | Payment description shown to the customer |
| logoLink | string | No | URL to your brand logo displayed on the checkout page |
ReturnObject
Response object passed to all callback handlers.
| Field | Type | Description |
|---|---|---|
| status | statusType | Payment status (see table below) |
| tx_ref | string | Your transaction reference |
| transaction_id | string? | Valuepay's unique transaction identifier |
| message | string? | Human-readable status message |
Status Values
| Status | Description | Callback |
|---|---|---|
| 'successful' | Payment completed successfully | onSuccess |
| 'completed' | Payment completed successfully | onSuccess |
| 'success' | Payment completed successfully | onSuccess |
| 'cancelled' | User cancelled the payment | onCancelled |
| 'aborted' | Payment encountered an error | onAborted |
| 'closed' | User closed the payment modal | onClosed |
| 'unknown' | Unable to determine payment status | callback |
Validation
Two validation functions are available for checking payment configuration before initiating a transaction.
validatePaymentProp(payment: PaymentProp): boolean
Returns true if the payment configuration is valid. Use this for simple pass/fail checks.
import { validatePaymentProp } from 'valuepay-react-native';
if (validatePaymentProp(paymentDetails)) {
setPaymentVisible(true);
}validatePaymentPropDetailed(payment: PaymentProp): ValidationResult
Returns a detailed validation result with specific error messages. Use this when you need to display validation errors to the user or for debugging.
import { validatePaymentPropDetailed } from 'valuepay-react-native';
const result = validatePaymentPropDetailed(paymentDetails);
if (!result.valid) {
console.log('Validation errors:', result.errors);
// ['amount is required and must be a positive number', 'customer.email is required']
}ValidationResult
| Field | Type | Description |
|---|---|---|
| valid | boolean | Whether the payment configuration is valid |
| errors | string[] | List of validation error messages (empty if valid) |
Validation rules applied:
publicKeymust be a non-empty stringtransactionRefmust be a non-empty stringamountmust be a positive numbercustomer.emailmust be a valid email addresschannels(if provided) must only contain valid payment channel values
Payment Channels
Restrict which payment methods are shown by passing a channels array. If omitted, all channels enabled on your merchant dashboard are displayed.
| Channel | Value | Description |
|---|---|---|
| Card | 'card' | Credit and debit card payments |
| USSD | 'ussd' | USSD banking (Nigeria) |
| Bank Transfer | 'transfer' | Direct bank transfer |
| Mobile Money | 'mobile' | Mobile money providers |
| QR Code | 'qrcode' | Scan-to-pay QR code |
| OPay | 'opay' | OPay digital wallet |
// Only show card and bank transfer options
const paymentDetails: PaymentProp = {
// ...
channels: ['card', 'transfer'],
};Supported Currencies
| Code | Currency |
|---|---|
| NGN | Nigerian Naira |
| USD | United States Dollar |
| EUR | Euro |
| GBP | British Pound Sterling |
| GHS | Ghanaian Cedi |
| ZAR | South African Rand |
| KES | Kenyan Shilling |
| UGX | Ugandan Shilling |
| TZS | Tanzanian Shilling |
| RWF | Rwandan Franc |
| MWK | Malawian Kwacha |
| XAF | Central African CFA Franc |
| XOF | West African CFA Franc |
Payment Flow
1. Configure PaymentProp with your public key and transaction details
|
2. Call validatePaymentProp() to verify configuration
|
3. Set isVisible to true to display the payment modal
|
4. User completes payment on the Valuepay checkout page (WebView)
|
5. SDK parses the payment response from the redirect URL
|
6. Appropriate callback fires (onSuccess / onCancelled / onAborted / onClosed / callback)
|
7. Your app dismisses the modal (set isVisible to false)
|
8. IMPORTANT: Verify the payment on your backend server
using the transaction_id and tx_ref from the responseBackend verification is mandatory. Never rely solely on the client-side callback to confirm payment. Use the Valuepay Verify API with
transaction_idand your secret key to confirm the payment status and amount on your server.
Advanced Usage
Detailed Validation
Display specific validation errors to help users correct their input:
import { validatePaymentPropDetailed } from 'valuepay-react-native';
const handlePay = () => {
const { valid, errors } = validatePaymentPropDetailed(paymentDetails);
if (!valid) {
Alert.alert('Payment Error', errors.join('\n'));
return;
}
setPaymentVisible(true);
};Custom Metadata
Attach custom data to the transaction for order tracking, analytics, or reconciliation:
const paymentDetails: PaymentProp = {
// ...required fields
metaData: {
orderId: 'ORD-12345',
productName: 'Premium Subscription',
customer_mac: 'unique-device-id',
linkId: 'invoice-456', // required when type is not 'default'
},
};Customised Checkout
Brand the checkout page with your company details:
const paymentDetails: PaymentProp = {
// ...required fields
customisedCheckout: {
title: 'Acme Store',
description: 'Payment for Order #12345',
logoLink: 'https://yourdomain.com/logo.png',
},
};Full Example with All Callbacks
import { useState } from 'react';
import { Button, View, StyleSheet, Alert } from 'react-native';
import {
ValuepayReactNative,
validatePaymentPropDetailed,
PaymentProp,
ReturnObject,
} from 'valuepay-react-native';
const PaymentScreen = () => {
const [isPaymentVisible, setPaymentVisible] = useState(false);
const paymentDetails: PaymentProp = {
publicKey: 'YOUR_PUBLIC_KEY',
transactionRef: 'TX_' + Date.now().toString(),
amount: 10000, // 100 NGN in kobo
currency: 'NGN',
channels: ['card', 'transfer', 'ussd'],
redirectUrl: 'https://yourdomain.com/payment/callback',
customer: {
email: '[email protected]',
fullName: 'Jane Doe',
phone: '+2341234567890',
},
customisedCheckout: {
title: 'My Store',
description: 'Order #12345',
logoLink: 'https://yourdomain.com/logo.png',
},
metaData: {
orderId: '12345',
},
onSuccess: (response: ReturnObject) => {
setPaymentVisible(false);
Alert.alert('Success', 'Payment completed!');
// Send response.transaction_id to your backend for verification
},
callback: (response: ReturnObject) => {
setPaymentVisible(false);
Alert.alert('Failed', response.message || 'Payment failed');
},
onCancelled: (response: ReturnObject) => {
setPaymentVisible(false);
Alert.alert('Cancelled', 'You cancelled the payment');
},
onAborted: (response: ReturnObject) => {
setPaymentVisible(false);
Alert.alert('Error', response.message || 'Payment was aborted');
},
onClosed: (response: ReturnObject) => {
setPaymentVisible(false);
// User closed modal without completing payment
},
};
const handlePay = () => {
const { valid, errors } = validatePaymentPropDetailed(paymentDetails);
if (valid) {
setPaymentVisible(true);
} else {
Alert.alert('Validation Error', errors.join('\n'));
}
};
return (
<View style={styles.container}>
<Button title="Pay 100 NGN" onPress={handlePay} />
{isPaymentVisible && (
<ValuepayReactNative
payment={paymentDetails}
isVisible={isPaymentVisible}
/>
)}
</View>
);
};
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
});
export default PaymentScreen;Migration from v1.0.x
v1.1.x is backward compatible with v1.0.x. The following changes are additive and require no code modifications:
What changed
- Callbacks are now optional (except
onSuccess). Previously all 5 callbacks (onSuccess,callback,onCancelled,onAborted,onClosed) were required. Now onlyonSuccessis required. Existing code passing all callbacks continues to work. channelsis now typed asPaymentChannel[]instead ofstring[]. Valid string values are unchanged, but TypeScript will now catch typos at compile time.metaDatais now typed asRecord<string, unknown>instead ofobjectfor better type safety.- Currency type
'US'corrected to'USD'. If you were using'US', update to'USD'. - New
validatePaymentPropDetailed()function for detailed error reporting alongside the existingvalidatePaymentProp(). - New exported types:
ValidationResult,PaymentChannel,currencyTypes. - Validation now checks
publicKey,amount > 0, and email format in addition to the existing checks. - Production logging removed. Console output is now gated behind
__DEV__and will not appear in release builds. - WebView debugging disabled in production. Chrome DevTools attachment is now restricted to development builds only.
Breaking changes
- If you were using the currency code
'US', change it to'USD'.
Security
This SDK is designed with payment security in mind:
- HTTPS only — All communication with Valuepay servers uses HTTPS. Mixed content is blocked.
- No secrets in client code — Only your public key is used client-side. Payment verification must happen on your backend with your secret key.
- WebView debugging disabled in production — Chrome DevTools cannot attach to the payment WebView in release builds.
- No production logging — Payment URLs and navigation data are not logged in production builds.
- Server-side verification required — Always verify payments on your backend. See the Valuepay API documentation for verification endpoints.
Exports
All public exports from the package:
import {
// Component
ValuepayReactNative,
// Validation
validatePaymentProp,
validatePaymentPropDetailed,
// Types
PaymentProp,
ReturnObject,
ValidationResult,
PaymentChannel,
currencyTypes,
} from 'valuepay-react-native';Contributing
See the contributing guide to learn how to contribute to the repository and the development workflow.
Support
- Documentation: developer.valuepayng.com
- Issues: GitHub Issues
- Email: [email protected]
License
MIT
Made with create-react-native-library
