跳转到内容

SDK

本 SDK 提供 游戏 与原生客户端(iOS、Android)之间的安全双向通信能力,帮助第三方开发者调用原生能力。

暴露的全局 API 名称:window.GameTokSDK

提供能力:

动作说明
GET_PROFILE获取当前用户资料
PURCHASE发起购买(如内购)
STORAGE_SET写入本地键值存储(用于保存设置、进度等)
STORAGE_GET读取本地键值存储(获取先前保存的数据)
ADD_SCORE上报分数(用于排行榜/分享等)
GET_PERMISSION_MIC获取麦克风权限(安卓)
TOPUP充值,游戏中金币不足,可以调起客户端充值
ROUND_START开局通知(每局开始时上报,与平台局次、能量等策略相关)
ROUND_END局末通知(每局结束时上报,round_id 须与本局 ROUND_START 一致)
onAudioSuspend监听音频暂停事件(平台要求游戏静音时触发)
offAudioSuspend移除音频暂停事件监听
onAudioResume监听音频恢复事件(平台允许游戏恢复声音时触发)
offAudioResume移除音频恢复事件监听

集成示例

以下示例展示如何在页面中引入 SDK 并调用各项能力。

1.1 引入代码

方式一:通过 <script> 直接引入打包产物

html
<script src="https://play.letskix.com/res/game/sdk-js/GameTokSDK.js"></script>
<script>
  console.log('GameTokSDK version loaded:', !!window.GameTokSDK);
</script>

本地开发(未嵌入 App、在浏览器里调试):在引入 SDK 后调用 **GameTokSDK.enableMock()** 即可,Promise 类接口会走内置模拟数据,无需原生客户端。正式发布或提审包中请勿调用,否则用户会看到虚假数据。

html
<script src="https://play.letskix.com/res/game/sdk-js/GameTokSDK.js"></script>
<script>
  GameTokSDK.enableMock();
</script>

真机测试(已嵌入 App 的 WebView):需要看日志时,在引入 SDK 后调用 **GameTokSDK.enableDebug()**(返回 Promise,会在页面加载 vConsole,并打印与原生通信相关日志)。不要与 enableMock 同时使用。

html
<script src="https://play.letskix.com/res/game/sdk-js/GameTokSDK.js"></script>
<script>
  GameTokSDK.enableDebug();
</script>

1.2 调用示例

以下示例统一采用 Promise 的 then/catch 调用方式。成功时返回统一响应对象,失败时通过 Promise.reject 抛出错误。

1.2.1 获取个人资料

javascript
// 调用示例
GameTokSDK.getProfile()
  .then(({ action, error, data }) => {
    console.log('获取个人资料成功:', data);
  })
  .catch((e) => {
    console.error('获取个人资料失败:', e);
  });

返回示例(JSON):

json
{
  "action": "GET_PROFILE",
  "error": false,
  "data": {
    "uid": 1234567,
    "avatar": "https://profile-file-pre.lobah.net/files/2024/11/15/3/fd1c01ac6640466f92a59c0aaa6b0112_lp_profile_img_frame_male_17.png",
    "userName": "Tim tim",
    "userCoins": 0,
    "level": 0,
    "gender": 0,
    "testAccount": true,
    "guest": true
  }
}

1.2.2 游戏内购(例如购买道具)

javascript
/**
 * 游戏内购
 * @param productId   商品ID,需要在开发者后台(https://developer.lobah.net/)提前定义好
 */
GameTokSDK.purchase({ productId: 'HAB.WATER.10.COINS' })
  .then(({ data }) => {
    //需要注意,购买成功和失败需要根据这儿得返回值code码来确定  
    console.log('购买完成:', data);
  })
  .catch((e) => {
    console.error('错误捕获:', e);
  });

返回示例(JSON):

json
{
  "action": "PURCHASE",
  "error": false,
  "data": {
    "purchaseResultCode": 0, //结果码"
    "testAccount":false,     //是否测试账号,或平台审核人员账号
    "userBalance":22514      //用户的金币余额
  }
}


purchaseResultCode 的结果如下:

0: 购买成功
11: product_id 不正确
12: 用户金币不足
13: 重复或无效的 reference_id
14: 用户是游客,游客不能进行购买操作
16: product_id 不正确
20: 其他错误

1.2.3 存储键值

javascript
/**
 * 存储键值
 * @param key   需要存储的自定义键值
 * @param value 需要存储的值 可以是字符串,也可以是对象
 */
GameTokSDK.storageSet({ key: 'settings', value: { theme: 'dark', volume: 0.8 } })
  .then(() => {
    console.log('存储成功');
  })
  .catch((e) => {
    console.error('存储失败:', e);
  });

返回示例(JSON):

json
{
  "action": "STORAGE_SET",
  "error": false,
  "data": null
}

1.2.4 读取键值

