跳到主要内容

订单履约

在用户完成支付后,您的系统需要接收确认信号并交付商品或服务(即“履约”)。

由于区块链交易的异步特性,前端的跳转(Redirect)并不能作为支付成功的最终依据。Webhook 是确认支付状态并进行订单履约的唯一权威方式。

履约流程概览

GStable 的结算速度极快(通常在 30-40 秒内),因此我们建议采用以下标准的履约逻辑:

  1. 监听 Webhook:在您的服务器上配置一个端点接收 POST 请求。
  2. 验证签名:确保请求来自 GStable,防止伪造。
  3. 检查状态:根据事件类型(paidcompleted)决定履约时机。
  4. 执行业务逻辑:在数据库中更新订单状态、发送邮件或发放权益。

核心事件状态

在 Checkout 流程中,您主要需要关注 session 相关的生命周期事件。

1. 支付成功 (session.paid)

  • 触发时机:用户已在链上完成转账,且交易已被区块链确认。
  • 资金状态:资金已从用户钱包转出,正在进行跨链路由或归集。
  • 建议动作
    • 锁定库存:防止超卖。
    • 即时交付:对于低风险的数字商品(如游戏道具、电子书),可在此阶段提前履约,无需等待资金最终入账。

2. 结算完成 (session.completed)

  • 触发时机:资金已成功到达商户配置的收款钱包地址。
  • 资金状态落袋为安。交易流程彻底结束。
  • 建议动作
    • 高价值履约:对于发货实物、大额充值等场景,建议等待此事件。
    • 财务对账:将此作为收入确认的依据。
结算速度

得益于我们的无资金池全链支付架构,从 session.paidsession.completed 通常仅需 30 至 40 秒


Webhook 数据结构

当事件触发时,您的服务器将收到包含以下 JSON 结构的 POST 请求。

Payload 中的数据结构与 查询支付会话 接口返回的数据完全一致。

示例:结算完成事件 (session.completed)

{
"eventId": "evt_i4NWz4J3QkWugyq1",
"eventType": "session.completed",
"businessType": "session",
"occurrence": "2026-01-04 02:52:38",
"isSubscribable": true,
"payload": {
// --- 会话详情 (对应 API 响应中的 session 对象) ---
"sessionData": {
"sessionId": "sess_example_payment_01",
"sessionType": "chk",
"businessId": "",
"businessType": "",
"clientCode": "clt_l8ZBnpOSV9pVlaLK0dP5jsq5NzfqN3Vc",
"payer": "0xUserWalletAddress...", // 付款人钱包地址
"payerEmail": "user@example.com",
"payerEmailRequired": 1,
"paidToken": "0xTokenAddress...", // 用户实际支付的代币合约
"receiptId": "rcpt_txUdSs2ASditQhrr",
"recipient": "0xMerchantWalletAddress...",
"settlementToken": "polygon::usdc",
"feeModel": 1,
"amount": 15000000, // 订单金额 (Micro-USD)
"lineItems": {
"items": [
{
"lineItemId": "li_example_item_03",
"itemType": "product",
"quantity": 1,
"unitPrice": 10000000,
"productData": { "productName": "高级会员" }
}
// ...
]
},
"expirationTime": 1767343946,
"successUrl": "https://yoursite.com/order/success",
"paymentUrl": "https://pay.gstable.io/checkout/sess_...",
"signedOnce": 1,
"initiateTx": "0xSourceTxHash...",
"completeTx": "0xTargetTxHash...",
"paymentSucceededTime": "2025-12-25 07:26:35",
"settlementSucceededTime": "2025-12-25 07:27:10",
"createAt": "2026-01-02 07:52:26",
"status": "completed",
"metadata": {
"internalOrderId": "ord_8823_xyz"
}
},
// --- 交易详情 (对应 API 响应中的 transaction 对象) ---
"transaction": {
"orderId": "0x8a7f...",
"channelId": "da1e3483",
"orderType": 7106155,
"from": "0xUserWalletAddress...",
"to": "0xPlatformContractAddress...",
"metaData": "0x",
"totalValue": 15000000, // 用户支付总额
"paymentValue": 15000000, // 订单面额
"feeValue": 30000, // 手续费 (Micro-USD)
"netValue": 14970000, // 商户实收净额 (Micro-USD)
"sourceTx": "0xSourceTxHash...",
"targetTx": "0xTargetTxHash...",
"executeTime": "2025-12-25 07:26:35",
"finalizeTime": "2025-12-25 07:26:35"
}
}
}

关键字段解析

  • eventId: 事件的全局唯一标识符。建议用于幂等性处理(即如果收到相同的 eventId,则忽略处理,防止重复发货)。
  • payload.sessionData.metadata: 您在创建 Session 时传入的自定义数据。这是将 Webhook 通知与您本地数据库中的订单(internalOrderId)进行关联的关键。
  • payload.transaction.netValue: 商户实际到账金额(Micro-USD)。财务对账时请以此字段为准。

安全与处理

为了确保资金安全,您必须在服务器端验证所有 Webhook 请求的签名。

1. 验证签名

GStable 会在请求 Header 中包含 x-gstable-signature。您需要使用 Dashboard 中获取的 Signing Secret 计算 HMAC-SHA256 签名并进行比对。

2. 幂等性处理

网络波动可能导致 Webhook 重试。请务必记录已处理过的 eventId

伪代码示例:处理履约
app.post('/webhook', (req, res) => {
// 1. 验证签名 (参考 Webhook 开发文档)
verifySignature(req);

const event = req.body;

// 2. 幂等性检查
if (isEventProcessed(event.eventId)) {
return res.send({ received: true });
}

// 3. 处理业务逻辑
if (event.eventType === 'session.completed') {
const session = event.payload.sessionData;
const transaction = event.payload.transaction;

const orderId = session.metadata.internalOrderId;
const receivedAmount = transaction.netValue; // 实收金额

// 执行履约:更新数据库,发货
fulfillOrder(orderId, receivedAmount);
}

// 4. 记录事件已处理
recordEvent(event.eventId);

res.send({ received: true });
});
开发指南

关于详细的验签代码实现(Node.js, Python, Go 等)以及完整的事件类型列表,请参阅专门的 Webhook 开发文档。


总结

至此,您已经完成了 Checkout 的集成!

  1. 您通过 API 创建了支付会话。
  2. 用户在托管页面完成了支付。
  3. 您的服务器通过 Webhook 确认了收款并完成了订单履约。

现在,您可以前往 Dashboard 查看交易数据,或继续探索更多高级功能。