Next.js 启动模板
完整的 Next.js 应用,已预先接入鉴权、定价页和 ChainPay 付款。克隆后 5 分钟即可运行。
快速开始
三步接受加密货币付款 —— 无需区块链知识。
创建付款订单
const response = await fetch("https://chainpay.pro/api/v1/orders", {
method: "POST",
headers: {
"Authorization": "Bearer sk_live_YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
amount: 29.99,
currency: "USDT",
chain: "trc20",
externalId: "order_abc123", // your internal order ID
metadata: { userId: "user_456" } // arbitrary JSON, returned in webhook
})
});
const order = await response.json();
// order.checkoutUrl → redirect user here
// order.payAddress → or show the address directly将用户重定向到收银台
// Server-side redirect
res.redirect(order.checkoutUrl);
// Or client-side
window.location.href = order.checkoutUrl;付款确认后接收 Webhook
{
"event": "payment.completed",
"orderId": "ord_a1b2c3d4e5f6",
"externalId": "order_abc123",
"amount": "29.99",
"netAmount": "29.75", // after 0.8% fee
"currency": "USDT",
"chain": "trc20",
"txHash": "e3b0c44298fc1c149afb...",
"completedAt": "2026-03-22T08:15:00Z",
"metadata": { "userId": "user_456" }
}处理前请先校验 X-ChainPay-Signature 请求头。验证代码见 章节。
鉴权
所有 API 请求都必须以 Bearer token 形式包含你的 API 密钥。
Authorization: Bearer sk_live_YOUR_API_KEYcurl -X POST https://chainpay.pro/api/v1/orders \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 10, "currency": "USDT", "chain": "trc20"}'| 密钥前缀 | 环境 | 区块链 |
|---|---|---|
| sk_live_… | 生产 | 真实交易 |
| sk_test_… | 沙盒 | 不动用真实资金 |
创建订单
https://chainpay.pro/api/v1/orders请求参数
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
| amount | number | 必填 | 以 USD 计的付款金额(例如 29.99)。等值的加密货币金额会按当前市场汇率计算。 |
| currency | string | 必填 | 要收取的加密货币。取值之一:"USDT"、"ETH"、"BTC"、"SOL"。 |
| chain | string | 必填 | 区块链网络。取值之一:"trc20"、"erc20"、"btc"、"sol"。必须与所选 currency 兼容。 |
| externalId | string | 可选 | 你的内部订单标识符。会原样在 Webhook 中返回。每个商户内必须唯一。 |
| metadata | object | 可选 | 任意 JSON 对象(最大 2 KB)。会在该订单的所有 Webhook 中返回 —— 适合传递用户 ID、购物车引用等。 |
支持的 currency + chain 组合
| currency | chain | 网络 | 平均确认时间 |
|---|---|---|---|
| USDT | trc20 | TRON (TRC-20) | 约 1 分钟 |
| USDT | erc20 | Ethereum (ERC-20) | 约 2 分钟 |
| ETH | erc20 | Ethereum | 约 2 分钟 |
| BTC | btc | Bitcoin | 约 30 分钟 |
| SOL | sol | Solana | <5 秒 |
响应
{
"orderId": "ord_a1b2c3d4e5f6g7h8",
"payAddress": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"cryptoAmount": "29.99",
"currency": "USDT",
"chain": "trc20",
"checkoutUrl": "https://chainpay.pro/pay/ord_a1b2c3d4",
"expiresAt": "2026-03-22T09:00:00Z",
"createdAt": "2026-03-22T08:30:00Z"
}收银流程
托管收银页的工作方式。
- 1重定向 — 你的服务器将用户重定向到创建订单时返回的 checkoutUrl。
- 2收银页 — 托管页面会展示二维码和钱包地址,并预填精确的加密货币金额。用户扫描二维码或将地址复制到钱包应用中。
- 3确认 — ChainPay 会监控区块链。一旦达到所需的确认数,订单状态将变为 confirming,随后变为 completed。
- 4重定向返回 — 收银页会显示成功界面。如果你在 dashboard 中配置了 successUrl,用户会被自动重定向到那里。
- 5Webhook — 你的服务器会收到 payment.completed Webhook。请在校验 Webhook 签名后再履行订单。
expired,并发送 payment.expired Webhook。请创建新订单重试。Webhook
当订单状态变化时,ChainPay 会向你的 Webhook URL 发送带签名的 HTTP POST 请求。
配置
进入 Dashboard → Apps → New App
填写你的 Webhook URL(例如 https://yourapp.com/api/webhooks/chainpay)
复制生成的 Webhook Secret —— 用于校验签名
Webhook 事件
当前支持的事件:
| 事件 | 触发时机 |
|---|---|
| payment.completed | 订单已付款并在链上确认 |
| payment.expired | 订单未付款而过期 |
负载格式
{
"event": "payment.completed",
"orderId": "ord_xxxxxxxx",
"amount": "9.99",
"currency": "USDT",
"chain": "trc20",
"txHash": "abc123...",
"netAmount": "9.92",
"completedAt": "2026-01-01T00:00:00.000Z",
"metadata": {
"userId": "your-user-id",
"plan": "monthly"
}
}签名校验
每个 Webhook 请求都包含一个 X-ChainPay-Signature 请求头。请使用 HMAC-SHA256 和你的 App 的 Webhook Secret 进行校验:
import crypto from 'crypto'
function verifyWebhook(rawBody: string, signature: string, secret: string): boolean {
const computed = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(computed),
Buffer.from(signature)
)
}
// In your webhook handler:
export async function POST(req: Request) {
const rawBody = await req.text()
const signature = req.headers.get('x-chainpay-signature') ?? ''
if (!verifyWebhook(rawBody, signature, process.env.CHAINPAY_WEBHOOK_SECRET!)) {
return new Response('Unauthorized', { status: 401 })
}
const event = JSON.parse(rawBody)
if (event.event === 'payment.completed') {
const { userId, plan } = event.metadata
// activate user's plan
}
return new Response('OK')
}import hmac, hashlib
def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
computed = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(computed, signature)测试你的 Webhook
进入 Dashboard → Apps → 选择你的 App
点击 “Send Test Event”
确认你的服务器已收到请求(预期 HTTP 200)
重试策略
失败的投递会以指数退避重试:1 分钟 → 5 分钟 → 30 分钟 → 2 小时 → 24 小时(共 5 次尝试)。
5 次尝试均失败后,该 Webhook 将被标记为失败。可在 Dashboard → Alerts 中查看失败的投递。
最佳实践
- 处理前务必先校验签名
- 尽快返回 HTTP 200 —— 繁重处理请异步执行
- 使用
orderId对事件去重(Webhook 可能会被投递多次) - 在解析前保存原始请求体,以确保签名校验准确
查询订单
https://chainpay.pro/api/v1/orders/:id{
"id": "ord_a1b2c3d4e5f6g7h8",
"amount": "29.99",
"cryptoAmount":"29.99",
"netAmount": "29.75",
"currency": "USDT",
"chain": "trc20",
"status": "completed",
"payAddress": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"txHash": "e3b0c44298fc1c149afbf4c8996fb92...",
"externalId": "order_abc123",
"metadata": { "userId": "user_456" },
"createdAt": "2026-03-22T08:30:00Z",
"expiresAt": "2026-03-22T09:00:00Z",
"completedAt": "2026-03-22T08:45:00Z"
}订单状态取值
| 状态 | 描述 |
|---|---|
| pending | 订单已创建,等待用户付款。 |
| confirming | 已在链上检测到交易,等待足够的区块确认。 |
| completed | 付款已完全确认。可以安全履行订单。 |
| expired | 已过 30 分钟仍未检测到付款。 |
| failed | 发生意外错误。请凭 orderId 联系客服。 |
汇率 API
获取当前 USD 汇率。无需 API 密钥。
https://chainpay.pro/api/v1/rates{
"USDT": 1.0,
"ETH": 3450.00,
"BTC": 87500.00,
"SOL": 145.00,
"updatedAt": "2026-03-22T08:00:00Z"
}汇率每 60 秒从聚合市场数据更新一次。你传给创建订单接口的 amount 始终按 USD 解释;API 会在订单创建时按当时汇率换算为加密货币。
沙盒模式
在不动用真实资金的情况下测试完整集成。
在注册时附加 ?mode=test 即可获得 sk_test_ API 密钥。所有标准接口在沙盒模式下表现完全一致 —— 跳过区块链轮询,由你手动触发确认。
步骤 1 —— 获取沙盒 API 密钥
curl -X POST "https://chainpay.pro/api/auth/register?mode=test" \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "yourpassword"}'
# Response includes:
# { "merchant": { "apiKey": "sk_test_xxxxxxxxxxxxxxxx" } }步骤 2 —— 使用测试密钥创建订单
curl -X POST https://chainpay.pro/api/v1/orders \
-H "Authorization: Bearer sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 10, "currency": "USDT", "chain": "trc20", "externalId": "test_order_1"}'步骤 3 —— 模拟一笔付款
curl -X POST https://chainpay.pro/api/v1/sandbox/simulate-payment \
-H "Authorization: Bearer sk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"orderId": "ord_abc123"}'
# Response:
{
"success": true,
"orderId": "ord_abc123",
"txHash": "sandbox_ord_abc123_1711000000000",
"netAmount": "9.92000000"
}
# The order status is now "completed" and your webhook is fired.sandbox_ 为前缀。simulate-payment 接口仅对 sk_test_ 密钥可用。使用正式密钥调用将返回 403。错误码
所有错误响应都使用统一的 JSON 结构:
{
"error": "INVALID_CHAIN",
"message": "chain 'foo' is not supported for currency USDT",
"status": 400
}| HTTP 状态 | 常见错误码 | 原因与解决 |
|---|---|---|
| 400 | INVALID_AMOUNT, INVALID_CURRENCY, INVALID_CHAIN, MISSING_FIELD | 请求体格式错误或缺少必填字段。请检查上方的请求参数表。 |
| 401 | UNAUTHORIZED, INVALID_API_KEY | 缺少或无效的 Authorization 请求头。请确保发送的是 Bearer <key>。 |
| 403 | FORBIDDEN, SANDBOX_ONLY | API 密钥没有执行该操作的权限(例如用正式密钥调用 simulate-payment)。 |
| 404 | ORDER_NOT_FOUND | 不存在该 ID 的订单,或该订单不属于你的商户账号。 |
| 429 | RATE_LIMITED | 请求过多。默认限制为每个 API 密钥 60 req/min。请退避,并在 Retry-After 头指定的时间后重试。 |
| 500 | INTERNAL_ERROR | 意外的服务端错误。请以指数退避重试。如持续出现,请凭 request ID 联系客服。 |
结算
ChainPay 如何以及何时将收取的资金发送到你的钱包。
结算会将所有已完成、未结算的金额发送到你在 dashboard 的 Settings → Settlement Wallets 中配置的钱包地址。你可以为每种货币配置不同的收款地址。
netAmount 已反映扣费后的金额。结算会转账当日所有 netAmount 的总和。准备好集成了吗?
创建账号,几秒内获取你的 API 密钥。