开放娱乐平台

接口认证

所有POST请求使用Content-Type: application/json。除health和create_token外,公开接口使用token请求头。

服务器 IP 白名单

领取token和后续公开API请求都校验第三方服务器的出口IP;不在白名单时返回HTTP 403,错误码ip_not_allowed。空白名单拒绝接入。申请时填写调用接口的服务器公网出口IP,不要填写平台代理服务器的IP。

平台HTTPS入口会覆盖并传递真实来源IP。WebDeliverServer仅在连接来自管理员明确配置的可信代理时读取其X-Real-IP;其他来源的代理头均不受信任,X-Forwarded-For和请求体中自行声明的IP不能绕过白名单。第三方无需自行设置这些请求头。

白名单变更、暂停或secret重置随运行服务的配置刷新生效,通常数秒。已有token也会重新校验IP,不能通过提前领取token绕过限制。

领取token

POST /api/v1/create_token

{
  "partner": "YOUR_CODE",
  "timestamp": "UNIX_SECONDS",
  "nonce": "32位小写十六进制随机数",
  "sign": "64位小写十六进制HMAC"
}

签名算法:HMAC-SHA256(secret, timestamp + ":" + nonce),结果编码为小写十六进制。timestamp必须是秒级Unix时间的字符串,允许前后300秒时钟误差;nonce 必须恰好为 32 位小写十六进制文本(16 个随机字节编码),用加密安全随机数生成。每次领取,包括失败后的重试,都重新生成 nonce 和 timestamp。secret 按平台展示的文本原样作为 HMAC 密钥,不做十六进制解码。

{
  "success": true,
  "message": "TOKEN",
  "expires_in": 3600
}

错误secret、过期签名、重复nonce、未开通合作方均被拒绝。token最长有效1小时,同一合作方重复获取会复用尚未过期的token;建议缓存不超过50分钟。DBServer重启后需重新领取,secret修改或合作方暂停后旧token失效。

不要每个请求重新领取token。业务请求失败时不能无条件重放;领取新token后,只对明确允许重试的请求重试。接口错误、会话中断和钱包回调失败是不同问题。

Go签名示例

h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(timestamp + ":" + nonce))
sign := hex.EncodeToString(h.Sum(nil))

HTTP示例中的域名与凭据均为占位内容。正式部署使用HTTPS;本机测试可使用HTTP。访问日志必须移除token、secret、sign、user_key及包含会话的启动链接。

请求与响应约定

API 基础地址来自「接入应用 → 对应应用 → 接入凭据」。接口地址、code、secret 必须属于同一应用。partner 参数填写该应用的 code,不是应用 ID、邮箱或固定字符串 code。secret 只用于本地计算签名,不直接发送到 API。此协议不使用 Authorization: Bearer,请使用名为 token 的请求头。

领取 token 参数 类型 要求
partner string 必填,已审核应用的 code
timestamp string 必填,当前 Unix 秒的十进制文本;不是毫秒
nonce string 必填,32 位小写十六进制随机文本
sign string 必填,64 位小写十六进制 HMAC-SHA256 结果
token 响应字段 类型 说明
success boolean 业务结果
message string 成功为 token;失败为错误说明
expires_in integer 当前返回 3600;重复获取会复用 token,不代表其剩余有效期又延长一小时
POST /api/v1/gamelist HTTP/1.1
Host: api.example.invalid
Content-Type: application/json
token: YOUR_TOKEN

{}

先判断 HTTP 状态,再判断业务 success。游戏目录、机台目录、游戏动态的成功响应 message 是 JSON 字符串;只有这三个接口需要对 message 再做一次 JSON 解析。其他接口使用顶层字段;健康检查没有 success 字段。不要对所有 message 无条件 JSON.parse。

const response = await fetch(apiBase + "/api/v1/gamelist", {
  method: "POST",
  headers: { "Content-Type": "application/json", token },
  body: "{}"
});
const body = await response.json();
if (!response.ok || body.success !== true) {
  throw new Error(body.message || body.error || "API request failed");
}
const catalog = JSON.parse(body.message);
const games = catalog.list;

示例仅在第三方服务端执行。生产实现还须设置请求超时、处理非 JSON 响应、限制日志中的敏感信息。

错误与重试

当前协议存在两类错误外形,不保证每次都有 error 字段。HTTP 200 也可能为业务失败。

{
  "success": false,
  "message": "invalid user code"
}
{
  "error": "ip_not_allowed",
  "message": "server IP is not in the partner whitelist"
}
HTTP 状态 常见反馈 接入方处理
200 且 success=false message 为业务原因 修正参数或业务条件;不能当作成功
400 request_body_required / invalid_json_body 检查请求体和 JSON 编码
401 invalid credentials 核对接口地址、code、secret、时钟和 nonce
401 missing partner token / invalid or expired partner token 携带有效 token;失效后重新领取
403 ip_not_allowed 修改的服务器出口 IP;不是玩家浏览器 IP
404 route_not_found / method_not_allowed 检查路径和 HTTP 方法;当前方法错误也返回 404
413 请求体过大 缩小请求,不要直接重复发送
500 / 503 服务异常或 db_unavailable 记录脱敏上下文,稍后有限退避重试只读请求
504 http_timeout 结果可能未知;先查询状态或核对业务记录

只读目录与状态查询可在短暂故障后有限重试。启动、退出发生超时时,不应认定服务端未执行;先检查玩家状态。业务 API 未提供通用幂等请求头;不要套用其他平台的 Idempotency-Key 规则。回调幂等与确认机制见回调与结算。