Platform Capability Integration
The Host SDK allows integrators to override some of the JS interfaces open to minigame developers to integrate platform-side login SDK, advertising SDK, payment SDK, and other functions. Developers integrating the Host SDK can access customized functions through the CustomCommand .
1 Login SDK
1.1 Login Component Interface
The login JS interface provided by the Host SDK to minigame developers is as follows.
tj.login
- Input parameters: Object args
| Attribute | Type | Required | Description |
|---|---|---|---|
| timeout | number | N | Timeout, unit: ms |
| success | function | N | Callback function for successful interface call |
| fail | function | N | Callback function for interface call failure |
| complete | function | N | Callback function for the end of interface call (executed upon both successful and failed calls) |
- args.success callback function parameter: Object res
| Attribute | Type | Description |
|---|---|---|
| code | string | Game developers should call Game Server code2session (Step 9 in login process diagram) with this code to obtain the login credential |
Login capabilities can be implemented by overriding the tj.login interface.
tj.login = function (obj) {
tj.customCommand({
success: function(res) {
let resObj = JSON.parse(res);
obj.success(resObj);
},
fail: function(res) {
let apiRes = {
errMsg: res.errorMsg,
errno: res.errorCode
};
obj.fail(apiRes);
},
complete: function() {
obj.complete();
}
}, "loginUnity");
};
The code also uses CustomCommand to execute the Native Func loginUnity () in Java, loginUnity () whose main function is to obtain the Code through the platform's own login SDK and return it to the host. After the host passes it to the game, the game can exchange it for user information through Game Server code2session API.
In the scenario of a multi-process game, if the user has already logged in to the main process, they can use AIDL or other Inter-Process Communication methods to initiate a request for obtaining the Code from the game process to the main process, and the main process will uniformly return the Code.
hostHandle.setCustomCommandListener("loginUnity", ((customCommandHandle, bundle) -> {
try {
loginService.requesetLogin(new ILoginCallback.Stub() {
@Override
public void loginEnd(String code) {
JSONObject loginRes = new JSONObject();
try {
loginRes.put("code", code);
} catch (Exception e) {
customCommandHandle.fail(1002, "Failed to serialize login result" + e.getMessage());
}
customCommandHandle.pushResult(loginRes.toString());
customCommandHandle.success();
}
});
} catch (RemoteException e) {
customCommandHandle.fail(1001, "Failed to connect Login Service: " + e.getMessage());
}
}));
1.2 Full Login Process
The schematic diagram of the entire login process is as follows:

