DEV Community

Aritra Dutta
Aritra Dutta

Posted on

πŸ’³ PhonePe Payment Gateway Integration – A Complete Guide

In today’s digital-first world, enabling seamless online payments is a must-have for any modern application. Whether you're running an e-commerce platform, a service-based website, or a mobile app, integrating a reliable and secure payment gateway is crucial. PhonePe offers a robust Payment Gateway API for development and business purposes. Recently, I have integrated the same into my project, and I would like to share the steps to do it. I have shown the process using the UAT API and credentials of PhonePe, but I will also mention the steps to do the same using a merchant Id.

Prerequisites

Before starting with the integration steps, let's consider some of the prerequisites for the API to function properly.

  • A registered PhonePe business account.
  • A test API key and merchant credentials (from the PhonePe dashboard).
  • Basic understanding of REST APIs, Node.js/Java/PHP (or your preferred backend language).
  • Your application URL (for redirect and webhook setup).

Getting the credentials

Go to the PhonePe Business Dashboard and sign up as a merchant. On approval of your account, PhonePe will give you the following

  • Merchant ID
  • Salt Key
  • Salt Index
  • API Credentials

Payment API Integration

I will show the integration process step by step with UAT credentials. When integrating for a business application, replace the UAT credentials with those given by PhonePe.

Payment API URL for Testing -
https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/pay
Salt Key - 96434309-7796-489d-8924-ab56988a6076
PhonePe Merchannt Id - PGTESTPAYUAT86.

Request Headers -

Header Name Header Value
Content-Type X-VERIFY
application/json SHA256(base64 encoded payload + β€œ/pg/v1/pay” + salt key) + ### + salt index

Request/Payload Parameters-

Parameter Name Datatype Mandatory/Optional Possible Values
merchantId String Mandatory Unique MerchantID assigned to the merchant by PhonePe Note: merchantId length will be less than 38 characters.
merchantTransactionId String Mandatory Unique TransactionID generated by the merchant to track request to PhonePe Note: – merchantTransactionId length should be less than 35 characters.
amount Long Mandatory Transaction amount in Paise. Note: Amount should be greater than 100 (in Paise)
merchantUserId String **Mandatory** if paymentInstrument.type is: ● PAY_PAGE ● CARD ● SAVED_CARD **Optional** for if paymentInstrument.type is: ● UPI_INTENT ● UPI_COLLECT ● UPI_QR ● TOKEN ● NET_BANKING Unique UserID of the users generated by the merchant. Note: – merchantUserId length should be less than 36 characters
redirectUrl String Mandatory The url where the user will be redirected after transaction completion. Note - The redirectUrl should be an existing page of the application.
redirectMode Enum Mandatory ● REDIRECT and ● POST
callbackUrl String Mandatory The URL where server to server callback will be posted. Always POST
paymentInstrument Object Mandatory PayMent Details
paymentInstrument.type Enum Mandatory ● PAY_PAGE ● CARD ● UPI_INTENT ● SAVED_CARD ● TOKEN ● UPI_COLLECT ● UPI_QR ● NET_BANKING
mobileNumber String Optional Mobile number of the user Note: There should not be any space.

Payload-
Firstly, we need to prepare the payload for the request. We will create an object with the fields which are mentioned above. Replace the PHONEPE_MERCHANT_ID with the merchant id provided by PhonePe. Also note that the amount should be in paise so we are multiplying it with 100.

let data = {
        merchantId: PHONEPE_MERCHANT_ID,
        merchantTransactionId: merchantTransactionId,
        name: customerName,
        mobileNumber: customerMobileNumber,
        amount: totalAmount * 100,
        redirectUrl:
          <YOUR_REDIRECT_URL>,
        callbackUrl:
          <YOUR_CALLBACK_URL>,
        redirectMode: "REDIRECT",
        paymentInstrument: {
          type: "PAY_PAGE",
        },
      };
Enter fullscreen mode Exit fullscreen mode

Now we have to convert this data to a string and take the base64 encoded value.

const payload = JSON.stringify(data);
const payloadMain = Buffer.from(payload).toString("base64");
Enter fullscreen mode Exit fullscreen mode

Next, we will concatenate the base64 encoded payload with "/pg/v1/pay" and the Salt key given by PhonePe. Now, hash the string using sha256 algorithm and prepare the checksum. The Salt index is 1 for UAT.

const string = payloadMain + "/pg/v1/pay" + PHONEPE_SALT_KEY;
let sha256hash = crypto.createHash("sha256").update(string).digest("hex");
let checkSum = sha256hash + "###" + process.env.SALT_INDEX;
Enter fullscreen mode Exit fullscreen mode

Now, prepare an object for axios to hit the payment API.
Payment API URL for Testing -
https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/pay

let options = {
        method: "POST",
        URL: "https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/pay",
        headers: {
          accept: "application/json",
          "Content-Type": "application/json",
          "X-VERIFY": checkSum,
        },
        data: {
          request: payloadMain,
        },
      };
let phonePayRes = await axios(options);
Enter fullscreen mode Exit fullscreen mode

Payment Status API Integration

Payment Staus API URL for Testing -
https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/status

Now, it's time to check the status of the payment made.
Create a string combining "/pg/v1/status/", the Merchant ID, and the transaction ID.

const string ="/pg/v1/status/" + PHONEPE_MERCHANT_ID + YOUR_TRANSACTION_ID + PHONEPE_SALT_KEY;
Enter fullscreen mode Exit fullscreen mode

Similarly, we will create the hash and checksum.

let sha256hash = crypto.createHash("sha256").update(string).digest("hex");
let checkSum = sha256hash + "###" + process.env.SALT_INDEX;
Enter fullscreen mode Exit fullscreen mode

Now, we will prepare the object to be passed to axios for hitting the API.

let options = {
        method: "GET",
        url: https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/status/{PHONEPE_MERCHANT_ID}/{YOUR_TRANSACTION_ID},
        headers: {
          accept: "application/json",
          "Content-Type": "application/json",
          "X-VERIFY": checkSum,
        },
      };

let phonePeStsRes = await axios(options);
Enter fullscreen mode Exit fullscreen mode

This will give the status of the transaction, whether it was a failure or a success.

I hope this blog will help you integrate these APIs into your own application. I would be pleased to know if any points remained uncovered, so that I can further add them.

Top comments (0)