Authentication

Pockyt uses three credentials to authenticate every API call: merchantNo, storeNo, and an API Token. The token is never sent over the wire — instead, it is used to generate a verifySign hash that proves you hold the token.

This same signing mechanism also lets you verify that incoming IPN (Instant Payment Notification) callbacks genuinely came from Pockyt.


Obtaining API Credentials

Sandbox Access

Obtain sandbox credentials by contacting [email protected] or by registering at the Pockyt Sandbox Application.

Production Access

Production credentials are provided after completing the merchant onboarding process.

Credentials Breakdown

CredentialDescription
merchantNoA unique number assigned to your merchant account.
storeNoA number associated with a specific store under the merchant. Additional store numbers can be created via the Pockyt Merchant Portal.
API TokenA developer token used to generate verifySign signatures. Never send this token directly in an API request.

All three credentials are required to sign and verify API calls.

Best Practices for API Token Security

  • Secure Storage — Store your API token in a database or backend configuration file. Do not hard-code it into source code or commit it to version control.
  • Encryption — Use strong encryption algorithms like AES or RSA to protect stored tokens.
  • Rate Limiting — Implement rate limiting to prevent brute force attacks.
  • Log Monitoring — Regularly check logs for suspicious activity, such as repeated failed API requests.

Signing API Calls

Pockyt secures API transactions using the verifySign parameter, which authenticates requests without requiring secret tokens or passwords to be transmitted.

How to Generate verifySign

📘

Steps for generating the verifySign signature

  1. Collect all request parameters (excluding verifySign itself).
  2. Sort the parameters alphabetically by key name.
  3. Concatenate them in key=value format, joined by &.
  4. Compute the MD5 hash of your API Token and append it to the string, prefixed with &.
  5. Compute the MD5 hash of the entire concatenated string. This is your verifySign.

Worked Example

Assume the following request parameters and API token:

API Token: 5cbfb079f15b150122261c8537086d77

Input Parameters:

amount = '1.00'
storeNo = '300014'
currency = 'USD'
settleCurrency = 'USD'
merchantNo = '200043'
callbackUrl = 'https://wx.yuansfer.yunkeguan.com/wx'
terminal = 'ONLINE'
ipnUrl = 'https://wx.yuansfer.yunkeguan.com/wx'
reference = 'seq_1525922323'
vendor = 'alipay'
goodsInfo = '[{"goods_name":"Yuansfer","quantity":"1"}]'
timeout = '120'

Step 1 — Sort parameters alphabetically:

amount = '1.00'
callbackUrl = 'https://wx.yuansfer.yunkeguan.com/wx'
currency = 'USD'
goodsInfo = '[{"goods_name":"Yuansfer","quantity":"1"}]'
ipnUrl = 'https://wx.yuansfer.yunkeguan.com/wx'
merchantNo = '200043'
reference = 'seq_1525922323'
settleCurrency = 'USD'
storeNo = '300014'
terminal = 'ONLINE'
timeout = '120'
vendor = 'alipay'

Step 2 — Concatenate as key=value&key=value:

amount=1.00&callbackUrl=https://wx.yuansfer.yunkeguan.com/wx&currency=USD&goodsInfo=[{"goods_name":"Yuansfer","quantity":"1"}]&ipnUrl=https://wx.yuansfer.yunkeguan.com/wx&merchantNo=200043&reference=seq_1525922323&settleCurrency=USD&storeNo=300014&terminal=ONLINE&timeout=120&vendor=alipay

Step 3 — Hash the API Token and append it:

MD5("5cbfb079f15b150122261c8537086d77") = 45ba0f07f3b6d4acb3f3278f629dc9e6

Append with &:

amount=1.00&callbackUrl=https://wx.yuansfer.yunkeguan.com/wx&currency=USD&goodsInfo=[{"goods_name":"Yuansfer","quantity":"1"}]&ipnUrl=https://wx.yuansfer.yunkeguan.com/wx&merchantNo=200043&reference=seq_1525922323&settleCurrency=USD&storeNo=300014&terminal=ONLINE&timeout=120&vendor=alipay&45ba0f07f3b6d4acb3f3278f629dc9e6

Step 4 — Compute the final MD5 hash:

MD5(concatenated string) = 5876be977662d1b66c88e8df4d0babe7

Your verifySign value is 5876be977662d1b66c88e8df4d0babe7.

Example cURL Request

curl -X POST 'https://mapi.yuansfer.com/online/v3/secure-pay' \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "1.00",
    "storeNo": "300014",
    "currency": "USD",
    "settleCurrency": "USD",
    "merchantNo": "200043",
    "callbackUrl": "https://wx.yuansfer.yunkeguan.com/wx",
    "terminal": "ONLINE",
    "ipnUrl": "https://wx.yuansfer.yunkeguan.com/wx",
    "reference": "seq_1525922323",
    "vendor": "alipay",
    "goodsInfo": "[{\"goods_name\":\"Yuansfer\",\"quantity\":\"1\"}]",
    "timeout": "120",
    "verifySign": "5876be977662d1b66c88e8df4d0babe7"
  }'

Verifying IPN Webhook Signatures

