Skip to content
logo
  • Products
    • Amwal Checkout
    • Merchant App
    • Merchant Control Panel
  • Pricing
  • Developers
  • About us
  • Contact Us
Edit Content
  • Products
    • Amwal Checkout
    • Merchant App
    • Merchant Control Panel
  • Pricing
  • Developers
  • About us
  • Contact Us
Login
Get Started
Login
Get Started
BA Booking

BA Booking

2
  • BA Booking overview
  • BA Booking Installation
amwalpay woocommerce

Woocommerce

2
  • Overview
  • Woocommerce Installation
CS-Cart

CS Cart

2
  • CS-Cart Overview
  • CS CART Installation
Shopify

Shopify

2
  • Shopify Overview
  • Shopify Installation
odoo

Odoo

2
  • Odoo Overview
  • Odoo Installation
whmcs

WHMCS

2
  • WHMCS Overview
  • WHMCS Installation
Magento

Magento

2
  • Magento 2 Overview
  • Magento Installation
Opencart

Opencart

2
  • OpenCart Overview
  • Opencart Installtion
ZenCart

ZenCart

2
  • ZenCart Overview
  • Zencart Installation
Drupal

Drupal

2
  • Drupal Overview
  • Drupal Installation
PrestaShop

PrestaShop

2
  • PrestaShop Overview
  • PrestaShop Installation
Contact Form 7

Contact Form 7

2
  • Contact Form 7 Overview
  • Contact Form 7 Installation
Joomla

Joomla

2
  • Joomla Overview
  • Joomla Installation
AMWAL INTEGRATED PAYMENT LINK

Integrated Payment Link

1
  • Implementation

ECR

5
  • ECR SDK for iOS Cocoapods
  • ECR SDK for iOS SPM
  • Android ECR
  • Flutter ECR
  • React Native ECR
Android SDk

Native Android SDK

2
  • Pre Requisites
  • Implementation
ios SDk

Native iOS SDK

3
  • Apple Pay Specific Configuration
  • Pre Requisites
  • Implementation
React SDk

React Native SDK

1
  • Implementation

Laravel Package

2
  • Installation
  • Configuration

Flutter SDK

2
  • Implementation
  • Flutter SDK Overview

SMARTBOX

4
  • Express ApplePay Implementation
  • Offsite Implementation
  • Pre Requisites
  • Implementation

Merchant Cloud Notification

1
  • Merchant Cloud Notification Integration Guide

Secure Hash Calculation

1
  • Secure Hash Calculation

Wp Travel Engine

1
  • Wp Travel Engine Installation

Webhooks

12
  • Get Order by Merchant Reference
  • Get Transaction by Merchant Reference
  • Acquiring Session Token
  • Initialize Payment
  • Encryption and Decryption
  • Refund Payment
  • Void Payment
  • Get Transaction by ID
  • Transactions with Statistics
  • Transactions Summary
  • Delete Customer Token
  • Pay by Token
View Categories
  • Home
  • Amwal Pay Developer Portal
  • Mobile SDKs
  • ECR
  • React Native ECR

React Native ECR

Drive an Amwal POS terminal from a React Native Android or iOS application over
the local network. The package is a typed bridge over the same published native
providers used by the Amwal Flutter package:

  • Android: com.amwal-pay:ecr-sdk:1.0.4 from Maven Central
  • iOS: AmwalECR ~> 0.2.0 from CocoaPods trunk

The bridge contains no payment protocol implementation. Android and iOS use the
native Amwal ECR SDKs unchanged and return the same outcomes for sale, void,
refund, inquiry, and e-receipt operations.

The one rule #

A failed exchange is not a decline. A timeout or lost connection can happen
after the terminal accepted the request and completed the payment. When
outcomeIsUnknown is true, do not send the sale again. Inquire using the same
merchantReferenceId and reconcile first.

const result = await terminal.sale('1.234', {
  merchantReferenceId: order.id,
});

switch (result.outcome) {
  case 'approved':
    completeOrder(result.amount, result.rrn);
    break;
  case 'declined':
    if (result.outcomeIsUnknown) {
      await terminal.inquireByReference(result.merchantReferenceId);
    } else {
      showDecline(result.reason);
    }
    break;
  case 'failed':
    if (result.settled && result.recovered?.outcome === 'found') {
      reconcile(result.recovered.transaction);
    } else if (result.outcomeIsUnknown) {
      await terminal.inquireByReference(result.merchantReferenceId);
    }
    break;
}

Install #

yarn add react-native-amwal-ecr

React Native autolinking installs the Android module. On iOS, install pods after
adding the package:

cd ios
pod install

The package requires React Native’s New Architecture/TurboModules, Java 17,
Android API 24+, and iOS 15.1+ (the effective minimum of current React Native;
the native Amwal ECR pod itself supports iOS 12+).

