跳到主内容

INTEGRATION GUIDE

Game Service Integration Guide

Complete integration documentation for engineering teams: client loading, JS Bridge communication, server deployment, signed APIs, and callbacks.

1. Game Integration Modes

Gamefans supports two integration modes on the game side: the game-owned lobby mode and the business-side matchmaking mode. The business workflow and the APIs that need to be invoked differ between the two modes.

1.1 Game-Owned Lobby Mode

The sequence diagram for this mode is shown below. In this mode, the game itself maintains the seat state: when a player joins or leaves the game, the game actively calls the relevant server-side APIs. The business side can also use the related APIs to seat/unseat players or add bots.

1.2 Business-Side Matchmaking Mode

In this mode, the business side maintains the game player state and, when a game needs to start, calls the game service APIs to inform the game of the player list and to start the game. The sequence diagram after integrating this mode is shown below.

2. Client Integration

The game package is delivered as static files, deployed as a web page, and loaded via a URL. The interaction between the game and the business-side client is performed through a JS Bridge. The URL parameters control the game's behavior; the JS Bridge methods and events enable interaction between the game and the business-side client. The game ships with a set of predefined events and methods, and additional events or methods can be added per business-side requirements.

2.1 Client Deployment

The delivered game client consists of static files. It must be deployed as a web page to the appropriate server, object storage, or other location, with CDN enabled as required.

2.2 Client Loading

Once the game is deployed, it can be loaded via a URL. The following parameters are required to load the game:

ParameterTypeDescription
app_idstringAPP ID
room_idstringRoom ID
tokenstringUser identifier
languagestringGame language code
extraJSONOther information

The extra field contains the following parameters:

FieldTypeRequiredDefaultDescription
http_urlstringYes--URL of the HTTP API called by the game
ws_urlstringYes--URL of the WebSocket API called by the game
topintNo0Safe area top boundary
bottomintNo0Safe area bottom boundary
leftintNo0Safe area left boundary
rightintNo0Safe area right boundary
widthintNo--Game width
heightintNo--Game height
auto_scaleintNo0Whether to auto-scale: 0 disables, 1 enables

Taking the following parameter values as an example:

ParameterValue
app_id5147182126419264
room_id89945
tokenHWUEv2uXigqYEG0t
languagezh-CN
extra{"http_url":"https://example.com/api","ws_url":"wss://example.com/websocket-endpoint","top":100,"bottom":300,"auto_scale":0}

The final constructed game URL is as follows:

plain
https://example.com/ludo?app_id=5147182126419264&room_id=89945&token=HWUEv2uXigqYEG0t&language=zh-CN&extra=%7B%22http_url%22%3A%22https%3A%2F%2Fexample.com%2Fapi%22%2C%22ws_url%22%3A%22wss%3A%2F%2Fexample.com%2Fwebsocket-endpoint%22%2C%22top%22%3A100%2C%22bottom%22%3A300%2C%22auto_scale%22%3A0%7D

The extra parameter is a url-encoded JSON string, which after decoding is:

json
{"http_url":"https://example.com/api","ws_url":"wss://example.com/websocket-endpoint","top":100,"bottom":300,"auto_scale":0}

2.3 Client APIs

The game and the business side communicate through a JS Bridge. The business-side APP needs to register a JS Bridge to implement the relevant functions. The following files contain the Android and iOS integration code samples:

2.3.1 Android Integration

1. Add JS Interface
java
mViewModel = new GameViewModel(mWebView);
mWebView.addJavascriptInterface(mViewModel, "GameJSBridgeAndroid");
2. GameViewModel.java

Communication is centralized in this file and can be reused directly

1. Send message to the game
java
String state = "app_common_android";
String json = "{\"key\":\"value\"}";
mViewModel.sendMessageToGame(state, json, new GameViewModel.GameMessageCallback() {
    @Override
    public void onCallbackMessage(String json) {
        LogUtils.d("收到了游戏的消息回调:" + json);
    }
});
2. Set up a listener to receive data from the game
java
mViewModel.setOnGameMessageListener(new GameViewModel.OnGameMessageListener() {
    @Override
    public void onMessage(String state, String json, GameViewModel.GameMessageHandler handler) {
        LogUtils.d("收到游戏发送过来的消息:" + state + " json:" + json);
        // 给游戏回调应答消息,必须要调用,格式和内容请查看文档定义
        String backJson = "{\"msg\":\"Android收到消息了\"}";
        handler.completed(backJson);
    }
});

