Integration Steps

Learn how you can integrate with Plural APIs to start accepting payments on Plural Hosted Checkout.

Follow the below steps to integrate with Plural hosted checkout APIs in your application.

  1. [Prerequisite] Generate Token
  2. Generate Checkout Link
  3. Handle Payment
    1. Store Payment Details on Your Server
    2. Verify Payment Signature
  4. Capture Order
  5. Cancel Order

1. [Prerequisite] Generate Token

Integrate our Generate Token API in your backend servers to generate the access token. Use the token generated to authenticate Plural APIs.

Use the below endpoint to generate a token.

POST: https://pluraluat.v2.pinepg.in/api/auth/v1/token
POST: https://api.pluralpay.in/api/auth/v1/token

Below is a sample request and response for the Generate Token API.

curl --request POST \
     --url https://pluraluat.v2.pinepg.in/api/auth/v1/token \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "client_id": "a17ce30e-f88e-4f81-ada1-c3b4909ed232",
  "client_secret": "fgwei7egyhuggwp39w8rh",
  "grant_type": "client_credentials"
}
'
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "expires_in": 3600
}

Refer to our Generate Token API documentation to learn more.

2. Generate Checkout Link

To create a Plural-hosted checkout link, use our Generate Checkout Link API. Include the access token in the request headers for Bearer Authentication.

Use the below endpoint to generate checkout link.

POST: https://pluraluat.v2.pinepg.in/api/checkout/v1/orders
POST: https://api.pluralpay.in/api/checkout/v1/orders

Below is a sample curl request and response for a Generate Checkout Link API.

curl --location 'https://pluraluat.v2.pinepg.in/api/checkout/v1/orders' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJVeDFRWk5ZdDdFcWg2YnNVb2ZpeXdiZkFVY0JTdzB4clVTdlI2WkF2VURBIn0.eyJleHAiOjE3MjgzMTgwMjcsImlhdCI6MTcyODI4OTIyNywianRpIjoiMzAxMTZjYWUtYWNlZi00ZjY5LTkxOTgtNGE0ZmUzZjI2ZjJhIiwiaXNzIjoiaHR0cDovL2tleWNsb2FrLmtleWNsb2FrLnN2Yy5jbHVzdGVyLmxvY2FsL3JlYWxtcy9rb25nLWF1dGgiLCJzdWIiOiIwYTY4MTNlMC04M2I3LTQ4ODItOWNkZC1lODhhYzk5YmUxM2YiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiIxMTE4NDliZC05MjJiLTQzNzctOWRhNC0zMmM2ZjVkNjgwODMiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYm90QGZjMmEzYmYyLTZjNmQtNDRlMy05MmZiLTk2NGNiYWZiM2NmYSIsIm9mZmxpbmVfYWNjZXNzIiwiZGVmYXVsdC1yb2xlcy1rb25nLWF1dGgiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwic2NvcGUiOiIiLCJjbGllbnRIb3N0IjoiMTAuMjA4Ljg5LjE0NiIsImNsaWVudEFkZHJlc3MiOiIxMC4yMDguODkuMTQ2IiwiY2xpZW50X2lkIjoiMTExODQ5YmQtOTIyYi00Mzc3LTlkYTQtMzJjNmY1ZDY4MDgzIiwiYXR0cnMiOnsibWVyY2hhbnQtaWQiOiIxMDgyNzIifX0.sUDhXMGvdvNtpNv2-IO4ItQN5cRptJ_TbbikQmhkIvxVk7FyLP0pcdnJG0hQY4RNcjBk1ouzCdXNYVr9mpLxyGL-mlTQpUUJULzUFBTiwTa3dyo26Kx2sEg6sxngZgHjdHND9vAbgVS7h6Vt5UDrfRZedPbftcFbZz_CfM8TwMHPPqWScGIHg9wovU0ELYg06pwdgiXNCmXVGd2oRluyDbW_0ID_IGbhQ6pUSViMx6EW5xO1vrlST5WCWV8Aw7zHeSzg7MXpUKuStVgTYNzFElAY0gNyjRNAdanNGISdX2U4MfhHsqJU-UOwWAaOQ6X4v5BCMOK1KlhOVmQPM1IzLQ' \
--data-raw '{
 "merchant_order_reference": 112345171,
  "order_amount": {
    "value": 500,
    "currency": "INR"
  },
  "pre_auth": false,
  "purchase_details": {
    "customer": {
      "email_id": "[email protected]",
      "first_name": "Kevin",
      "last_name": "Bob",
      "customer_id": "192212",
      "mobile_number": "9876543210",
      "billing_address": {
        "address1": "H.No 15, Sector 17",
        "address2": "",
        "address3": "",
        "pincode": "61232112",
        "city": "CHANDIGARH",
        "state": "PUNJAB",
        "country": "INDIA"
      },
      "shipping_address": {
        "address1": "H.No 15, Sector 17",
        "address2": "",
        "address3": "",
        "pincode": "144001123",
        "city": "CHANDIGARH",
        "state": "PUNJAB",
        "country": "INDIA"
      }
    },
    "merchant_metadata": {
      "key1": "DD",
      "key2": "XOF"
    }
  }
}'
{
  "token": "<<Redirect Token>>",
  "order_id": "<<Order ID>>",
  "redirect_url": "https://api.pluralonline.com/api/v3/checkout-bff/redirect/checkout?token=<<Redirect Token>>",
  "response_code": 200,
  "response_message": "Order Creation Successful."
}

