# Callback Transaction Result
# Callback Interface Signature Verification
Purpose of Signature Verification
There is a risk of tampering with API requests during transmission over the public internet. To ensure the integrity and authenticity of the callback data, the platform supports and strongly recommends that merchants perform signature verification when receiving callbacks.
Setup Method
Login to [Cashier Backend] → [Developer Center] → [Callback URL] → Add/Edit.
Signature Verification Steps
The signature verification logic is similar to the interface request signature, with the main difference being that the data source is the received callback content.
1.Obtain the Signature
Retrieve the signature field from the HTTP request Header:
sign: {Platform-generated signature string}
2.Obtain the Callback Parameters
Store the JSON parameters from the callback Body in a Map (dictionary) structure in key-value form.
3.Add Public Parameters
Also retrieve the following fields from the Header and include them in the Map for signature verification:
access_key
timestamp
nonce
4.Construct the String to Be Signed
Sort all the keys in the Map in ASCII order from smallest to largest, and concatenate them into the following format:
key1=value1&key2=value2&...&keyN=valueN
5.Perform Signature Calculation
- Use the
secret_key
bound to the merchant's backend to process the above string as follows:- Encrypt using the
HMAC_SHA1
algorithm - Base64 encode the result to obtain the local
sign
value
- Encrypt using the
6.Compare Signatures
Compare the locally generated
sign
with thesign
provided in the Header by the platform:- ✅ If they match → Signature verification passes, and business logic can be processed
- ❌ If they don't match → Reject processing and consider logging the event for troubleshooting
# Payment Callback
When a payment order enters its final state (e.g., success, failure), the platform will send the following callback data to the merchant's preset notifyUrl
.
Callback Data
{
"currencyType": "INR",
"orderAmount": "40.2",
"orderActualAmount":"40.2",
"orderFee":"10",
"orderTime": 1692687588000,
"payType": 102,
"orderId": "OCURRPAID202308220659471692687587691DOCK02OO0000000400003652",
"orderStatusCode": 1,
"orderStatus": "Wait pay",
"markStatus": 0,
"payParam": "https://rarpay.test.rarpay.com/index/pay/mchtestpage/tp/dd/ordernum/230822170261LXvDYM",
"externalOrderId": "716134866255702461",
"tradeNote": "123",
"payTypeName": "BANK"
}
Callback Parameter Descriptions
Param | Type | Description |
---|---|---|
currencyType | String | Legal currency type, such as INR |
externalOrderId | String | Merchant’s order ID |
markStatus | int64 | Mark status |
orderAmount | float64 | Order creation amount |
orderActualAmount | float64 | Actual paid amount |
orderFee | float64 | Transaction fee |
orderId | String | System order ID |
orderPayTime | int64 | Payment time (timestamp in milliseconds) |
orderTime | int64 | Order creation time (timestamp in milliseconds) |
orderStatusCode | int64 | Order status code: 1 - Pending payment, 2 - Payment successful |
orderStatus | String | Order status description, e.g., "Wait pay" |
payType | int64 | Payment type code, such as 102 - BANK |
payTypeName | String | Payment type name, such as BANK |
payParam | String | Payment parameter (e.g., redirect link/payment QR code) |
tradeNote | String | Notes information |
errorMsg | String | Error message (optional) |
errorMsgEn | String | Error message in English (optional) |
Tips: Manual Callback Mechanism
Merchants can trigger the order callback manually at any time by logging into the merchant backend.
Important Notes:
- Do not manually trigger callbacks when the order is not in a final state (e.g., pending payment, processing), as it may cause business logic issues.
- In manual callback responses, the order status information reflects the actual current status. Merchants should handle it based on the status.
- If the order is not in a final state (e.g., processing), the platform will still trigger a callback when the order status changes to a final state. Merchants should handle business redundancy to ensure idempotency and avoid duplicate entries or notification conflicts.
- If the order is already in a final state, even if the manual callback is triggered in the merchant backend (not recommended), the platform will still send another notification. Merchants should handle business redundancy to ensure idempotency and avoid duplicate entries or notification conflicts.
# Transfer Callback
When a payment order enters its final state (such as success or failure), the platform will send a callback to the merchant's pre-set notifyUrl
with the following data.
Callback Data
{
"currencyType": "INR",
"userInfoNo": "SBIN0002604",
"accountCode": "ANDB",
"accountName": "AndhraBank",
"orderId": "OCURRDRAW202410231700001729702800073EDEG2OOO0000000225020722",
"orderFee": "12",
"orderStatus": "Completed",
"errorMsgEn": "query success",
"externalOrderId": "601TX2410238055601",
"errorMsg": "query success",
"payTypeName": "BANK",
"orderAmount": "200",
"orderTime": 1729702800000,
"payType": 202,
"userInfoName": "imran Ali",
"accountNo": "30754929349",
"orderStatusCode": 8,
"markStatus": 0,
"orderPayTime": 1729710552000
}
Callback Parameter Description
Param | Type | Description |
---|---|---|
currencyType | String | Currency type (e.g., INR) |
externalOrderId | String | Merchant order ID |
orderId | String | System order ID |
orderAmount | String | Order amount |
orderFee | String | Order fee |
orderStatus | String | Order status description (e.g., Completed) |
orderStatusCode | int64 | Order status code: 1-Accepted 2-Banking 4-Failed (Bank not accepted) 8-Success 16-Failed |
orderTime | int64 | Order creation time (in milliseconds timestamp) |
orderPayTime | int64 | Order completion time (in milliseconds timestamp) |
markStatus | int64 | Mark status (0/1) |
payType | int64 | Payment type code, e.g., 202-BANK |
payTypeName | String | Payment type name, e.g., BANK |
userInfoName | String | User information name |
userInfoNo | String | User identification number |
accountNo | String | Payee account number |
accountCode | String | Bank code (e.g., ANDB) |
accountName | String | Bank name (e.g., AndhraBank) |
errorMsg | String | Error message |
errorMsgEn | String | Error message (in English) |
tradeNote | String | Transaction note (may be empty) |
Tips: Manual Callback Mechanism Explanation
Merchants can trigger a manual order callback at any time by logging into the merchant backend.
Important Notes:
- Do not trigger the callback manually unless the order is in its final state (e.g., not paid or processing), as this may cause business logic errors.
- In the manual callback response, the order status information reflects the current actual state. The business side should determine whether to proceed based on the status.
- If the order is not yet in its final state (e.g., in processing status), the platform will still send another notification when the order state changes to the final state. The merchant should implement redundancy handling to ensure idempotency and avoid duplicate charges or notification conflicts.
# Callback Response
Explanation
- All callbacks include a signature field, and merchants are advised to verify the signature to ensure the callback content has not been tampered with.
- Once the merchant receives the callback data and completes processing, they should respond to the gateway with the following JSON format:
Example Response (Success)
{
"code": 200,
"success": true
}
Callback Retry Mechanism Explanation (Important)🔥
To ensure stable delivery of callback notifications and business consistency, the platform has designed a retry strategy. When the merchant system fails to respond successfully to the callback (e.g., network timeout, non-200 status code), the system will retry according to the following rules:
Callback Retry Rhythm (4 attempts in total):
Attempt Number | Retry Interval (Approx.) | Description |
---|---|---|
1st attempt | About 2 minutes later | First retry after failure |
2nd attempt | About 2 minutes later | Second retry after the first failure |
3rd attempt | About 11 minutes later | Third retry after the second failure |
4th attempt | About 2 minutes later | Fourth retry after the third failure |
Note: The above intervals are system internal scheduling intervals, so the "callback time" recorded in the merchant's backend includes merchant processing/response time, so there might be a 1-minute discrepancy compared to the actual push time.
Actual Situation Reminder
- When there is a high order volume online, callbacks may experience queue delays, so please ensure the server can handle high concurrency.
- Each callback is an idempotent operation, and the merchant side should ensure idempotency checks are implemented.
- If after 4 retry attempts the callback still fails, no further retries will be performed. The merchant is advised to manually trigger the callback via the backend.
Callback Response Parameters
Param | Type | Required | Description |
---|---|---|---|
code | int | ✅ | Status code, 200 for success |
success | boolean | ✅ | Whether the response is successful |
# Callback URL Configuration
Two callback URL configuration methods are supported:
- Merchant Backend: Configure the unified callback URL
- This can be configured in the "Merchant Backend" → "Developer Center."
- Suitable for most orders with shared callback processing logic.
2.Manually Specify Callback URL at the Order Level (notifyUrl)
- The
notifyUrl
field can be passed when creating an order. - If a
notifyUrl
parameter is specified in the order, the system will use only this address as the callback notification target.
Priority of Address Explanation
The notifyUrl
in the order takes precedence over the callback URL configured at the platform level.
Priority of Response Status Codes Explanation
The platform uses the HTTP response status code (status_code
) as the sole criterion for determining whether the notification was successful.
Specific rules are as follows:
- ✅ As long as the merchant system returns
HTTP 200
, the platform considers the callback to be successful.- In this case, even if the returned content is not
{ "code": 200, "success": true }
, it will be ignored.
- In this case, even if the returned content is not
- ❌If the response is
status_code ≠ 200
(such as 400/500) or no response is received, it will be considered a failure, and the platform will automatically retry the push.