SDK
This SDK provides secure bidirectional communication between the game and the native clients (iOS and Android), enabling third‑party developers to invoke native capabilities.
Exposed global API name: window.GameTokSDK
Capabilities:
| Action | Description |
|---|---|
| GET_PROFILE | Get the current user profile |
| PURCHASE | Initiate a purchase (e.g., in‑app purchase) |
| STORAGE_SET | Write to local key‑value storage (settings, progress, etc.) |
| STORAGE_GET | Read from local key‑value storage (retrieve previously saved data) |
| ADD_SCORE | Report a score (leaderboards, sharing, etc.) |
| GET_PERMISSION_MIC | Request microphone permission (Android) |
| TOPUP | Top up when in‑game currency is low; opens the client top‑up flow |
| ROUND_START | Round start notification (call once per round start; tied to platform round/energy policies) |
| ROUND_END | Round end notification (call when a round ends; round_id must match this round's ROUND_START) |
| onAudioSuspend | Listen for audio suspend event (triggered when the platform requires the game to mute) |
| offAudioSuspend | Remove audio suspend event listener |
| onAudioResume | Listen for audio resume event (triggered when the platform allows the game to restore sound) |
| offAudioResume | Remove audio resume event listener |
Integration examples
The following shows how to include the SDK on a page and call each capability.
1.1 Including the script
Option 1: Load the bundle via <script>
<script src="https://play.letskix.com/res/game/sdk-js/GameTokSDK.js"></script>
<script>
console.log('GameTokSDK version loaded:', !!window.GameTokSDK);
</script>Local development (not embedded in the app, debugging in a browser): After loading the SDK, call GameTokSDK.enableMock(). Promise‑based APIs will use built‑in mock data; no native client is required. Do not call this in production or store submission builds, or users will see fake data.
<script src="https://play.letskix.com/res/game/sdk-js/GameTokSDK.js"></script>
<script>
GameTokSDK.enableMock();
</script>Device testing (WebView inside the app): When you need logs, after loading the SDK call GameTokSDK.enableDebug() (returns a Promise; loads vConsole on the page and logs native bridge traffic). Do not use together with enableMock.
<script src="https://play.letskix.com/res/game/sdk-js/GameTokSDK.js"></script>
<script>
GameTokSDK.enableDebug();
</script>1.2 Usage examples
All examples use then / catch with Promises. On success, a unified response object is returned; on failure, the Promise rejects.
1.2.1 Get profile
// Example call
GameTokSDK.getProfile()
.then(({ action, error, data }) => {
console.log('Profile loaded:', data);
})
.catch((e) => {
console.error('Failed to get profile:', e);
});Sample response (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 In‑app purchase (e.g., buy an item)
/**
* In‑app purchase
* @param productId Product ID; must be defined beforehand in the developer console (https://developer.lobah.net/)
*/
GameTokSDK.purchase({ productId: 'HAB.WATER.10.COINS' })
.then(({ data }) => {
// Success vs failure must be determined from the returned code here
console.log('Purchase finished:', data);
})
.catch((e) => {
console.error('Error:', e);
});Sample response (JSON):
{
"action": "PURCHASE",
"error": false,
"data": {
"purchaseResultCode": 0,
"testAccount": false,
"userBalance": 22514
}
}purchaseResultCode values:
0: Purchase succeeded11: Invalidproduct_id12: Insufficient user coins13: Duplicate or invalidreference_id14: User is a guest; guests cannot purchase16: Invalidproduct_id20: Other error
1.2.3 Store key‑value
/**
* Store a key‑value pair
* @param key Custom key
* @param value Value; may be a string or an object
*/
GameTokSDK.storageSet({ key: 'settings', value: { theme: 'dark', volume: 0.8 } })
.then(() => {
console.log('Stored successfully');
})
.catch((e) => {
console.error('Store failed:', e);
});Sample response (JSON):
{
"action": "STORAGE_SET",
"error": false,
"data": null
}1.2.4 Read key‑value
/**
* Read a key‑value pair
* @param key Predefined key to read
*/
GameTokSDK.storageGet({ key: 'settings' })
.then((result) => {
console.log('Read OK:', result.data.value); // object or string
})
.catch((e) => {
console.error('Read failed:', e);
});Sample response (JSON):
{
"action": "STORAGE_GET",
"error": false,
"data": {
"value": {
"theme": "dark",
"volume": 0.8
}
}
}1.2.5 Report score
/**
* Depending on the game, you may report score, stage, or level.
* For score: { score: 300, scoreType: 'score', remark: 'score' }
* For level: { score: 1, scoreType: 'level', remark: 'level' }
* @param score Value to report; must be a positive integer
* @param scoreType Category (business‑defined label for the uploaded data)
* @param remark Optional note (may match scoreType)
*/
GameTokSDK.addScore({ score: 10, scoreType: 'score', remark: 'score' })
.then(() => {
console.log('Score reported');
})
.catch((e) => {
console.error('Report failed:', e);
});Sample response (JSON):
{
"action": "ADD_SCORE",
"error": false,
"data": null
}1.2.6 Microphone permission
/**
* Request microphone permission (Android)
* Use in‑game to prompt the user for mic access (e.g., voice features).
* No return value; only triggers the native permission UI.
*/
GameTokSDK.getPermissionMic();1.2.7 Top up (TOPUP)
Important: User cancel, payment failure, etc. still resolve via then. In then, check data.code for success. catch is only for SDK unavailability, timeouts, and similar errors.
/**
* Top up
* @param amount Amount (units as agreed with the client)
*/
GameTokSDK.topup({ amount: 100 })
.then(({ action, error, data }) => {
const code = data && data.code;
if (code === 200) {
console.log('Top‑up succeeded:', data);
} else {
console.warn('Top‑up incomplete or failed, code:', code, data);
}
})
.catch((e) => {
console.error('Top‑up request error (e.g., SDK unavailable):', e);
});Sample response (JSON, success):
{
"action": "TOPUP",
"error": false,
"data": {
"code": 200,
"message": "ok"
}
}
code values:
200 Success
401 Top-up failed (error)
402 Top-up failed (user cancelled)1.2.8 Round start (ROUND_START)
Call once after a round actually starts. round_id is required (unique ID for this round, generated by the game). Optional timestamp (ms; defaults to now if omitted). No Promise return — fire‑and‑forget.
/**
* Round start notification
* @param round_id Unique ID for this round
* @param timestamp Optional start time (ms)
*/
GameTokSDK.roundStart({
round_id: 'round-' + Date.now(),
timestamp: Date.now(),
});If round_id is missing, the SDK logs a warning and does not send to native.
1.2.9 Round end (ROUND_END)
Call when the round ends. round_id must match this round's roundStart. Optional timestamp. No Promise return.
/**
* Round end notification
* @param round_id Same as this round's roundStart
* @param timestamp Optional end time (ms)
*/
const roundId = 'round-' + Date.now();
GameTokSDK.roundStart({ round_id: roundId });
// ... round logic ...
GameTokSDK.roundEnd({ round_id: roundId, timestamp: Date.now() });1.2.10 Audio event listeners (onAudioSuspend / offAudioSuspend / onAudioResume / offAudioResume)
When the platform requires the game to mute (e.g., the user enters a live room, a system call comes in, etc.), an audio suspend event is pushed to the game; when sound is allowed to resume, an audio resume event is pushed. The game should promptly mute/unmute all sound effects and background music upon receiving these events.
This is an event listener interface, not a Promise interface, and has no return value.
// Listen for audio suspend event
function handleAudioSuspend(payload) {
console.log('Mute notification received:', payload);
// Mute all sound effects and background music in the game
myGame.muteAll();
}
GameTokSDK.onAudioSuspend(handleAudioSuspend);
// Listen for audio resume event
function handleAudioResume(payload) {
console.log('Resume sound notification received:', payload);
// Restore all sound effects and background music in the game
myGame.unmuteAll();
}
GameTokSDK.onAudioResume(handleAudioResume);Remove listeners:
// Remove audio suspend listener (pass the same function reference used when registering)
GameTokSDK.offAudioSuspend(handleAudioSuspend);
// Remove audio resume listener
GameTokSDK.offAudioResume(handleAudioResume);options.sync parameter (state synchronization):
onAudioSuspend and onAudioResume support a second optional options parameter, where sync (default true) handles the case where the listener is registered after the event has already fired:
sync: true(default) — If audio is already in a suspended/resumed state when the listener is registered, the callback will be called once immediately in the next microtask, ensuring the game does not miss previous state changes.sync: false— Only listens for subsequent new event pushes; no state sync on registration.
// Default sync: true — if audio is already suspended, callback fires immediately once
GameTokSDK.onAudioSuspend((payload) => {
myGame.muteAll();
});
// Disable state sync, only listen for subsequent events
GameTokSDK.onAudioSuspend((payload) => {
myGame.muteAll();
}, { sync: false });Recommended usage: Register listeners as early as possible during game initialization and keep sync: true (default), so the game can correctly sync state even if the platform has already sent a mute instruction before registration.
Parameters and response shape
- Typical call parameters (reference; see each API for exact fields):
- getProfile: `` (usually no extra parameters)
- purchase:
{ productId: string } - storageSet:
{ key: string, value: any } - storageGet:
{ key: string } - addScore:
{ score: number, scoreType: string } - getPermissionMic: `` (usually no extra parameters)
- topup:
{ amount: number, ... }(other fields per client protocol) - roundStart / roundEnd:
{ round_id: string, timestamp?: number } - onAudioSuspend / onAudioResume:
(handler: Function, options?: { sync?: boolean }) - offAudioSuspend / offAudioResume:
(handler: Function)
- Successful responses share this shape:
{
action: string; // Action name for this call (e.g. 'GET_PROFILE')
error: false; // false on success (on failure the Promise rejects)
data: any; // Native payload; fields depend on the action
}- Failure behavior:
topup: Most business outcomes (success/failure/cancel) resolve inthenviadata.code;catchis for SDK errors and timeouts.- Other Promise interfaces: On failure the Promise rejects with an
Error; handle in.catch(log, retry, or show UI).
Important notes
Do not overwrite or remove these globals, or the SDK will break:
window.GameTokSDK(main SDK entry)
Example (do not do this):
// Dangerous — breaks iOS / Android bridge
window.GameTokSDK = {};
window.GameTokSDK = null;
delete window.GameTokSDK;Full example
// Profile
GameTokSDK.getProfile({})
.then((resp) => {
console.log('Profile:', resp.data);
})
.catch((e) => {
console.error('Failed to get profile:', e);
});
// Store
GameTokSDK.storageSet({ key: 'config', value: { lang: 'zh-CN' } })
.then(() => {
console.log('Stored successfully');
})
.catch((e) => {
console.error('Store failed:', e);
});
// Read
GameTokSDK.storageGet({ key: 'config' })
.then((resp) => {
console.log('Config:', resp.data.value);
})
.catch((e) => {
console.error('Read failed:', e);
});
// Purchase
GameTokSDK.purchase({ productId: 'HAB.WATER.10.COINS' })
.then((resp) => {
console.log('Purchase:', resp.data);
})
.catch((e) => {
console.error('Purchase failed:', e);
});
// Score
GameTokSDK.addScore({ score: 5, scoreType: 'score' })
.then(() => {
console.log('Score added');
})
.catch((e) => {
console.error('Score report failed:', e);
});
// Microphone (Android, no return value)
GameTokSDK.getPermissionMic();
// Top up: check data.code in then (200 = success)
GameTokSDK.topup({ amount: 100 })
.then(({ data }) => {
if (data && data.code === 200) {
console.log('Top-up succeeded', data);
} else {
console.log('Top-up not successful', data);
}
})
.catch((e) => console.error('Top-up error', e));
// Round notifications (same round_id)
const rid = 'r-' + Date.now();
GameTokSDK.roundStart({ round_id: rid });
GameTokSDK.roundEnd({ round_id: rid });
// Audio event listeners (register during game initialization)
GameTokSDK.onAudioSuspend((payload) => {
console.log('Mute', payload);
myGame.muteAll();
});
GameTokSDK.onAudioResume((payload) => {
console.log('Resume sound', payload);
myGame.unmuteAll();
});