javascript
/**
 * 读取键值
 * @param key   需要读取的定义好的键值
 */
GameTokSDK.storageGet({ key: 'settings' })
  .then((result) => {
    console.log('读取成功:', result.data.value); // 可能是对象或字符串
  })
  .catch((e) => {
    console.error('读取失败:', e);
  });

返回示例(JSON):

json
{
  "action": "STORAGE_GET",
  "error": false,
  "data": {
    "value": {
        "theme": "dark",
        "volume": 0.8
    }
  }
}

1.2.5 上报分数

javascript
/**
 * 对于不同的游戏,可能需要上报的是分数,也可能是关卡、等级
 * 如果是分数,就可以这样传{score:300,scoreType:'score',remark:'score'}
 * 如果是等级,就可以传 {score:1,scoreType:'level',remark:'level'}
 * @param score     需要上报的值 这个值需要为正整数
 * @param scoreType 数据类别(由业务自定义,作为上传数据的说明) 
 * @param remark    自定义说明 (可以和scoreType一致)
 */

GameTokSDK.addScore({ score: 10, scoreType: 'score',remark:'score' })
  .then(() => {
    console.log('加分成功');
  })
  .catch((e) => {
    console.error('加分失败:', e);
  });

返回示例(JSON):

json
{
  "action": "ADD_SCORE",
  "error": false,
  "data": null
}

1.2.6 获取麦克风权限

javascript
/**
 * 获取麦克风权限(安卓)
 * 用于在游戏中请求用户授予麦克风权限,以便使用语音相关功能。
 * 无返回值,仅触发原生端弹出权限请求。
 */
GameTokSDK.getPermissionMic();

1.2.7 充值(TOPUP)

重要: 用户取消支付、支付失败等结果 仍走 then,请在 then 里根据 **data.code** 判断是否成功。只有 SDK不可用、超时等异常才会进入 **catch**。

javascript
/**
 * 充值
 * @param amount 充值金额(具体单位与客户端约定一致)
 */
GameTokSDK.topup({ amount: 100 })
  .then(({ action, error, data }) => {
    const code = data && data.code;
    if (code === 200) {
      console.log('充值成功:', data);
    } else {
      console.warn('充值未完成或失败, code:', code, data);
    }
  })
  .catch((e) => {
    console.error('充值请求异常(如SDK不可用):', e);
  });

返回示例(JSON,成功):

json
{
  "action": "TOPUP",
  "error": false,
  "data": {
    "code": 200,
    "message": "ok"
  }
}

code 的值定义:
200 成功,
401 充值失败(充值异常)
402 充值失败(主动取消)

1.2.8 开局通知(ROUND_START)

每局游戏 正式开始后 调用一次,必填 round_id(本局唯一标识,由游戏侧生成)。可选 timestamp(毫秒时间戳,不传则使用当前时间)。无 Promise 返回值,发后即忘。

javascript
/**
 * 开局通知
 * @param round_id 本局唯一 ID
 * @param timestamp 可选,开局时间戳(ms)
 */
GameTokSDK.roundStart({
  round_id: 'round-' + Date.now(),
  timestamp: Date.now(),
});

若未传 round_id,SDK 会在控制台告警且 不会 向原生发送。

1.2.9 局末通知(ROUND_END)

每局 结束后 调用,round_id 须与 本局 roundStart 一致。可选 timestamp无 Promise 返回值

javascript
/**
 * 局末通知
 * @param round_id 与本局 roundStart 相同
 * @param timestamp 可选,结束时间戳(ms)
 */
const roundId = 'round-' + Date.now();
GameTokSDK.roundStart({ round_id: roundId });
// ... 本局逻辑 ...
GameTokSDK.roundEnd({ round_id: roundId, timestamp: Date.now() });

1.2.10 音频事件监听(onAudioSuspend / offAudioSuspend / onAudioResume / offAudioResume)

当平台需要游戏静音(如用户进入直播间、系统来电等场景),会向游戏推送音频暂停事件;当允许恢复声音时,会推送音频恢复事件。游戏应在收到事件后及时暂停/恢复所有音效和背景音乐。

这是事件监听接口,不是 Promise 接口,无返回值。

javascript
// 监听音频暂停事件
function handleAudioSuspend(payload) {
  console.log('收到静音通知:', payload);
  // 暂停游戏中所有音效、背景音乐
  myGame.muteAll();
}

GameTokSDK.onAudioSuspend(handleAudioSuspend);

// 监听音频恢复事件
function handleAudioResume(payload) {
  console.log('收到恢复声音通知:', payload);
  // 恢复游戏中所有音效、背景音乐
  myGame.unmuteAll();
}

GameTokSDK.onAudioResume(handleAudioResume);

移除监听:

javascript
// 移除音频暂停监听(传入注册时的同一函数引用)
GameTokSDK.offAudioSuspend(handleAudioSuspend);

