Skip to main content

Requirements

  • React Native 0.73+ or Expo SDK 50+
  • react-native-webview >= 13
  • react-native-safe-area-context >= 4
Expo Go can preview the sheet and hosted eSewa/Khalti screens. Native QR sharing and reliable installed-app detection require the config plugin and a development build. Expo Go cannot apply native app-query configuration.

Installation

Add the config plugin, then rebuild the native app:
app.json
Use your normal local or EAS development-build command after prebuild. eSewa’s sandbox Intent app is currently an Android UAT APK. The config plugin adds what the sheet needs to the native projects: A bare React Native app without Expo adds the same entries by hand. Without the iOS photo text, leave allowSaveToPhotos off: iOS ends an app that saves a photo without it.

How it works

Your backend creates an amount-bound session using your secret API key. Your app receives that short-lived session and uses a publishable key to present the server-approved methods. Your secret API key never touches the device.

The sheet shows whichever payment methods the merchant has on. Your app never picks a provider or builds payment screens, so turning a method on is a dashboard change, not an app release.
The payment sheet showing Bank App, Fonepay QR, eSewa and Khalti

A merchant with Fonepay: Bank App (detected apps only), Fonepay QR, eSewa, Khalti.

The payment sheet showing Fonepay QR, eSewa and Khalti

The same sheet for a merchant without Fonepay bank-app access: Fonepay QR, eSewa, Khalti.

1. Your backend creates a session

Session creation requires the payments:write scope when your secret key has an explicit scope list. Unrestricted secret keys continue to work. The app uses a publishable key and the session client secret for the device calls. Call POST /v1/mobile/session with your secret key and no provider:
methods comes from the server, based on the merchant’s providers, mode and plan. Payment limits are checked again when the buyer picks a method. If a supported bank app is installed, Bank App comes before Fonepay QR. One bank opens directly; several show a short picker. Return session_id and client_secret to your app. Do not send your secret key to the device. Use one Idempotency-Key per order, so a retry returns the same session instead of a second one.

2. Your app presents the sheet

The app uses your publishable key (safe to ship) and the session’s client secret, which works for that one session only. After the session expires, the secret cannot start a payment but can still read the status, so keep it in secure storage and out of logs.

How each method behaves

Choose bank app: the detected bank apps listed in the sheet

Bank App lists only the bank apps installed on the device.

Fonepay QR shown inside the payment sheet with an expiry countdown

Fonepay QR renders natively with a countdown and one QR button: Save QR where the phone can save, otherwise Share QR.

Confirming a payment

onComplete reports a confirmed success, or expired when no payment is still pending; otherwise the sheet keeps checking. While the hook stays mounted, each session reports once, and reopening a reported session closes the sheet without another callback (after an app restart it may report again). A failed or cancelled attempt goes back to the method picker when it is safe to retry. After returning from an app or timing out, the buyer can check the status by hand. A buyer can close the bank app after paying, so fulfil orders from the payment.succeeded webhook, as on web.
The demo shop showing the paid state after the sheet completed

The demo app after onComplete: the sheet heard success, the server's webhook is still the final word.

App restart recovery

The SDK does not store the session for you. Save it in secure storage and call resume(session) when your checkout screen comes back. Clear it when onComplete reports success, or when onComplete or onCancel reports paymentPending: false. While paymentPending is true, keep it: the buyer may have paid in their bank app, and resuming shows the result instead of starting a second payment. On Android, initialise callbacks during lifecycle setup; do not rely on in-memory checkout variables.

usePaymentSheet(options)

Returns { present, resume, dismiss, isVisible, loading, paymentSheetProps }.

Theming

appearance accepts tokens only: colors, radius, typography and the primary button. Light and dark are both supported. Layout is deliberately not overridable so the sheet stays upgradeable.

Usage (legacy usePayBridgeNP)

usePayBridgeNP and ProviderSheet require your app to choose the provider before a session exists, which means the provider list lives in your app and changing it needs an app release. They still work and are not going away without notice, but new integrations should use the payment sheet above.
Let the user pick the provider - session is created lazily after they tap.

Pre-built session

Use this when your backend picks the provider before showing the sheet.

ProviderSheet directly


API reference

usePayBridgeNP(options)

Returns { present, dismiss, isVisible, sheetProps }.
Pass either session or createSession - not both. createSession is preferred as it defers session creation until the user has picked a provider.

ProviderSheet props

Same options as usePayBridgeNP, plus visible: boolean.

PayBridgeNPMobileConfig

PayBridgeMobileConfig is still exported as a deprecated alias, so existing imports keep compiling.

CheckoutResult

MobileSession


Sandbox testing

Create the session with a sk_test_... key and the sheet runs in test mode. eSewa and Khalti need no setup: buyers sign in with the test accounts below. Fonepay has no test environment. eSewa (sandbox, rc-epay.esewa.com.np) Khalti (test checkout, test-pay.khalti.com) Khalti’s test wallets are shared by everyone. 9800000001 to 9800000004 are often drained; errors like “insufficient balance” come from Khalti’s sandbox, not your integration. Fonepay (no sandbox, real money)
Fonepay has no test environment. In test mode the sheet shows Fonepay only if you have added your own Fonepay merchant details (dashboard, Providers), and payments move real money. Test mode caps Fonepay at NPR 1,000 per payment and NPR 5,000 a month, so use tiny amounts like NPR 10.
The sandbox testing guide walks through the same flow on the hosted checkout page.