Paymob runs millions of transactions for different business sizes across the Middle East and Africa. Start using Paymob’s solutions and API’s to accept and send payments for your online business now.
To learn more about Paymob’s offerings and capabilities, visit Paymob.com.
To get started with the paymob-reactnative package, follow these steps:
-
Install the Package
Open your terminal, navigate to your React Native project directory, and install the
paymob-reactnativepackage using npm:npm install paymob-reactnative@https://github.com/PaymobAccept/paymob-reactnative-sdk.git
If you prefer using Yarn, you can run:
yarn add paymob-reactnative@https://github.com/PaymobAccept/paymob-reactnative-sdk.git
-
Install CocoaPods for iOS
If you are developing for iOS, you will need to install CocoaPods to manage your project's dependencies. Run the following commands:
cd ios && pod install && cd ..
This step ensures that the necessary native modules are linked correctly in your iOS project.
Important Notice: If you encounter an issue with the native iOS SDK, you may need to create a new blank Swift file in Xcode. After creating the blank file, be sure to click on
Create Bridging Headerwhen prompted. -
Append the following snippet to your project-level
build.gradlefile.allprojects { repositories { maven { url = rootProject.projectDir.toURI().resolve("../node_modules/paymob-reactnative/android/libs") } maven { url = uri("https://jitpack.io") } } }
-
Add the following snippet to your app-level
build.gradlefile.android { buildFeatures { dataBinding = true } }
To begin using the Paymob SDK in your React Native application, start by importing the module in your component:
import Paymob, {
PaymentStatus,
FailureCallBackVersion,
} from 'paymob-reactnative';You can customize the Paymob SDK to match your app's branding and user experience by calling the following functions:
Paymob.setAppIcon(base64Image); // Set your merchant logo using a base64 encoded image
Paymob.setAppName('Paymob SDK'); // Customize merchant app name displayed in the Paymob interface
Paymob.setButtonTextColor('#FFFFFF'); // Set the text color of buttons in the SDK
Paymob.setButtonBackgroundColor('#000000'); // Set the background color of buttons in the SDK
Paymob.setShowSaveCard(true); // Enable the option for users to save their cards
Paymob.setSaveCardDefault(true); // Set saved card option as default for transactions
Paymob.setShowConfirmationPage(true); // Show confirmation page upon paymentThese customization options allow you to tailor the Paymob SDK interface to align with your brand identity.
Please ensure that all SDK customizations are completed before calling Paymob.presentPayVC(). Failing to do so may result in the payment interface not reflecting your desired branding and settings.
To handle payment results, register a listener with Paymob.setSdkListener. The listener receives a response object each time the full-screen payment flow started by Paymob.presentPayVC() finishes, and it is the single entry point for the success, failure, cancellation, and pending outcomes:
Paymob.setSdkListener((response) => {
switch (response.status) {
case PaymentStatus.SUCCESS:
// Handle successful payment (transaction data is in response.details)
break;
case PaymentStatus.FAIL:
// Handle failed payment (the reason is in response.message)
break;
case PaymentStatus.CANCELLED:
// Handle a payment cancelled by the user
break;
case PaymentStatus.PENDING:
// Handle pending payment status
break;
}
});The response object has the following fields:
| Field | Type | Description |
|---|---|---|
status |
string |
One of PaymentStatus.SUCCESS ('Success'), PaymentStatus.FAIL ('Fail'), PaymentStatus.CANCELLED ('Cancelled'), or PaymentStatus.PENDING ('Pending'). |
details |
object |
Transaction data returned by the native SDK for a successful payment. On Android it is also present, as an empty object, for the other statuses; on iOS it is omitted. |
message |
string |
The failure reason. Only present when status is 'Fail'. |
Keep the following in mind:
- Only one listener is active at a time. Calling
setSdkListeneragain replaces the previous listener, andPaymob.removeSdkListener()removes it (for example, when your component unmounts). - Register the listener before calling
Paymob.presentPayVC(). On Android, results are only delivered while a listener is registered. - The native module delivers results through the
onTransactionStatusevent.setSdkListenersubscribes to it for you, so you do not need to useNativeEventEmitterdirectly.
A failed payment is reported through the same listener, as a response with status equal to PaymentStatus.FAIL. There is no separate failure API for the full-screen flow.
Callback parameters
response.status:'Fail'(PaymentStatus.FAIL).response.message: a string describing why the payment failed, as reported by the native SDK.
Failure callback version
You can select the failure callback version used by the native SDK with Paymob.setFailureCallbackVersion:
Paymob.setFailureCallbackVersion(FailureCallBackVersion.V2);- Supported values are
FailureCallBackVersion.V1andFailureCallBackVersion.V2. The strings'V1'and'V2'are also accepted (case-insensitive); any other value falls back toV1. - Call it before
Paymob.presentPayVC(), like the other SDK customizations. - It applies to the full-screen flow started by
Paymob.presentPayVC(). The embedded view does not use it. - The React Native bridge always delivers the failure reason to your listener as
response.message. What differs betweenV1andV2is defined by the native SDKs and is not documented in this package.
Complete example
import React, { useEffect } from 'react';
import { Alert, Button, View } from 'react-native';
import Paymob, {
PaymentStatus,
FailureCallBackVersion,
} from 'paymob-reactnative';
const showAlert = (title, message) =>
requestAnimationFrame(() => Alert.alert(title, message));
export default function CheckoutScreen({ clientSecret, publicKey }) {
useEffect(() => {
Paymob.setSdkListener((response) => {
switch (response.status) {
case PaymentStatus.SUCCESS:
console.log('Payment succeeded', response.details);
break;
case PaymentStatus.FAIL:
showAlert('Payment failed', response.message ?? 'Unknown error');
break;
case PaymentStatus.CANCELLED:
showAlert('Payment cancelled');
break;
case PaymentStatus.PENDING:
showAlert('Payment pending');
break;
}
});
return () => {
Paymob.removeSdkListener();
};
}, []);
const pay = () => {
Paymob.setFailureCallbackVersion(FailureCallBackVersion.V2);
Paymob.presentPayVC(clientSecret, publicKey);
};
return (
<View>
<Button title="Pay" onPress={pay} />
</View>
);
}Cancellation is supported and is reported through the same listener, as a response with status equal to PaymentStatus.CANCELLED ('Cancelled'). It is emitted when the native SDK reports that the payment was cancelled.
- Payload: only
response.status. There is nomessage, anddetailsis empty (an empty object on Android, omitted on iOS).
Paymob.setSdkListener((response) => {
if (response.status === PaymentStatus.CANCELLED) {
// The payment was cancelled, for example return the user to the cart
}
});For the embedded view, cancellation is delivered through the onCancelled prop instead. See Embedded View.
After configuring the SDK, you can invoke the Paymob payment interface with the following code:
Paymob.presentPayVC('CLIENT_SECRET', 'PUBLIC_KEY');This function call opens the Paymob payment interface, allowing users to complete their transactions securely. Make sure to replace 'CLIENT_SECRET' and 'PUBLIC_KEY' with your actual credentials.
Besides the full-screen flow started by Paymob.presentPayVC(), the SDK can render the card checkout inside your own screen through the native PaymobCheckoutView component. This keeps the customer inside your app UI while card entry and payment processing happen in an embedded native view.
The embedded view is available on both iOS and Android. It uses the same native SDKs and the same installation steps described above; no additional setup is required.
Important: the package does not export a JavaScript wrapper for the embedded view. You obtain the component with requireNativeComponent('PaymobCheckoutView') and drive it with two native commands, configure and setPaymentKeys, exactly as the example app does. The embedded view is not covered by the package's TypeScript declarations.
Register the native component once, at module scope, then render it and keep a ref to it:
import { requireNativeComponent } from 'react-native';
const PaymobCheckoutView = requireNativeComponent('PaymobCheckoutView');| Prop | Type | Description |
|---|---|---|
style |
StyleProp<ViewStyle> |
Standard view style. See Layout and Styling. |
onSuccess |
(event) => void |
Called when the payment succeeds. event.nativeEvent contains the transaction details. |
onFailure |
(event) => void |
Called when the payment fails. event.nativeEvent.error contains the failure reason. |
onCancelled |
(event) => void |
Called when the payment is cancelled. event.nativeEvent is an empty object. |
onPending |
(event) => void |
Called when the payment is pending. event.nativeEvent is an empty object. |
Note that the embedded view reports the failure reason as event.nativeEvent.error, whereas the full-screen listener reports it as response.message.
Commands are sent to the view with UIManager.dispatchViewManagerCommand(findNodeHandle(ref.current), commandName, args). Send each command once, using the command name as a string; this works on both platforms.
| Command | Arguments | Description |
|---|---|---|
configure |
[config] |
Applies the embedded view configuration. Send it once after the view has mounted and before setting the payment keys. |
setPaymentKeys |
[{ publicKey, clientSecret }] |
Provides the payment keys used by the embedded checkout. |
The configure command takes a single configuration object. All fields are optional:
| Field | Type | Default | Description |
|---|---|---|---|
showAddNewCard |
boolean |
true |
Show or hide the "Add new card" option. |
showSaveCard |
boolean |
true |
Show or hide the save card option. |
saveCardByDefault |
boolean |
iOS: false, Android: true |
Pre-check the save card option. The default differs between platforms, so set it explicitly. |
payFromOutside |
boolean |
false |
Not currently usable from React Native. See Limitations. |
uiCustomization |
string |
none | Optional UI customization, passed to the native SDK as a JSON-encoded string. Omit it to use the default appearance. The supported keys are defined by the native SDKs. |
The full-screen customization functions (Paymob.setAppName, Paymob.setButtonBackgroundColor, and so on) apply to Paymob.presentPayVC() only and do not affect the embedded view.
Your backend creates the payment intention with your secret key and returns the publicKey and clientSecret to the app. Never put your secret key inside the app. Once you have the keys, send them to the view:
UIManager.dispatchViewManagerCommand(
findNodeHandle(checkoutRef.current),
'setPaymentKeys',
[{ publicKey, clientSecret }]
);- The height of the embedded view is dynamic. The native view reports its content height to React Native's layout on both platforms, so the view grows and shrinks as its content changes (for example, when the customer opens the card form). Do not set a fixed
heighton it, because that would override the reported height. - Give the view the full available width, for example
width: '100%'(oralignSelf: 'stretch'). - Because the height can change, place the view inside a
ScrollViewwhen the screen has other content around it.
import React, { useEffect, useRef } from 'react';
import {
ScrollView,
StyleSheet,
Text,
UIManager,
findNodeHandle,
requireNativeComponent,
} from 'react-native';
const PaymobCheckoutView = requireNativeComponent('PaymobCheckoutView');
const sendCommand = (ref, commandName, args) => {
const handle = findNodeHandle(ref.current);
if (handle) {
UIManager.dispatchViewManagerCommand(handle, commandName, args);
}
};
export default function EmbeddedCheckoutScreen({ publicKey, clientSecret }) {
const checkoutRef = useRef(null);
// 1. Configure the view once it has mounted
useEffect(() => {
sendCommand(checkoutRef, 'configure', [
{
showAddNewCard: true,
showSaveCard: true,
saveCardByDefault: false,
payFromOutside: false,
},
]);
}, []);
// 2. Provide the keys returned by your backend
useEffect(() => {
if (publicKey && clientSecret) {
sendCommand(checkoutRef, 'setPaymentKeys', [{ publicKey, clientSecret }]);
}
}, [publicKey, clientSecret]);
return (
<ScrollView contentContainerStyle={styles.content}>
<Text style={styles.title}>Checkout</Text>
<PaymobCheckoutView
ref={checkoutRef}
style={styles.checkout}
onSuccess={(event) => {
console.log('Payment succeeded', event.nativeEvent);
}}
onFailure={(event) => {
console.log('Payment failed', event.nativeEvent.error);
}}
onCancelled={() => {
console.log('Payment cancelled');
}}
onPending={() => {
console.log('Payment pending');
}}
/>
</ScrollView>
);
}
const styles = StyleSheet.create({
content: { padding: 16 },
title: { fontSize: 18, fontWeight: 'bold', marginBottom: 16 },
checkout: { width: '100%' },
});- No external payment trigger. The native SDK supports a
payFromOutsidemode, but the React Native bridge does not expose a command to start the payment from your own button. LeavepayFromOutsideasfalseand use the pay button rendered inside the embedded view. - No height callback. The dynamic height is handled internally; there is no
onHeightChangedprop. - No single result callback. Results are delivered through the four
onSuccess,onFailure,onCancelled, andonPendingprops. - No dispose method. No explicit release command is exposed.
- Android: the
configurecommand requires the current Activity to be anandroidx.activity.ComponentActivity, which the defaultReactActivityis. - Architecture: the embedded view is implemented as a legacy native view manager, and the example app runs with the New Architecture disabled. Behavior with the New Architecture enabled is not documented here.
Here’s the updated explanation with a revised first sentence and the inclusion of the repository cloning step:
To explore the SDK or test its features, you can clone the repository and run the example app by following these steps:
-
Clone the Repository
Clone the repository to your local machine. -
Install Dependencies
Navigate to the project directory and install the required dependencies using Yarn. Run:yarn
-
Run the Example App
You can run the example app for both iOS and Android platforms:-
To run the app on iOS, use the following command:
yarn example ios
-
To run the app on Android, use this command:
yarn example android
-
By following these steps, you can explore the functionality of the SDK in the example app.
For more detailed information about the supported APIs, usage guidelines, and advanced features, please refer to our comprehensive Documentation. Here, you will find examples, best practices, and troubleshooting tips to help you make the most out of the Paymob SDK.