logo

Search...

⌘ K

English

Product Guide
API Reference
Resource Download
Help Center

Getting Started

Overview

Scenario Capabilities

Onboarding Steps

Payin Capabilities

CKP Checkout Page

Interaction

Integration Prep

Integration Steps

Deeplink Redirect

Interaction

Integration Prep

Integration Steps

QRCode Display

Interaction

Integration Prep

Integration Steps

Payout Capabilities

Capability Overview

Deposit

Crypto Withdraw / Payout

Fiat Withdraw

Receive Payout Result

Supported Chains and Currencies

Supported Chains

Supported Currencies

Appendix

Wallets / Currencies / Chains

Transaction Status

Payment Status

Refund Status

Withdraw Status

Batch Status

Error Code Description

Signature Algorithm

Signature Algorithm

Algorithm Description

Fields participating in the signature:

  • apiPath: Request URI path (required), excluding host, query string, and the /crypto-payment prefix, e.g. /payin/v1/createPayment
  • body: Raw JSON string of the request body (required), byte-for-byte identical to what is sent to Paydify
  • x-api-key: Same as appId (required)
  • x-api-timestamp: Current timestamp in milliseconds (required)

Note: URL query string parameters are not included in the signature. Make sure your signing content contains only the 4 fields above. For this reason, never pass sensitive business parameters via the query string — put them in the signed request body instead.

Steps:

  1. Put the 4 fields above into a contentMap and sort entries by key in ascending order
  2. JSON-serialize the contentMap into a content string
  3. Compute HMAC-SHA256(content, apiSecret)
  4. Base64-encode the HMAC output — that is the signature string

Example:

curl -H 'x-api-key: key' \
     -H 'x-api-timestamp: 1744636844000' \
     -H 'x-api-signature: 0xb7Kxxxx=' \
      'https://{HOST}/path/to/pay' \
      -d '{"data":"test"}'

After sorting and serialization, contentMap looks like this (note: body is a raw string, not an object):

{
  "apiPath": "/path/to/pay",
  "body": "{\"data\":\"test\"}",
  "x-api-key": "key",
  "x-api-timestamp": "1744636844000"
}

HMAC-SHA256 this JSON string with apiSecret and Base64-encode the result to get the signature.

Code Implementation

Backend Examples

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "net/url"
    "sort"
)

func GenSign(appId, apiSecret, pathUrl, payload string, tm int64) string {
	// Parse URL
	path := ""
	contentMap := make(map[string]string)
	if u, err := url.Parse(pathUrl); err == nil {
		path = u.Path
		for k, v := range u.Query() {
			if len(v) > 0 {
				contentMap[k] = v[0]
			}
		}
	}

	// Build the map to be signed
	contentMap["x-api-key"] = appId
	contentMap["x-api-timestamp"] = fmt.Sprintf("%d", tm) // milliseconds
	contentMap["apiPath"] = path
	contentMap["body"] = payload

	// Get all keys and sort
	keys := make([]string, 0, len(contentMap))
	for k := range contentMap {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	// Create ordered map
	orderedMap := make(map[string]string)
	for _, k := range keys {
		orderedMap[k] = contentMap[k]
	}

	// JSON serialization
	content, _ := json.Marshal(orderedMap)

	// Calculate HMAC
	mac := hmac.New(sha256.New, []byte(apiSecret))
	mac.Write(content)
	return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}

// Usage example
GenSign("A123456", "ABC123", "/path/to/pay?param1=test1&param2=test2", "{"data":"test"}", time.Now().UnixMilli())

Postman Pre-request Script

Paste the following script into the Pre-request Script tab for Payin / Payout:

const appId = 'YOUR_APP_ID';
const apiSecret = 'YOUR_API_SECRET';

const ts = Date.now();

pm.request.headers.upsert({ key: 'x-api-key', value: appId });
pm.request.headers.upsert({ key: 'x-api-timestamp', value: String(ts) });

const path = pm.request.url.getPath();
const rawBody =
  pm.request.body && pm.request.body.raw ? pm.request.body.raw : '';
const bodyForSign = rawBody.replace(/\r?\n/g, '');

const ordered = {
  apiPath: path,
  body: bodyForSign,
  'x-api-key': appId,
  'x-api-timestamp': String(ts),
};

const content = JSON.stringify(ordered);

console.log('Signature content:', ordered);

const signature = CryptoJS.HmacSHA256(content, apiSecret).toString(
  CryptoJS.enc.Base64
);

pm.request.headers.upsert({ key: 'x-api-signature', value: signature });

console.log('Generated signature:', signature);

QR Pay and Fusion Pay use the X-DAPI-* header family with a different signing rule. See QR Pay Signature Algorithm.

Catalogue