API Key 模式 - HTTP API 集成
使用 API Key 在服务端访问商户业务 HTTP API。API Key 认证成功后会绕过面向交互式登录的 Step-Up 重认证。
获取 API Key
- 登录 PolyPay 商户后台
- 进入「API 密钥」页面
- 点击「创建密钥」
- 选择过期时间;新建 API Key 默认 7 天后过期。选择永不过期时,该 API Key 不会自动失效;历史 API Key 默认永不过期。
- 安全保存生成的 API Key
⚠️ API Key 只会显示一次,请立即保存。如果丢失,需要重新生成。永远不要在前端代码、Git 仓库或日志中暴露 API Key。
每个 API Key 可选配置来源 IP 白名单,支持单个 IPv4/IPv6 地址或 CIDR 网段;不配置时不限制来源 IP。白名单在 API Key 认证阶段校验,建议生产密钥仅允许固定服务器出口 IP。为防止泄露的旧 Key 维持访问,API Key 不能创建新 API Key。
套餐额度与计费口径
- 收款套餐、订单额度和收款钱包用量按商户独立计算。钱包监控套餐、监控地址及通知额度归账号所有;切换商户不会获得另一份监控额度。
- 公开定价见定价页。PolyPay 不抽取交易流水,按套餐额度和按量用量收费。
- 每个账号首个创建的商户会固定持有 Free 收款资格,禁用其他商户不会转移该资格;额外商户需要为该商户启用用多少付多少、Pro 或 Ultra 后才能创建收款订单或 Checkout。
- 账号余额按用户维度保存,并分为实付余额和赠金余额;消费时优先使用赠金。订阅余额不足时会预占可用余额,并将剩余金额带到加密货币收银台;支付失败或超时后原路释放预占。套餐页的可选套餐下方会分页展示充值、消费账务流水以及待处理、已完成或已拒绝的提现申请,并标明状态。
- 实付余额和赠金余额都可以申请 USDT 提现。收款地址可从当前商户已启用、网络匹配且支持 USDT 的钱包中选择,也可自定义输入。手续费由后端按所选网络的实时快速费率加 20% 波动余量计价,提交时重新计算,并与提现金额一起冻结、从赠金开始扣减。后端不会自动发起链上转账;人工转账完成或拒绝后,由运维机器人按钮完成扣账或按原余额类型退回。
- Pro 和 Ultra 等付费定期套餐可按商户分别开启余额自动续费。套餐到期后系统会从共享账号余额扣除该商户下一周期费用;余额不足时不会扣款,该商户套餐按过期处理。
- 用多少付多少按商户独立启用。该商户的订单和钱包地址从第一笔用量开始按对应单价从共享账号余额扣费;不会为其他商户自动开通。 关闭用多少付多少开关后,当前商户立即恢复 Free 权益,不扣款、不创建套餐订单,也不影响其他商户。重复关闭不会重复处理。没有 Free 生产资格的商户将无法新建生产收款订单或 Checkout。
- 支付 Webhook 回调用于订单状态同步,不计入外部提醒通知额度。
- 支付人工通知和钱包监控 Webhook 不限次数。只有钱包监控人工渠道按目标首次成功投递才消耗账号监控额度或产生对应 PAYG 费用;投递失败、站内信及系统通知不消耗该额度。
- 套餐订阅即将到期和已到期通知由 PolyPay 使用固定系统文案发送,商户不能在通知模板中自定义修改。
- 自定义域名和 AI Agent 收款是有效订阅能力,Pay-as-you-go 也可使用。套餐过期或未启用订阅后配置会保留但进入冻结状态:不能管理配置,自定义域名会从 PolyPay 的 Cloudflare 路由中移除(用户侧 DNS 记录可保留),x402 verify/settle 会拒绝运行;恢复有效订阅后 PolyPay 会自动重新创建自定义主机名并恢复。
- 套餐开通、手动续费、自动续费结果及到期提醒会发送站内信和账号邮件。到期前 7、3、1 天提醒;若错过扫描,会补发当前提醒阶段。系统先尝试自动续费,再判断是否到期;已续费套餐的旧到期提醒会取消。邮件发送失败会自动重试。
API 接口文档
基础信息
| SDK 兼容 Base URL | https://api.polypay.ai/api/v1/pay/sdk |
| 商户业务 Base URL | https://api.polypay.ai/api/v1/pay |
| 认证方式 | X-API-Key(推荐)或 Bearer Token(兼容) |
| 数据格式 | JSON |
认证方式
商户业务接口同时接受后台登录 JWT 和 API Key。API Key 请求无需传入 Step-Up Ticket;服务端调用时可使用以下任一方式,推荐使用含义明确的 X-API-Key:
| Header | 值 |
|---|---|
X-API-Key | YOUR_API_KEY (推荐) |
Authorization | Bearer YOUR_API_KEY (兼容旧方式) |
Content-Type | application/json |
跳转到托管 Checkout
如果希望由 PolyPay 展示支付方式选择页,不要先调用 /order/add。服务端使用 API Key 调用下面的接口获取 checkout_url,然后把用户重定向到该地址。未传 currency/network 时,系统会立即创建 Method pending 订单并进入支付方式选择页。付款链接本身就是完整的公开付款入口,客户端无需保存 checkout session;页面只允许客户选择 currency/network,金额、商户订单号和回调地址始终从已创建的订单读取。链接使用 /pay/{trade_id},选择或更换支付方式后继续保留同一 trade_id 和 URL。同时传入 currency 和 network 时会跳过选择页。订单过期后可使用同一商户订单号重新获取 checkout_url。选择本位币时,收银台会展示实时 USD 参考汇率和预估支付数量。
POST /order/checkout
curl -X POST https://api.polypay.ai/api/v1/pay/sdk/order/checkout \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{
"mch_order_id": "ORDER_001",
"amount": 10.00,
"notify_url": "https://your-site.com/webhook",
"redirect_url": "https://your-site.com/success",
"locale": "en"
}'响应示例:
{
"code": 0,
"message": "",
"data": {
"checkout_url": "https://checkout.polypay.ai/en/pay/202607311785497228532519443",
"payment_url": "https://checkout.polypay.ai/en/pay/202607311785497228532519443"
}
}创建订单
POST /order/add
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
currency | string | ✅ | 币种 (USDT/USDC/BUSD) |
network | string | ✅ | 网络 (tron/ethereum/bsc/polygon/solana) |
amount | number | ✅ | 金额 |
mch_order_id | string | ❌ | 商户订单号(最长32位,未传则自动生成) |
notify_url | string | ❌ | Webhook 回调地址 |
redirect_url | string | ❌ | 支付完成跳转地址 |
响应参数
| 参数 | 类型 | 说明 |
|---|---|---|
trade_id | string | PolyPay 交易号 |
currency | string | 币种 |
network | string | 区块链网络 |
amount | number | 订单金额 |
actual_amount | number | 实际需支付金额(保留4位小数) |
address | string | 收款钱包地址 |
expiration_time | number | 过期时间戳(秒) |
payment_url | string | 支付页面 URL |
代码示例
curl -X POST https://api.polypay.ai/api/v1/pay/sdk/order/add \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"currency": "USDT",
"network": "tron",
"amount": 100.00,
"mch_order_id": "ORDER_123456",
"notify_url": "https://your-site.com/webhook",
"redirect_url": "https://your-site.com/success"
}'响应示例
{
"code": 0,
"message": "success",
"data": {
"trade_id": "PP202412110001",
"currency": "USDT",
"network": "tron",
"amount": 100.00,
"actual_amount": 100.0001,
"address": "TXxx...xxx",
"expiration_time": 1704067200,
"payment_url": "https://checkout.polypay.ai/status/PP202412110001"
}
}查询订单
POST /order/detail
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
trade_id | string | 二选一 | PolyPay 交易号 |
mch_order_id | string | 二选一 | 商户订单号 |
trade_id 和 mch_order_id 至少传入一个;如果同时传入,优先按 trade_id 查询。
响应示例
curl -X POST https://api.polypay.ai/api/v1/pay/sdk/order/detail \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"trade_id": "PP202412110001"
}'取消订单
POST /order/cancel
当你的平台取消、作废或替换尚未支付的订单时,应同步取消 PolyPay 订单。取消成功会立即释放该订单占用的“收款地址 + 实付金额”,避免后续相同金额订单因为旧占用而调整实付金额(稳定币通常增加 0.01)。接口支持通过 trade_id 或 mch_order_id 定位订单;已经支付或过期的订单不能取消。旧版 /order/cancel-by-trade-id 路径继续保留用于兼容已有接入。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
trade_id | string | 二选一 | PolyPay 交易号 |
mch_order_id | string | 二选一 | 商户订单号 |
至少传入一个订单标识;如果同时传入,优先按 trade_id 取消。
curl -X POST https://api.polypay.ai/api/v1/pay/sdk/order/cancel \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"trade_id": "PP202412110001"
}'Webhook 回调
订单创建以及订单状态变化时,我们会向你配置的 Webhook URL 发送 HTTP POST 请求。
回调载荷示例
{
"order_no": "ORDER_123456",
"status": 2,
"amount": 100.0001,
"currency": "USDT",
"currency_name": "usdt",
"network": "Tron",
"contract_addr": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"hash": "abc123...",
"wallet_address": "TXxx...xxx",
"environment": "production",
"event_id": "evt_xxx"
}network 表示支付链;currency_name 是小写币种名(例如 usdt/usdc);hash 为链上交易哈希。主币或暂未配置合约的币种 contract_addr 为空字符串。
状态类型
| status 值 | 描述 |
|---|---|
1 | 等待支付 |
2 | 支付成功 |
3 | 订单已过期 |
4 | 订单已取消 |
5 | 人工充值(按支付成功处理) |
6 | 链上确认中(商户侧按等待支付处理,不会触发支付成功回调) |
7 | 标记支付(按支付成功处理) |
验证 Webhook v2 签名
Webhook v2 使用 PolyPay 平台 Ed25519 密钥签名,不依赖商户 API Key。服务端必须使用原始请求体,并从平台 JWKS 获取公钥完成验签。
验证流程(服务端)
- 要求 X-Webhook-Signature-Version 为 v2,并读取 Key ID、商户 ID、环境、时间戳、nonce 和 v2 签名请求头。
- 校验商户 ID 和环境与服务端预期值完全一致,并限制时间戳窗口为 300 秒。
- 根据 Key ID 从 /api/v1/pay/public/webhook-jwks 选择 Ed25519 公钥,使用原始请求体验证签名。
- 在 Redis 等共享存储中原子消费 nonce,拒绝重复请求。
- 验签成功后再解析事件,并按 environment 和 event_id 幂等处理。
<?php
use PolyPay\PolyPay;
use PolyPay\WebhookHandler;
use PolyPay\Exception\SignatureException;
$polypay = new PolyPay(getenv('POLYPAY_API_KEY') ?: '');
try {
$event = $polypay
->webhookV2('MCH_YOUR_ID', 'production')
->handle();
$status = WebhookHandler::resolveStatus($event);
if ($status === 'paid') {
handleOrderPaidIdempotently($event);
}
http_response_code(200);
echo 'OK';
} catch (SignatureException $e) {
http_response_code($e->getHttpStatus());
echo 'Unauthorized';
}完整的请求头、签名原文和 Node.js 示例请查看 Webhook 安全指南。
错误码
| 错误码 | 说明 |
|---|---|
0 | 成功 |
10001 | 参数错误 |
10002 | 签名错误 |
10003 | 订单不存在 |
10004 | 商户已禁用 |
10005 | API Key 无效 |
90001 | 服务器内部错误;底层 SQL、网络地址和依赖错误仅记录在服务端日志中 |
安全最佳实践
- 保护 API Key:永远不要在前端代码、Git 仓库或日志中暴露 API Key
- 使用环境变量:将 API Key 存储在环境变量中
- 验证 Webhook 签名:始终验证 Webhook 请求的签名
- 使用 HTTPS:确保你的 Webhook 端点使用 HTTPS
- 实现幂等性:Webhook 可能会重复发送,处理逻辑要保证幂等性