Refer to our Generate Checkout Link API documentation to learn more.

Refer to our Test Card Details documentation to learn more.

πŸ“˜

Note:

  • You can set pre-auth as true to use pre-authorization flow for card payments only through hosted checkout.

3. Handle Payment

In the response to the Generate Checkout Link API, a redirect_url is returned. Use this URL to redirect your customers to the Plural-hosted checkout page to accept payment.

πŸ“˜

Note:

For pre_auth true

  • On successful payment we send the webhook event ORDER_AUTHORIZED and the status of the payment is updated to AUTHORIZED.
  • You can capture or cancel an order only when the order status is AUTHORIZED.

For pre_auth false

  • On successful payment we send the webhook event ORDER_PROCESSED and the status of the payment is updated to PROCESSED

3.1 Store Payment Details on Your Server

On a successful and failed payment we return the following fields to the return url.

  • We recommend you to store the payment details on your server.
  • You must validate the authenticity of the payment details returned. You can authenticate by verifying the signature.
{
  "order_id": "v1-4405071524-aa-qlAtAf",
  "payment_status": "AUTHORIZED",
  "signature": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
}
{
  "order_id": "v1-4405071524-aa-qlAtAf",
  "payment_status": "AUTHORIZED",
  "error_code": "USER_AUTHENTICATION_REQUIRED",
  "error_message": "Consumer Authentication Required",
  "signature": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
}

3.2 Verify Payment Signature

Ensure you follow this as a mandatory step to verify the authenticity of the details returned to the checkout form for successful payments.

Follow the below steps to verify the signature.

  1. Create a signature on your server using the following parameters using the SHA256 algorithm.
    1. order_id: Unique Identifier generated for an order request on Plural database.
    2. payment_status: Payment status.
    3. error_code: Short code for the error returned.
    4. error_message: Corresponding error message for the code.
    5. secret_key: The Onboarding team has provided you with this information as part of the onboarding process.

Use the below sample code to construct HashMap signature using the SHA256 algorithm.

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
 