After the game client obtains the code by calling tj.login, platform app needs to obtain the user's login information through JS code2session to implement user login (Step 10 in the diagram above).
jscode2session
Here defines the implementation guidelines for the platform's APIs. If you are a game developer, please refer to
Minihost Platform Funtionality Documentation - Section 2.1.2 - jscode2sessionfor integration.
Provides the login capability of the platform. The host backend will pass the user's login credential (code) to the platform, which needs to return the user's login information based on this credential.
The host backend will map the uid returned by the platform to the openid and unionid available on the game side, based on the context of the request, and forward the session_key to the game side as a login credential.
Example of request:
GET /jscode2session?js_code={code} HTTP/1.1
Authorization: Bearer {service_token}
Request Parameter Description:
| parameter | Description |
|---|---|
| js_code | Platform Login Credentials |
| Authorization | Server token, formatted as Bearer {service_token} |
Response Example:
HTTP/1.1 200 OK
Content-Type: application/json
{
"uid": "123456"
"session_key": "abcdefg",
"errcode": 0,
"errmsg": "ok"
}
Response field description:
| Field | Description |
|---|---|
| uid | Unique user identifier returned by the platform |
| session_key | session_key returned by the platform |
| errcode | Error code, 0 indicates success |
| errmsg | Error Message |
2 Advertising SDK
2.1 Advertising Component Interface
The advertising JS interfaces provided by the Host SDK to minigame developers are as follows.
tj.createRewardedVideoAd()
The return value is RewardedVideoAd, and the exposed methods are:
| Function Name | Function Description | Return value |
|---|---|---|
| RewardedVideoAd.load() | Load rewarded video ad | Promise
|
| RewardedVideoAd.show() | Show incentive video ad | Promise
|
| RewardedVideoAd.destroy() | Destroy the rewarded video ad instance | |
| RewardedVideoAd.onLoad(function listener) | Listen for the incentive video ad loading event. Parameter: function listener
| |
| RewardedVideoAd.offLoad(function listener) | Listen for the incentive video ad loading event. Parameter: function listener
| |
| RewardedVideoAd.onError(function listener) | Listen for the error event of the incentive video. Parameter: function listener
| |
| RewardedVideoAd.offError(function listener) | Remove the listener function for the incentive video error event Parameter: function listener
| |
| RewardedVideoAd.onClose(function listener) | Listen for the event when the user clicks the close ad button. Parameter: function listener
| |
| RewardedVideoAd.offClose(function listener) | Remove the event listener function for the user click Close Ad button Parameter: function listener
|
The following describes how to override the ad interface and integrate ad logic for "Create Rewarded Video Ad".
2.2 Advertising Component Interface Example
tj.createRewardedVideoAd()
This interface is used to create an interstitial ad component and returns RewardedVideoAd instance. Some of the methods exposed by the instance are:
-
RewardedVideoAd.load()loads a rewarded ad and returns a Promise -
RewardedVideoAd.onLoad(callback)accepts a function as a parameter to listen for the interstitial ad load event -
RewardedVideoAd.offLoad(callback)Removes the listener function for the interstitial ad load event; if no parameters are passed, all listeners will be removed
The Host SDK does not have built-in advertising functionality and only provides a default implementation of tj.createRewardedVideoAd() . The methods exposed by the RewardedVideoAd instance returned by this implementation are all empty implementations . When a minigame developer calls RewardedVideoAd.load() , it cannot actually load rewarded ads.
Therefore, the access party's App needs to override this tj.createRewardedVideoAd(), so that the RewardedVideoAd.load() calls the loading interface of the third-party advertising SDK integrated within the App, and similarly implements the other interfaces exposed by RewardedVideoAd to achieve the integration of advertising functionality.
The access party's App can provide several custom JS files within the project (under the assets directory for Android) to overwrite JS interfaces, and specify the path of the custom JS files when setting game startup parameters.
Taking Android as an example, you can create a customScripts directory under the assets directory, add the JS file ad.js for overriding the ad interface, and then set the game startup parameters as follows:
bundle.putString(TJConstants.BUILTIN_CUSTOM_SCRIPTS_PATH, "customScripts");
The Host SDK will read all JS files under this directory and use the methods defined within the files to overwrite the JS interfaces provided by the Host SDK.
2.3 Access Third-Party Advertising SDK
Taking the incentive ad API described in the integration instructions as an example, you can refer to ad.js in the Demo project as follows:
let rewardedVideoAdOnLoadCallbacks = [];
tj.createRewardedVideoAd = (obj) => {
return {
onLoad: (callback) => {
if (callback && typeof callback === "function") {
if (!rewardedVideoAdOnLoadCallbacks.includes(callback)) {
rewardedVideoAdOnLoadCallbacks.push(callback);
}
}
},
load: () => {
tj.customCommand({},"loadRewardAd");
},
offLoad: (callback) => {
console.info("[Host] invoke RewardedVideoAd.offLoad");
if (callback === undefined) rewardedVideoAdOnLoadCallbacks = [];
else if (callback && typeof callback === "function") {
rewardedVideoAdOnLoadCallbacks = rewardedVideoAdOnLoadCallbacks.filter(
(cb) => cb !== callback,
);
}
},
// Other RewardedVideoAd methods ...
};
};
rewardedVideoLoadCallbackFromJava = () => {
try {
rewardedVideoAdOnLoadCallbacks.forEach((callback) => callback());
} catch (error) {
console.error("[Host] Error in rewardedVideoLoadCallbackFromJava:", error);
}
};
In this ad.js, by defining tj.createRewardedVideoAd, the default implementation is overridden, and within the RewardedVideoAd instance's load() method, CustomCommand (used for mutual calls between JS and Java code, for details refer to API Reference) is used to execute the Native Func loadRewardAd() in Java.
The code for setting up a listener for loadRewardAd in Java is as follows:
hostHandle.setCustomCommandListener("loadRewardAd", ((customCommandHandle, bundle) -> {
if (isGamePlayed) {
adManager.loadRewardAd(); // Ad SDK API
}
}));
// In the Ad SDK loadSuccess callback
String script = "rewardedVideoLoadCallbackFromJava();";
customCommand.runCustomScript(script, bundle -> Log.i("AdManager", "onVideoAdLoadSuccess rewardedVideoLoadCallbackFromJava end"));
In the Java example, after listening to the loadRewardAd call from JS, the Ad SDK API is actually executed to load the rewarded ad, and within the callback upon completion of loading, the JS method rewardedVideoLoadCallbackFromJava() is called via CustomCommand to notify the JS side to execute the callback registered by the minigame developer, thereby implementing the complete logic from the minigame developer's call to the Host JS interface to the Java Native Ad SDK API and then to the JS callback registered by the minigame developer.
3 Payment SDK
3.1 Flowchart
3.1.1 Minigame Payment

