入门
English商户 API
在服务端接入 HansaPay:卡与钱包支付、退款及签名的异步通知。所有接口均为 JSON POST,并使用 HMAC-SHA256 签名。
Base URL
请先对接测试环境,上线时再切换 Base URL 与密钥。所有接口均为 POST + JSON 请求体,且每个请求都需要签名。文档中的示例统一使用 https://api.example.com 作为参考域名。
测试环境
https://api-test.hansapay.io生产环境
https://api.hansapay.io快速开始
最快的第一笔支付是收银台下单:你提交订单,HansaPay 返回 checkout_url,付款人在 HansaPay 的页面上输入卡信息,你无需接触卡数据。签名方法见签名与验签。
{
"payment_method": "CARD",
"merchant_order_no": "M202406240002",
"trans_amount": {
"currency": "USD",
"value": "49.99"
},
"notify_url": "https://merchant.example.com/callback/payment",
"return_url": "https://merchant.example.com/pay/success",
"trade_info": {
"goods_name": "VIP Membership",
"description": "Monthly subscription"
},
"metadata": "biz=member&uid=10001",
"client_ip": "203.0.113.10"
}BODY='{"payment_method":"CARD","merchant_order_no":"M202406240002","trans_amount":{"currency":"USD","value":"49.99"},"notify_url":"https://merchant.example.com/callback/payment","return_url":"https://merchant.example.com/pay/success","trade_info":{"goods_name":"VIP Membership","description":"Monthly subscription"},"metadata":"biz=member&uid=10001","client_ip":"203.0.113.10"}'
TIMESTAMP="$(date +%s)"
NONCE="$(openssl rand -hex 8)"
SIGN_PAYLOAD="${MERCHANT_ID}"$'\n'"${TIMESTAMP}"$'\n'"${NONCE}"$'\n'"${BODY}"
SIGN=$(printf '%s' "$SIGN_PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET_KEY" -binary | xxd -p -c 256)
curl -X POST "https://api-test.hansapay.io/api/v1/payments/checkout" \
-H "Content-Type: application/json" \
-H "X-MerchantID: ${MERCHANT_ID}" \
-H "X-Timestamp: ${TIMESTAMP}" \
-H "X-Nonce: ${NONCE}" \
-H "X-Sign: ${SIGN}" \
-d "$BODY"import crypto from "node:crypto";
const body = JSON.stringify({
payment_method: "CARD",
merchant_order_no: "M202406240002",
trans_amount: {
currency: "USD",
value: "49.99"
},
notify_url: "https://merchant.example.com/callback/payment",
return_url: "https://merchant.example.com/pay/success",
trade_info: {
goods_name: "VIP Membership",
description: "Monthly subscription"
},
metadata: "biz=member&uid=10001",
client_ip: "203.0.113.10"
});
const timestamp = String(Math.floor(Date.now() / 1000));
const nonce = crypto.randomBytes(8).toString("hex");
const sign = crypto
.createHmac("sha256", process.env.SECRET_KEY)
.update(`${process.env.MERCHANT_ID}\n${timestamp}\n${nonce}\n${body}`)
.digest("hex");
const res = await fetch("https://api-test.hansapay.io/api/v1/payments/checkout", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-MerchantID": process.env.MERCHANT_ID,
"X-Timestamp": timestamp,
"X-Nonce": nonce,
"X-Sign": sign,
},
body, // send exactly the string you signed
});
const { code, msg, data } = JSON.parse(await res.text());<?php
$merchantId = getenv('MERCHANT_ID');
$secret = getenv('SECRET_KEY');
$rawBody = '{"payment_method":"CARD","merchant_order_no":"M202406240002","trans_amount":{"currency":"USD","value":"49.99"},"notify_url":"https://merchant.example.com/callback/payment","return_url":"https://merchant.example.com/pay/success","trade_info":{"goods_name":"VIP Membership","description":"Monthly subscription"},"metadata":"biz=member&uid=10001","client_ip":"203.0.113.10"}';
$timestamp = (string) time();
$nonce = bin2hex(random_bytes(8));
$payload = $merchantId . "\n" . $timestamp . "\n" . $nonce . "\n" . $rawBody;
$sign = hash_hmac('sha256', $payload, $secret);
$ch = curl_init('https://api-test.hansapay.io/api/v1/payments/checkout');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $rawBody,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-MerchantID: ' . $merchantId,
'X-Timestamp: ' . $timestamp,
'X-Nonce: ' . $nonce,
'X-Sign: ' . $sign,
],
]);
$response = json_decode(curl_exec($ch), true);{
"code": 0,
"msg": "success",
"data": {
"payment_method": "CARD",
"order_no": "O202406240002",
"merchant_order_no": "M202406240002",
"status": "CHECKOUT_REQUIRED",
"trans_amount": {
"currency": "USD",
"value": "49.99"
},
"next_action": "CHECKOUT_REQUIRED",
"token": "5c4f0f53-c0e9-4d11-8a2b-0f3e6a1d9b27",
"checkout_url": "https://cashier.example.com/pay/5c4f0f53-c0e9-4d11-8a2b-0f3e6a1d9b27",
"created_at": "2026-06-24T10:05:00+08:00"
}
}将付款人跳转到 checkout_url,并在收到后立即保存:它 30 分钟后失效,且无法再次获取。支付完成后,HansaPay 会向你的 notify_url 发送签名的 payment.updated 异步通知。
接口列表
所有接口均为签名的 JSON POST。如需在终端中直接调试,见 cURL 联调。
