{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-@l10n/zh/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"7. Webhook（订单与订阅状态回调）","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"7-webhook订单与订阅状态回调","__idx":0},"children":["7. Webhook（订单与订阅状态回调）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Infini 会在订单或订阅状态发生变更时，向商户预先配置的 Webhook 地址发送 HTTP POST 请求，通知最新状态与异常情况，便于商户进行发货、开通服务、库存解锁及客服处理。"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"71-可订阅事件与事件类型","__idx":1},"children":["7.1 可订阅事件与事件类型"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["在商户后台可以配置订阅类型，不同订阅类型对应的事件如下："]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["订单事件："]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["订阅 order.create → 会收到：",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.create"]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["订阅 order.update → 会收到：",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.processing"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.completed"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.expired"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.late_payment"]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["订单事件类型说明："]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.created：订单创建成功，进入待支付状态。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.processing：订单进入处理中（收到部分支付或存在确认中的链上交易）。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.completed：订单金额已满足，订单状态为 paid。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.expired：订单在有效期内未完成支付，已过期。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order.late_payment：订单过期后（24 小时内）收到付款。"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["订阅事件："]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["订阅 subscription.update → 会收到：",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["subscription.update"]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["订阅 subscription.cancel → 会收到：",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["subscription.cancel"]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["订阅事件类型说明："]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["subscription.update：订阅状态更新（如首次支付完成后激活、续费支付成功后计费周期更新）。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["subscription.cancel：订阅已取消（商户 API 取消、用户退订、或系统因未支付自动取消）。"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"711-测试工具","__idx":2},"children":["7.1.1 测试工具"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["如果你只是想检查事件是否有被触发以及真实的webhook字段，你可以使用 ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://webhook.cool/"},"children":["Webhook Cool"]}," 这个测试工具，它会提供给你一个唯一的 WEBHOOK URL 来接收这些事件。"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"72-webhook-payload-字段说明","__idx":3},"children":["7.2 Webhook Payload 字段说明"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"订单-webhook-payload-字段","__idx":4},"children":["订单 Webhook Payload 字段"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Webhook 请求的 body 为 JSON 格式，字段包括："]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["event：事件类型（如 order.create）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["order_id：订单唯一标识"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["client_reference：商户侧订单号（即 client_reference）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["amount：订单应付金额（法币金额）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["currency：订单币种（如 USD）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["status：订单状态：",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["pending"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["processing"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["paid"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["partial_paid"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["expired"]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["amount_confirming：确认中金额（链上交易存在但尚未达到确认要求）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["amount_confirmed：已确认金额（链上确认完成）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["created_at：订单创建时间（Unix 时间戳，秒）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["updated_at：订单最近一次更新时间（Unix 时间戳，秒）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["exception_tags（如果有）：订单异常标签数组（如 [\"underpaid\", \"late\"]），详见「业务核心概念」章节"]}]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["说明："]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["amount_confirmed + amount_confirming 反映链上已识别到的总支付金额。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["订单状态与是否过期、已确认/确认中金额共同构成订单当前语义。"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"订阅-webhook-payload-字段","__idx":5},"children":["订阅 Webhook Payload 字段"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["订阅 Webhook 请求的 body 为 JSON 格式，字段包括："]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["event：事件类型（",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subscription.update"]}," 或 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subscription.cancel"]},"）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["subscription_id：系统生成的订阅 ID"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["merchant_sub_id：商户自定义订阅 ID"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["plan_name：订阅计划名称"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["trigger_method：扣费触发方式（如 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invoice"]},"）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["status：订阅状态：",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["pending"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["active"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["canceled"]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["currency：订阅币种（如 USD）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["amount：每期扣款金额"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["interval_unit：扣款周期单位（",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DAY"]}," 或 ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MONTH"]},"）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["interval_count：每个扣款周期的间隔数量"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["payer_email：付款人邮箱"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["current_period_start：当前计费周期开始时间（Unix 时间戳，秒）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["current_period_end：当前计费周期结束时间（Unix 时间戳，秒）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["subscription_end_at：订阅终止时间（Unix 时间戳，秒）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["next_invoice_at：下次发送 Invoice 的时间（Unix 时间戳，秒）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["cancel_reason：取消原因（仅订阅被取消时返回）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["canceled_at：取消时间（Unix 时间戳，秒；仅订阅被取消时返回）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["created_at：订阅创建时间（Unix 时间戳，秒）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["updated_at：订阅最近一次更新时间（Unix 时间戳，秒）"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"73-webhook-请求-headers","__idx":6},"children":["7.3 Webhook 请求 Headers"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Infini 在发送 Webhook 时，会附带以下 HTTP Header 用于安全校验与幂等处理："]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Content-Type: application/json"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Timestamp：Unix 时间戳（秒）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Event-Id：事件唯一标识，用于幂等去重"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Signature：HMAC-SHA256 签名，用于商户侧验签"]}]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["建议商户使用 X-Webhook-Event-Id 做幂等处理，避免重复消费同一事件。"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"74-webhook-示例-payload","__idx":7},"children":["7.4 Webhook 示例 Payload"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["以下示例展示典型场景下的 Webhook 内容。"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"741-场景-1订单创建ordercreated","__idx":8},"children":["7.4.1 场景 1：订单创建（order.created）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["订单创建后，状态为 pending，等待用户付款。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"order.create\",\n  \"order_id\": \"10290d05-8f5c-4ecb-84f0-f78d6f30557f\",\n  \"client_reference\": \"\",\n  \"amount\": \"1\",\n  \"currency\": \"USD\",\n  \"status\": \"pending\",\n  \"amount_confirmed\": \"0\",\n  \"amount_confirming\": \"0\",\n  \"created_at\": 1763512195,\n  \"updated_at\": 1763512195\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"742-场景-2订单处理中收到款项在确认中orderprocessing","__idx":9},"children":["7.4.2 场景 2：订单处理中（收到款项在确认中，order.processing）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["收到付款，但交易仍在区块链确认中。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"order.processing\",\n  \"order_id\": \"20290d05-8f5c-4ecb-84f0-f78d6f30557f\",\n  \"client_reference\": \"\",\n  \"amount\": \"1\",\n  \"currency\": \"USD\",\n  \"status\": \"processing\",\n  \"amount_confirmed\": \"0\",\n  \"amount_confirming\": \"0.5\",\n  \"created_at\": 1763512349,\n  \"updated_at\": 1763512403\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"743-场景-3订单处理中收到部分款项已确认orderprocessing","__idx":10},"children":["7.4.3 场景 3：订单处理中（收到部分款项已确认，order.processing）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["部分付款已经在区块链上确认。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"order.processing\",\n  \"order_id\": \"20290d05-8f5c-4ecb-84f0-f78d6f30557f\",\n  \"client_reference\": \"\",\n  \"amount\": \"1\",\n  \"currency\": \"USD\",\n  \"status\": \"processing\",\n  \"amount_confirmed\": \"0.5\",\n  \"amount_confirming\": \"0\",\n  \"created_at\": 1763512349,\n  \"updated_at\": 1763512453\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"744-场景-4订单完成收到完整付款ordercompleted","__idx":11},"children":["7.4.4 场景 4：订单完成（收到完整付款，order.completed）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["收到足额付款并确认，订单完成。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"order.completed\",\n  \"order_id\": \"20290d05-8f5c-4ecb-84f0-f78d6f30557f\",\n  \"client_reference\": \"\",\n  \"amount\": \"1\",\n  \"currency\": \"USD\",\n  \"status\": \"paid\",\n  \"amount_confirmed\": \"1\",\n  \"amount_confirming\": \"0\",\n  \"created_at\": 1763512349,\n  \"updated_at\": 1763512573,\n  \"payments\": [\n    {\n      \"id\": \"pay_9c1e2f3a4b5c\",\n      \"method\": \"crypto_transfer\",\n      \"status\": \"paid\",\n      \"currency\": \"USD\",\n      \"amount\": \"1\",\n      \"network\": \"ETH\",\n      \"tx_hash\": \"0xabc123def456...\",\n      \"paid_amount\": \"1.000000\"\n    }\n  ]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"745-场景-5订单过期完全未付款orderexpired","__idx":12},"children":["7.4.5 场景 5：订单过期（完全未付款，order.expired）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["订单超时未收到任何付款。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"order.expired\",\n  \"order_id\": \"10290d05-8f5c-4ecb-84f0-f78d6f30557f\",\n  \"client_reference\": \"\",\n  \"amount\": \"1\",\n  \"currency\": \"USD\",\n  \"status\": \"expired\",\n  \"amount_confirmed\": \"0\",\n  \"amount_confirming\": \"0\",\n  \"created_at\": 1763512195,\n  \"updated_at\": 1763512255\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"746-场景-6订单过期收到部分款项orderexpired--partial_paid","__idx":13},"children":["7.4.6 场景 6：订单过期（收到部分款项，order.expired + partial_paid）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["订单超时但收到了部分付款，未达到订单金额。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"order.expired\",\n  \"order_id\": \"60290d05-8f5c-4ecb-84f0-f78d6f30557f\",\n  \"client_reference\": \"\",\n  \"amount\": \"1\",\n  \"currency\": \"USD\",\n  \"status\": \"partial_paid\",\n  \"amount_confirmed\": \"0.5\",\n  \"amount_confirming\": \"0\",\n  \"created_at\": 1763514565,\n  \"updated_at\": 1763514765\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"747-场景-7订单过期后收到付款晚到付款orderlate_payment","__idx":14},"children":["7.4.7 场景 7：订单过期后收到付款（晚到付款，order.late_payment）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["订单过期后 24 小时内收到付款。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"order.late_payment\",\n  \"order_id\": \"30290d05-8f5c-4ecb-84f0-f78d6f30557f\",\n  \"client_reference\": \"\",\n  \"amount\": \"1\",\n  \"currency\": \"USD\",\n  \"status\": \"expired\",\n  \"amount_confirmed\": \"1\",\n  \"amount_confirming\": \"0\",\n  \"created_at\": 1763512622,\n  \"updated_at\": 1763512815\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["提示："]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["late_payment 场景下，订单状态仍为 expired，但 amount_confirmed 已达到订单金额，商户可根据业务策略决定是否发货或退款。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["建议结合异常标签（如 late、underpaid、overpaid）进行业务决策。"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"748-场景-8订阅激活subscriptionupdate","__idx":15},"children":["7.4.8 场景 8：订阅激活（subscription.update）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["首次支付完成后，订阅从 pending 状态变为 active。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"subscription.update\",\n  \"subscription_id\": \"sub-9f3c1f2e\",\n  \"merchant_sub_id\": \"msub_001\",\n  \"plan_name\": \"Monthly Plan\",\n  \"trigger_method\": \"invoice\",\n  \"status\": \"active\",\n  \"currency\": \"USD\",\n  \"amount\": \"9.99\",\n  \"interval_unit\": \"MONTH\",\n  \"interval_count\": 1,\n  \"payer_email\": \"user@example.com\",\n  \"current_period_start\": 1740000000,\n  \"current_period_end\": 1742678400,\n  \"next_invoice_at\": 1742592000,\n  \"created_at\": 1740000000,\n  \"updated_at\": 1740000100\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"749-场景-9订阅续费subscriptionupdate","__idx":16},"children":["7.4.9 场景 9：订阅续费（subscription.update）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["续费支付完成后，计费周期更新至下一个周期。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"subscription.update\",\n  \"subscription_id\": \"sub-9f3c1f2e\",\n  \"merchant_sub_id\": \"msub_001\",\n  \"plan_name\": \"Monthly Plan\",\n  \"trigger_method\": \"invoice\",\n  \"status\": \"active\",\n  \"currency\": \"USD\",\n  \"amount\": \"9.99\",\n  \"interval_unit\": \"MONTH\",\n  \"interval_count\": 1,\n  \"payer_email\": \"user@example.com\",\n  \"current_period_start\": 1742678400,\n  \"current_period_end\": 1745356800,\n  \"next_invoice_at\": 1745270400,\n  \"created_at\": 1740000000,\n  \"updated_at\": 1742678500\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"7410-场景-10订阅取消subscriptioncancel","__idx":17},"children":["7.4.10 场景 10：订阅取消（subscription.cancel）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["订阅被商户 API 取消、用户退订、或系统因未支付自动取消。"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"event\": \"subscription.cancel\",\n  \"subscription_id\": \"sub-9f3c1f2e\",\n  \"merchant_sub_id\": \"msub_001\",\n  \"plan_name\": \"Monthly Plan\",\n  \"trigger_method\": \"invoice\",\n  \"status\": \"canceled\",\n  \"currency\": \"USD\",\n  \"amount\": \"9.99\",\n  \"interval_unit\": \"MONTH\",\n  \"interval_count\": 1,\n  \"payer_email\": \"user@example.com\",\n  \"current_period_start\": 1742678400,\n  \"current_period_end\": 1745356800,\n  \"cancel_reason\": \"by_merchant_api\",\n  \"canceled_at\": 1743000000,\n  \"created_at\": 1740000000,\n  \"updated_at\": 1743000000\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"75-接收-webhook-与安全校验","__idx":18},"children":["7.5 接收 Webhook 与安全校验"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Infini 会向你配置的 Webhook URL 发起 POST 请求，建议接收端遵循以下原则："]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["校验所有必需 Header 是否存在："]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Signature"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Timestamp"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Event-Id"]}]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":2},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["验证签名合法性（见下一小节）。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["基于 X-Webhook-Event-Id 实现幂等处理（如仅处理一次）。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["业务逻辑应 ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["异步处理"]},"，快速返回 HTTP 200，避免超时。"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"76-webhook-签名校验signature-verification","__idx":19},"children":["7.6 Webhook 签名校验（Signature Verification）"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["验签步骤："]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["从 Header 中读取："]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Signature（签名）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Timestamp（时间戳）"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Webhook-Event-Id（事件 ID）"]}]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":2},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["获取原始请求体字符串 payload。"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["组装签名内容字符串："]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"{timestamp}.{event_id}.{payload}\n"},"children":[]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["使用你的 WEBHOOK_SECRET 做 HMAC-SHA256 计算："]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"signed_content = f\"{timestamp}.{event_id}.{payload}\"\nexpected_sig = hmac.new(\nWEBHOOK_SECRET.encode(),\nsigned_content.encode(),\nhashlib.sha256\n).hexdigest()\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["对比 expected_sig 与 X-Webhook-Signature 是否一致。"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"761-python-验签示例","__idx":20},"children":["7.6.1 Python 验签示例"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"@app.route('/webhook', methods=['POST'])\ndef webhook_verification():\n    signature = request.headers.get('X-Webhook-Signature')\n    timestamp = request.headers.get('X-Webhook-Timestamp')\n    event_id = request.headers.get('X-Webhook-Event-Id')\n\n    if not all([signature, timestamp, event_id]):\n        return jsonify({\"error\": \"Missing required headers\"}), 400\n\n    payload = request.get_data(as_text=True)\n    signed_content = f\"{timestamp}.{event_id}.{payload}\"\n    expected_sig = hmac.new(\n        WEBHOOK_SECRET.encode(),\n        signed_content.encode(),\n        hashlib.sha256\n    ).hexdigest()\n\n    if expected_sig != signature:\n        return jsonify({\"error\": \"Invalid signature\"}), 401\n\n    # Process valid webhook\n    return jsonify({\"status\": \"ok\"})\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"77-webhook-重试策略","__idx":21},"children":["7.7 Webhook 重试策略"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["若商户端未返回 HTTP 200，Infini 会对该事件进行重试。"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["最多重试：8 次"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["前 3 次重试间隔：30 秒"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["第 4～8 次采用递增退避策略"]},"，示例："]}]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"尝试次数"},"children":["尝试次数"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"说明"},"children":["说明"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"间隔时间（示例）"},"children":["间隔时间（示例）"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 1 次"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["首次发送"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["立即"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 2 次"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 1 次失败"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["30 秒"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 3 次"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 2 次失败"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["30 秒"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 4 次"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 3 次失败"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["30 秒"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 5 次"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 4 次失败"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["60 秒"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 6 次"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 5 次失败"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["120 秒"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 7 次"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 6 次失败"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["240 秒"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 8 次"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["第 7 次失败"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["480 秒"]}]}]}]}]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["若最终多次重试仍失败，该事件将被标记为投递失败，建议商户通过日志与对账工具进行排查。"]}]}]},"headings":[{"value":"7. Webhook（订单与订阅状态回调）","id":"7-webhook订单与订阅状态回调","depth":2},{"value":"7.1 可订阅事件与事件类型","id":"71-可订阅事件与事件类型","depth":3},{"value":"7.1.1 测试工具","id":"711-测试工具","depth":4},{"value":"7.2 Webhook Payload 字段说明","id":"72-webhook-payload-字段说明","depth":3},{"value":"订单 Webhook Payload 字段","id":"订单-webhook-payload-字段","depth":4},{"value":"订阅 Webhook Payload 字段","id":"订阅-webhook-payload-字段","depth":4},{"value":"7.3 Webhook 请求 Headers","id":"73-webhook-请求-headers","depth":3},{"value":"7.4 Webhook 示例 Payload","id":"74-webhook-示例-payload","depth":3},{"value":"7.4.1 场景 1：订单创建（order.created）","id":"741-场景-1订单创建ordercreated","depth":4},{"value":"7.4.2 场景 2：订单处理中（收到款项在确认中，order.processing）","id":"742-场景-2订单处理中收到款项在确认中orderprocessing","depth":4},{"value":"7.4.3 场景 3：订单处理中（收到部分款项已确认，order.processing）","id":"743-场景-3订单处理中收到部分款项已确认orderprocessing","depth":4},{"value":"7.4.4 场景 4：订单完成（收到完整付款，order.completed）","id":"744-场景-4订单完成收到完整付款ordercompleted","depth":4},{"value":"7.4.5 场景 5：订单过期（完全未付款，order.expired）","id":"745-场景-5订单过期完全未付款orderexpired","depth":4},{"value":"7.4.6 场景 6：订单过期（收到部分款项，order.expired + partial_paid）","id":"746-场景-6订单过期收到部分款项orderexpired--partial_paid","depth":4},{"value":"7.4.7 场景 7：订单过期后收到付款（晚到付款，order.late_payment）","id":"747-场景-7订单过期后收到付款晚到付款orderlate_payment","depth":4},{"value":"7.4.8 场景 8：订阅激活（subscription.update）","id":"748-场景-8订阅激活subscriptionupdate","depth":4},{"value":"7.4.9 场景 9：订阅续费（subscription.update）","id":"749-场景-9订阅续费subscriptionupdate","depth":4},{"value":"7.4.10 场景 10：订阅取消（subscription.cancel）","id":"7410-场景-10订阅取消subscriptioncancel","depth":4},{"value":"7.5 接收 Webhook 与安全校验","id":"75-接收-webhook-与安全校验","depth":3},{"value":"7.6 Webhook 签名校验（Signature Verification）","id":"76-webhook-签名校验signature-verification","depth":3},{"value":"7.6.1 Python 验签示例","id":"761-python-验签示例","depth":4},{"value":"7.7 Webhook 重试策略","id":"77-webhook-重试策略","depth":3}],"frontmatter":{"seo":{"title":"7. Webhook（订单与订阅状态回调）"}},"lastModified":"2026-07-17T08:59:36.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/zh/docs/en/7-webhook","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}