# Callback Transaction Result

# Callback Interface Signature Verification

Purpose of Signature Verification

During API requests, there is a risk of data being tampered with by a middleman while being transmitted over the public network. To ensure the integrity and trustworthiness of the callback data, the platform supports and strongly recommends that merchants perform signature verification when receiving the callback.

Setup Method

Log in to the [Cashier Backend] → [Developer Center] → [Callback Address] → Add/Edit.

Signature Verification Steps

The signature verification logic is generally the same as the API request signature, with the key 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:

  1. 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

  1. 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

6.Compare Signatures

Compare the locally generated sign with the sign 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

Callback Data Example

{
  "currencyType": "USD",
  "orderActualAmount": "1",
  "orderId": "OCRYPPAID202307310902391690794159441DOCKER020000000400001108",
  "tradeHash": "0x806d5b3da29c8426a644e2ded85b865b37504dcdec4cfb9db13af5e962815528",
  "orderFee": "1",
  "orderStatus": "Completed",
  "chainType": "ETH",
  "externalOrderId": "402297358314559082",
  "addressTo": "0xe072c63c1e04f8c6f36133f6629f66778147d5d8",
  "orderAmount": "1",
  "orderTime": 1690794159000,
  "exchangeRate": "0.983",
  "orderStatusCode": 4,
  "orderPayTime": 1690794247000,
  "addressFrom": "0x0cbfd17ae9e1d6d881b2cade71277f48abf64d24",
  "tokenType": "USDT"
}

Callback Field Description

Parameter Name Type Description
currencyType String Fiat currency type (e.g., USD)
orderActualAmount String Actual payment amount
orderId String Platform order ID
tradeHash String Blockchain transaction hash
orderFee String Transaction fee amount
orderStatus String Order status text (e.g., Completed)
orderStatusCode int64 Order status code (see explanation below)
chainType String Blockchain main chain type (e.g., ETH)
externalOrderId String Merchant order ID
addressTo String Receiving address
addressFrom String Sending address
orderAmount String Original order amount
orderTime int64 Order creation time (Unix timestamp in ms)
orderPayTime int64 Actual payment time (Unix timestamp in ms)
exchangeRate String Exchange rate
tokenType String Cryptocurrency type (e.g., USDT)
markStatus String Mark status (if applicable)
errorMsg String Error message (in Chinese)
errorMsgEn String Error message (in English)

Order Status Code Description (orderStatusCode)

Status Code Description
1 Pending Payment: Order created successfully, awaiting user payment
2 On-chain Confirmation: User clicked "I have paid," awaiting blockchain confirmation
4 Completed: Payment successful, the platform will automatically send the callback notification
8 Payment Amount Mismatch: Callback notification sent again, please credit based on actual amount
16 Timeout: User did not pay on time, no further callbacks
32 Unpaid: Address expired and will not be processed

⚠️ Callback Handling Recommendations

  • Once the callback is successfully verified and orderStatusCode == 4, the payment is considered successful. The business process (e.g., crediting account) should be performed immediately.
  • The platform may resend callbacks due to network issues. Please ensure idempotent processing to avoid duplicate crediting.
  • If verification fails or data is abnormal, please log the issue and return an error response. The platform will automatically retry up to 2 times within 30 minutes.

Manual Callback Explanation

Merchants can manually trigger a callback in the backend order management system to fix missed callbacks. However, please note the following:

  • If the order status is not in a final state (e.g., Pending Payment, Confirming), manual callbacks are not recommended.
  • If a manual callback is triggered but the order is not yet completed, the platform will still send the callback again when the status changes to a final state. Merchants should ensure deduplication at the business layer.

# Transfer Callback

Callback Data Example

{
  "orderAmount": "1",
  "orderTime": 1690794160000,
  "orderId": "OCRYPDRAW202307310902401690794160841DOCKER020000000200001109",
  "orderStatusCode": 2,
  "tradeHash": "0xe9d043c9cbdb96ed7a71c5a0923baabe9e23316b3f1b0a01975bcd6d69b41fa3",
  "orderFee": "0.01",
  "orderStatus": "Completed",
  "orderPayTime": 1690794182000,
  "chainType": "ETH",
  "externalOrderId": "622257420681202921",
  "tokenType": "USDT",
  "addressTo": "0xa8666442fA7583F783a169CC9F5449ec660295E8"
}

