hyapp-server/docs/幸运礼物外接接口对接文档.md
2026-07-15 13:20:33 +08:00

8.7 KiB
Raw Blame History

幸运礼物外接接口对接文档

文档版本2026-07-15
接入方式服务端对服务端Server-to-Server
金额单位:对接 App 的金币最小整数单位

1. 接口用途

外部 App 在自己的账务系统完成幸运礼物扣费后,调用本接口获取一次最终抽奖结果。

平台负责:

  • app_code 隔离规则、奖池、RTP 和抽奖流水。
  • app_code + request_id 保证抽奖幂等。
  • 返回最终 reward_amount 和倍率。

对接 App 负责:

  • 调用前完成用户扣费。
  • 成功收到结果后,在自己的账务系统中向用户发放 reward_amount
  • 对超时或网络失败使用原 request_id 重试,不得重新生成业务请求 ID。

HyApp 不会操作外部 App 的用户钱包。reward_status=granted 表示抽奖结果已经生成并交给调用方,不表示奖励已在外部 App 入账。

2. 接口地址

类型 地址
Base URL https://lucky-api.global-interaction.com
送礼接口 POST https://lucky-api.global-interaction.com/api/v1/lucky-gifts/send
就绪检查 GET https://lucky-api.global-interaction.com/healthz/ready

就绪检查:

GET https://lucky-api.global-interaction.com/healthz/ready

2026-07-15 实测就绪检查返回 HTTP 200送礼请求可到达幸运礼物网关。

3. 调用前置条件

  1. 向平台申请唯一 app_code,并加入幸运礼物网关白名单。
  2. 确认该 App 的幸运礼物规则已启用。
  3. 对接 App 必须先扣费,再调用抽奖接口。
  4. 本接口只允许对接 App 服务端调用,禁止将请求能力下发到 App 或 Web 客户端。

当前版本的 HTTP 入口使用 app_code 白名单,尚未启用 Authorization Token 或请求签名,因此必须仅由已开通的对接 App 服务端调用。

4. 发送幸运礼物

4.1 请求

POST /api/v1/lucky-gifts/send HTTP/1.1
Host: lucky-api.global-interaction.com
Content-Type: application/json
X-Request-Id: trace-20260715-000001

X-Request-Id 为可选的链路追踪 ID。如果不传平台会自动生成。它只用于日志排查不是抽奖幂等键。

4.2 请求体

{
  "app_code": "partner_app",
  "request_id": "gift-order-20260715-000001",
  "external_user_id": "user-10001",
  "gift_count": 3,
  "unit_amount": 100,
  "currency": "COIN",
  "metadata": {
    "external_order_id": "order-1000001",
    "gift_id": "lucky-rose",
    "room_id": "room-20001"
  }
}

4.3 字段说明

字段 类型 必填 约束 说明
app_code string 去除首尾空格后 132 字符 平台分配的 App 编码;按小写存储和校验。
request_id string 去除首尾空格后 1128 字符 对接 App 生成的业务幂等 ID建议直接使用送礼订单号或 UUID。
external_user_id string 去除首尾空格后 1128 字符 用户在对接 App 中的稳定唯一 ID。
gift_count int64 > 0 本次已扣费的礼物数量。
unit_amount int64 > 0 单个礼物的金币整数价格。
currency string 只支持 COIN 缺省或空字符串时按 COIN 处理。
metadata object JSON object 对接方的展示或排查元数据;不参与金额、规则或幂等判定。

服务端按下式计算本次金额:

total_amount = gift_count * unit_amount

请求体不得传入 total_amountpool_idpaid_at_ms。奖池由平台规则选择,扣费完成时间由网关按 UTC 服务端时间写入。接口会拒绝所有未定义的顶层字段。

一个请求只返回一个聚合抽奖结果;gift_count 不会产生多个独立响应。

4.4 成功响应

HTTP Status200 OK

{
  "code": 0,
  "message": "ok",
  "request_id": "trace-20260715-000001",
  "data": {
    "draw_id": "external_lucky_draw_xxxxxxxxxx",
    "request_id": "gift-order-20260715-000001",
    "app_code": "partner_app",
    "external_user_id": "user-10001",
    "gift_count": 3,
    "unit_amount": 100,
    "total_amount": 300,
    "reward_amount": 600,
    "multiplier_ppm": 2000000,
    "reward_status": "granted",
    "rule_version": 1,
    "created_at_ms": 1784073600000
  }
}

