How to Integrate PayHere Payment Gateway in Expo React Native (2026 Guide)

Appblee
0




Hello friends 👋 ,  Recently, I was working on a React Native project with Expo. In that mobile application, I had to integrate the PayHere payment gateway in an Expo compatible way.


At first, I searched everywhere  articles, YouTube videos, and many other resources. But I couldn’t find a proper working solution. Then I started going through the documentation carefully and even used AI tools to guide me. After trying different approaches, I finally found the solution. So today, I’m going to share it with you.


Before starting, you need to create a PayHere account and enable the sandbox environment.


Now you might be wondering  what is PayHere?


PayHere is a Sri Lankan based payment gateway. It allows developers to integrate secure online payments into their own applications.


While developing this feature, I used Expo Go on my mobile phone to check all the changes I made to the app. The solution itself is not very complicated  it’s actually simple. But there is one very important thing you need to know.

IMPORTANT 🚨

PayHere WILL NOT work in Expo Go!

You must build a development client using Expo Application Services (EAS Build). This is a one-time process that takes around 30 minutes. After that, all your code updates will be instant.


The Challenge : Expo + Native Modules


This is where most developers get stuck.  

PayHere provides a React Native SDK, but there’s a catch it is a native module. That means it contains actual Java code (for Android) and Swift code (for iOS), not just JavaScript.


Now here’s the problem.

Expo Go  the  app we use to test our projects  does not include PayHere’s native code. And it cannot include all native modules because there are thousands of them. If it did, the app would be extremely large.


So when you try to use PayHere inside Expo Go, it simply won’t work.


What happens when you try?


import PayHere from '@payhere/payhere-mobilesdk-reactnative';

PayHere.startPayment(paymentObject);

// ❌ Error: Native module cannot be null


You will get this error:

Native module cannot be null

And that’s because Expo Go does not have the PayHere native module inside it.


Before you implement PayHere, you need to install a few dependencies.

Install dependencies


# Install dependencies
npm install @payhere/payhere-mobilesdk-reactnative@4.0.14
npx expo install expo-dev-client

The expo-dev-client package is important because it allows you to:
  • Build a custom version of your app with PayHere included
  • Keep useful Expo features like Fast Refresh and debugging
  • Update JavaScript instantly without rebuilding the app

By installing these first, your project will be ready for the PayHere integration without running into native module issues.

Implementation


Then you need to follow the PayHere documentation and integrate the model as shown below. I have included sample details, but you will need to update them according to your own implementation. Make sure the 
paymentObject reflects the details relevant to the place or service where you are using the payment gateway.



// Prepare PayHere payment object

const paymentObject = {
  sandbox: PAYMENT_CONFIG.SANDBOX,
  merchant_id: PAYMENT_CONFIG.MERCHANT_ID,
  notify_url: "", // Optional: Add your backend notification URL
  order_id: order123,
  items: ITEM_01,
  amount: 200,
  currency: "LKR",
  first_name: "John",
  last_name: "Silva",
  email: "john@gmail.com",
  phone: "0771234567",
  address: "No:123,ABC Road,Colombo",
  city: "Colombo",
  country: "Sri Lanka",
  custom_1: "PROPERTY TYPE",
  custom_2: currentUser.uid,
};




Here PAYMENT_CONFIG can be defined as

export const PAYMENT_CONFIG = {
  MERCHANT_ID: process.env.MERCHANT_ID!,
  SANDBOX: true, // Set to false for production
};


Your MERCHANT_ID should add to the .env file and here you can use it.Also here we use SANDBOX as true because we are on developing stage and testing when you push this to production have to make it true.


After above part you can do the payment .


PayHere.startPayment(
  paymentObject,
  async (paymentId: string) => {
  
    // ✅ Payment Success
    console.log('✅ Payment successful:', paymentId);
    
    //update payment on database
    try {
      await updatePaymentRecord(orderId, {
        status: 'completed',
        paymentId: paymentId,
      });

      resolve({
        success: true,
        status: 'completed',
        paymentId: paymentId,
        orderId: orderId,
        amount: paymentInput.amount,
      });
    } catch (error: any) {
      console.error('Error updating payment record:', error);
      resolve({
        success: true,
        status: 'completed',
        paymentId: paymentId,
        orderId: orderId,
        amount: paymentInput.amount,
        error: 'Payment successful but record update failed'
      });
    }
  },
  async (errorData: string) => {
  
    // ❌ Payment Error
    console.log('❌ Payment failed:', errorData);
    
    
    //update payment on database 
    try {
      await updatePaymentRecord(orderId, {
        status: 'failed',
        error: errorData,
      });
    } catch (error) {
      console.error('Error updating failed payment:', error);
    }

    resolve({
      success: false,
      status: 'failed',
      orderId: orderId,
      error: errorData,
    });
  },
  async () => {
  
    // ⚠️ Payment Dismissed/Cancelled
    console.log('⚠️ Payment cancelled by user');
    
    try {
    
    //update the database
      await updatePaymentRecord(orderId, {
        status: 'cancelled',
      });
    } catch (error) {
      console.error('Error updating cancelled payment:', error);
    }

    resolve({
      success: false,
      status: 'cancelled',
      orderId: orderId,
      error: 'Payment was cancelled by user',
    });
  }
);

For PayHere.startPayment(), you need to provide the paymentObject and the callbacks for success, error, and dismissal


At the top of your service file, import PayHere:
import PayHere from '@payhere/payhere-mobilesdk-reactnative';