Callback Field Description

Parameter Name Type Description
orderAmount String Order amount
orderTime int64 Order creation time (Unix timestamp in ms)
orderId String Platform order ID
orderStatusCode int64 Order status code (see explanation below)
tradeHash String Blockchain transaction hash
orderFee String Transaction fee amount
orderStatus String Order status description (e.g., Completed)
orderPayTime int64 Payment completion time (Unix timestamp in ms)
chainType String Blockchain main chain type (e.g., ETH)
externalOrderId String Merchant order ID
tokenType String Cryptocurrency type (e.g., USDT)
addressTo String Receiving address

Order Status Code Description (orderStatusCode)

Status Code Description
1 Accepted: Order has been accepted, awaiting processing
2 Completed: Payment successful, the platform will automatically send the callback notification
4 Payment Failed: Payment could not be completed
8 Pending Approval: Payment is awaiting approval
16 Payment Rejected: The payment has been rejected

⚠️ Callback Handling Recommendations

  • Once orderStatusCode == 2 and the signature verification is successful, the payment is confirmed as completed. Proceed with crediting / shipment / status update operations.
  • Callback notifications may be resent, so ensure idempotent processing.
  • If a non-200 response or signature verification failure occurs, the platform will retry the callback.

Manual Callback Explanation

Merchants can manually trigger a callback in the backend order management system. Please note the following:

  • It is not recommended to trigger manual callbacks for orders that are not in a final state, such as "Accepted", "Pending Approval", etc.
  • If a manual callback is triggered but the order is not yet in a final state, the platform will resend the callback when the order's status changes to a final state. Merchants should ensure proper deduplication at the business layer.

# Callback Response

Description

  • All callbacks include a signature field. It is recommended that merchants validate the callback to ensure the integrity of the callback data.
  • After receiving and processing the callback data, merchants must respond to the gateway with the following JSON format:

Example Response (Success)

{
  "code": 200,
  "success": true
}

Callback Retries Mechanism (Important) 🔥

To ensure stable delivery and business consistency of the callback notifications, the platform has designed a retry strategy. If the merchant system fails to respond to the callback (e.g., network timeout, returns a non-200 status code, etc.), the system will retry according to the following rules:

Callback Retry Schedule (4 attempts total):

Attempt No. Interval (approx.) Description
1st Attempt About 2 minutes First retry after initial failure
2nd Attempt About 2 minutes Second retry after first failure
3rd Attempt About 11 minutes Third retry after second failure
4th Attempt About 2 minutes Final retry after third failure

Note: The intervals above represent internal scheduling intervals. The "callback time" recorded in the merchant's backend includes the merchant's processing/response time, so there may be a slight discrepancy (about 1 minute) between the displayed and actual push times.

Practical Reminders

  • When there is a large volume of orders online, callbacks may experience queue delays, so please ensure the server can handle high concurrency.
  • Each callback is an idempotent operation, and merchants should support idempotent checks.
  • After 4 failed retry attempts, the system will stop retrying automatically, and it is recommended 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 was successful

# Callback Notification URL Configuration

Two types of notification address configurations are supported:

  1. [Merchant Backend] Configure a Unified Callback Address
  • This can be configured in the "Merchant Backend" → "Developer Center."

  • Suitable for handling callbacks with common logic across most orders.

    img

2.Order-level Manual Specification of Callback URL (notifyUrl)

  • The notifyUrl field can be passed when creating an order.
  • If the order specifies the notifyUrl parameter, the system will use that address as the only callback notification target.

Priority of Address Configuration

The notifyUrl in the order takes precedence over the unified callback address configured in the system.

Priority of Response Status Code

The platform uses the HTTP response status code (status_code) as the only criterion to determine whether the callback was successful.

Specific Rules:

  • As long as the merchant system returns HTTP 200, the platform will consider the callback as successful.
    • In this case, even if the returned content is not { "code": 200, "success": true }, it will be ignored.
  • ❌ If the response status_code ≠ 200 (e.g., 400/500) or there is no response, the callback will be considered failed, and the platform will automatically retry the push.