GoodRoad API Reference

GoodRoad 后端接口文档

这份文档详细说明 GoodRoad 插件与后端交互的所有 API。

接口概览

GoodRoad 目前只保留两个主要阶段的接口调用:

阶段 接口 方法 说明
1. 获取快照 GET /plugin/v1/tables/snapshot GET 公开接口,获取桌台列表及路盘数据
2. 进入游戏 POST /plugin/v1/game/enter POST 使用 我方免转文档的Login接口返回 的 token 进入指定桌台
接口调用流程是 token-first:宿主先拿到 Login接口 颁发的 token,再把 token 传给插件; snapshot 可公开访问,enter 需要 Authorization: Bearer <token>

认证与签名

签名校验(可选)

如果后端启用了 GOODROAD_CHANNEL_SECRET 环境变量,所有请求都需要包含签名头。

签名算法

signText = "{channelId}|{timestamp}|{nonce}"
signature = HMAC-SHA256(signText, secret).hex()

必需头部

  • x-channel-id: 渠道号
  • x-timestamp: 当前 Unix 时间戳(秒),允许偏差 ±300 秒
  • x-nonce: 随机字符串,每个时间窗口内一次性使用
  • x-signature: 上述签名结果

域名白名单(可选)

如果配置了 GOODROAD_CHANNEL_DOMAIN_MAP,请求时需要在 domain 字段里传当前页面域名,后端会校验是否在该 channel 的白名单内。

3. token 说明

插件初始化时可以接收宿主传入的会员 token。当前版本不再使用 init-ticket / session-exchange,第三方只需要在宿主侧拿到登录 token 并传给插件即可。

推荐写法是把 token 直接传给 GoodRoadWidget.mount({ token }),或者在零代码模式下使用 data-goodroad-token

GET tables/snapshot

/plugin/v1/tables/snapshot

获取可用桌台列表及其路盘数据。这个接口是公开的,不需要登录 token。插件会定期调用此接口以刷新桌台列表。

请求字段

字段来源类型说明
limitQuerynumber最多返回多少个桌台(默认 6,范围 1-50)
include_good_roadQuerybool是否包含好路数据(默认 1)
include_historyQuerybool是否包含游戏历史(默认 1)

成功响应

result = 0
{
  "result": 0,
  "desc": "ok",
  "data": {
    "generated_at": 1718358000,
    "user_type": "guest",
    "channel_id": "demo-channel",
    "table_count": 3,
    "table_list": [
      {
        "room_id": 1001,
        "game_code": "baccarat_001",
        "game_name": "百家乐 1 号桌",
        "game_type": 4,
        "online": 1,
        "shoe_id": 42,
        "round_count": 28,
        "player_count": 10,
        "banker_count": 16,
        "tie_count": 2,
        "good_road": {
          "list": ["b", "p", "b", "b", "t", "p"],
          "is_good_road": 1,
          "rule": "BACCARAT_LONG_BANKER_4",
          "rule_name": "长庄 >=4",
          "duration_rounds": 4
        },
        "game_history": [ ... ],
        "analy_data": "{...}"
      }
    ]
  }
}
重要:仅返回有路盘数据的桌台(即路盘列表不为空)。无任何落点的空桌将被过滤。

POST game/enter

/plugin/v1/game/enter

请求进入指定桌台。仅会员可进入,调用时必须携带 Authorization: Bearer <token>

请求字段

字段类型必需说明
room_idnumber目标桌台 ID

成功响应

result = 0
{
  "result": 0,
  "desc": "ok",
  "data": {
    "room_id": 1001,
    "game_code": "baccarat_001",
    "open_url": "https://game.example.com/baccarat?room=1001&token=..."
  }
}

常见错误

TOKEN_INVALID
登录 token 无效或已过期
NEED_LOGIN
当前没有可用的会员 token
GUEST_FORBIDDEN_ENTER
游客无法进入游戏
ROOM_NOT_AVAILABLE
目标桌台不可用或不存在

完整示例

JavaScript/TypeScript 联调示例

async function setupGoodRoadWidget() {
  const apiBase = 'http://127.0.0.1:13100';
  const token = window.USER_TOKEN || '';
  
  // 1. 获取桌台快照(公开接口)
  const snapshotResp = await fetch(`${apiBase}/plugin/v1/tables/snapshot?limit=8`).then(r => r.json());
  
  console.log('Tables:', snapshotResp.data.table_list);
  
  // 2. 进入游戏(需要会员 token)
  if (token) {
    const enterResp = await fetch(`${apiBase}/plugin/v1/game/enter`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`
      },
      body: JSON.stringify({ room_id: 1001 })
    }).then(r => r.json());

    console.log('Enter response:', enterResp);
  }
}

setupGoodRoadWidget().catch(console.error);