2.3.2 iOS Integration

1. Add JS Message Handlers
swift
// 添加消息处理,其中onMessageFromGame和onCallbackMessage是必须的
userContentController.add(context.coordinator, name: "onMessageFromGame")
userContentController.add(context.coordinator, name: "onCallbackMessage")

// 在Coordinator的userContentController方法中,将消息传递给GameViewModel
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    parent.viewModel.userContentController(name: message.name,body: "\(message.body)")
}
2. GameViewModel.swift

Communication is centralized in this file and can be reused directly

1. Send message to the game
swift
let state = "app_common_ios"
let json = "{\"testKey\":\"haha\"}"
viewModel.sendMessageToGame(state:state,json:json){ json in
    print("count:\(count) 游戏给的回调数据为:\(json ?? "")")
}
2. Set up a listener to receive data from the game
swift
// 设置游戏消息监听
viewModel.setOnGameMessageListener(listener: MyGameMessageListener())

class MyGameMessageListener: OnGameMessageListener {
    func onMessage(state: String, json: String, handler: (String) -> Void) {
        print("iOS收到游戏发来的消息,state:\(state) json:\(json)")

        // 给游戏回调应答消息,必须要调用,格式和内容请查看文档定义
        let backJson = "{\"msg\":\"iOS收到消息了\"}"
        handler(backJson)
    }
}

2.4 Client Events

When the game and the APP communicate bidirectionally through the JS Bridge, both sides need to pass the state and data parameters, together with callback as the response handler.

Using sendMsgToApp as an example:

javascript
bridge.sendMsgToApp = function (state, data, callback) { ... }
ParameterTypeDescription
statestringCommand identifier — the event carried by the communication
dataJSON stringData carried by the communication, formatted as a valid JSON string
callbackcallableResponse callback

2.4.1 Events Sent from the Game to the APP

1. Game Load Completed

mg_common_notify_load_completed notifies the app that the game has finished loading

ParameterContentDescription
statemg_common_notify_load_completedThis message is sent when the game finishes loading
json---
callback---
2. Game Settlement

mg_common_game_settlement notifies the app of the game-end data

ParameterContentDescription
statemg_common_game_settlementSent when the game settlement screen appears
jsonStructure as follows
callback---

The data field structure is as follows:

json
{
    "results": IResult[], // 玩家信息列表
    "reason": number,     // 游戏结束原因 0: 正常结束  3: 提前结束
    "roundId": string,    // 局id
    "chessNum": number,   // 当局玩法棋子个数 4 或者 2
    "item": number,       // 当局游戏是否有道具 0:无 1:有
    "model": number       // 当局游戏是快速模式还是经典模式 0:快速 1:经典
}

IResult interface definition:

typescript
interface IResult{
    uid: string,
    appId: string,
    userId: string,    // 对应app侧的玩家id    
    name: string,
    avatar: string,
    gender: string,
    score: number,    // 得分
    rank: number,
    isEscaped: number,
    isAI: number,
    isManaged: number, // 是否托管完成游戏 1:托管完成 0:不是托管完成
    extras: string,
}

3. Other Events

The game can send relevant events during the game flow according to the business-side requirements.

2.4.2 Events Sent from the APP to the Game

These events can be flexibly defined according to business-side requirements, for example operating the game's background music or sound effects through the native UI, or showing relevant game UI. After registering the JS Bridge, the following call can be used to send events to the game:

javascript
bridge.sendMsgToGame = function (message) {}

3. Server Deployment

The server side is delivered as compiled binaries. The business side must provide the required APIs according to the documentation to complete the server configuration and deployment.

3.1 Server Resources

The server deployment must meet the following minimum server requirements:

No.SpecCountPurpose
11 core / 2 GB1 unitetcd service
22 cores / 4 GBdepends on request volumeGame service

If a single-machine deployment is required, the etcd service can be deployed together with the game service on the same server with a 2-core/4GB configuration; however, for environment management and scalability, it is recommended to keep them on separate servers.

In addition to the server resources above, the business side also needs to prepare a redis service.

