Webhooks

Card operation and transaction event webhook notifications with signature verification.

The system pushes card operation and transaction events in real-time to the merchant's configured callback URL.

Common Specifications

Request Headers

HeaderTypeRequiredDescription
Content-TypeStringYesapplication/json;charset=UTF-8
x-timestampStringYesUnix timestamp (seconds)
x-signatureStringYesHMAC-SHA256(webhook_secret, x-timestamp + "." + raw_body) → Hex encoded,
where webhook_secret is obtained from the merchant portal,
raw_body is the original payload structure content, refer to the table below

Payload Structure

FieldTypeRequiredDescription
request_idStringYesUnique event identifier for deduplication, 64-bit
event_typeStringYesEvent type: issuing.cardOperateEvent card operation event change / issuing.cardTransactionEvent card transaction event change
created_atStringYesEvent creation time (ISO 8601 format)
versionStringNoAPI version (selected when creating the Webhook subscription, default 1.0)
dataObjectYesBusiness data, structure varies by event_type

Merchant Response Requirements

The merchant callback must return the following JSON structure. The system uses this to determine if the push was successful. If the response code is not 20000, the system will retry every 15 seconds, up to 10 times.

FieldTypeDescription
respCodeStringResponse code, return 20000 to confirm receipt
respMsgStringResponse message

Card Operation Event

event_type = issuing.cardOperateEvent

data

FieldTypeDescription
operateRecordIdnumberOperation record ID, required
cardIdnumberCard ID, required
clientRequestIdStringIdempotent request ID, required
typeStringOperation type: CREATE / FREEZE / UNFREEZE / DEPOSIT
statusStringOperation status, required (P Processing / S Success / F Failed)
remarkStringRemark
amountnumberAmount
currencyStringCurrency
feeList[]ArrayFee detail list
feeList[].feeTypeStringFee type: CREATE card creation fee / DEPOSIT deposit fee
feeList[].feeAmountnumberFee amount
feeList[].feeCurrencyStringFee currency

Example

{
  "operateRecordId": 200001,
  "cardId": 100001,
  "clientRequestId": "REQ_20260101_001",
  "type": "DEPOSIT",
  "status": "S",
  "remark": null,
  "amount": 100.00,
  "currency": "USD",
  "feeList": [
    { "feeType": "DEPOSIT", "feeAmount": 1.00, "feeCurrency": "USD" }
  ]
}

Transaction Event

Pushed when transactions (authorization, clearing, refund, etc.) occur.

event_type = issuing.cardTransactionEvent

data

FieldTypeDescription
txnTypeStringTransaction type: AUTHORIZATION / REVERSAL / CLEARING / REFUND / VERIFICATION
txnStatusStringTransaction status: S Success / F Failed / P Processing
txnOrderNoStringTransaction order number
originTxnOrderNoStringOriginal transaction order number
originTxnOrderNoForRefundStringOriginal payment order number for refund
cardIdStringCard ID
authTimenumberAuthorization time (timestamp, milliseconds)
authorizationCodeStringAuthorization code
authMessageDescStringAuthorization description
transactionAmountnumberTransaction amount
transactionCurrencyStringTransaction currency
transactionTimenumberTransaction time (timestamp, milliseconds)
cardAmountnumberCard amount
cardCurrencyStringCard currency
settleAmountnumberSettlement amount
settleCurrencyStringSettlement currency
settleTimenumberSettlement time (timestamp, milliseconds)
transactionFeenumberTransaction fee
transactionFeeCurrencyStringTransaction fee currency
crossBorderFeenumberCross-border fee
crossBorderFeeCurrencyStringCross-border fee currency
exchangeFeenumberExchange fee
exchangeFeeCurrencyStringExchange fee currency
merchantIdStringMerchant ID
merchantNameStringMerchant name
merchantCountryStringMerchant country
merchantCountryCodeStringMerchant country code
merchantStateProvinceStringMerchant state/province
merchantCityStringMerchant city
merchantPostalCodeStringMerchant postal code
merchantMccCodeStringMerchant MCC code

Example

{
  "txnType": "AUTHORIZATION",
  "txnStatus": "S",
  "txnOrderNo": "TXN20260101001",
  "originTxnOrderNo": null,
  "originTxnOrderNoForRefund": null,
  "cardId": "411111******1111",
  "authTime": 1735689600000,
  "authorizationCode": "AUTH001",
  "authMessageDesc": "Approved",
  "transactionAmount": 50.00,
  "transactionCurrency": "USD",
  "transactionTime": 1735689600000,
  "cardAmount": 50.00,
  "cardCurrency": "USD",
  "settleAmount": 50.00,
  "settleCurrency": "USD",
  "settleTime": 1735776000000,
  "transactionFee": 0.50,
  "transactionFeeCurrency": "USD",
  "crossBorderFee": null,
  "crossBorderFeeCurrency": null,
  "exchangeFee": null,
  "exchangeFeeCurrency": null,
  "merchantId": "MCH001",
  "merchantName": "Amazon",
  "merchantCountry": "United States",
  "merchantCountryCode": "US",
  "merchantStateProvince": "WA",
  "merchantCity": "Seattle",
  "merchantPostalCode": "98101",
  "merchantMccCode": "5411"
}

Signature & Verification

Signing is used to verify the integrity and authenticity of messages, ensuring that requests or notifications have not been tampered with during transmission, while supporting server-side verification and auditing.

When Onerway pushes asynchronous notifications (such as transaction/card events) to merchants, the notification payload is signed. HMAC-SHA256 signing algorithm is supported. Reference code is as follows.

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class HmacSHA256Util {

    // Signing
    public static String signHmacSHA256(String plainCert, String content)
            throws NoSuchAlgorithmException, InvalidKeyException {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec keySpec = new SecretKeySpec(
                    Base64.decodeBase64(plainCert), "HmacSHA256");
            mac.init(keySpec);
            byte[] result = mac.doFinal(content.getBytes());
            return HexUtil.encodeHexStr(result);
        } catch (Exception e) {
            throw e;
        }
    }

    // Verification
    private static boolean verifyHmacSHA256(String plainCert, String sign, String signed)
            throws NoSuchAlgorithmException, InvalidKeyException {
        String hmacSHA256Str = signHmacSHA256(plainCert, sign);
        return StrUtil.equalsAnyIgnoreCase(hmacSHA256Str, signed);
    }
}