跳到主要内容

订阅快速入门

流程概览


1. 概述

订阅(Subscription):UtcPay 的订阅是商户在管理后台预先创建「订阅方案」,再通过接口为用户生成专属订阅链接,用户跳转后通过钱包完成签约和授权,商户通过签名机按方案设定的周期主动发起扣款,并在每次事件触发时回调商户。

流程: 👉 管理员后台 创建订阅方案 → 商户调用 createSubscribeOrder → 拼接订阅页面 URL → 用户跳转完成签约和授权 → 商户定时调用 查询待扣款订阅 + 签名机扣款 → 触发各类 订阅回调 → 商户处理。

注意:接口调用环节需要签名


2. 前提条件

  • 开通商户账号:沙盒注册地址

  • 获取 API Key / Secret:获取 API Key / Secret

  • 需要配置 回调地址 (notifyUrl)跳转地址 (redirectionUrl)

  • 已在管理后台创建订阅方案(详见下方步骤 4)

  • 已部署签名机服务(用于自动扣款,详见下方步骤 8)

  • 确认使用的网络:

    • 沙盒环境:https://api-sandbox.utcpay.com/api/mer
    • 生产环境:https://api.utcpay.com/api/mer

3. API 签名认证

所有请求需要在 Header 中添加:

Header说明
X-PAY-KEY商户 API Key
X-PAY-TIMESTAMP当前 Unix 时间戳(单位秒,误差 ≤ 60 秒)
X-PAY-SIGN签名,规则请看下面「签名生成规则」

🔹 签名生成规则

参考官方文档:签名规则

  1. 拼接字符串
signString = timestamp + method + requestPath + body
  • timestamp:请求的 Unix 时间戳(秒)
  • method:HTTP 方法,例如 GETPOST
  • requestPath:接口路径,不含域名,例如 /api/mer/subscribe/payment/create
  • body:POST 请求的 JSON 字符串,GET 请求为空字符串
  1. 使用 HMAC-SHA256 算法
HMAC_SHA256(apiSecret, signString)
  1. Base64 编码

    将上一步得到的哈希值进行 Base64 编码,得到最终的 X-PAY-SIGN

🔹 请求头示例(HTTPS)

POST /api/mer/subscribe/payment/create
Host: api-sandbox.utcpay.com
Content-Type: application/json
X-PAY-KEY: <your_api_key>
X-PAY-TIMESTAMP: 1723971200
X-PAY-SIGN: <生成的签名>

🔹 注意事项

  1. 所有 POST 请求需带 Content-Type: application/json
  2. timestamp 与服务器时间差值不能超过 60 秒,防止重放攻击
  3. body 必须是有效 JSON,否则签名验证会失败

4. 创建订阅方案(管理员后台)

订阅方案需要在管理后台预先创建,方案上链后商户才能调用接口生成订阅链接。

💡 订阅方案需要多签审批后才会上链生效,请确保至少有两个管理员账号。

🔹 步骤 1:登录管理员后台

登录后右上角可确认当前链和钱包地址。

🔹 步骤 2:进入订阅方案

顶部导航:支付工具 → 订阅方案

订阅方案页面

🔹 步骤 3:创建订阅方案

点击「增加」按钮,填写方案参数后点击「提交」。 钱包弹出 Signature request,确认参数无误后点击 Confirm 完成第一签。

增加方案

信息

方案 ID 需要商户自己填写,必须保证在商户侧唯一且不变(只能使用数字 ID)。后续接口调用需要用到该方案 ID。

🔹 步骤 4:多签审批

切换到 另一个管理员账号 登录后台,进入 支付工具 → 订阅方案 列表,对该方案发起审批,钱包再次签名确认。

多签审批

注意

多签审批通过后,方案参数才会真正上链生效。审批前方案处于待审批状态,无法被使用。

🔹 步骤 5:创建成功

多签通过后,方案状态变为「正常」,可被商户用于创建订阅链接。记录方案 ID,后续接口调用需要用到。

多签成功


5. 创建订阅链接(createSubscribeOrder)

createSubscribeOrder 接口文档

请求体参数说明

参数类型必填说明
chainIdint32平台内部链 ID,可从查询链列表接口获取
planIdint64订阅方案 ID
externalUserIdstring商户侧用户标识
redirectionUrluri用户订阅成功后的跳转地址
notifyUrluri商户回调地址,必须为公网可访问 HTTPS 地址

请求示例

POST /api/mer/subscribe/payment/create
Host: api-sandbox.utcpay.com
Content-Type: application/json
X-PAY-KEY: your_api_key
X-PAY-TIMESTAMP: 1723971200
X-PAY-SIGN: RlpTCwGT7lECP7achGM4oqT+Y5fXYjOqTRAJ9VPdY2U=

请求体示例

{
"chainId": 1,
"planId": 3,
"externalUserId": "USER10001",
"redirectionUrl": "https://merchant.com/subscribe-success",
"notifyUrl": "https://merchant.com/api/subscription-callback"
}