3.2 Deployment Process

  • File preparation: the delivered game server binary package gfs.zip
  • API preparation: the get-user-info API and the game-event notification callback API required by the game server; refer to the next section for details
  1. Deploy the etcd service according to the server requirements in the table above
  2. Prepare the redis service
  3. Upload gfs.zip to the game deployment server and unzip it
  4. Modify etcd settings in httpgate/config/config.yaml, return to the httpgate directory, and run bash service.sh start to launch the service
  5. Modify etcd and redis settings in tcpgate/config/config.yaml, return to the tcpgate directory, and run bash service.sh start to launch the service
  6. Modify etcd and redis settings in timer/config/config.yaml, return to the timer directory, and run bash service.sh start to launch the service
  7. Modify etcd and redis settings in {{game_name}}/config/config.yaml, fill in get_user_info_url and notify_url, return to the ludo directory, and run bash service.sh start to launch the service
  8. If distributed deployment is required, repeat steps 3 through 7

Notes:

  • Use bash to execute the service.sh script

    Configuration items that need to be modified include:

    • etcd_urls: etcd service address
    • redis: redis service configuration
    • app_info.app_id
    • app_info.secret
    • app_info.get_user_info_url: get-user-info endpoint URL the game server calls
    • app_info.notify_url: event-notification endpoint URL the game server calls
  • Check the executable permission of the service.sh script before starting the service; if it lacks execute permission, add it via chmod +x service.sh

4. Server Integration

All server APIs follow the rules below:

  1. All APIs exchange data using UTF-8 encoded JSON strings
  2. The basic format of the API response is as follows. The callback APIs provided by the business side must also follow this format. Unless otherwise specified, the rest of this document assumes this response format and does not list it separately.
json
{
    "ret_code": 0,        // 接口响应码,用来判断本次请求是否成功
    "ret_msg": "ok",      // 接口响应信息,可提供简单的
    "data": []            // 响应数据,由具体业务确定其类型
}

4.1 Game Callback APIs Provided by the Business Side

All APIs in this section must be provided by the business side. The game server calls them at appropriate moments during the game's runtime to obtain the relevant information and complete the corresponding functions.

4.1.1 Get User Info

The game server uses this API to retrieve the basic information of in-game users, such as username and avatar.

- Request Definition

http
POST  业务侧提供URL
Accept: application/json  
Content-Type: application/json

{
    "token": "{{token}}", 
    "app_id": "{{app_id}}"
}    
ParameterTypeDescription
tokenstringUnique user identifier
app_idstringAPP unique identifier

- Response Definition

json
{
    "ret_code": 0,
    "ret_msg": "",
    "data": {
        "user_id": "123456",  
        "name": "Username",  
        "avatar": "https://example.com/avatar.png",  
        "gender": "male",
        "is_ai": 0,
        "extras": "{\"skin_type\": 0}"
    }
}
`data` Type Definition
FieldTypeDescription
user_idstringUnique user identifier
namestringDisplay name
avatarstringAvatar URL
genderstringGender
is_aiintBot: 0 = real player, 1-3 = bot level
extrasstringJSON-string extension field

`extras` field definition: this field has type `string`, which is an escaped `JSON` string. The specific data interface needs to be defined according to the concrete business requirements.

4.1.2 Game Event Callback

When the game state changes, the game server synchronizes the game state by calling this API.

Common API Information

All game callback APIs include the parameters specified here. The data field is determined by each individual event — refer to the corresponding request definition for the specific event.

- Request Definition

http
POST 业务侧提供URL
Accept: application/json  
Content-Type: application/json

{ 
    "event": "{{game_event}}", 
    "notify_id": "{{notify_id}}", 
    "game_name": "{{game_name}}", 
    "app_id": "{{app_id}}", 
    "room_id": "{{room_id}}", 
    "timestamp":"{{timestamp}}", 
    "data": {} 
}
ParameterTypeDescription
eventstringGame event type
notify_idstringUnique identifier of the event message
game_namestringGame name
app_idstringAPP unique identifier
room_idstringRoom unique identifier
timestampstringMillisecond timestamp string
dataobjectOther related information; refer to the request definition of the specific event

- Response Definition

json
{
    "ret_code": 0,
    "ret_msg": "",
    "data": null
}
Game start event: game_start

When the game officially starts, the server calls this API to notify the game_start event.

- Request Definition

