Skip to content

GlomoPay React Native SDK v4

Official React Native SDK for integrating GlomoPay payment checkout flows into your mobile applications.

Upgrading from v1 or v3? See the Migration Guide. Full Changelog is also available.

Prerequisites

Before using this SDK, you need:

  • API credentials (Public Key) from your GlomoPay dashboard
  • An order ID created via the GlomoPay API (or a subscription ID for subscription payments)

System Requirements

RequirementVersion
Node.js>= 16.0.0
npm>= 8.0.0
React>= 17.0.0
React Native>= 0.68.0
react-native-webview^13.0.0
jail-monkey (optional, but strongly recommended)^2.6.0

Installation

React Native CLI

npm install @glomopay/react-native-sdk react-native-webview
cd ios && pod install

Expo

npx expo install @glomopay/react-native-sdk react-native-webview

For rooted/jailbroken device detection (strongly recommended for regulated flows):

npm install jail-monkey

The SDK works without jail-monkey, but installing it enables automatic device security checks. Without it, the SDK logs a warning on every start() call.

Quick Start

import React, { useRef } from "react";
import { View, Button } from "react-native";
import {
  GlomoCheckout,
  ASYNC_PAYMENT_EVENTS,
  type GlomoCheckoutRef,
  type GlomoCheckoutPayload,
  type SdkError,
} from "@glomopay/react-native-sdk";

export default function PaymentScreen() {
  const checkoutRef = useRef<GlomoCheckoutRef>(null);

  const handlePay = async () => {
    const started = await checkoutRef.current?.start();
    if (!started) {
      console.log("Checkout could not start - check onSdkError for details");
    }
  };

  return (
    <View style={{ flex: 1 }}>
      <Button title="Pay Now" onPress={handlePay} />

      <GlomoCheckout
        ref={checkoutRef}
        publicKey="live_pk_abc123"
        orderId="order_xyz789"
        onPaymentSuccess={(payload: GlomoCheckoutPayload) => {
          console.log("Payment success:", payload.paymentId);
        }}
        onPaymentFailure={(payload: GlomoCheckoutPayload) => {
          console.log("Payment failed:", payload.paymentId);
        }}
        onPaymentTerminate={() => {
          console.log("User dismissed checkout");
        }}
        onConnectionError={(error) => {
          console.log("Connection error:", error);
        }}
        onUserJourneyCompleted={(payload) => {
          switch (payload.journeyType) {
            case ASYNC_PAYMENT_EVENTS.BANK_TRANSFER_SUBMITTED:
              console.log("Bank transfer submitted:", payload.transactionReference);
              break;
            case ASYNC_PAYMENT_EVENTS.PAY_VIA_BANK_COMPLETED:
              console.log("Pay via bank completed:", payload.status);
              break;
          }
        }}
        onUserRefusedCameraPermissions={() => {
          console.log("User refused camera - cannot proceed with bank authentication");
        }}
        onSdkError={(errors: SdkError[]) => {
          errors.forEach((e) => console.error(e.type, e.message, e.field));
        }}
      />
    </View>
  );
}

Subscriptions Checkout

To process subscription payments, pass a subscriptionId instead of an orderId:

<GlomoCheckout
  ref={checkoutRef}
  publicKey="live_pk_abc123"
  subscriptionId="sub_xyz789"
  onPaymentSuccess={(payload) => {
    console.log("Subscription payment success:", payload.paymentId);
  }}
  onPaymentFailure={(payload) => {
    console.log("Subscription payment failed:", payload.paymentId);
  }}
  onSdkError={(errors) => {
    errors.forEach((e) => console.error(e.type, e.message));
  }}
/>

When subscriptionId is provided:

  • The SDK skips order type detection (no API call)
  • The subscriptionId must start with sub_
  • onUserJourneyCompleted is not applicable - subscriptions are card-only (onPaymentSuccess/onPaymentFailure)
  • Do not pass both orderId and subscriptionId - the SDK will fire onSdkError
  • The detecting_order_type status is not emitted for subscription flows

Features

  • Cross-platform - works on both iOS and Android
  • TypeScript - full type definitions for all exports
  • Unified checkout - renders the correct checkout flow automatically based on your order
  • Asynchronous payment flows - single onUserJourneyCompleted callback for bank transfer and pay via bank events
  • Camera permissions - built-in handling for bank authentication
  • Device security - optional (but strongly recommended) jail-monkey integration for rooted/jailbroken device detection
  • Input validation - publicKey and orderId format enforcement before checkout starts
  • Mock mode - test with test_ / mock_ prefixed keys without hitting production

API Reference

GlomoCheckout Component

The unified checkout component. Place it in your render tree and control it via a ref.

<GlomoCheckout ref={checkoutRef} {...props} />

Props (GlomoCheckoutProps)