响应示例

{
"code": 200,
"msg": "操作成功",
"data": {
"subscriptionId": 123,
"paymentUrl": "/subscription?apiSign=CSetiUau5zInfAZukEGsSfelBSmlVB3XVh5t7Ozoits%3D",
"expiration": 1723974800
}
}

说明:

  • paymentUrl → 订阅页面路径,需要拼接官方域名才能访问
  • subscriptionId → UtcPay 订阅订单号(保存以便查询)
  • expiration → 链接过期时间戳

💡 订阅之前不需要预先为用户创建子合约地址,用户在订阅页面连接钱包即可完成签约。externalUserId 仅作为商户侧的用户标识。

🔹 拼接订阅页面 URL

返回的 paymentUrl 是相对路径,必须拼接 UtcPay 官方域名才能访问:

  • 正式环境: https://payment.utcpay.com + paymentUrl
  • 沙盒环境: https://payment-sandbox.utcpay.com + paymentUrl

例如: https://payment.utcpay.com/subscription?apiSign=CSetiUau5zInfAZukEGsSfelBSmlVB3XVh5t7Ozoits%3D

注意

请勿直接使用返回的 paymentUrl,必须拼接官方域名以避免误用或安全风险。

🔹 集成到商户平台

将拼接好的 URL 加到商户自己的订阅平台,例如增加一个「USDT 支付」按钮跳转到该链接:

<a href="https://payment.utcpay.com/subscription?apiSign=...">
USDT 支付
</a>

用户点击后跳转到 UtcPay 订阅页面,完成 确认方案 → 签约 → 授权额度 三步流程。

用户订阅

注意

💡 在沙盒环境中,您可以领取测试代币用于模拟订阅交易:

  1. 参考测试币领取教程
  2. 根据当前选择的链(Tron Nile 或 Ethereum Sepolia),打开对应的官方水龙头网站。
  3. 输入您的测试钱包地址,领取测试代币(USDT、ETH、TRX 等)。
  4. 使用领取的测试代币,通过生成的 paymentUrl 进行订阅,完成订阅流程的测试。

提示:所有测试网代币仅可用于沙盒测试环境,不具备实际价值。

提示:测试网和主网是完全独立的区块链网络,切勿将主网资产发送到测试网地址,反之亦然。


6. 订阅回调(subscriptionCallback)

subscriptionCallback 接口文档

UtcPay 会异步 POST 到 notifyUrl,商户收到后需:

  1. 校验 sign 签名是否合法
  2. 根据 subscriptionType 处理对应业务逻辑
  3. 返回 HTTP 200 并响应 success 确认

🔹 回调类型说明

通过 subscriptionType 字段区分回调类型:

subscriptionType触发时机商户处理建议
SubscriptionRegister用户在订阅页面完成签约记录订阅关系,标记用户已签约
SubscriptionApprove用户完成钱包授权扣款额度标记授权状态,订阅生效
SubscriptionBilling每次周期扣款完成(含首期)更新用户订阅有效期,发放权益
SubscriptionCancel用户主动退订标记订阅已取消,停止后续服务

🔹 回调示例

{
"subscriptionType": "SubscriptionBilling",
"outTradeNo": "SUB202508191519455758358",
"externalUserId": "USER10001",
"planId": 3,
"planVersion": 1,
"chainId": 1,
"userWallet": "0xF631...90A9",
"amount": "1000000",
"currencySymbol": "USDT",
"transferHash": "0x928b3243...",
"blockTime": 1712122830,
"createTime": "2025-08-19 15:19:45"
}

🔹 重试策略

回调最多发送 6 次,分别在事件确认后的 0 秒、15 秒、30 秒、3 分钟、5 分钟、10 分钟 时发送。

当商户正常返回 success 时,系统会认为回调成功,不再发送后续回调。

📌 商户需要验证回调通知的签名,确保通知的安全性,回调的加签方式与普通请求一致。


7. 自动扣费流程

订阅创建成功且用户完成授权后,商户需要 主动调用扣款流程 触发周期性扣费。整体分两步:查询待扣款订阅 → 调用签名机扣款。签名机内部会自动广播交易上链,商户无需手动处理。

💡 调用频率由商户自定,按业务实际需要触发即可(例如每小时、每日定时任务)。

🔹 流程概览

商户定时任务

1. getChargeableSubscriptionList 查询待扣款订阅

2. signProcessSubscribePlan 调用签名机扣款(按链区分 EVM/TVM)

成功 → 签名机自动广播上链 → SubscriptionBilling 回调(成功)
失败 → 返回失败原因 → SubscriptionBilling 回调(失败)

🔹 查询待扣款订阅列表

getChargeableSubscriptionList 接口文档

商户定时调用此接口,获取需要扣款的订阅列表。

