Payin P2P Non-Seamless Integration

Request Payment from Web/Android/iOS App Follow these steps to integrate the payment request from your app.

Note: The IP must be whitelisted by us to accept the request. This process involves back-end to back-end communication

Api Key

Your provided API key must be passed in X-Api-Key header for all requests.

Security

All requests are secured with signature verification and IP whitelisting.

AUTHENTICATION :

Required Authentications

All requests must include the following authentication:

  • API Key: Your provided API key must be passed in X-Api-Key header

  • Signature: SHA256 signature for request validation

  • IP Whitelisting: Your server IP must be pre-registered in our system.

All V2 API requests must be authenticated by including a signature parameter in the JSON body.

The logic for creating this signature is identical for all V2 endpoints. Please follow the detailed instructions on our central guide:

➡️ V2 API Signature Generation

PAYMENT REQUEST :

Procedure Steps:

  1. Send the following details to the given API

POST {baseurl}/pay/v2/request.php

Headers

Name
Value

Content-Type

application/json

X-Api-Key

your-provided-api-key

Request Body

Name
Type
Required
Description

pid

string

Required

Your unique Partner ID provided during registration

amount

integer

Required

Your order amount

order_id

string

Required

Your unique order identifier

signature

string

Required

SHA256 signature for request validation (Refer this for signature generation logic Signature Generation)

ip

string

Required

Customer's IP address

name

string

Required

customer's name

email

string

Required

customer's email address

phone

string

Required

customer's phone number

latitude

string

Required

customer's location latitude

longitude

string

Required

customer's location longitude

customer_id

string

Required

customer's gameID

redirect_url

string

Required*

URL to redirect user the payment completion. *Required if not configured during registration

upi_id

string

Required*

Customer's UPI ID. *Required for intent flow

X-Api-Key: your-provided-api-key
Content-Type: application/json

Sample Response Body

{
    "hash_value":"1304d033331712f0de5d44665d10a2285241fe7d6a78753d779941cb7cd7f9c3",
    "status":"ok",
    "redirect_url":"your_redirect_url.com"
}
  1. Append hash_value to connect.php for transferring customers to the payment completion page.

redirect https://<domain>/pay/connect.php?code=1304d033331712f0de5d44665d10a2285241fe7d6a78753d779941cb7cd7f9c3
  1. Launch this URL from your app using the Launch Mode.external application.

Here are examples in Kotlin, Java, and Flutter for launching a URL with Launch Mode.external:

Val webIntent: Intent=
Uri.parse('{baseUrl}/pay/connect.php?code=b3JkZXJfaWQ9
eW91cl9vcmRIcl9pZCZwaWQ9Z2l2ZW5fbWVyY2hhbnR
faWQmcHVycG9zZT1hbnlfcHVycG9zZSZhbXQ9eW91cl9
hbW91bnQmZW1haWw9eW91cmVtYWlsQGV4YW1wbG
UuY29t').let{webpage>Intent(Intent.ACTION_VIEW,web
page)

Error Responses

Note

This endpoint always returns an HTTP 200 status code, even in case of errors. To determine whether the request was successful or not, check the value of the status field in the JSON response — it will be "ok" for successful requests and "error" for failed ones.

Error Message
Cause
Solution

Invalid Request data

Malformed JSON in request body

Check JSON syntax and structure

pid is required field

Missing partner ID

Include valid pid parameter

amount is required field

Missing amount parameter

Include valid amount parameter

order_id is required field

Missing order ID

Include valid order_id parameter

signature is required field

Missing signature for signature verification

Generate and include signature parameter

Invalid signature

Signature verification failed

Check signature generation logic

Unauthorized access

Missing API key in header

Include valid X-Api-key header

Invalid API key

API key doesn't match account

Use correct API key for your account

Invalid pid

Partner ID not found

Use correct partner ID

Please contact admin to Active Account...!

Account is inactive

Contact support for account activation

amount should be greater than: X

Amount below minimum limit

Use amount ≥ minimum limit

amount should be less than: X

Amount above maximum limit

use amount <= maximum limit

Duplicate order_id found

Order ID already exists

Use unique order_id for each request

Please contact admin to request whitelist your IP

IP not whitelisted

Contact support to whitelist your IP

Rate Limiting

Rate Limits: API request are subject to rate limiting based on your account configuration. Exceeding the rate limit will result in temporary blocking of requests.