public class hash {
    public static void main(String[] args) {
        // Test the GenerateHash method
        String input = "<string>";
        String secretKey = "<secret_key>";  // Example key in hex
 
        String hash = GenerateHash(input, secretKey);
        System.out.println("Generated Hash: " + hash);
    }
    public static String GenerateHash(String input, String strSecretKey) {
        String strHash = "";
        try {
            if (!isValidString(input) || !isValidString(strSecretKey)) {
                return strHash;
            }
            byte[] convertedHashKey = new byte[strSecretKey.length() / 2];
 
            for (int i = 0; i < strSecretKey.length() / 2; i++) {
                convertedHashKey[i] =
                        (byte)Integer.parseInt(strSecretKey.substring(i * 2, (i*2)+2),16); //hexNumber radix
            }
            strHash = hmacDigest(input.toString(), convertedHashKey,
                    "HmacSHA256");
        } catch (Exception ex) {
            strHash = "";
        }
        return strHash.toUpperCase();
    }
    private static String hmacDigest(String msg, byte[] keyString, String algo) {
        String digest = null;
        try {
            SecretKeySpec key = new SecretKeySpec(keyString, algo);
            Mac mac = Mac.getInstance(algo);
            mac.init(key);
            byte[] bytes = mac.doFinal(msg.getBytes("UTF-8"));
            StringBuffer hash = new StringBuffer();
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(0xFF & bytes[i]);
                if (hex.length() == 1) {
                    hash.append('0');
                }
                hash.append(hex);
            }
            digest = hash.toString();
        } catch (UnsupportedEncodingException e) {
// logger.error("Exception occured in hashing the pine payment gateway request"+e);
        } catch (InvalidKeyException e) {
// logger.error("Exception occured in hashing the pine payment gateway request"+e);
        } catch (NoSuchAlgorithmException e) {
// logger.error("Exception occured in hashing the pine payment gateway request"+e);
        }
        return digest;
    }
    public static boolean isValidString(String str){
        if(str != null && !"".equals(str.trim())){
            return true;
        }
        return false;
    }
}

πŸ“˜

Note:

To create a request string, format the key-value pairs of data returned to the return URL. The pairs are separated by & and arranged in ascending order based on a lexicographical comparison of the keys.

Shown below is a example to create a request string.

"key1=value1&key2=value2", ["order_id=random_order_id&status=AUTHORIZED"]
"key1=value1&key2=value2&key3=value3&key4=value4", ["error_code=USER_AUTHENTICATION_FAILED&error_message=Consumer Authentication required&order_id=<order_id>&status=FAILED"]
  1. If the signature generated on your server matches the Plural signature returned in the return URL, it confirms that the payment details are from Plural.
  2. Capture the status returned on your database. Once the payment status is AUTHORIZED you can either capture or cancel an order.

πŸ“˜

Important:

  • With pre-authorization set to true, you can capture or cancel a payment for an order against a card payment.

4. Capture Order

Use this API to capture the payment against an order. On successful capture of an order the order status is updated as processed.

Use the below endpoint to capture the payment against the order.

PUT: https://pluraluat.v2.pinepg.in/api/pay/v1/orders/{order_id}/capture
PUT: https://api.pluralpay.in/api/pay/v1/orders/{order_id}/capture

Shown below is a sample request and sample response for a Capture Order API.

{
  "merchant_capture_reference": "merchant-capture-ref-r4y",
  "capture_amount": {
    "value": 4000,
    "currency": "INR"
  }
}
{
  "data": {
    "order_id": "v1-5757575757-aa-hU1rUd",
    "merchant_order_reference": "f4548bbf-a029-43d3-9209-e3385c80b1e9",
    "type": "CHARGE",
    "status": "PROCESSED",
    "merchant_id": "123456",
    "order_amount": {
      "value": 1100,
      "currency": "INR"
    },
    "pre_auth": true,
    "purchase_details": {
      "customer": {
        "email_id": "[email protected]",
        "first_name": "Kevin",
        "last_name": "Bob",
        "customer_id": "232323",
        "mobile_number": "9876543210",
        "billing_address": {
          "address1": "H.No 15, Sector 17",
          "address2": "",
          "address3": "",
          "pincode": "61232112",
          "city": "CHANDIGARH",
          "state": "PUNJAB",
          "country": "INDIA"
        },
        "shipping_address": {
          "address1": "H.No 15, Sector 17",
          "address2": "string",
          "address3": "string",
          "pincode": "144001123",
          "city": "CHANDIGARH",
          "state": "PUNJAB",
          "country": "INDIA"
        }
      },
      "merchant_metadata": {
        "key1": "DD",
        "key2": "XOF"
      }
    },
    "payments": [
      {
        "id": "v1-1111071924-aa-zzSkOA-cc-G",
        "status": "PROCESSED",
        "payment_amount": {
          "value": 1100,
          "currency": "INR"
        },
        "payment_method": "CARD",
        "payment_option": {
          "card_data": {
            "card_type": "CREDIT",
            "network_name": "VISA",
            "issuer_name": "NONE",
            "card_category": "CONSUMER",
            "country_code": "IND",
            "token_txn_type": "ALT_TOKEN"
          }
        },
        "acquirer_data": {
          "approval_code": "000000",
          "acquirer_reference": "202456643801053",
          "rrn": "420145000226"
        },
        "capture_data": [
          {
            "merchant_capture_reference": "f31d8c60-0dc8-4788-a577-5ced930cc175",
            "capture_amount": {
              "value": 1100,
              "currency": "INR"
            },
            "created_at": "2024-07-19T11:13:21.523516426Z"
          }
        ],
        "created_at": "2024-07-19T11:11:48.944147Z",
        "updated_at": "2024-07-19T11:13:23.962461Z"
      }
    ],
    "created_at": "2024-07-19T11:11:48.944147Z",
    "updated_at": "2024-07-19T11:13:23.962461Z"
  }
}

