edfapay-softpos-sdk-rn
v1.0.7
Published
Edfapay SoftPOS SDK helps developer to easily integrate Edfapay SoftPOS to their mobile application
Readme
EdfaPay SoftPOS SDK — React Native
Wiki & Documentation
EdfaPay SoftPOS SDK
[!IMPORTANT]
Install edfapay-softpos-sdk-rn
- Add the dependency by running:
npm install edfapay-softpos-sdk-rn # or yarn add edfapay-softpos-sdk-rn
[!IMPORTANT]
Set Repository Access Credentials
- Add the following credentials to your project
android/gradle.propertiesor~/.gradle/gradle.propertiesPARTNER_REPO_USERNAME=edfapay-sdk-consumer PARTNER_REPO_PASSWORD=Edfapay@123
[!IMPORTANT]
Packaging Options (Android)
- Add the following
packagingOptionsblock inside theandroid { }section of yourandroid/app/build.gradleto avoid duplicate META-INF file conflicts:android { // ... other config ... packagingOptions { resources { excludes += ['META-INF/DEPENDENCIES', 'META-INF/LICENSE', 'META-INF/LICENSE.txt', 'META-INF/NOTICE', 'META-INF/NOTICE.txt', 'META-INF/**'] } } }
Usage
1: Imports
import {
EdfaPayPlugin,
EdfaPayCredentials,
Env,
TxnParams,
Transaction,
TransactionType,
FlowType,
Presentation,
PresentationConfig,
PurchaseSecondaryAction,
// Invoice / BNPL / Checkout
InvoiceRequest,
InvoiceRefundRequest,
Invoice,
InvoiceLineItem,
AdditionalData,
PaymentMethod,
// Online receipt
ReceiptType,
} from 'edfapay-softpos-sdk-rn';2: Setting Theme (Optional)
2.1: Colors and Logos
const logoBase64 = "base64 encoded image string";
EdfaPayPlugin.theme()
.setPrimaryColor('#06E59F')
.setSecondaryColor('#000000')
.setPoweredByImage(logoBase64)
.setHeaderImage(logoBase64);2.2: Setting Presentation
Presentation.FULLSCREENPresentation.DIALOG_CENTERPresentation.DIALOG_TOP_FILLPresentation.DIALOG_BOTTOM_FILLPresentation.DIALOG_TOP_STARTPresentation.DIALOG_TOP_ENDPresentation.DIALOG_TOP_CENTERPresentation.DIALOG_BOTTOM_STARTPresentation.DIALOG_BOTTOM_ENDPresentation.DIALOG_BOTTOM_CENTER
EdfaPayPlugin.theme()
.setPresentation(
new PresentationConfig(Presentation.DIALOG_CENTER)
.sizePercent(0.85) // 0.20 to 1.0, aligned to screen smallest axis
.dismissOnBackPress(true)
.dismissOnTouchOutside(true)
.animateExit(true)
.animateEntry(true)
.dimBackground(true)
.dimAmount(1.0) // 0.0 to 1.0
.marginAll(0)
.cornerRadius(20)
.marginHorizontal(10)
.marginVertical(10)
.setPurchaseSecondaryAction(PurchaseSecondaryAction.NONE)
);2.3: Secondary / Post-Purchase Action
PurchaseSecondaryAction.REVERSEPurchaseSecondaryAction.REFUNDPurchaseSecondaryAction.NONE
EdfaPayPlugin.theme()
.setPresentation(
new PresentationConfig(Presentation.DIALOG_CENTER)
.setPurchaseSecondaryAction(PurchaseSecondaryAction.REVERSE)
);2.4: PIN PAD Shuffle
EdfaPayPlugin.theme()
.setPresentation(
new PresentationConfig(Presentation.DIALOG_CENTER)
.setShufflePinPad(true) // default false
);2.5: Reconciliation Notification Sounds
Each kind is a base64-encoded sound file; omit or pass null to mute that kind.
EdfaPayPlugin.theme()
.setReconciliationNotificationSounds({
success: successSoundBase64,
error: errorSoundBase64,
processing: processingSoundBase64,
});3: Initialization
3.1: Create Credentials
Prompt for credentials (email/password or token input):
const credentials = EdfaPayCredentials.withInput(Env.PRODUCTION);Prompt with pre-filled email/password:
const credentials = EdfaPayCredentials.withEmailPassword( Env.DEVELOPMENT, '[email protected]', 'Password@123' );Prompt with pre-filled email only:
const credentials = EdfaPayCredentials.withEmail(Env.DEVELOPMENT, '[email protected]');Silent initialization with a Terminal Token:
const credentials = EdfaPayCredentials.withToken( Env.DEVELOPMENT, // also: Env.STAGING | Env.SANDBOX | Env.PRODUCTION | Env.REVAMP '****Terminal Token Generated at EdfaPay SoftPOS Portal****' );
3.2: Initialize with Credentials
EdfaPayPlugin.enableLogs(true);
EdfaPayPlugin.setAnimationSpeedX(2.5); // Optional: animation speed multiplier
EdfaPayPlugin.initiate({
credentials,
onSuccess: (sessionId) => {
console.log('>>> SDK Initialized — Session ID: ' + sessionId);
},
onTerminalBindingTask: (task) => {
console.log('>>> Terminal Binding Required');
const terminals = task.terminals;
// Option 1: Show SDK's built-in terminal selection UI
task.bind();
// Option 2: Bind the first terminal programmatically
terminals[0]?.bind();
// Option 3: Refresh terminal list from server, then show custom UI
task.refresh((error, list) => {
if (error) {
console.error('>>> Refresh error: ' + JSON.stringify(error));
} else {
console.log('>>> Terminals refreshed: ' + list.length);
}
});
},
onError: (error) => {
console.error('>>> Init error: ' + JSON.stringify(error));
},
});3.3: Enable Remote Channel (Optional)
Open after successful initialization to accept transactions from a remote source (e.g. POS terminal on the same local network):
// Open local network channel on port 8080 with 30s timeout
EdfaPayPlugin.RemoteChannel.LocalNetwork({ port: 8080, timeout: 30 }).open();Send a transaction request from a remote source:
echo '{"id":"pay.1","data":{"fun":"purchase","flowType":"DETAIL","amount":"12.0"}}' | nc 192.168.1.100 80804: Purchase
FlowType options:
FlowType.IMMEDIATE— closes card scan UI immediately after server responseFlowType.STATUS— closes at status animation (check/cross)FlowType.DETAIL— flows to transaction detail screen, completes on screen close
Note: Observe the 4th
isFlowCompleteparameter ofonPaymentProcessComplete.
const params = new TxnParams('01.010', '12340987');
EdfaPayPlugin.purchase({
txnParams: params,
flowType: FlowType.DETAIL,
onPaymentProcessComplete: (status, code, transaction, isFlowComplete) => {
if (status) {
console.log('>>> Success: ' + JSON.stringify(transaction));
} else {
console.log('>>> Failed: ' + JSON.stringify(transaction));
}
},
onRequestTimerEnd: () => {
console.log('>>> Server Timeout');
},
onCardScanTimerEnd: () => {
console.log('>>> Scan Card Timeout');
},
onCancelByUser: () => {
console.log('>>> Canceled By User');
},
onError: (error) => {
console.error('>>> Error: ' + JSON.stringify(error));
},
});5: Refund
const params = new TxnParams(
'01.010',
'',
Transaction.withRRN('123456789012', '', TransactionType.PURCHASE)
);
EdfaPayPlugin.refund({
txnParams: params,
onPaymentProcessComplete: (status, code, transaction, isFlowComplete) => {
console.log('>>> Refund ' + (status ? 'Success' : 'Failed'));
},
onRequestTimerEnd: () => { console.log('>>> Server Timeout'); },
onCardScanTimerEnd: () => { console.log('>>> Scan Card Timeout'); },
onCancelByUser: () => { console.log('>>> Canceled By User'); },
onError: (error) => { console.error('>>> Error: ' + JSON.stringify(error)); },
});6: Reverse Last Transaction
EdfaPayPlugin.reverseLastTransaction({
onSuccess: (response) => {
console.log('>>> Reverse Success: ' + JSON.stringify(response));
},
onError: (error) => {
console.error('>>> Reverse Error: ' + JSON.stringify(error));
},
});7: Reconciliation
EdfaPayPlugin.reconcile({
onSuccess: (response) => {
console.log('>>> Reconciliation Success: ' + JSON.stringify(response));
},
onError: (error) => {
console.error('>>> Reconciliation Error: ' + JSON.stringify(error));
},
});8: Transaction History
EdfaPayPlugin.txnHistory({
onSuccess: (response) => {
console.log('>>> Txn History: ' + JSON.stringify(response));
},
onError: (error) => {
console.error('>>> Txn History Error: ' + JSON.stringify(error));
},
});9: Invoice Payment (BNPL / Checkout)
Generate a checkout link (Tamara / Tabby / Payment Gateway). onSuccess returns
a BnplResponse with the checkoutDeeplink to redirect the customer to.
PaymentMethodvalues:PaymentMethod.TAMARA,PaymentMethod.TABBY,PaymentMethod.CHECKOUT,PaymentMethod.CONTACTLESS,PaymentMethod.UNKNOWN.
const request = new InvoiceRequest(
PaymentMethod.TAMARA,
'a590eaf1-c11c-4d1d-8c83-9d8cbc39486d', // merchantId
11100, // amount (minor units → 111.00)
'SAR',
'+966512345678',
'[email protected]',
'ORD-111', // orderReferenceId
'10111', // orderNumber
new Invoice(11100, [
new InvoiceLineItem('SKU-001', 'Product A', 11100, 1, 11100, 0, 0, 11100),
]),
new AdditionalData('STORE-01'),
'ar_SA' // locale (optional)
);
EdfaPayPlugin.invoicePayment({
request,
onSuccess: (response) => {
console.log('>>> Checkout ID: ' + response.checkoutId);
console.log('>>> Deeplink: ' + response.checkoutDeeplink);
},
onError: (error) => {
console.error('>>> Invoice Payment Error: ' + JSON.stringify(error));
},
});Deprecated:
buyNowPayLater(...)andcheckoutLinkApi(...)are aliases kept for backward compatibility — useinvoicePayment(...)instead.
10: Invoice Refund
Refund a previous invoice payment by its transactionId.
const request = new InvoiceRefundRequest(PaymentMethod.TAMARA, 11100, 'TXN-ID');
EdfaPayPlugin.invoiceRefund({
request,
onSuccess: (response) => {
console.log('>>> Refund Txn ID: ' + response.transactionId);
},
onError: (error) => {
console.error('>>> Invoice Refund Error: ' + JSON.stringify(error));
},
});11: Transaction Lookup APIs
Server-backed lookups (do not require card interaction).
// Detail via API
EdfaPayPlugin.txnDetailApi({
txnId: 'TXN-ID',
onSuccess: (txn) => console.log('>>> Txn Detail: ' + JSON.stringify(txn)),
onError: (error) => console.error('>>> Error: ' + JSON.stringify(error)),
});
// Search
EdfaPayPlugin.searchTxnApi({
parameters: { page: 0, size: 20 },
onSuccess: (result) => console.log('>>> Search: ' + JSON.stringify(result)),
onError: (error) => console.error('>>> Error: ' + JSON.stringify(error)),
});
// Payment-gateway transaction status by session id
EdfaPayPlugin.pgTxnStatusApi({
sessionId: 'SESSION-ID',
onSuccess: (result) => console.log('>>> PG Status: ' + JSON.stringify(result)),
onError: (error) => console.error('>>> Error: ' + JSON.stringify(error)),
});12: Extension — Online Receipt & Terminal
// Build the receipt URL (RECONCILIATION or TRANSACTION)
EdfaPayPlugin.Extension.generateOnlineReceipt({
type: ReceiptType.TRANSACTION,
id: 'TXN-OR-RECON-ID',
onSuccess: (url) => console.log('>>> Receipt URL: ' + url),
onError: (error) => console.error('>>> Error: ' + JSON.stringify(error)),
});
// Or open the receipt directly in the device browser
EdfaPayPlugin.Extension.openOnlineReceipt({
type: ReceiptType.RECONCILIATION,
id: 'RECON-ID',
onError: (error) => console.error('>>> Error: ' + JSON.stringify(error)),
});
// Unbind the currently bound terminal from this device
EdfaPayPlugin.Extension.unbindTerminal({
onSuccess: (r) => console.log('>>> Terminal unbound: ' + JSON.stringify(r)),
onError: (error) => console.error('>>> Error: ' + JSON.stringify(error)),
});13: Utils — Android Permission Helpers
Helpers for background reconciliation and notifications. All have*/can*/is*
checks are async; request* helpers take a callback.
// Notifications (Android 13+)
await EdfaPayPlugin.Utils.haveNotificationPermission();
EdfaPayPlugin.Utils.requestNotificationPermission({
callback: (granted) => console.log('>>> Notifications: ' + granted),
});
// Exact alarms (scheduled reconciliation, Android 12+)
await EdfaPayPlugin.Utils.canScheduleExactAlarms();
EdfaPayPlugin.Utils.requestExactAlarmPermission({ callback: (g) => console.log(g) });
EdfaPayPlugin.Utils.openExactAlarmSettings();
// Battery "Unrestricted" (background work in Doze)
await EdfaPayPlugin.Utils.isBatteryUnrestricted();
EdfaPayPlugin.Utils.requestBatteryUnrestricted({ callback: (g) => console.log(g) });
EdfaPayPlugin.Utils.openBatteryUnrestrictedSettings();
// Autostart allowlist (aggressive OEMs; no-op on stock Android)
await EdfaPayPlugin.Utils.deviceNeedsAutostart();
EdfaPayPlugin.Utils.requestAutostartPermission({ callback: (g) => console.log(g) });
EdfaPayPlugin.Utils.openAutostartSettings();Example
Full working example — copy and paste into your App.tsx:
import * as React from 'react';
import { View, Button, Image, Text } from 'react-native';
import {
EdfaPayPlugin,
EdfaPayCredentials,
Env,
TxnParams,
Transaction,
TransactionType,
EPStrings,
EPStyles
} from 'edfapay-softpos-sdk-rn';
const TERMINAL_TOKEN = '47FC92D42FA08EDC1BB663C4709363654942875EE9F18E3BB075EEC70F4A8828';
const amountToPay = '01.00';
export default function App() {
const [initialized, setInitialized] = React.useState(false);
return (
<View style={{ flex: 1, justifyContent: 'flex-end', padding: 20, gap: 12 }}>
<View style={EPStyles.content}>
<Text style={EPStyles.heading1}>{EPStrings.sdk}</Text>
<Text style={EPStyles.heading2}>{EPStrings.version}</Text>
<Text style={[EPStyles.heading3, { textAlign: 'center' }]}>
{EPStrings.message}
</Text>
</View>
{!initialized && (
<Button
color="#06E59F"
title="Initialize"
onPress={() => initiateSdk(setInitialized)}
/>
)}
{initialized && (
<>
<Button color="#06E59F" title={'Purchase ' + amountToPay} onPress={purchase} />
<Button color="#FF9800" title={'Refund ' + amountToPay} onPress={refund} />
<Button color="#F44336" title="Reverse Last Transaction" onPress={reverse} />
<Button color="#2196F3" title="Reconciliation" onPress={reconcile} />
<Button color="#9C27B0" title="Txn History" onPress={txnHistory} />
</>
)}
</View>
);
}
function initiateSdk(onInitialized: (status: boolean) => void) {
EdfaPayPlugin.enableLogs(true);
EdfaPayPlugin.setAnimationSpeedX(2.5);
const credentials = EdfaPayCredentials.withToken(Env.REVAMP, TERMINAL_TOKEN);
EdfaPayPlugin.initiate({
credentials,
onSuccess: (sessionId) => {
onInitialized(true);
console.log('>>> SDK Initialized — Session ID: ' + sessionId);
},
onTerminalBindingTask: (task) => {
console.log('>>> Terminal Binding Required');
// Option 1: Show SDK's built-in terminal selection UI
task.bind();
// Option 2: Bind first terminal programmatically
// task.terminals[0]?.bind();
},
onError: (error) => {
onInitialized(false);
console.error('>>> Init Error: ' + JSON.stringify(error));
},
});
}
function purchase() {
EdfaPayPlugin.purchase({
txnParams: new TxnParams(amountToPay),
onPaymentProcessComplete: (status, code, transaction, isFlowComplete) => {
console.log('>>> Purchase ' + (status ? 'Success' : 'Failed') + ' | Code: ' + code);
console.log('>>> Transaction: ' + JSON.stringify(transaction));
},
onRequestTimerEnd: () => { console.log('>>> Server Timeout'); },
onCardScanTimerEnd: () => { console.log('>>> Scan Card Timeout'); },
onCancelByUser: () => { console.log('>>> Canceled By User'); },
onError: (error) => { console.error('>>> Error: ' + JSON.stringify(error)); },
});
}
function refund() {
const params = new TxnParams(
amountToPay,
'',
Transaction.withRRN('123456789012', '', TransactionType.PURCHASE)
);
EdfaPayPlugin.refund({
txnParams: params,
onPaymentProcessComplete: (status, code, transaction, isFlowComplete) => {
console.log('>>> Refund ' + (status ? 'Success' : 'Failed') + ' | Code: ' + code);
},
onRequestTimerEnd: () => { console.log('>>> Server Timeout'); },
onCardScanTimerEnd: () => { console.log('>>> Scan Card Timeout'); },
onCancelByUser: () => { console.log('>>> Canceled By User'); },
onError: (error) => { console.error('>>> Error: ' + JSON.stringify(error)); },
});
}
function reverse() {
EdfaPayPlugin.reverseLastTransaction({
onSuccess: (response) => {
console.log('>>> Reverse Success: ' + JSON.stringify(response));
},
onError: (error) => {
console.error('>>> Reverse Error: ' + JSON.stringify(error));
},
});
}
function reconcile() {
EdfaPayPlugin.reconcile({
onSuccess: (response) => {
console.log('>>> Reconciliation Success: ' + JSON.stringify(response));
},
onError: (error) => {
console.error('>>> Reconciliation Error: ' + JSON.stringify(error));
},
});
}
function txnHistory() {
EdfaPayPlugin.txnHistory({
onSuccess: (response) => {
console.log('>>> Txn History: ' + JSON.stringify(response));
},
onError: (error) => {
console.error('>>> Txn History Error: ' + JSON.stringify(error));
},
});
}License
MIT