Best Practices

  • Unique Order IDs: Always use unique order_id for each transaction

  • Amount validation: Validate amount limits before making requests

  • Error handling: Implement proper error handling for all possible responses

  • Secure storage: Keep your secret key and API key secure

  • HTTPS Only: Always use Https for Api requests

  • API key Security: Use your provided API key in X-Api-Key header for all requests

CALLBACK

We invoke your callback URL with callback data whenever there is a status change against the transaction.

Valid Transaction status are:

  1. Pending

  2. Approved

  3. Late Approved

  4. Amount Mismatch

  5. User Timed out

  6. Declined

  7. Cancelled

  8. Failed

The most famous transaction changes are (but not limited):

  1. Pending=>Approved

  2. Pending=>Amount Mismatch

  3. Pending=>Declined

  4. Pending=>User Timed Out

  5. User Timed Out=>Late Approved

The callback landing page must be set up on your server at a secret path, but it should be publicly accessible from our whitelisted IP. (Ensure that it is only accessible from our server IP.)

In the POST body, the following properties will be provided in JSON format:

Name
Type
Description

order_id

string

Your order id shared

requested_amount

string

requested amount

received_amount

string

received amount

bank_ref

string

transaction reference/bank reference/UTR if available

ref_code

string

unique code for the transaction

status

string

status of payment at this time

post_hash

string

signature post hash for security verification

Note:

please consider received_amount for final transaction processing

Follow the steps to verify the integrity of received data:

  1. Capture and Decode the Payload

Capture the raw JSON data from the POST body and decode it.

// Capture and decode the raw POST body
$data = file_get_contents("php://input");
$array = json_decode($data, true);
  1. Extract and Decode the post_hash

The post_hash field in the JSON payload is a Base64-encoded string. You must Base64-decode it to get the raw binary data needed for decryption.

// Get the Base64 string from the array
$post_hash_base64 = $array['post_hash'];
 
// Decode it to get the raw binary ciphertext
$ivHashCiphertext = base64_decode($post_hash_base64);
  1. Decrypt the Binary Data to get the Remote Hash

Pass the raw binary data (not the Base64 string) to the decrypt function along with your secret key.

//$secret_key is your provided SECRET KEY
$remote_hash = decrypt($ivHashCiphertext, $secret_key);

The decrypt function for your language is provided in the reference section below.

function decrypt($ivHashCiphertext, $password) 
{    
    $method = "AES-256-CBC";    
    $iv = substr($ivHashCiphertext, 0, 16);    
    $hash = substr($ivHashCiphertext, 16, 32);    
    $ciphertext = substr($ivHashCiphertext, 48);    
    $key = hash('sha256', $password, true);    
    if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true),$hash)) 
    return null;    
    return openssl_decrypt($ciphertext, $method, $key,    		    
    OPENSSL_RAW_DATA, $iv);                               
}

  1. Compute the Local Hash

Compute the local hash using the MD5 128-bit hashing algorithm. Use the order_id, received_amount, and status received in the callback array for computing the local hash.

Note: The received_amount in the callback payload is always sent as an integer string (e.g., "100", "0").

// Get the values from the same callback $array
$order_id = $array['order_id'];
$received_amount = $array['received_amount'];
$status = $array['status'];
 
$local_hash = md5($order_id . $received_amount . $status . $secret_key);
  1. Verify Hash

Compare the decrypted $remote_hash from the request and the computed $local_hash.

if ($remote_hash !== null && hash_equals($local_hash, $remote_hash)) {  
    // Mark the transaction as success & process the order  
    $hash_status = "Hash Matched";    
} else {  
    // Verification failed       
    $hash_status = "Hash Mismatch";  
}
  1. Acknowledge the Payment Gateway

To confirm you have received the callback and to prevent our gateway from sending retries, you must do two things:

  • Respond with an HTTP 200 OK status code.

  • Respond with a JSON body containing the key "acknowledge" set to the string "yes".

Our system will check for both the 200 status and the {"acknowledge": "yes"} in the response body. If either is missing, we will assume the callback failed and will attempt to send it again.

// --- This is the required acknowledgment ---

// 1. Set the HTTP 200 OK status code
http_response_code(200);

// 2. Prepare the required JSON response body
$response_data = [
    'acknowledge' => 'yes',
    'hash_status' => $hash_status // You can include this for your own logs
];

// 3. Send the response
header('Content-Type: application/json; charset=utf-8');
echo json_encode($response_data);
exit;