json
{ 
    // 通用字段
    "event": "game_start", 
    ...
    "data": {
        "mode": 1,
        "round_id": "{{round_id}}",
        "start_time": 11230182038080,
        "players": [{
            "user_id": "{{user_id}}",
            "seat_index": 0,
            "status": "IDLE",
            "is_ai": 0
        }],
        "extras": "",
        "app_extras": ""
    } 
}
`data` Type Definition
ParameterTypeDescription
modeintMode
round_idstringRound ID
start_timeintGame start timestamp
playersPlayerInfo[]List of players participating in the game
extrasstringExtension field
app_extrasstringBusiness-side pass-through field
`PlayerInfo` Type Definition
ParameterTypeDescription
user_idstringUser ID
seat_indexintSeat index
statusstringStatus: IDLE = idle, READY = ready
is_aiintWhether the player is a bot
Game end event: game_end

When the game ends, the server calls this API to notify the game_end event.

- Request Definition

json

{ 
    // 通用字段
    "event": "game_end", 
    ...
    "data": {
        "mode": 1,
        "round_id": "{{round_id}}",
        "start_time": 11230182038080,
        "end_time": 11230182038080,
        "duration": 5000,
        "results": [{
            "user_id": "{{user_id}}",
            "is_ai": 0,
            "rank": 1,
            "score": 10,
            "is_win": 1,
            "is_escaped": 0,
            "is_managed": 0,
            "extras": ""
        }],
        "extras": "",
        "app_extras": ""
    } 
}
`data` Type Definition
ParameterTypeDescription
modeintMode
round_idstringRound ID
start_timeintGame start timestamp
end_timeintGame end timestamp
durationintGame duration in milliseconds
resultsResult[]List of players
extrasstringExtension field
app_extrasstringBusiness-side pass-through field
`Result` Type Definition
ParameterTypeDescription
user_idstringUser ID
is_aiintWhether the player is a bot
rankintRank
scoreintScore
is_winintResult: 1 = loss, 2 = win, 3 = draw
is_escapedintWhether escaped: 0 = no, 1 = yes
is_managedintWhether managed (auto-play): 0 = no, 1 = yes
extrasstringExtension field

4.2 Calling the Game Server APIs

4.2.1 API Signature Mechanism

Calling the game server APIs requires signature verification. This section describes the parameters and the signature method required for API signing. Unless otherwise specified, signature verification is required for all APIs.

1. Signature Parameters
ParameterTypeDescription
auth_typestringAuthentication type: gfs
app_idstringAPP unique identifier
secretstringAPP key
timestampstringRequest timestamp
noncestringRandom string
bodyjson stringRequest body in JSON format
2. Signature Steps

Concatenate the parameters in the following format: four lines, each ending with \n (including the last line).

plain
{{app_id}}\n
{{timestamp}}\n
{{nonce}}\n
{{body}}\n

Use `secret` as the key to apply `HmacSHA1` encryption on the string from the previous step, producing the request signature.

plain
sign = hmac_sha1(origin, secret)

Add the `Authorization` request header to the request. The content must be written on a single line.

http
POST url
Authorization: {{auth_type}} app_id="{{app_id}}",timestamp={{timestamp}},nonce={{nonce}},signature={{sign}}
3. Signature Example

Use the following data for the signature demonstration

ParameterSample value
auth_typegfs
app_id123456
secretabcdef
timestamp1718777147021
noncewHwZk4veHDFSpiw5
body--

Build the signature string `origin`

plain
123456
1718777147021
wHwZk4veHDFSpiw5
{"event":"user_enter","app_id":"123456","room_id":"200071","timestamp":"1718777146975","data":{"user_info":{"user_id":"200001","avatar":"https://gfs-static.cyouth.cn/upload/avatar/133482529220956160.png","name":"CYouth","gender":"0","is_ai":0}}}

# 最后一行也有换行符\n

Compute the signature

plain
sign = hmac_sha1(origin, secret)
# secret = abcdef
# sign = 24e819bb9a6bac0c02f141e0ff41ed1bf342db79

Add the request header

http
Authorization: gfs app_id="123456",timestamp="1718777147021",nonce="wHwZk4veHDFSpiw5",signature="24e819bb9a6bac0c02f141e0ff41ed1bf342db79"

Send the request

4.2.2 API Response Codes

