跳到主要内容

订单端点

通过 HashNut API 创建和管理支付订单。

创建支付订单

创建新的支付订单并返回支付详情,包括支付 URL。

端点POST /api/v3.0.0/pay/createPayOrderOnSplitWalletWithApiKey

请求

请求头

hashnut-request-uuid: <uuid>
hashnut-request-timestamp: <timestamp>
hashnut-request-sign: <signature>
Content-Type: application/json

请求体

{
"accessKeyId": "string",
"merchantOrderId": "string",
"chainCode": "string",
"coinCode": "string",
"amount": 0.01,
"callBackUrl": "string",
"frontendCallbackUrl": "string",
"receiptAddress": "string",
"splitterAddress": "string"
}

请求参数

参数类型必填描述
accessKeyIdstring✅ 是您的商户访问密钥 ID
merchantOrderIdstring✅ 是唯一商户订单 ID(最多 255 个字符,每个商户必须唯一)
chainCodestring✅ 是链代码。支持的值:"erc20""bsc-erc20""polygon-erc20""tron-trc20"
coinCodestring✅ 是货币代码(例如,"usdt""usdc""MockUSDT")- 区分大小写
amountdecimal✅ 是基础单位的支付金额(例如,0.01 表示 0.01 USDT)。最小值:0.01。四舍五入到 2 位小数。
callBackUrlstring⚠️ 可选用于支付状态更新的后端 webhook URL
frontendCallbackUrlstring⚠️ 可选支付完成后的前端重定向 URL
receiptAddressstring⚠️ 可选自定义商户接收地址。必须匹配格式:EVM (0x...) 或 TRON (T...)。如果未提供,则使用账户的默认地址。
splitterAddressstring⚠️ 可选分账合约地址(用于接收支付的智能合约)。必须是 EVM 格式 (0x...)。

响应

成功响应(200 OK):

{
"code": 0,
"msg": "success",
"data": {
"payOrderId": "01KBZ292SK2GKFK97916F5EC3B",
"accessSign": "D3DE7E4002057C0EAED1BE2268DA53CC9058DCFC9DCAF50D999AF270A7B033C5",
"merchantOrderId": "e30ff306-5552-497d-9083-fd6e943dfd73"
}
}

响应字段

字段类型描述
payOrderIdstringHashNut 平台订单 ID(唯一标识符)
accessSignstring用于查询订单状态的访问签名
merchantOrderIdstring商户订单 ID 的回显

支付 URL 构造

收到响应后,构造支付 URL:

https://testnet.hashnut.io/pay?accessSign={accessSign}&merchantOrderId={merchantOrderId}&payOrderId={payOrderId}&chainCode={chainCode}

示例

https://testnet.hashnut.io/pay?accessSign=D3DE7E4002057C0EAED1BE2268DA53CC9058DCFC9DCAF50D999AF270A7B033C5&merchantOrderId=e30ff306-5552-497d-9083-fd6e943dfd73&payOrderId=01KBZ292SK2GKFK97916F5EC3B&chainCode=erc20

错误响应

签名无效(401):

{
"code": -2,
"msg": "Invalid signature or credentials",
"data": null
}

参数无效(400):

{
"code": -2,
"msg": "Invalid parameters",
"data": null
}

常见错误

  • -2:认证/签名错误、凭据无效或缺少必需字段
  • 其他代码:参见错误代码

代码示例

const response = await fetch(
'https://testnet.hashnut.io/api/v3.0.0/pay/createPayOrderOnSplitWalletWithApiKey',
{
method: 'POST',
headers: {
'hashnut-request-uuid': uuid,
'hashnut-request-timestamp': timestamp,
'hashnut-request-sign': signature,
'Content-Type': 'application/json'
},
body: JSON.stringify({
accessKeyId: 'YOUR_ACCESS_KEY_ID',
merchantOrderId: `order-${Date.now()}`,
chainCode: 'erc20',
coinCode: 'usdt',
amount: 0.01,
callBackUrl: 'https://your-site.com/webhook',
frontendCallbackUrl: 'https://your-site.com/payment/success'
})
}
);

const result = await response.json();
if (result.code === 0) {
const paymentUrl = `https://testnet.hashnut.io/pay?accessSign=${result.data.accessSign}&merchantOrderId=${result.data.merchantOrderId}&payOrderId=${result.data.payOrderId}&chainCode=erc20`;
console.log('Payment URL:', paymentUrl);
}