PropTypeRequiredDescription
publicKeystringYesYour GlomoPay public key (must start with live_, mock_, or test_)
orderIdstringNo*Order ID from the GlomoPay API (must start with order_)
subscriptionIdstringNo*Subscription ID (must start with sub_). Bypasses order type detection.
onPaymentSuccess(payload: GlomoCheckoutPayload) => voidYesCalled when payment succeeds
onPaymentFailure(payload: GlomoCheckoutPayload) => voidYesCalled when payment fails
onConnectionError(error: unknown) => voidNoCalled on network/connection errors
onPaymentTerminate() => voidNoCalled when user dismisses checkout (back button or swipe)
onSdkError(errors: SdkError[]) => voidYesCalled on validation errors or device compliance failures
onUserJourneyCompleted(payload: GlomoUserJourneyCompletedPayload) => voidNoCalled when an asynchronous payment flow completes (bank transfer submission, pay via bank completion). Check payload.journeyType to determine the flow.
onUserRefusedCameraPermissions() => voidNoCalled when user denies camera access needed for bank authentication

*Exactly one of orderId or subscriptionId must be provided. If both or neither are set, onSdkError fires and start() returns false.

Ref Methods (GlomoCheckoutRef)

MethodSignatureDescription
start()() => Promise<boolean>Validates inputs, and opens the checkout modal. Resolves true if successful, false otherwise.
getStatus()() => CheckoutStatusReturns the current checkout status.

CheckoutStatus

StatusDescription
readyInitial state - checkout can be started
detecting_order_typeOrder type detection in progress (after start(), before checkout opens)
payment_in_progressCheckout modal is open, user is interacting
payment_successfulPayment completed successfully. Cannot restart with same order
payment_failedPayment failed. Can retry with same order
payment_cancelledUser dismissed checkout mid-flow. Can retry
bank_transfer_submittedUser submitted bank transfer details
pay_via_bank_completedPay via bank flow completed

Type Definitions

GlomoCheckoutPayload

interface GlomoCheckoutPayload {
  orderId: string;
  paymentId: string;
  signature: string;
}

ASYNC_PAYMENT_EVENTS

enum ASYNC_PAYMENT_EVENTS {
  BANK_TRANSFER_SUBMITTED = "bank_transfer_submitted",
  PAY_VIA_BANK_COMPLETED = "pay_via_bank_completed",
}

GlomoUserJourneyCompletedPayload

interface GlomoUserJourneyCompletedPayload {
  journeyType: ASYNC_PAYMENT_EVENTS;
  orderId?: string;
  status?: string;
  senderAccountNumber?: string;
  transactionReference?: string;
}

SdkError

interface SdkError {
  type: "validation_error" | "device_forbidden";
  message: string;
  field?: "publicKey" | "orderId" | "subscriptionId" | "baseCheckoutUrl" | "generatedCheckoutUrl";
}

Asynchronous Payment Flows

The SDK fires onUserJourneyCompleted when an asynchronous payment flow completes. Use payload.journeyType to determine which flow triggered the callback:

onUserJourneyCompleted={(payload) => {
  switch (payload.journeyType) {
    case ASYNC_PAYMENT_EVENTS.BANK_TRANSFER_SUBMITTED:
      /**
       * User submitted bank transfer details.
       * Relevant fields: orderId, senderAccountNumber, transactionReference
       * Note: fields may be absent if the checkout page omits them.
       */
      console.log("Transfer ref:", payload.transactionReference);
      break;
    case ASYNC_PAYMENT_EVENTS.PAY_VIA_BANK_COMPLETED:
      /**
       * Pay via bank journey completed.
       * Relevant fields: orderId, status
       * The SDK deduplicates this event - fires only once per session.
       */
      console.log("Pay via bank status:", payload.status);
      break;
  }
}}

The checkout status transitions to bank_transfer_submitted or pay_via_bank_completed respectively. Use getStatus() for granular programmatic checks.

Camera Permissions

Some checkout flows may require camera access for bank authentication. The SDK handles permission prompts automatically, but you must declare the permissions in your native project config.

Android

Add to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" />

iOS

Add to ios/<YourApp>/Info.plist:

<key>NSCameraUsageDescription</key>
<string>Camera access is required for identity verification during checkout</string>

Behavior

  • Android: SDK prompts the user via a native permission dialog. If denied, checkout closes and onUserRefusedCameraPermissions fires.
  • iOS: SDK grants the WebView permission request; iOS shows its own system prompt. If the user denies at the system level, the WebView handles the denial.

Platform Behavior

  • iOS: Checkout opens as a pageSheet modal (swipe-down to dismiss). Dismissing fires onPaymentTerminate.
  • Android: Checkout opens fullscreen. The hardware back button dismisses it and fires onPaymentTerminate.

Device Security Compliance