3.1.2 Game Servers Actively Query Order

3.2 Client Interface
tj.requestPayment(Object obj)
Parameter Description
| Attribute Name | Type | Default Value | Required | Description |
|---|---|---|---|---|
| mode | string | game | Yes | Payment type, enumeration value
|
| env | number | 0 | Yes | Environment Configuration, Enumerated Value
|
| currencyType | string | CNY | Yes | Currency, enumeration value
|
| platform | string | Yes | Platform at the time of application for access, android or ios | |
| buyQuantity | number | No | Quantity Purchased | |
| zoneId | string | 1 | No | Game service area ID, customized by the developer. If the game does not have different regions, default to "1". |
| customId | string | Yes | A unique order number customized by the game developer, which will be postbacked via server payment result callback after the order payment is successful. It must be unique; otherwise, an error will occur if it is not passed or the same value is passed repeatedly. | |
| extraInfo | string | No | Other information customized by game developers will be postbacked viaserver payment result callbackafter the order payment is successful. The maximum length of the string cannot exceed 256. | |
| goodType | number | 2 | No | Payment scenario, enumeration value
|
| orderAmount | number | Yes | represents the cash price of the item, with the unit being [Chinese Yuan cents] | |
| goodName | string | Yes | When goodType is for the direct purchase scenario of items, it represents the item name, with a length limit of less than or equal to 10 characters, used to distinguish item types | |
| options | map | No | Extended Parameters, can be customized based on platform requirements | |
| success | function | No | Callback function for successful interface call | |
| fail | function | No | Callback function for interface call failure | |
| complete | function | No | Callback function for the end of interface call (executed upon both successful and failed calls) |
3.2.1 Callback Success Parameters
Object type, with the following properties
| Attribute Name | Type | Description |
|---|---|---|
| errMsg | string | requestPayment:ok |
3.2.2 Callback Failure Parameters
Object type, with the following properties
| Attribute Name | Type | Description |
|---|---|---|
| errMsg | string | "requestPayment:fail " + Error Details |
| errCode | number | Error code, for corresponding information, please refer to the error code description |
3.2.3 Callback End Parameters
Object type, with the following properties
| Attribute Name | Type | Description |
|---|---|---|
| errMsg | string | requestPayment:ok |
3.2.4 Error Code Description
Map according to actual support situation
| errCode | errMsg | Description |
|---|---|---|
| -1 | requestPayment:fail Payment failed | User payment failed |
| -1 | requestPayment:fail internal error | Internal error in the minigame framework |
| -2 | requestPayment:fail Payment cancelled | User cancelled payment |
| 3 | requestPayment:fail error_tip_start_cash_register_fail | Failed to launch the cashier desk, such as encountering an internal error in the minigame framework |
| 4 | requestPayment:fail Network error | User network is abnormal |
| -15002 | requestPayment:fail The request parameters are invalid | Request parameters are invalid |
| -15006 | requestPayment:fail The app does not have payment permissions | Please confirm whether to set the game coin exchange rate |
| -15098 | requestPayment:fail The current user has not passed real-name authentication | The current user has not passed real-name authentication |
| -15099 | requestPayment:fail The current user's cumulative payment amount exceeds the limit | The cumulative payment amount of the current user exceeds the limit |
| -15101 | requestPayment:fail customId is empty or not unique | customId is empty or not unique |
| -16000 | requestPayment:fail User not logged in | User is not logged in |
| -20002 | requestPayment:fail Transaction is at risk | The transaction is risky and has been intercepted by the risk control strategy |
| 21113 | requestPayment:fail face authentication failed | A suspected minor order was detected, face verification was initiated, and the face verification failed |
3.2.5 Example Code
tj.requestPayment({
mode: 'game',
env: 0,
currencyType: 'CNY',
platform: 'ios',
zoneId: '1',
customId: 'order_' + Date.now(),
extraInfo: JSON.stringify({
orderId: 'test_order_' + Date.now(),
userId: '10001'
}),
goodType: 2,
orderAmount: 100,
goodName: 'Remove Ads',
options: {
'PRODUCT_CODE': '1001'
},
success: function success(res) {
console.log('[Game JS Side] Payment successful:', res);
tj.showToast({
title: 'Payment successful, play again!',
duration: 2000
});
},
fail: function fail(err) {
if (err.errCode && err.errCode == -2) {
console.log('[Game JS Side] User canceled payment');
tj.showToast({
title: 'Payment canceled, please try again!',
duration: 2000
});
} else {
console.error('[Game JS Side] Payment failed:', err);
tj.showToast({
title: 'Payment failed, please retry!',
duration: 2000
});
}
},
complete: function complete(res) {
console.log('[Game JS Side] Payment process completed:', res);
}
})
3.3 Server Interface
3.3.1 Server Callback Interface
After the payment is successful, the platform server sends a payment success callback to the host server. After verifying the signature, the host server sends the callback to the game server.
3.3.1.1 Callback Address
POST https://minihost.tuanjie.cn/game-api/v1/payment/callback
3.3.1.2 Request Parameters
| Parameter Name | Type | Description |
|---|---|---|
| timestamp | string | Timestamp |
| nonce | string | Random Number |
| msg | string | Payment result information of Json string type, see 3.3.1.3 PaymentInfo object |
| signature | string | Signature, see Section 3.3.1.4 Signature for the signature algorithm |
3.3.1.3 PaymentInfo
| Parameter Name | Type | Description |
|---|---|---|
| appid | string | Platform-side minigame appid |
| cp_orderno | string | Developer-defined order number, the customId parameter in the tj.requestPayment method |
| cp_extra | string | Extra parameters passed by the developer, the extra parameter in the tj.requestPayment method |
| order_no_channel | string | Minigame Backend Transaction Order Number |
| amount_cent | int64 | Order amount, in RMB cents |
| amount_coin | int64 | The quantity of game coins purchased is not involved in the platform's integration process and can be ignored. |
| currency | string | Payment currency, CNY Renminbi, DIAMOND Diamond |
3.3.1.4 Signature
Generate a signature using the SHA1 algorithm based on token, timestamp, nonce, and msg, and compare it with the signature returned by the platform's server.
Precondition: When associating a game, the platform party needs to pass token to the host for signature verification
Sample Golang code:
sortedString := make([]string, 4)
sortedString = append(sortedString, token)
sortedString = append(sortedString, timestamp)
sortedString = append(sortedString, nonce)
sortedString = append(sortedString, string(msg))
sort.Strings(sortedString)h := sha1.New()
h.Write([]byte(strings.Join(sortedString, "")))_signature := h.Sum(nil)
3.3.1.5 Response
The host server returns a 200 status code as a successful response. If the returned HTTP status code is not 200, it indicates that the notification has failed and a retry is required.
3.3.2 Game Server Actively Query Order Interface
Server-side payment callbacks may fail to reach 100% due to reasons such as network anomalies. Developers can use this interface to actively check the order status to prevent over-delivery or under-delivery. Developers send a query order request to the host server, which then encapsulates and sends the query order request to the platform server.
3.3.2.1 Interface Address
Provided by the platform
3.3.2.2 Request Parameters
| Parameter Name | Type | Description |
|---|---|---|
| token | string | The two parties agree on the server token |
| orderno | string | cp Custom Order Number, passed in when placing an order, the customId parameter in the tj.requestPayment method |
3.3.2.3 Response
| Parameter Name | Type | Description |
|---|---|---|
| status | string | Payment status. "success" indicates successful payment and coin arrival, "unsuccess" indicates payment failure |
3.3.2.4 Authentication
The request must include the server token agreed upon by both parties, placed in the Authorization header, with a format like
Bearer {service_token}