Refer to our Capture Order API documentation to learn more.

5. Cancel Order

Use this API to cancel the payment against an order.

Use the below endpoint to cancel the payment against the order.

PuT: https://pluraluat.v2.pinepg.in/api/pay/v1/orders/{order_id}/cancel
PUT: https://api.pluralpay.in/api/pay/v1/orders/{order_id}/cancel

Shown below is a sample request and sample response for a Cancel Order API.

{
  "data": {
    "order_id": "v1-5757575757-aa-hU1rUd",
    "merchant_order_reference": "2177120b-3be1-4330-a15f-53ce14d19841",
    "type": "CHARGE",
    "status": "CANCELLED",
    "merchant_id": "123456",
    "order_amount": {
      "value": 50000,
      "currency": "INR"
    },
    "pre_auth": true,
    "purchase_details": {
      "customer": {
        "email_id": "[email protected]",
        "first_name": "Kevin",
        "last_name": "Bob",
        "customer_id": "232323",
        "mobile_number": "9876543210",
        "billing_address": {
          "address1": "H.No 15, Sector 17",
          "address2": "",
          "address3": "",
          "pincode": "61232112",
          "city": "CHANDIGARH",
          "state": "PUNJAB",
          "country": "INDIA"
        },
        "shipping_address": {
          "address1": "H.No 15, Sector 17",
          "address2": "",
          "address3": "",
          "pincode": "144001123",
          "city": "CHANDIGARH",
          "state": "PUNJAB",
          "country": "INDIA"
        }
      },
      "merchant_metadata": {
        "key1": "DD",
        "key2": "XOF"
      }
    },
    "payments": [
      {
        "id": "v1-2711071924-aa-VxIzq1-cc-Z",
        "status": "CANCELLED",
        "payment_amount": {
          "value": 1100,
          "currency": "INR"
        },
        "payment_method": "CARD",
        "payment_option": {
          "card_data": {
            "card_type": "CREDIT",
            "network_name": "VISA",
            "issuer_name": "NONE",
            "card_category": "CONSUMER",
            "country_code": "IND",
            "token_txn_type": "ALT_TOKEN"
          }
        },
        "acquirer_data": {
          "approval_code": "000000",
          "acquirer_reference": "202456644249243",
          "rrn": "420123000239"
        },
        "created_at": "2024-07-19T11:27:55.664651Z",
        "updated_at": "2024-07-19T11:28:52.487287Z"
      }
    ],
    "created_at": "2024-07-19T11:27:55.664651Z",
    "updated_at": "2024-07-19T11:28:52.487287Z"
  }
}

Refer to our Cancel Order API documentation to learn more.

To Know Your Payment Status

To check your payment status, you can either rely on Webhook events or use our Get Orders APIs for real-time updates.

  1. Webhook Notification: We send Webhook notifications on the successful payment or any changes to the payments object. Refer to our Webhooks documentation to learn more.
  2. Get Orders API: Use our Get Orders API to know the real time status of the payment. Refer to our Manage Orders documentation to learn more.

Refunds

Plural processes refund directly to the customer's original payment method to prevent chargebacks.

Refer to our Refunds documentation to learn more.