// 移除音频恢复监听
GameTokSDK.offAudioResume(handleAudioResume);

**options.sync 参数(状态同步):**

onAudioSuspendonAudioResume 支持第二个可选参数 options,其中 sync(默认 true)用于处理"注册时机晚于事件触发"的场景:

  • sync: true(默认)—— 若注册监听时音频已经处于暂停/恢复状态,回调会在下一个微任务中被立即同步调用一次,确保游戏不会错过之前的状态变化。
  • sync: false —— 只监听后续新的事件推送,不做注册时的状态同步。
javascript
// 默认 sync: true,若此时音频已被暂停,回调会立即触发一次
GameTokSDK.onAudioSuspend((payload) => {
  myGame.muteAll();
});

// 关闭状态同步,仅监听后续事件
GameTokSDK.onAudioSuspend((payload) => {
  myGame.muteAll();
}, { sync: false });

推荐用法: 在游戏初始化阶段尽早注册监听,并保持 sync: true(默认),这样即使注册时平台已经发送过静音指令,游戏也能正确同步状态。

参数与返回结构

  • 通用调用参数示例(参考,具体参数以各能力为准):
    • getProfile:``(通常无需额外参数)
    • purchase:{ productId: string }
    • storageSet:{ key: string, value: any }
    • storageGet:{ key: string }
    • addScore:{ score: number, scoreType: string }
    • getPermissionMic:``(通常无需额外参数)
    • topup:{ amount: number, ... }(其它字段以客户端协议为准)
    • roundStart / roundEnd:{ round_id: string, timestamp?: number }
    • onAudioSuspend / onAudioResume:(handler: Function, options?: { sync?: boolean })
    • offAudioSuspend / offAudioResume:(handler: Function)
  • 成功返回统一结构:
typescript
{
  action: string;      // 本次调用的动作名(如 'GET_PROFILE')
  error: false;        // 成功时为 false(失败时 promise 会直接 reject)
  data: any;           // 原生回包内容,字段由具体动作定义
}
  • 失败行为:
    • **topup:** 业务成功/失败/取消等 多数在 then 通过 **data.code** 区分;catch 多为SDK异常、超时等。
    • 其它 Promise 接口: 失败时 Promise 将直接 reject 一个 Error 对象;建议在 .catch 中记录错误并进行重试或提示。

重要说明

为确保 SDK 正常工作,请勿覆盖或删除以下关键全局对象:

  • window.GameTokSDK(SDK 主接口)

示例(错误用法,请勿复制):

javascript
// 危险!将导致 iOS 或 Android 通信失效
window.GameTokSDK = {};
window.GameTokSDK = null;
delete window.GameTokSDK;

完整示例

javascript
// 获取用户资料
GameTokSDK.getProfile({})
        .then((resp) => {
          console.log('Profile:', resp.data);
        })
        .catch((e) => {
          console.error('获取个人资料失败:', e);
        });

// 存储数据
GameTokSDK.storageSet({ key: 'config', value: { lang: 'zh-CN' } })
        .then(() => {
          console.log('存储成功');
        })
        .catch((e) => {
          console.error('存储失败:', e);
        });

// 读取数据
GameTokSDK.storageGet({ key: 'config' })
        .then((resp) => {
          console.log('Config:', resp.data.value);
        })
        .catch((e) => {
          console.error('读取失败:', e);
        });

// 购买示例
GameTokSDK.purchase({ productId: 'HAB.WATER.10.COINS' })
        .then((resp) => {
          console.log('Purchase:', resp.data);
        })
        .catch((e) => {
          console.error('购买失败:', e);
        });

// 加分示例
GameTokSDK.addScore({ score: 5, scoreType: 'score' })
        .then(() => {
          console.log('Score added');
        })
        .catch((e) => {
          console.error('加分失败:', e);
        });

// 获取麦克风权限(安卓,无返回值)
GameTokSDK.getPermissionMic();

// 充值:在 then 里用 data.code 判断(如 200 表示成功)
GameTokSDK.topup({ amount: 100 })
        .then(({ data }) => {
          if (data && data.code === 200) {
            console.log('充值成功', data);
          } else {
            console.log('充值未成功', data);
          }
        })
        .catch((e) => console.error('充值异常', e));

// 局次通知(round_id 前后一致)
const rid = 'r-' + Date.now();
GameTokSDK.roundStart({ round_id: rid });
GameTokSDK.roundEnd({ round_id: rid });

// 音频事件监听(在游戏初始化阶段注册)
GameTokSDK.onAudioSuspend((payload) => {
  console.log('静音', payload);
  myGame.muteAll();
});

GameTokSDK.onAudioResume((payload) => {
  console.log('恢复声音', payload);
  myGame.unmuteAll();
});

Swipe & Play Endless Game Together