5 分钟接入
这一页只做一件事:让你在最短时间里收到第一笔钱,并在自己的服务端上看到回调。 下面的示例里 API_BASE 指你的接入域名(例如 https://api.web3sdk.com,实际以接入时获得的地址为准)。
第 0 步:拿到 API KEY
通过官网注册入口提交商户资料,平台开通后为你的商户号签发 API KEY。
自助注册已开放
API KEY 不随注册响应下发。注册完成后登录商户后台,在「支付收款 → 支付设置」里点「查看」 即可看到当前明文(每次查看都会记审计,平台也不会把 KEY 写进邮件)。 要换 KEY 在同一页点「重置」,旧 KEY 在过渡期后失效。
拿到之后把 KEY 存在服务端的环境变量里,不要写进代码仓库、不要放进前端:
export PAY_API_KEY='<你的 API KEY>'
export API_BASE='https://api.web3sdk.com'平台侧的商户接口 GET /api/pay/getMyProfile 会返回你的 merchantNo、collectName、 脱敏后的 apiKey 与 cashierBaseUrl。KEY 的明文请到商户后台「支付收款 → 支付设置」查看 (单独接口、每次记审计;getMyProfile 永远只回末 4 位)。
第 1 步:配置收款地址
在商户后台登录后,为一条已授权的链填收款地址并设为启用。商户侧接口:
GET {API_BASE}/api/pay/getMyChains拿到可用链与代币的 id 之后(收银页可用同一份清单):
curl -X POST "$API_BASE/api/pay/saveMyAddress" \
-H 'Content-Type: application/json' \
-H 'x-token: <商户后台登录后的 JWT>' \
-d '{
"chainId": 2,
"address": "TXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"label": "主收款地址"
}'再把它设为启用:
curl -X POST "$API_BASE/api/pay/setActiveAddress" \
-H 'Content-Type: application/json' \
-H 'x-token: <商户后台登录后的 JWT>' \
-d '{"chainId": 2, "address": "TXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"}'收款地址决定钱去哪儿
下单时平台会把当时启用的那个地址锁定进订单快照。之后你换地址,不会影响已经创建的订单 —— 买家仍按老地址转账,系统也仍然监听它。
第 2 步:服务端创建订单
在你自己的服务端调用开放接口。请求头带 API KEY,字段里的 amount 是代币单位的小数字符串:
curl -X POST "$API_BASE/api/pay/open/createOrder" \
-H "X-Pay-Api-Key: $PAY_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"merchantOrderNo": "SHOP-2026-0001",
"chainId": 2,
"tokenId": 1,
"amount": "100.5",
"subject": "订单 SHOP-2026-0001",
"notifyUrl": "https://your-shop.com/pay/notify",
"returnUrl": "https://your-shop.com/pay/done"
}'响应(节选):
{
"code": 0,
"data": {
"order": {
"orderNo": "PO20261011XXXXXXXXXXXX",
"merchantOrderNo": "SHOP-2026-0001",
"merchantNo": "M00000XXXX",
"status": 1,
"statusText": "待支付",
"orderType": 1,
"amountMinimal": "100500000",
"payAmountMinimal": "100500123",
"payAmountDisplay": "100.500123",
"payAddress": "TXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"chainId": 2,
"tokenId": 1,
"identify": {
"mode": 1,
"orderNo": "PO20261011XXXXXXXXXXXX",
"calldataSuffix": "0x...订单识别码..."
}
},
"idempotentReplay": false
},
"msg": "下单成功"
}三个金额字段的分工要记住:
amountMinimal—— 你下单时给的金额(最小单位)。payAmountMinimal—— 实际应该转的金额。当识别方式是"金额尾数"时会比上面多一段尾数。以它为准。payAmountDisplay—— 上面那个给人看的形式。
identify 是这笔订单的识别信息,必须原样透传,不要改大小写、不要加前缀,否则扫块时认不出这一单。
第 3 步:买家扫码付款
把你的收款台链接或二维码给买家。收款台地址的形状是:
{cashierBaseUrl}/pay/cashier/m/{merchantNo}cashierBaseUrl 与 merchantNo 都来自 GET /api/pay/getMyProfile。 注意商户号是路径段而不是查询串 —— 查询串会被部分钱包的深链按 = 截断。
买家打开后,收银页会调这几个公开接口(无需登录):
GET /api/pay/getCashierMerchant # 收款名称等展示信息
GET /api/pay/getCashierChains # 可用的链与代币清单(脱敏)
GET /api/pay/getCashierOrder # 按订单号查这一单
POST /api/pay/createCashierOrder # 线下扫码:买家先输金额再下单
POST /api/pay/submitCashierTxHash # 买家签名后回传交易哈希如果你是从自己的系统推过来的订单(线上单),让买家直接进 getCashierOrder 对应的收银页即可, 不需要再走 createCashierOrder。
第 4 步:收回调并改单
确认数达标后,平台会 POST 到你配置的(或本单 notifyUrl 指定的)地址。先校验签名,再处理业务:
// 关键:验签用的是**你自己的 API KEY**,报文体用**原始字节**,不要先解析再重编码
func verify(apiKey, ts, rawBody, sig string) bool {
mac := hmac.New(sha256.New, []byte(apiKey))
mac.Write([]byte(ts))
mac.Write([]byte(rawBody))
want := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(want), []byte(sig))
}
func handler(w http.ResponseWriter, r *http.Request) {
raw, _ := io.ReadAll(r.Body)
ts := r.Header.Get("X-Pay-Timestamp")
sig := r.Header.Get("X-Pay-Signature")
if !verify(os.Getenv("PAY_API_KEY"), ts, string(raw), sig) {
http.Error(w, "bad signature", http.StatusUnauthorized)
return
}
var p struct {
MerchantOrderNo string `json:"merchantOrderNo"`
OrderNo string `json:"orderNo"`
Status int `json:"status"`
ReceivedAmount string `json:"receivedAmount"`
TxHash string `json:"txHash"`
}
_ = json.Unmarshal(raw, &p)
// 幂等:同一个 merchantOrderNo 只处理一次,回调会重试
if alreadyDone(p.MerchantOrderNo) {
w.WriteHeader(http.StatusOK) // 2xx 才会让平台停止重试
return
}
markPaid(p.MerchantOrderNo, p.TxHash, p.ReceivedAmount)
w.WriteHeader(http.StatusOK)
}处理完之后:
- 返回 2xx 表示你收到了,平台不会再重试。
- 返回其它状态码或不响应,平台会按退避序列重试。
- 不要只依赖回调:任何时刻都可以用查询接口主动核对真实状态。
curl "$API_BASE/api/pay/open/queryOrder?merchantOrderNo=SHOP-2026-0001" \
-H "X-Pay-Api-Key: $PAY_API_KEY"到这里,一笔钱就走完了。接下来可以按你的形态挑一条更细的路径: