GravityDock 引力聚合
服务端集成与发货通知
接收 GravityDock 支付到账通知,按原始请求体验签,校验订单并幂等发货,返回平台确认回执。
渠道支付经 GravityDock 校验后,Dock 向游戏服务端发送 payment.paid 通知。游戏服务端校验通知和商户订单,在事务中发放道具,提交后返回确认。
配置接收地址
- 游戏服务端提供可直接访问的公网 HTTPS POST 地址,使用 443 端口和有效 TLS 证书。接收地址应直接处理请求,Dock 不跟随重定向。
- 在「游戏管理 → 编辑游戏」填写「游戏发货通知地址」和独立的「通知签名密钥」,游戏服务端配置相同密钥。
- 先完成验签、订单校验、幂等发货和回执测试,再开启「启用游戏发货通知」,用受控订单验证整条链路。
请求格式
请求为 POST,Content-Type 为 application/json; charset=utf-8。
| 请求头 | 含义 |
|---|---|
X-Dock-Timestamp | 当前投递尝试的 Unix 秒时间戳。 |
X-Dock-Delivery-Id | 投递标识,重试时保持一致。 |
X-Dock-Signature | v1= 加 HMAC-SHA256 小写十六进制摘要。 |
{
"version": 1,
"event": "payment.paid",
"delivery_id": "PS-example-delivery",
"order_no": "PS-example-order",
"merchant_order_no": "game-order-123",
"channel_order_id": "channel-order-456",
"game_id": "12345",
"channel_id": "23456",
"provider": "xiaomi",
"user_id": "player-uid",
"amount": "1.00",
"amount_minor": 100,
"currency": "CNY",
"product_id": "sku-1",
"paid_at": "2026-11-04T08:00:00Z",
"product_count": 2,
"product_desc": "游戏商品描述",
"product_id": "游戏商品id",
"product_name": "游戏商品名",
"extra": {"role_id": "role-123", "server_id": "server-1"}
}amount_minor 为整数分,amount 为十进制字符串。按整数分或精确十进制校验金额。游戏与渠道 ID 为字符串,extra 来自下单时的透传快照。游戏服务端应以自身订单保存的角色和区服为准。
签名验证
使用独立通知密钥和原始请求体计算签名。签名输入为时间戳字符串、英文句点和收到的请求体字节依次拼接。应在解析 JSON 前完成验签。
import hashlib
import hmac
import json
import time
def verify_notification(raw_body: bytes, headers, secret: str):
timestamp = headers["X-Dock-Timestamp"]
if not timestamp.isascii() or not timestamp.isdecimal():
raise ValueError("invalid timestamp")
if abs(int(time.time()) - int(timestamp)) > 300:
raise ValueError("expired notification")
message = timestamp.encode("ascii") + b"." + raw_body
expected = "v1=" + hmac.new(
secret.encode("utf-8"), message, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, headers["X-Dock-Signature"]):
raise ValueError("invalid signature")
event = json.loads(raw_body)
if (
event["version"] != 1
or event["event"] != "payment.paid"
or event["delivery_id"] != headers["X-Dock-Delivery-Id"]
):
raise ValueError("invalid notification")
return event示例采用 300 秒时间窗。实际处理时,将缺失请求头、格式错误和验签失败映射为失败响应,并保持接收端时钟同步。
幂等发货与回执
- 按
merchant_order_no查游戏订单,核对游戏、渠道、商品、金额、币种及绑定的玩家和角色。 - 在同一事务内保存发货记录和道具变更,以游戏与
order_no设唯一键,并确保同一商户订单只发货一次。已成功处理的重复投递应复用成功结果。 - 发货事务提交后返回 HTTP 200 和 JSON。回执中的
code为整数 0,delivery_id回传当前通知标识。
{"code": 0, "delivery_id": "PS-example-delivery"}重试和对账
通知可能重复到达。响应失败、超时或回执不匹配会触发退避重试,最多连续 8 次失败。到「玩家运营 → 订单运营」检查通知状态和投递记录。自动重试沿用首次排队的地址和密钥快照。修改地址或轮换密钥后,对仍需投递的旧记录由授权人员排障后人工重试,使用当前配置。历史已支付订单需逐笔核对,由授权人员对符合条件的订单发起补发。
文档维护:Gravity Engine
文档修改日期: