快速开始
AnonyPay 是面向商户的加密货币收款网关,通过服务器对服务器的 HTTP API 提供收款地址创建、充值到账通知与提现下单能力,当前支持 TRON / Solana / ETH·BNB / TON 多链,Bitcoin 为预留链、仍在接入中。所有业务请求、响应与回调均经 RSA-OAEP 加密、SHA256withRSA 签名,并以时间戳 + nonce 双向防重放。对接工作可概括为三件事:拿到凭据并加载官方 SDK(PHP / Python / Node.js / Go / Java 五种语言)、实现「取 token → 加密签名请求 → 验签解密响应」的调用链、实现接收平台回调的处理端点。
前置条件
开始写代码之前,请逐项确认:
- 已获取 4 个凭据:
APP-ID(商户号)、获取 token 的secret、服务端公钥public_t、商户私钥private_u。密钥格式为base64(PEM)的 RSA-2048,获取方式与格式细节见凭据与密钥。凭据请妥善保管,切勿外泄。 - 服务器已做 NTP 校时:协议依赖秒级 Unix 时间戳,服务端时间窗仅 ±5 分钟,时钟漂移会直接触发
signatureFailed。 - 出口 IP 已加入白名单:把你服务器的出口 IP 提供给平台配置。来源 IP 不在白名单时,请求会收到纯文本
Oops(不是 JSON)。 - 运行环境就绪:PHP 需 openssl 扩展;Python 需
cryptography;Node.js 使用内置crypto(getToken()需 Node ≥ 18);Go / Java 仅用标准库。各语言 SDK 获取方式见 SDK 总览。
调用流程:三步
所有业务接口均为 POST,基址 https://api.anonypay.io/api/merchant/。
① getToken ── 用 APP-ID + secret 取 token(请求体不加密、不签名;但响应仍是加密+签名信封,需验签+解密)
② 业务接口 ── OAEP 加密 body → 生成 ts/nonce → 对 canonical 串 SHA256 签名 → 带 5 个头 POST
③ 处理响应 ── 验时间窗/nonce → 验签 → 解密 → 得到业务数据- getToken — 用
APP-ID+secret做 md5 鉴权,换取后续接口所需的ANONY-TOKEN;此接口请求体不加密、不签名。 - 业务请求 — 业务 JSON 经 RSA-OAEP 加密为密文 body,生成时间戳与 nonce,对 canonical 串做 SHA256withRSA 签名,带全套
ANONY-*请求头发起 POST。 - 处理响应 — 校验时间窗(±5 分钟)与 nonce 去重,用平台公钥验签,再用商户私钥 OAEP 解密
data,得到业务数据。
getToken 的响应不是明文 token
getToken 的响应与其它接口一样是加密+签名信封。务必用 SDK 验签+解密后再取出 token 字段,不要直接把响应体当 token 用。
五语言最小示例
以下示例完成「取 token → 创建一个 TRON 收款地址 → 验签解密响应」。getToken 的支持方式因语言而异:PHP / Node.js 提供开箱即用的 getToken()(内含 HTTP 调用);Python / Go / Java 提供 authHeader()(计算 auth + md5(APP-ID & secret)),HTTP 由你选用的库发起、响应用 verifyResponse / verify+decrypt 处理。
require 'AnonyV2Client.php';
$client = new AnonyV2Client($appId, $serverPublicKeyB64, $merchantPrivateKeyB64);
$token = $client->getToken($secret); // 自动 md5 鉴权 + 验签解密取出 token
$res = $client->post('createAddress', ['userOrder'=>'A1001','addressType'=>'trx'], $token);
// $res['data'] 已自动验签+解密from anony_v2 import AnonyV2Client, auth_header
import requests
c = AnonyV2Client(app_id, server_pub_b64, merchant_priv_b64)
# 先取 token:请求不加密,仅 md5 鉴权;响应仍需验签+解密
tr = requests.post(c.base_url + "getToken",
headers={"ANONY-APP-ID": str(app_id), "Authorization": auth_header(app_id, secret)})
tb = tr.json()
token = c.verify_response(tb["data"], tr.headers["ANONY-TIMESTAMP"],
tr.headers["ANONY-NONCE"], tr.headers["ANONY-SIGN"])["token"]
req = c.build_request({"userOrder": "A1001", "addressType": "trx"}, token)
r = requests.post(c.base_url + "createAddress", data=req["body"], headers=req["headers"])
body = r.json()
if body["code"] == 10000:
data = c.verify_response(body["data"], r.headers["ANONY-TIMESTAMP"],
r.headers["ANONY-NONCE"], r.headers["ANONY-SIGN"])const { AnonyV2Client } = require('./anony_v2');
const c = new AnonyV2Client(appId, serverPubB64, merchantPrivB64);
const token = await c.getToken(secret); // Node ≥18:自动 md5 鉴权 + 验签解密取出 token
const req = c.buildRequest({ userOrder: 'A1001', addressType: 'trx' }, token);
const r = await fetch(c.baseUrl + 'createAddress', { method: 'POST', body: req.body, headers: req.headers });
const body = await r.json();
if (body.code === 10000) {
const data = c.verifyResponse(body.data, r.headers.get('anony-timestamp'),
r.headers.get('anony-nonce'), r.headers.get('anony-sign'));
}// Go SDK(sdk/go/anonyv2.go,仅依赖标准库)不内置 HTTP 调用,
// 导出函数:Encrypt / Decrypt / Sign / Verify / Canonical / NewNonce / AuthHeader。
// JSON 序列化与 HTTP 发送由你选用的库完成。
//
// 取 token:用 AuthHeader() 计算 Authorization 头(auth + md5(APP-ID & secret)),
// POST getToken 后用 Verify + Decrypt 处理响应信封,取出 token。
//
// 业务请求:Encrypt 加密 body → NewNonce 生成随机串 → Canonical 拼签名串
// → Sign 签名 → 带 5 个 ANONY-* 头 POST;响应同样 Verify + Decrypt 处理。// Java SDK(sdk/java/AnonyV2Client.java,仅依赖 JDK 标准库)不内置 HTTP 调用,
// 静态方法:encrypt / decrypt / sign / verify / canonical / newNonce / buildHeaders / authHeader。
// JSON 序列化与 HTTP 发送由你选用的库完成。
//
// 取 token:用 authHeader() 计算 Authorization 头(auth + md5(APP-ID & secret)),
// POST getToken 后用 verify + decrypt 处理响应信封,取出 token。
//
// 业务请求:encrypt 加密 body → newNonce 生成随机串 → canonical 拼签名串
// → sign 签名 → buildHeaders 组装请求头 → POST;响应同样 verify + decrypt 处理。Go / Java 的完整用法说明见 Go SDK 与 Java SDK;createAddress 的参数与响应见创建收款地址。
TRON 链 USDC 充值已关闭:到账不入账、不回调
示例中创建的 trx 类型地址请勿用于接收 TRON 链 USDC——该币种充值已关闭,转入后只做记录,不会入账、也不会触发回调。TRON 链收款请使用 TRX / USDT(TRC-20)。对外支持的币种枚举见接口参考。
上线前:先跑 selfcheck(强烈建议)
正式启用是一次性切换——平台为你的商户号开启后,你后续所有业务请求都会立即按本协议校验;若此时 SDK 有任何不一致(如 OAEP 哈希、canonical 串、签名算法),请求会全部失败、业务中断。selfcheck 是只读的联调探活接口,让你在启用之前就用真实密钥把完整链路跑通:
- 服务端对你的请求完整执行 token 校验 → 时间戳/nonce 防重放 → SHA256 验签 → OAEP 解密,再用同样的 v2 信封把内容原样
echo回去。 - 一次成功的调用同时证明上行(你的加密+签名能被服务端接受)与下行(服务端的响应能被你验签+解密)两个方向都正确。
- 该接口不创建任何订单/地址、不改任何状态,可反复调用。
- 自检通过后通知平台,由平台完成正式启用。
如遇 signatureFailed 或解密失败,按排错指南的顺序检查:① OAEP 是否用 SHA-1;② canonical 串是否用 \n 且顺序为 ts, nonce, body;③ 密钥角色是否用对(上行用平台公钥加密、商户私钥签名);④ 服务器时间是否同步。