履约回调
本页适用于 Halo 商城版 2.27.0 及以上版本。
订阅订单行不走物流发货,Halo 不会自行判定订阅权益是否已经交付:订单支付后 Halo 通知接入方交付,接入方交付完成后调用 Halo 的接口回执,Halo 据此记账。
- ① 在订单支付成功后自动发出一次,运营也可以在控制台订单详情页重新发送。
- ② 只接受订阅订单行。实物行与虚拟商品行沿用原有发货流程,上报会被拒绝。
- 上报不会创建发货单,也不会发放卡密或数字资源;虚拟交付见商城 / 虚拟交付。
鉴权准备
- 在控制台创建一个专用 Halo 用户,并绑定角色「订单发货上报」(
role-template-report-ecommerce-fulfillments)。 - 用该用户登录用户中心,创建个人令牌,只勾选该角色。
- 在接入方系统中配置令牌,请求时携带
Authorization: Bearer pat_xxx。
该角色只包含两项权限:
个人令牌只能申请签发者已有的角色,因此必须先在控制台给该用户授权,再用它创建令牌。请勿把管理员令牌交给接入方服务。
交付请求通知(出站)
订单支付成功后,只要订单中还有未履约的订阅行,Halo 就会投递一次 FULFILLMENT_REQUESTED:
data.order 与 ORDER_PAID 完全一致,包含订单行列表;订阅行的标识字段见订阅 Webhook。
- 收到该事件表示「Halo 希望你交付这个订单」,不代表订单已经发货。
- 该事件在支付后自动发送一次。自动重试与 Webhook 投递记录中的手动重新投递保留原
X-Halo-Webhook-Id;在订单详情页重新发送履约请求会产生新事件和新 ID,不能仅凭投递 ID 避免重复交付。 - 漏收时可以请运营在控制台订单详情页重新发送,也可以核对订单后直接上报,Halo 不要求必须先收到通知。
发货上报(入站)
{id} 是订单 ID,即 Webhook 载荷中的 data.order.id,不是订单编号。
请求示例:
响应 200:
整单上报(省略 items)时,目标为该订单所有还有剩余数量的订阅行,已经履约完成的行不会出现在响应中;显式上报的行都会出现在响应里,本次未记账的行 appliedQuantity 为 0。
幂等与重试
quantity 表示本次新增的交付数量,不是累计数量。例如订单行购买了 3 份,首次上报 1 份已经记账但响应丢失,再次上报 1 份会把累计已履约数量变为 2。externalReference 只用于审计,不是服务端幂等键;并发串行化也只能防止超额,不能识别重复报告。
建议:
- 交付成功后立即上报。超时、断网等结果不确定的情况,不要直接重发原参数;先查询订单,用
items[].fulfilledQuantity与本地实际交付记录核对,只补报确认尚未记账的数量。 - 以「订单 ID + 订单行 ID」组织本地交付与上报记录,同一订单行串行处理;分批交付时分别记录每批数量和上报结果,避免重复交付或重复记账。
- 查询时若前一次上报仍在处理中,或有其他上报方并发写入,暂时读到的数量不能证明首次请求未生效;应先确认请求结果或交由运营对账,不要根据一次查询立即重试。
- 收到
409时不要盲目重试,也不要直接把数量改成剩余数量;先核对实际交付与已记账数量。
错误处理
错误响应遵循 RFC 7807(application/problem+json),detail 为可读原因并会随 Accept-Language 变化,请按 HTTP 状态码判断处理方式。
对账与运维
- 查询订单:
GET /apis/console.api.ecommerce.halo.run/v1alpha1/orders/{id}(同一令牌可读),用items[].quantity、items[].fulfilledQuantity与fulfillmentStatus核对是否还有未履约行。 - 查看时间线:运营可以在控制台订单详情页看到「请求发货」「接入方上报发货」「订单履约状态已更新」等记录,上报写入的内容包含接入方的
externalReference。 - 漏收通知:请运营在订单详情页重新发送发货请求,或核对订单后直接上报。
- 人工兜底:订阅订单行不能在控制台手动发货,只能由接入方上报。
上报只会更新订单行的已履约数量、刷新订单履约状态并写入一条订单时间线:不会创建发货单,不会发放卡密或数字资源,也不会触发 FULFILLMENT_SHIPPED / FULFILLMENT_COMPLETED 事件。请以接口响应作为记账结果。