STATUS POLLING :

The payment Status Polling API allows you to retrieve real-time status information for payment transactions. This endpoint provides comprehensive transaction details including payment status, amounts etc.

Note : All requests must include proper authentication headers and IP whitelisting may be required for production environments.

POST baseurl/api/v2/status_polling.php

Authentication

This API required the following authentication mechanism:

Required Headers

Header
Type
Required
Description

Content-Type

string

Yes

Must be application/json

X-Api-Key

string

Yes

Your provided API key for authentication

IP Whitelisting

Your server IP address must be whitelisted in production environments. Contact your administration to ensure your IP is properly configured.

Request Parameters

Parameter
Type
Required
Description

pid

string

Yes

Merchant ID/PID

ref_code

string

Yes

Unique ref_code which is generated in payment request

post_hash

string

Yes

The Base64-encoded encrypted hash. (See steps below).

Steps to generate post_hash :

  1. Generate the Request post_hash

1.1 Create Plaintext Hash: Concatenate the ref_code, pid, and your secret_key, then create an MD5 hash.

$ref_code = "YOUR_REF_CODE";
$pid = "YOUR_PID";
$secret_key = "YOUR_SECRET_KEY";

$local_hash = md5($ref_code . $pid . $secret_key);

1.2 Encrypt the Hash: Encrypt the $local_hash using the encrypt function shown below.

$encrypted_hash = encrypt($local_hash, $secret_key);
function encrypt($plaintext, $password) 
{    
    $method = "AES-256-CBC";    
    $key = hash('sha256', $password, true);    
    $iv = openssl_random_pseudo_bytes(16);    
    $ciphertext = openssl_encrypt($plaintext, $method, $key,       
        OPENSSL_RAW_DATA, $iv);    
    $hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);    
    return $iv . $hash . $ciphertext;
}

1.3 Base64 Encode: Base64-encode the raw binary output from the encrypt function. This final string is your post_hash.

$post_hash = base64_encode($encrypted_hash);
  1. Send the POST Request

Send a POST request containing pid, ref_code, and post_hash as a JSON body , and you will receive a response after validating the data.

PHP (cURL) Example:
<?php
// Your transaction data
$pid = "YOUR_PID";
$ref_code = "YOUR_REF_CODE";
$secret_key = "YOUR_SECRET_KEY";

// --- Step 1: Generate Hash ---
$local_hash = md5($ref_code . $pid . $secret_key);
$encrypted_hash = encrypt($local_hash, $secret_key);
$post_hash = base64_encode($encrypted_hash);

// --- Step 2: Send Request ---
$api_url = "https://<domain>/api/v2/status_polling.php";

$data = [
    'pid' => $pid,
    'ref_code' => $ref_code,
    'post_hash' => $post_hash
];

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'X-Api-Key: YOUR_API_KEY_HERE'
]);

$server_output = curl_exec($ch);
curl_close($ch);

?>
  1. Processing the API Response

The API will respond with a JSON object. If the request is successful and the ref_code is found, it will return the transaction details. If it fails (e.g., bad hash, ref_code not found), it will return an error message.

Success Response Parameters

A successful response will contain the following parameters as JSON body:

order_id

String

Your order ID.

ref_code

String

The unique ref_code for this transaction.

upi_id

String

The UPI ID the payment was made to.

requested_amount

Number

The amount originally requested for the transaction.

received_amount

Number

The final amount confirmed as received.

bank_ref

String

The bank's UTR / reference number, if available.

sender_upi

String

The customer's UPI ID from which the payment was received.

webhook_acknowledged

String

"1" if our server has sent the callback, "0" otherwise.

status

String

The current status of the transaction (e.g., Approved, Pending, Declined, etc).

post_hash

String

A Base64-encoded encrypted hash to verify the integrity of this response.

Error Response

If your request fails, the server will respond with an appropriate HTTP status code and a JSON body like the following.

{
    "status": "error",
    "message": "error message"
}

Common Error Responses

400

No input data received

The raw POST body was empty.

400

Invalid JSON format in request body

The data sent was not valid JSON.

400

Missing required parameters (...)

Your JSON body is missing pid, ref_code, or post_hash.

400

Invalid PID

The pid sent does not exist in our system.

400

Reference code not found.

The ref_code sent does not exist in our system.

400

Invalid hash

The signature verification failed. The hashes do not match.

400

Invalid base64 encoding in post_hash