iOS local-network permission #

Add a user-facing reason to the application Info.plist:

<key>NSLocalNetworkUsageDescription</key>
<string>Connects to the payment terminal to take card payments.</string>

Android’s INTERNET permission is contributed by the library manifest.

Create a terminal #

import { EcrTerminal } from 'react-native-amwal-ecr';

const terminal = new EcrTerminal({
  host: '192.168.1.50',
  serialNumber: 'P653200085189',
  transport: 'wifi',
  config: {
    ecrId: 'TILL-01',
    currencyCode: '512',
    minorUnitDigits: 3,
    port: 9100,
    connectTimeoutMs: 10_000,
    responseTimeoutMs: 120_000,
    probeTimeoutMs: 3_000,
    secureHashKey: secretFromSecureStorage,
    autoInquireOnFailure: true,
  },
});

The ECR secret is issued by Amwal per terminal. Keep it in the platform keychain
or secure storage; never place it in source, logs, analytics, or crash reports.

Only ethernet and wifi open a local ECR listener. bluetooth and
webService return a typed unsupported failure without sending anything.

Operations #

Amounts are plain decimal strings in major units. Never pass a JavaScript
number: binary floating point cannot exactly represent OMR amounts such as
1.234.

await terminal.isReachable();

await terminal.sale('1.234', {
  merchantReferenceId: 'ORDER-1001',
});

await terminal.voidTransaction('123', {
  originalTerminalId: 'TILL-01',
  merchantReferenceId: 'VOID-1001',
});

await terminal.refund('0.500', {
  receiptNumber: '123',
  transactionDate: '20260902',
  originalTerminalId: 'TILL-01',
  merchantReferenceId: 'REFUND-1001',
});

await terminal.inquire({
  receiptNumber: '123',
  transactionDate: '20260902',
});

await terminal.inquireByReference('ORDER-1001');

await terminal.receipt({
  receiptNumber: '123',
  transactionDate: '20260902',
});

inquire, inquireByReference, and receipt are read-only and safe to repeat.
The native SDK also follows an unknown money-moving failure with one inquiry by
reference when autoInquireOnFailure is enabled.

Cancellation #

Every operation has a start... form that returns an EcrOperation:

const operation = terminal.startSale('1.234', {
  merchantReferenceId: 'ORDER-1001',
});

cancelButton.onPress = () => operation.cancel();
const result = await operation.result;

Cancellation stops this application waiting; it does not reverse or stop the
terminal. A cancelled money-moving request returns a failed result with an
unknown outcome. Inquire before retrying.

The cancellable forms are startSale, startVoid, startRefund,
startInquire, startInquireByReference, and startReceipt.

Result model #

EcrResult is a discriminated union:

  • approved: money moved; includes amount, RRN, authorisation code, masked PAN,
    and partial-approval fields.
  • declined: the terminal answered and refused; code 91 remains unknown and
    requests an inquiry.
  • failed: the exchange did not produce a trustworthy answer; includes a typed
    failure and an optional recovered inquiry.

Failure kinds are unreachable, timeout, malformed, connectionLost,
unauthenticated, cancelled, and unsupported. The public
outcomeIsUnknown flag is the decision field callers should use.

Development #

corepack yarn install
corepack yarn verify

cd example/android
./gradlew :app:assembleDebug

cd ../ios
pod install
xcodebuild -workspace AmwalEcrExample.xcworkspace \
  -scheme AmwalEcrExample -sdk iphonesimulator \
  -configuration Debug CODE_SIGNING_ALLOWED=NO build

The example intentionally does not persist terminal details or secrets.

Releases #

Versions follow semantic versioning. A vX.Y.Z tag triggers Codemagic after the
tag, package.json, and top CHANGELOG.md entry agree. CI verifies TypeScript,
tests, the package archive, Android, and iOS, then publishes idempotently to npm
and reads the exact version back from the registry.

Native providers must already be resolvable from Maven Central and CocoaPods
trunk before a React Native release is allowed.

Updated on September 10, 2026

What are your Feelings

  • Happy
  • Normal
  • Sad

Share This Article :

  • Facebook
  • X
  • LinkedIn
  • Pinterest
Flutter ECR
Table of Contents
  • The one rule
  • Install
    • iOS local-network permission
  • Create a terminal
  • Operations
  • Cancellation
  • Result model
  • Development
  • Releases

Secure. Seamless – Powering Payments for Every Business.

Sign Up
Support

4th Floor, Majan Tower Building
North Al Ghubrah, P.O. Box 233, P.C 118
Muscat, Sultanate of Oman

: support@amwal-pay.com

📞 : +96824121845

Resources
  • Developers
  • Careers
Company
  • About us
  • Contact Us
  • Contact Sales
  • Partners

2026 © AmwalPay. All Rights Reserved.

  • Terms & Conditions
  • Privacy Policy