If you are using TypeScript, create a file named payhere-mobilesdk-reactnative.d.ts in your model folder:


// types/payhere-mobilesdk-reactnative.d.ts
// Type definitions for @payhere/payhere-mobilesdk-reactnative

declare module '@payhere/payhere-mobilesdk-reactnative' {
  export interface PayHerePaymentObject {
    sandbox: boolean;
    merchant_id: string;
    notify_url?: string;
    order_id: string;
    items: string;
    amount: string;
    currency: string;
    first_name: string;
    last_name: string;
    email: string;
    phone: string;
    address: string;
    city: string;
    country: string;
    delivery_address?: string;
    delivery_city?: string;
    delivery_country?: string;
    custom_1?: string;
    custom_2?: string;
  }

  export interface PayHere {
    startPayment(
      paymentObject: PayHerePaymentObject,
      onSuccess: (paymentId: string) => void,
      onError: (errorData: string) => void,
      onDismiss: () => void
    ): void;
  }

  const PayHere: PayHere;
  export default PayHere;
}



Building and Testing Your App


Now that the implementation is complete, let's build and test the app. As mentioned earlier, you cannot use Expo Go to test PayHere. You must build the app first.

There are two ways to build your app:


Method 1: EAS Build 


This is the easiest and most beginner friendly method. The build happens on Expo's cloud servers, so you don't need to install Android Studio or configure anything on your computer.


Step 1: Build Your App



 npx eas-cli build --profile development --platform android


What happens:

  • First time: You'll be asked to login to your Expo account (create one free at expo.dev/signup)
  • Your code uploads to Expo's servers
  • Expo compiles your app with PayHere included
  • This takes 20-30 minutes
  • You'll get a download link when complete

Step 2: Download and Install


  1. Click the download link in your terminal (or check expo.dev/accounts/[your-account]/builds)
  2. Download the APK file to your Android phone
  3. Install the APK (you may need to enable "Install from unknown sources" in your phone settings)
  4. A new app icon will appear on your phone


Step 3: Run the Development Server



npx expo start --dev-client


Pros:

  • ✅ No Android Studio needed
  • ✅ No environment setup
  • ✅ Works on any computer (Windows/Mac/Linux)
  • ✅ Team members can easily replicate
  • ✅ Beginner-friendly

Cons:

  • ❌ Requires internet connection
  • ❌ First build takes 20-30 minutes
  • ❌ Uses Expo's build servers

Method 2: Local Build with Prebuild (Advanced Users)


This method builds the app locally on your computer. It gives you more control but requires more setup.

Prerequisites

Before starting, you need to:

  1. Install Android Studio
    • Download from: developer.android.com/studio
    • Install with default settings
    • Open Android Studio once to complete setup

  2. Set Up Environment Variables Add a new User Variable:
  • Variable name: ANDROID_HOME
  • Variable value: C:\Users\YourUsername\AppData\Local\Android\Sdk

Add to Path Variables (both of these):
  • %ANDROID_HOME%\platform-tools
  • %ANDROID_HOME%\tools

How to add environment variables (Windows):
  • Press Windows + R, type sysdm.cpl, press Enter
  • Go to "Advanced" tab → "Environment Variables"
  • Add the variables as described above
  • Click OK and restart your terminal

Step 1: Prebuild (Generate Native Folders)


Run the below command.


npx expo prebuild



After executing this code you can see there is folder named android will be on your folder.




Step 2: Create local.properties File


When it first build there won't be the file local.properties.So you have to go to android folder path using cmd then on that path you have to run the command.


echo sdk.dir=C:\\Users\\exampleuser\\AppData\\Local\\Android\\Sdk > local.properties


Then the local.properties file will be created with the properties.

Then you have to go to the gradlelew.bat file  on the android folder. There will be variable CLASSPATH so make it as 

CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
 

Step 3: Build and Run


Now you have two options:


Option A: Run on connected Android phone



npx expo run:android


Make sure:

  • Your phone is connected via USB cable
  • USB debugging is enabled on your phone
  • Your phone is recognized (check with adb devices)

Option B: Run on Android Emulator


# First, open Android Studio and start an emulator
# Then run:
npx expo run:android


Step 4: Development Mode


For subsequent runs (after the first build):


npx expo start --dev-client


Then:

  • Your app will automatically launch on the connected device/emulator
  • You can update JavaScript code and see changes instantly
  • Only rebuild if you add new native modules

Pros:

  • ✅ Build happens on your machine
  • ✅ More control over the build process
  • ✅ Can work offline
  • ✅ No dependency on Expo's servers

Cons:

  • ❌ Requires Android Studio (~5GB download)
  • ❌ Complex environment setup
  • ❌ Requires powerful computer
  • ❌ Build errors can be harder to debug
  • ❌ Different setup for each team member
  • ❌ Can't easily build for iOS on Windows

Integrating PayHere with your React Native Expo app might feel tricky at first, especially because Expo Go doesn’t support native modules. But don’t worry  once you follow the steps above, it’s actually pretty straightforward! 


A few friendly reminders:

  • Use sandbox mode for testing and switch to production when your app is live.
  • Make sure your paymentObject matches the details of your service or project.
  • EAS Build is the easiest way to get started, while local builds give more control if you’re up for it.
  • Test on a real device so everything works smoothly.


Once it’s set up, PayHere makes handling payments in your app super simple and reliable. Happy coding!

Post a Comment

0Comments

Post a Comment (0)