The SDK optionally integrates with jail-monkey to detect rooted (Android) or jailbroken (iOS) devices.

  • If jail-monkey is installed and the device is compromised: start() returns false and onSdkError fires with type: "device_forbidden".
  • If jail-monkey is installed and the device is clean: checkout proceeds normally.
  • If jail-monkey is not installed: SDK logs a warning and proceeds without checking. This is not recommended for production deployments handling regulated transactions.

Mock Mode

The SDK infers mock mode from the publicKey prefix:

PrefixModeEnvironment
live_LiveProduction
test_MockTest/sandbox
mock_MockTest/sandbox

Mock mode keys route to the sandbox backend. No real transactions are created.

Connection Handling

The SDK detects connection errors from the WebView and fires onConnectionError:

  • iOS: NSURLErrorDomain codes (-1001 timeout, -1003 host not found, -1004 connection refused, -1009 offline)
  • Android: ERR_EMPTY_RESPONSE, ERR_CONNECTION_REFUSED, ERR_NAME_NOT_RESOLVED, ERR_INTERNET_DISCONNECTED, ERR_CONNECTION_TIMED_OUT, ERR_NETWORK_CHANGED

The checkout modal is automatically dismissed on connection errors.

Input Validation

The SDK validates inputs before starting the checkout:

FieldRule
publicKeyMust start with live_, mock_, or test_. Min 6 characters.
orderIdMust start with order_. Min 7 characters. Required when subscriptionId is absent.
subscriptionIdMust start with sub_. Trimmed and checked for emptiness. Required when orderId is absent.

Validation failures fire onSdkError with type: "validation_error" and the relevant field name. start() returns false.

Providing both orderId and subscriptionId (or neither) also fires onSdkError.

useGlomoCheckout Hook (Deprecated)

Deprecated - Legacy hook, will be removed in a future major version.

useGlomoCheckout is a legacy placeholder from the v1.x hook-based API. In v1.x, the equivalent hook (useLrsCheckout) provided reactive WebView state and rendering primitives that merchants used to build custom checkout UIs. In v3+, the inner checkout components are no longer exported, making this hook ineffective for custom rendering.

The hook's public return type (UseGlomoCheckoutReturn) exposes:

  • start() - identical to GlomoCheckoutRef.start(). Returns Promise<boolean>.
  • getStatus() - returns a point-in-time CheckoutStatus snapshot. Not reactive - does not trigger re-renders when status changes.

Use the GlomoCheckout component with a ref instead:

import React, { useRef } from "react";
import { GlomoCheckout, type GlomoCheckoutRef } from "@glomopay/react-native-sdk";

const checkoutRef = useRef<GlomoCheckoutRef>(null);

// Start checkout
const started = await checkoutRef.current?.start();

// Check status (point-in-time, same as hook)
const status = checkoutRef.current?.getStatus();

The component-based API provides the same functionality with proper lifecycle management.

Troubleshooting

start() returns false

Check onSdkError for details. Common causes:

  • Invalid publicKey format (must start with live_, mock_, or test_)
  • Invalid orderId format (must start with order_)
  • Invalid subscriptionId format (must start with sub_, non-empty after trimming)
  • Both orderId and subscriptionId provided (or neither)
  • Device is rooted/jailbroken (when jail-monkey is installed)

Checkout opens but shows a blank screen

  • Verify network connectivity
  • Check that the publicKey and orderId are valid

Camera permission denied

  • Ensure AndroidManifest.xml and Info.plist include camera permission declarations
  • The onUserRefusedCameraPermissions callback will fire when the user denies

onUserJourneyCompleted not firing

  • Ensure you are passing onUserJourneyCompleted as a prop to GlomoCheckout
  • Verify the checkout flow involves an asynchronous payment (bank transfer or pay via bank)

Exports

// Components
export { GlomoCheckout } from "@glomopay/react-native-sdk";

// Hooks (deprecated - use GlomoCheckout component with ref instead)
export { useGlomoCheckout } from "@glomopay/react-native-sdk";

// Enums
export { ASYNC_PAYMENT_EVENTS } from "@glomopay/react-native-sdk";

// Types
export type {
  GlomoCheckoutRef,
  GlomoCheckoutProps,
  GlomoCheckoutPayload,
  CheckoutStatus,
  GlomoUserJourneyCompletedPayload,
  UseGlomoCheckoutReturn,  // deprecated
  SdkError,
} from "@glomopay/react-native-sdk";

Security

The SDK loads checkout pages in an isolated WebView. No PAN, CVV, or sensitive payment data passes through the React Native bridge - all sensitive input is handled within the WebView's sandboxed context.

Device integrity checking is available via optional jail-monkey integration (see Device Security Compliance).

To report a security vulnerability, email security@glomopay.com. Do not open a public GitHub issue for security reports.