API
游戏试玩 API 接入文档 Official Integration Guide
图片资源 图片压缩包 游戏资源清单
首页

游戏试玩 API 接入文档

APP
1

应用数

API
1

启动接口

DOCS
3015

游戏资源

类型统计

POST1

标签

服务端接入 HMAC-SHA256 播放短链

作者

平台官方

分组

名称方式接口
启动游戏POST/api/launch

接入概览

本文档面向第三方试玩站服务端接入。接入方根据平台提供的商户信息和游戏资源清单,在服务端请求启动接口,成功后将玩家跳转到平台返回的播放地址。

玩家点击游戏 接入方服务端签名 平台返回 play_url 302 跳转玩家
商户密钥只允许保存在服务端,不得出现在前端代码、App 包、公开仓库或日志明文中。

启动游戏

POST {API_BASE_URL}/api/launch
参数类型必填说明
merchant_idstring平台分配的商户 ID
launch_codestring游戏资源清单中的启动码
timestampintUnix 秒级时间戳,有效期 5 分钟
noncestring随机字符串,建议每次请求唯一
signaturestringHMAC-SHA256 签名
user_ipstring建议玩家客户端 IP,用于安全校验
visitor_idstring建议同一玩家保持稳定
user_agentstring建议玩家浏览器 User-Agent

签名规则

从请求 JSON 中移除 signature 字段,按参数名升序排序,使用 JSON 编码后,以商户密钥计算 HMAC-SHA256。

function canonicalPayload(payload):
    remove payload.signature
    sort payload by key ascending
    return jsonEncode(payload, unescapedUnicode = true, unescapedSlash = true)

payload.signature = hmacSha256(canonicalPayload(payload), merchantSecret)

代码示例

PHP

<?php
$apiBaseUrl = 'https://api.example.com';
$merchantId = 'your_merchant_id';
$merchantSecret = 'your_merchant_secret';

$payload = [
    'merchant_id' => $merchantId,
    'launch_code' => 'g_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    'timestamp' => time(),
    'nonce' => bin2hex(random_bytes(8)),
    'visitor_id' => 'v_1780000000abcdef',
    'user_ip' => '203.0.113.10',
    'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '',
];

$signPayload = $payload;
ksort($signPayload);
$canonical = json_encode($signPayload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$payload['signature'] = hash_hmac('sha256', $canonical, $merchantSecret);

$ch = curl_init($apiBaseUrl . '/api/launch');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],
    CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
curl_close($ch);

$result = json_decode((string)$response, true);
if (($result['success'] ?? false) && !empty($result['data']['play_url'])) {
    header('Location: ' . $result['data']['play_url'], true, 302);
    exit;
}

Node.js

import crypto from 'node:crypto';

const apiBaseUrl = 'https://api.example.com';
const merchantId = 'your_merchant_id';
const merchantSecret = 'your_merchant_secret';

const payload = {
  merchant_id: merchantId,
  launch_code: 'g_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  timestamp: Math.floor(Date.now() / 1000),
  nonce: crypto.randomBytes(8).toString('hex'),
  visitor_id: 'v_1780000000abcdef',
  user_ip: '203.0.113.10',
  user_agent: 'Mozilla/5.0',
};

const canonical = JSON.stringify(
  Object.fromEntries(Object.entries(payload).sort(([a], [b]) => a.localeCompare(b)))
);
payload.signature = crypto.createHmac('sha256', merchantSecret).update(canonical).digest('hex');

const response = await fetch(`${apiBaseUrl}/api/launch`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
  body: JSON.stringify(payload),
});

const result = await response.json();
if (result.success && result.data?.play_url) {
  // Web 框架中建议返回 302 跳转到 result.data.play_url
}

响应格式

成功响应

{
  "success": true,
  "message": "",
  "data": {
    "play_url": "https://play.example.com/xxx/index.html?...",
    "play_ttl_seconds": 900,
    "charged": 0.001
  }
}

失败响应

{
  "success": false,
  "message": "签名无效",
  "data": []
}

错误码

HTTP 状态message 示例处理建议
400/422请求格式无效 / 缺少参数检查 JSON 和必填参数
403签名无效检查签名字段、密钥和参数排序
403服务器 IP 不在白名单自行到商户端添加服务端出口 IP
422游戏不存在或未开通检查 launch_code 是否来自最新资源清单
429请求频率超限增加防抖和服务端冷却
502游戏启动失败,请稍后重试稍后重试或联系平台排查

游戏资源

游戏资源清单独立提供,接入方前台展示游戏时使用 game_namecategoryimage_path;启动游戏时只传对应的 launch_code

平台不提供可外链的 logo URL。交付包内只提供本地图片资源和相对路径映射,接入方需自行上传到自有静态目录、对象存储或 CDN,并在自己的前台使用自有图片地址。
试玩站游戏资源清单

14 个分类,3015 款游戏,JSON 格式。

查看图片 下载 JSON 下载图片包
{
  "game_id": 1,
  "game_name": "麻将胡了",
  "category": "PG",
  "launch_code": "g_d18d2c8a5d6f308aceb362c500750499",
  "image_path": "../game-images/images/PG/1_g_d18d2c8a5d6f308aceb362c500750499.jpg"
}

资源图片预览

正在载入游戏资源...

联调清单

  1. 平台提供 API 地址、商户 ID、商户密钥和游戏资源清单。
  2. 接入方自行到商户端,填入IP白名单。
  3. 接入方根据游戏资源清单展示游戏列表。
  4. 接入方服务端生成签名并请求启动接口。
  5. 成功响应后将玩家跳转到 play_url
  6. 测试签名错误、无效 launch_code、IP 未白名单等异常场景。