GET /api/mer/subscribe/chargeable/list?page=1&size=20
Host: api-sandbox.utcpay.com
X-PAY-KEY: your_api_key
X-PAY-TIMESTAMP: 1723971200
X-PAY-SIGN: <生成的签名>

返回的列表中每条订阅都包含 subscribeId 和必要的链上信息,作为下一步调用签名机的输入。

🔹 调用签名机进行扣款

注意

签名机需要按链区分调用接口:

  • EVM 链(ETH): POST /PayTool/EVM/subscribe/signProcessSubscribePlan
  • TVM 链(TRON): POST /PayTool/TVM/subscribe/signProcessSubscribePlan

接口文档:

将查询到的待扣款订阅信息传入签名机,签名机会完成 签名 + 自动广播 整个流程。

🔹 扣款响应说明

✅ 扣款成功(code = 1)

{
"code": 1,
"msg": "SUCCESS",
"data": {
"address": "0xf0d2db2740ca0cd94e76c1af85fc9e5ef88ee011",
"chainId": 139,
"gasRequired": "117803",
"signedTransactionData": "0xf8cc3983e441a88301cc2b943e8d3c579817fa235901096c64107c8c8867554f80b86452429e7f...",
"subscriptionIds": [49],
"txHash": "0xe222a81f39b38cc50a14a3539086066bcf4d0a2582dc5a81abab27ef158f4ed9"
},
"description": null
}

字段说明:

  • signedTransactionData → 已签名的交易数据(签名机内部自动广播,无需商户手动处理)
  • subscriptionIds → 本次扣款覆盖的订阅 ID 列表
  • txHash → 链上交易哈希(可用于后续追踪和对账)
  • gasRequired → 此次交易消耗的 Gas

扣款成功后等待 UtcPay 触发 SubscriptionBilling 回调即可。

❌ 扣款失败(code = 2)

{
"code": 2,
"msg": "SUCCESS",
"data": [
{
"amount": 8000000,
"failReason": "Allowance insufficient",
"planId": 6,
"subscribeId": 44,
"tokenAllowance": "0",
"tokenBalance": "944000000",
"userHash": "0xde1469a7d688f10c46f3a25f12c23bce48dfc52f999031664cca22df931a4382"
}
],
"description": null
}

返回数组列出每个无法扣款的订阅及具体原因。常见 failReason

failReason说明商户处理建议
Allowance insufficient用户授权额度不足引导用户重新授权或退订
Balance insufficient用户钱包余额不足通知用户补充余额或停止服务

无论扣款成功还是失败,UtcPay 都会发送 subscriptionType=SubscriptionBilling 的回调到商户的 notifyUrl,商户需要据此 更新订阅状态、发放服务或停止权益。回调的处理逻辑参见上文章节 6 订阅回调。


8. 部署签名机

签名机部署文档

签名机是用于 安全管理私钥并签名链上交易 的服务,由商户自行部署运行。订阅自动扣款依赖签名机完成签名和广播。

注意

签名机需要在调用扣款流程前预先部署完成并正常运行。

部署完成后,签名机会暴露 HTTP 接口供商户调用:

  • 签名 EVM 订阅扣款:POST /PayTool/EVM/subscribe/signProcessSubscribePlan
  • 签名 TVM 订阅扣款:POST /PayTool/TVM/subscribe/signProcessSubscribePlan

完整签名机接口列表参见:签名机 API 参考


9. 创建退订链接(createUnsubscribeOrder)

createUnsubscribeOrder 接口文档

请求体参数说明

参数类型必填说明
outTradeNostringUtcPay 订阅订单号
redirectionUrluri用户退订成功后的跳转地址
notifyUrluri商户回调地址,必须为公网可访问 HTTPS 地址

请求示例

POST /api/mer/subscribe/cancel/create
Host: api-sandbox.utcpay.com
Content-Type: application/json
X-PAY-KEY: your_api_key
X-PAY-TIMESTAMP: 1723971200
X-PAY-SIGN: <生成的签名>

请求体示例

{
"outTradeNo": "SUB202508191519455758358",
"redirectionUrl": "https://merchant.com/unsubscribe-success",
"notifyUrl": "https://merchant.com/api/subscription-callback"
}

响应示例

{
"code": 200,
"msg": "操作成功",
"data": {
"paymentUrl": "/unsubscription?apiSign=...",
"expiration": 1723974800
}
}

退订链接的拼接规则与订阅链接一致:

  • 正式环境: https://payment.utcpay.com + paymentUrl
  • 沙盒环境: https://payment-sandbox.utcpay.com + paymentUrl

将拼接好的 URL 提供给用户(例如商户订阅管理页面的「取消订阅」按钮),用户跳转后通过钱包取消授权完成退订。

退订完成后,商户会收到 subscriptionType=SubscriptionCancel 的回调通知。


10. 查询订阅信息


✅ 至此,你就完成了 订阅完整流程