查询支付订单状态

使用访问签名查询支付订单的当前状态。

端点POST /api/v3.0.0/pay/queryPayOrderWithAccessSign

请求

请求头

Content-Type: application/json

注意:此端点不需要签名认证(使用 accessSign 代替)。

请求体

{
"merchantOrderId": "string",
"payOrderId": "string",
"accessSign": "string"
}

请求参数

参数类型必填描述
merchantOrderIdstring✅ 是您的商户订单 ID
payOrderIdstring✅ 是HashNut 平台订单 ID
accessSignstring✅ 是来自创建订单响应的访问签名

响应

成功响应(200 OK):

{
"code": 0,
"msg": "success",
"data": {
"merchantAddress": "0x1234...",
"chain": "Ethereum",
"chainCode": "erc20",
"coinCode": "usdt",
"createChannel": 0,
"accessChannel": 0,
"merchantOrderId": "e30ff306-5552-497d-9083-fd6e943dfd73",
"payOrderId": "01KBZ292SK2GKFK97916F5EC3B",
"tokenAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"receiptAddress": "0x5678...",
"amount": 0.01,
"state": 4,
"accessSign": "D3DE7E4002057C0EAED1BE2268DA53CC9058DCFC9DCAF50D999AF270A7B033C5",
"payTxId": "0xabcdef1234567890...",
"confirmCount": "12",
"walletConnectEnable": true,
"bridgeServerAddress": "https://bridge.hashnut.io",
"eip712ChainId": "1",
"chainId": "1",
"callBackUrl": "https://merchant.com/api/payment/webhook",
"createTime": "2024-01-01T00:00:00Z",
"rate": 1.0,
"obtainAmount": 0.01,
"platformFee": 0
}
}

响应字段

字段类型描述
merchantAddressstring商户钱包地址
chainstring链名称(例如,"Ethereum"、"BSC")
chainCodestring链代码(例如,"erc20")
coinCodestring货币代码(例如,"usdt")
merchantOrderIdstring商户订单 ID
payOrderIdstringHashNut 平台订单 ID
tokenAddressstring代币合约地址
receiptAddressstring接收地址
amountdecimal支付金额
stateinteger订单状态(参见订单状态
accessSignstring访问签名
payTxIdstring交易哈希(如果已支付)
confirmCountstring确认数
walletConnectEnableboolean是否启用 WalletConnect
bridgeServerAddressstring桥接服务器地址
eip712ChainIdstringEIP-712 链 ID
chainIdstring链 ID
callBackUrlstringWebhook 回调 URL
createTimestring创建时间戳(ISO 格式)
ratedecimal汇率(如适用)
obtainAmountdecimal商户获得的金额
platformFeedecimal平台费用

订单状态

状态代码描述
未支付0订单已创建,等待支付
未完成1支付已发起但未完成
等待确认2交易已广播,等待确认
确认中3交易已确认,验证支付中
成功4支付完成并已验证
失败-1支付交易失败
已过期-2订单已过期未支付
已取消-3订单已被商户取消

参见订单状态了解详细信息。

代码示例

const response = await fetch(
'https://testnet.hashnut.io/api/v3.0.0/pay/queryPayOrderWithAccessSign',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
merchantOrderId: 'order-123',
payOrderId: '01KBZ292SK2GKFK97916F5EC3B',
accessSign: 'D3DE7E4002057C0EAED1BE2268DA53CC9058DCFC9DCAF50D999AF270A7B033C5'
})
}
);

const result = await response.json();
if (result.code === 0) {
const order = result.data;
console.log('Order State:', order.state);
console.log('Amount:', order.amount);
if (order.state === 4) {
console.log('Payment successful!');
}
}

最佳实践

  1. Webhook 后始终查询:即使收到 webhook,也要查询订单状态以获取最新状态
  2. 处理所有状态:实现对所有订单状态的处理,特别是终端状态(成功、失败、过期、取消)
  3. 轮询:如果不使用 webhook,定期轮询订单状态(但不要太频繁)
  4. 错误处理:在处理数据之前始终检查 response.code === 0
  5. 幂等性:使用 merchantOrderId 确保订单唯一性并防止重复

下一步


准备创建订单? 查看快速开始 →