4.5 响应字段

字段 类型 说明
code int 业务结果码;0 表示请求成功。
message string 结果说明。
外层 request_id string HTTP 链路追踪 ID来自 X-Request-Id 或由平台生成。
data.draw_id string 平台生成的唯一抽奖 ID对账时使用。
data.request_id string 请求体中的业务幂等 ID。
data.app_code string 归一化后的 App 编码。
data.external_user_id string 对接 App 的用户 ID。
data.gift_count int64 礼物数量。
data.unit_amount int64 单件礼物金币价格。
data.total_amount int64 服务端计算的已扣费总额。
data.reward_amount int64 对接 App 应向用户发放的金币整数金额;以该字段为最终结算依据。
data.multiplier_ppm int64 倍率 ppm1000000 表示 1x2000000 表示 2x。
data.reward_status string 当前为 granted,表示抽奖已完成且结果已交给对接 App 处理。
data.rule_version int64 本次抽奖命中的规则版本。
data.created_at_ms int64 抽奖结果创建时间Unix epoch millisecondsUTC。

未中奖时 reward_amountmultiplier_ppm0。当前 JSON 序列化会省略数值为 0 的结果字段,对接方必须将缺失的 reward_amountmultiplier_ppm0 处理,不得将字段缺失视为请求失败。

5. 幂等与重试

幂等键固定为:

app_code + request_id
  • 首次请求成功后,平台保存抽奖结果。
  • 使用相同 app_code + request_id 重试时,直接返回首次结果,不会重新抽奖。
  • 同一 request_id 不得对应不同用户、数量或金额。平台在幂等命中时会返回首次结果,不会用新参数覆盖。
  • 超时、连接中断或 HTTP 5xx 时,使用原请求体和原 request_id 重试。
  • 客户端超时建议设置为大于网关内部 3 秒处理超时,并对重试使用有上限的退避。

如果多次重试后仍无法确认结果,请保留 app_coderequest_id、外层 request_id 和扣费流水,由平台根据抽奖记录对账。

6. 错误响应

6.1 统一格式

{
  "code": 40000,
  "message": "request_id is required",
  "request_id": "trace-20260715-000001"
}

6.2 错误码

HTTP Status code 场景 对接方动作
400 40000 JSON 无效、出现未定义字段、必填字段缺失、金额非正数或币种不支持 修正请求,不要原样重试。
403 40300 app_code 未加入当前环境白名单 联系平台开通或检查环境。
404 无统一业务码 请求路径或 HTTP 方法错误 检查 Base URL、路径和请求方法。
500 50000 抽奖服务超时或内部处理失败 保持原 request_id 重试;不得重新扣费。

业务成功必须同时满足 HTTP Status 为 200 且响应 code0

7. cURL 示例

curl --request POST \
  'https://lucky-api.global-interaction.com/api/v1/lucky-gifts/send' \
  --header 'Content-Type: application/json' \
  --header 'X-Request-Id: trace-20260715-000001' \
  --data '{
    "app_code": "partner_app",
    "request_id": "gift-order-20260715-000001",
    "external_user_id": "user-10001",
    "gift_count": 3,
    "unit_amount": 100,
    "currency": "COIN",
    "metadata": {
      "external_order_id": "order-1000001",
      "gift_id": "lucky-rose",
      "room_id": "room-20001"
    }
  }'

8. 标准处理流程

  1. 对接 App 生成全局唯一的 request_id
  2. 对接 App 在自有账务系统扣除 gift_count * unit_amount
  3. 对接 App 调用幸运礼物接口。
  4. 平台按 app_code + request_id 创建或返回已有抽奖结果。
  5. 对接 App 在响应成功后按 reward_amount 入账,并保存 draw_id
  6. 任何未知结果都使用原 request_id 重试;禁止重复扣费或重新生成抽奖业务号。

9. 联调检查清单

  • app_code 已加入幸运礼物网关白名单。
  • 规则已启用,并确认金币单位一致。
  • 正常送礼可获得 HTTP 200 / code=0
  • 重复发送相同 request_id 可获得相同 draw_id 和结果。
  • 模拟超时后只重试抽奖请求,不重复扣费。
  • 未中奖响应中缺失的数值字段可正确按 0 处理。
  • 奖励按 reward_amount 在外部 App 入账,并持久化 draw_id
  • 上线前完成小额真实扣费、抽奖、返奖和幂等重试验收。