Response codeDescription
0Success
100000Generic error
100001code creation failed
100002code verification failed
100003code parsing failed
100004code invalid
100005code expired
100006get_user_info request failed
100007get_user_info data parsing failed
100008get_user_info integration error; HTTP status code is not 200
100009http missing code parameter
100010http missing appId parameter
100101Login error
100102Join error
100103Cannot join a seat in an ongoing game
100104Room is full
100105Duplicate join
100106Seat is occupied
100107A bot (AI) cannot be the team leader
100108Exit error
100109Not on a game seat
100110Cannot leave while not idle
100111Ready error
100112Cancel-ready error
100113Start error
100114Game already started
100115Only the team leader can start the game
100116Someone is not ready
100117Not enough players to start the game
100118Kick error
100119Only the team leader can kick
100120Cannot kick in an ongoing game
100121Cannot kick yourself
100122Change-leader error
100123Escape error
100124Game already ended when escaping
100125Player already left the game when escaping
100126Dissolve error
100127Game already ended when dissolving
100128Only the team leader can dissolve

4.2.3 Game Server APIs

1. Common API Information

This section provides the common information for calling the game server APIs. Unless otherwise specified, all APIs must be called using the method described here and carry the data fields defined here.

- Common Request Definition

http
POST {{baseURL}}/{game}/app_event
Accept: application/json
Content-Type: application/json

{  
    "event": "user_enter",  
    "app_id": "app_id_1",  
    "room_id": "room_id_1",  
    "timestamp": "1657770493152",  
    "data": {}
}
FieldLocationTypeDescription
gameURLstringGame name
eventbodystringEvent type
app_idbodystringAPP unique identifier
room_idbodystringRoom unique identifier
timestampbodystringMillisecond timestamp
databodyobjectData required by the API; varies per API

- Common Response Definition

FieldTypeDescription
ret_codeintResponse code
ret_msgstringResponse message
data----
2. Player Seat-Up API

This API is used to add a specified player to a game seat and requires the joining user's information.

- Request Definition

json
{
    "event": "user_enter",
    "app_id": "{{app_id}}",
    "room_id": "{{room_id}}",
    "timestamp": "{{timestamp}}",
    "data": {
        "user_info": {
            "user_id": "",
            "avatar": "",
            "name": "",
            "gender": "",
            "extra": ""
        }
    }
}

- `UserInfo` Definition

FieldTypeDescription
user_idstringUnique user identifier
avatarstringUser avatar URL
namestringUser display name
genderstringGender
extrasJSON stringExtension field

- `UserInfo.extras` Definition

FieldTypeDescription
skin_typeintSkin type; valid range: 1-4
3. End Game or User Escape

This API is used to end a round of the game or to mark a user as having escaped.

- Request Definition

json
{  
    // 通用字段
    "event": "game_end",  
    "app_id": "{{app_id}}",  
    "room_id": "{{room_id}}",  
    "timestamp": "{{timestamp}}",
    "data": {  
        "user_id": ""
    }
}
`data` Type Definition
FieldTypeDescription
user_idstringUser ID; included when a specific user is escaping. Defaults to empty, which means the game ends early
4. Add Bot

This API is used to add a bot player to the room. A bot cannot act as the team leader, so a player must already be in the game before adding a bot.

- Request Definition

json
{  
    // 通用字段
    "event": "ai_add",  
    "app_id": "{{app_id}}",  
    "room_id": "{{room_id}}",  
    "timestamp": "{{timestamp}}",
    "data": {  
        "user_infos": [
            {
                "user_id": "",
                "avatar": "",
                "name": "",
                "gender": "",
                "extra": ""
            }
        ],
        "is_ready": true
    }
}
`data` Type Definition
FieldTypeDescription
user_infosuserInfo[]Information for one or more bot players to add
is_readybooleanWhether the bot players are in the ready state

- Response Definition

When the request succeeds (i.e., `ret_code` is 0), the data has the following structure:

`data` Type Definition
FieldTypeDescription
user_idsstring[]Array of bot uids successfully added

5. FAQ

The game uses safe-area configuration to avoid UI occlusion, so that space is reserved for the business-side client UI even when the game is full screen. Simply provide the safe-area parameters (top, bottom, left, right) in the game URL; the parameter values are the size of the area to reserve.