Integration Steps

Learn how to integrate the Plural payment gateway on your website with an embedded iFrame setup.

Follow the below steps to integrate with Plural payment gateway using iFrame setup.

  1. [Prerequisite] Generate Token
  2. Create Checkout
  3. Integrate with Checkout on Client Side
  4. Handle Transaction Response
    1. Handle Payment Success and Failure
    2. Verify Payment Signature

📘

Note

  • Ensure you store your Client ID and Secret in your Backend securely.
  • Integrate our APIs on your backend system.
  • We strictly recommend not to call our APIs from the frontend.

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.

{
  "client_id": "1234567890",
  "client_secret": "asdfgwei7egyhuggwp39w8rh",
  "grant_type": "client_credentials"
}
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
  "expires_in": 3600
}

Refer to our Generate Token API documentation to learn more.

2. Create Checkout Link

Use this API to generate a checkout Link. 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, sample request and response for a Create Checkout 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"
  },
  "integration_mode":"IFRAME",
  "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"
    }
  }
}'
{
  "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."
}

❗️

Watch OUT

The parameter "integration_mode": "IFRAME" is mandatory to render the iframe checkout.

Refer to our Test Card Details documentation to learn more.

3. Integrate with Checkout on Client Side

To integrate with iFrame checkout on Client Side use the below code.

<html>
<button id="pay_button">Pay</button>
<script src="https://checkout-staging.pluralonline.com/v3/web-sdk-checkout.js"></script>
<script>
function handleCheckout(redirectUrl) {
  const options = {
    redirectUrl,
    successHandler: async function (response) {
      console.log(response);
    },
    failedHandler: async function (response) {
        console.log(response);
    },
  };

  const plural = new Plural(options);
  plural.open(options);
}

document.getElementById("pay_button").onclick = function(e){
    handleCheckout("https://api-staging.pluralonline.com/api/v3/checkout-bff/redirect/checkout?token=V3_N7fMbGAfE8xDtTMLptiWhWL%2Fgz7bv0aBUuFRH5NlzAPYpii%2BcRyvm1xllb8TP5JG"); // Pass `redirect_url` returned in our Create Checkout API response.
}
</script>
</html>

Configuration Object:

To View Click Here

Defines a configuration object labeled as options that contains key settings listed below:

  • redirectUrl: Use this key to pass the redirect_url returned in our Create Checkout API response.
  • successHandler: Handler functions are asynchronous, where you can customize handlers according to your specific needs.
  • failureHandler: Handler functions are asynchronous, allowing you to add handlers to notify users as required based on specific requirements.

4. Handle Transaction Response

You can add custom handler logic to manage specific actions or events within the successHandlerand failureHandler function to enhance responsiveness. It is essential to handle both successHandler and failureHandler functions and signature verification.

4.1 Handle Payment Success and Failure

On a successful and failed payment we return the following parameters listed below.

{
  "order_id": "v1-4405071524-aa-qlAtAf",
  "status": "AUTHORIZED",
  "signature": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
}
{
  "order_id": "v1-4405071524-aa-qlAtAf",
  "status": "FAILED",
  "signature": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
}
  • We recommend you to collect the payment details and send them to your server.
  • You must validate the authenticity of the payment details returned. You can authenticate by verifying the signature.

4.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. status: Payment status.
    3. 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, it confirms that the payment details are from Plural.

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.