When a transaction completes, Pockyt sends a POST request to the ipnUrl you provided. This payload includes a verifySign field so you can confirm the request actually came from Pockyt and was not tampered with.

⚠️

Always verify verifySign on incoming IPN callbacks. Skipping this step leaves your integration vulnerable to spoofed notifications.

How to Verify

  1. Extract all fields from the IPN payload except verifySign.
  2. Follow the exact same signing process described above (sort → concatenate → append MD5 of your API Token → hash).
  3. Compare the verifySign you computed with the one in the payload. If they match, the notification is authentic.

Worked Example

Pockyt sends the following IPN payload to your ipnUrl:

{
  "amount": "20.00",
  "currency": "USD",
  "note": "test note",
  "reference": "bIJrcfAwd11sdeddd944cZdZ",
  "settleCurrency": "USD",
  "status": "success",
  "supUserid": "$CASHTAG_C_TOKEN",
  "time": "20260410220643",
  "transactionNo": "305890742378708206",
  "vendorId": "PWC_22wq80e5qy5tar5kkq24h0knd",
  "verifySign": "ea1f9ad19f977d5f7d54dca746e2d88b"
}

Your API Token: 5cbfb079f15b150122261c8537086d77

Step 1 — Extract all fields except verifySign and sort alphabetically:

amount = '20.00'
currency = 'USD'
note = 'test note'
reference = 'bIJrcfAwd11sdeddd944cZdZ'
settleCurrency = 'USD'
status = 'success'
supUserid = '$CASHTAG_C_TOKEN'
time = '20260410220643'
transactionNo = '305890742378708206'
vendorId = 'PWC_22wq80e5qy5tar5kkq24h0knd'

Step 2 — Concatenate:

amount=20.00&currency=USD&note=test note&reference=bIJrcfAwd11sdeddd944cZdZ&settleCurrency=USD&status=success&supUserid=$CASHTAG_C_TOKEN&time=20260410220643&transactionNo=305890742378708206&vendorId=PWC_22wq80e5qy5tar5kkq24h0knd

Step 3 — Hash the API Token and append:

MD5("5cbfb079f15b150122261c8537086d77") = 45ba0f07f3b6d4acb3f3278f629dc9e6

Appended string:

amount=20.00&currency=USD&note=test note&reference=bIJrcfAwd11sdeddd944cZdZ&settleCurrency=USD&status=success&supUserid=$CASHTAG_C_TOKEN&time=20260410220643&transactionNo=305890742378708206&vendorId=PWC_22wq80e5qy5tar5kkq24h0knd&45ba0f07f3b6d4acb3f3278f629dc9e6

Step 4 — Compute the final MD5:

MD5(concatenated string) = ea1f9ad19f977d5f7d54dca746e2d88b

Step 5 — Compare:

ValueHash
Received verifySignea1f9ad19f977d5f7d54dca746e2d88b
Computed verifySignea1f9ad19f977d5f7d54dca746e2d88b

Match — the IPN notification is authentic. Process the transaction update. If they do not match, reject the request and log it for investigation.

Reference Implementation (Python)

import hashlib

def compute_verify_sign(params: dict, api_token: str) -> str:
    """
    Compute the verifySign hash for a set of parameters.
    Works for both signing outbound requests and verifying inbound IPNs.
    """
    # Remove verifySign if present (for IPN verification)
    filtered = {k: v for k, v in params.items() if k != "verifySign"}

    # Step 1 & 2: Sort and concatenate
    sorted_keys = sorted(filtered.keys())
    concatenated = "&".join(f"{k}={filtered[k]}" for k in sorted_keys)

    # Step 3: Append MD5 of API token
    token_md5 = hashlib.md5(api_token.encode()).hexdigest()
    final_string = concatenated + "&" + token_md5

    # Step 4: Compute final MD5
    return hashlib.md5(final_string.encode()).hexdigest()


def verify_ipn(payload: dict, api_token: str) -> bool:
    """
    Verify that an IPN callback is authentic.
    Returns True if the verifySign matches, False otherwise.
    """
    received_sign = payload.get("verifySign", "")
    computed_sign = compute_verify_sign(payload, api_token)
    return received_sign == computed_sign

Reference Implementation (Node.js)

const crypto = require("crypto");

function computeVerifySign(params, apiToken) {
  // Remove verifySign if present (for IPN verification)
  const filtered = Object.fromEntries(
    Object.entries(params).filter(([key]) => key !== "verifySign")
  );

  // Step 1 & 2: Sort and concatenate
  const concatenated = Object.keys(filtered)
    .sort()
    .map((key) => `${key}=${filtered[key]}`)
    .join("&");

  // Step 3: Append MD5 of API token
  const tokenMd5 = crypto.createHash("md5").update(apiToken).digest("hex");
  const finalString = `${concatenated}&${tokenMd5}`;

  // Step 4: Compute final MD5
  return crypto.createHash("md5").update(finalString).digest("hex");
}

function verifyIpn(payload, apiToken) {
  const receivedSign = payload.verifySign || "";
  const computedSign = computeVerifySign(payload, apiToken);
  return receivedSign === computedSign;
}