The post_hash string was not valid Base64.

401

X-Api-Key header is required

The X-Api-Key was not found in the request headers.

401

Invalid API key

The provided X-Api-Key is incorrect.

403

Please contact admin to whitelist your IP: ...

Your server's IP is not in the whitelist for this account.

429

[Dynamic rate limit message]

You have exceeded the allowed request rate.

500

Internal Server Error

A server-side error occurred. Please contact support.

  1. Verify the Response post_hash

Before trusting any data from the response, you must verify its post_hash to ensure the data is from us and has not been tampered with. This verification logic is identical to the logic used for verifying a callback.

You do not need to send an "Acknowledge" response for a status poll.

4.1 Compute the Local Hash

From the JSON response, get the order_id, received_amount, and status. Concatenate them with your secret_key and create an MD5 hash.

// $response_data is the decoded JSON response from /api/status_polling.php
$order_id = $response_data['order_id'];
$received_amount = $response_data['received_amount'];
$status = $response_data['status'];
 
$local_hash = md5($order_id . $received_amount . $status . $secret_key);

4.2 Decrypt the Remote Hash

Get the post_hash string from the JSON response. Base64-decode it, then pass the raw binary data to the decrypt function.

// Get the Base64 string from the response
$post_hash_base64 = $response_data['post_hash'];
 
// Decode it to get the raw binary ciphertext
$ivHashCiphertext = base64_decode($post_hash_base64);
 
// Decrypt using the function from the reference section below
$remote_hash = decrypt($ivHashCiphertext, $secret_key);

The decrypt function for your language is provided in the reference section below.

function decrypt($ivHashCiphertext, $password) 
{    
    $method = "AES-256-CBC";    
    $iv = substr($ivHashCiphertext, 0, 16);    
    $hash = substr($ivHashCiphertext, 16, 32);    
    $ciphertext = substr($ivHashCiphertext, 48);    
    $key = hash('sha256', $password, true);    
    if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true),$hash)) 
    return null;    
    return openssl_decrypt($ciphertext, $method, $key,    		    
    OPENSSL_RAW_DATA, $iv);                               
}

4.3 Compare the Hashes

Securely compare the local_hash you just computed with the remote_hash you decrypted. If they match, you can trust the data.

if ($remote_hash !== null && hash_equals($local_hash, $remote_hash)) {
    // --- SUCCESS: Data is verified ---
    // You can now trust the data and update your database.
    // echo "Status: " . $response_data['status'];
} else {
    // --- FAILURE: Hash mismatch! ---
    // Do NOT trust this data.
}

TRANSACTION STATUS :

  1. Amount Mismatch : We received money but customer paid different money than the requested money

  2. Approved : We received money same value as requested

  3. Late Approved : We recieved money but it happened late while doing reconcilation from bank side

  4. Declined : The transaction declined due to security reasons

  5. Failed : The payment failed from bank side

  6. Cancelled : This status for NonSeamess when customer cancel the payment from the screen

  7. User Timed Out: The user did not complete the payment within the session period.

P2P Accounts Wallet Balance API Overview

This API provides detailed information about an operator's payment gateway (PG) accounts, including balance details and account details. It allows you to query and retrieve information related to UPI, IMPS, IMPS with UPI, wallet and payout accounts linked to the operator. For more details on how to use this API, refer to the link below.

COMPLAINT

We have a dedicated Complaint Section where merchants can manage transaction-related complaints. Through this section, merchants can submit complaints with all necessary details and optional evidence. Upon submission, a unique complaint reference ID is generated, allowing merchants to track the complaint’s status and receive real-time updates via the status-check API. This ensures a smooth, secure, and efficient process for resolving any transaction issues.

Complaint

RECONCILIATION

This API endpoint allows authorized users to retrieve payment transactions based on a specific pid (Partner ID) and date. The API performs authentication using a token and signature verification to ensure secure communication.

Reconciliation

WALLET TRANSACTION SUMMARY

This API endpoint retrieves a summary of transactions for wallets associated with an operator, filtered by account number, date type, and date. It requires authentication via an API key and returns transaction counts and amounts grouped by status.

Wallet Transaction Summary

WALLET DATA ENDPOINT

This API endpoint retrieves cumulative wallet data for an operator, including both active and inactive wallet accounts across multiple wallet types. The endpoint requires authentication via an API key passed in the request headers.

Wallet Data Endpoint

Last updated