Skip to main content

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
AttributeTypeRequiredDescription
timeoutnumberNTimeout, unit: ms
successfunctionNCallback function for successful interface call
failfunctionNCallback function for interface call failure
completefunctionNCallback function for the end of interface call (executed upon both successful and failed calls)
  • args.success callback function parameter: Object res
AttributeTypeDescription
codestringGame 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 - jscode2session for 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:

parameterDescription
js_codePlatform Login Credentials
AuthorizationServer 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:

FieldDescription
uidUnique user identifier returned by the platform
session_keysession_key returned by the platform
errcodeError code, 0 indicates success
errmsgError 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 NameFunction DescriptionReturn value
RewardedVideoAd.load()Load rewarded video adPromise
  • Result of incentive video ad loading data
RewardedVideoAd.show()Show incentive video adPromise
  • Shows the result of the incentive video ad display operation
RewardedVideoAd.destroy()Destroy the rewarded video ad instance
RewardedVideoAd.onLoad(function listener)Listen for the incentive video ad loading event. Parameter: function listener
  • Listener function for the loading event of rewarded video ads
RewardedVideoAd.offLoad(function listener)Listen for the incentive video ad loading event. Parameter: function listener
  • The listener function passed to onLoad. If this parameter is not passed, all listener functions will be removed.
RewardedVideoAd.onError(function listener)Listen for the error event of the incentive video. Parameter: function listener
  • Listener function for incentive video error event
RewardedVideoAd.offError(function listener)Remove the listener function for the incentive video error event Parameter: function listener
  • The listener function passed to onError. If this parameter is not passed, all listener functions will be removed.
RewardedVideoAd.onClose(function listener)Listen for the event when the user clicks the close ad button. Parameter: function listener
  • The event listener function for the user clicking the Close Ad button
RewardedVideoAd.offClose(function listener)Remove the event listener function for the user click Close Ad button Parameter: function listener
  • The listener function passed to onClose. If this parameter is not passed, all listener functions will be removed.

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 NameTypeDefault ValueRequiredDescription
modestringgameYesPayment type, enumeration value
  • game - Currently only this type is supported
envnumber0YesEnvironment Configuration, Enumerated Value
  • 0 - Represents the formal payment environment, currently only this type is supported
currencyTypestringCNYYesCurrency, enumeration value
  • CNY - represents the Chinese Yuan
  • VND - represents Vietnamese Dong
  • EUR - represents the euro
  • ...
platformstringYesPlatform at the time of application for access, android or ios
buyQuantitynumberNo Quantity Purchased
zoneIdstring1No Game service area ID, customized by the developer. If the game does not have different regions, default to "1".
customIdstringYesA 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.
extraInfostringNo 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.
goodTypenumber2No Payment scenario, enumeration value
  • 2 - Represents the direct purchase scenario for items, currently only this type is supported
orderAmountnumberYesrepresents the cash price of the item, with the unit being [Chinese Yuan cents]
goodNamestringYesWhen 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
optionsmapNoExtended Parameters, can be customized based on platform requirements
successfunctionNo Callback function for successful interface call
failfunctionNo Callback function for interface call failure
completefunctionNo 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 NameTypeDescription
errMsgstringrequestPayment:ok

3.2.2 Callback Failure Parameters​

Object type, with the following properties

Attribute NameTypeDescription
errMsgstring"requestPayment:fail " + Error Details
errCodenumberError code, for corresponding information, please refer to the error code description

3.2.3 Callback End Parameters​

Object type, with the following properties

Attribute NameTypeDescription
errMsgstringrequestPayment:ok

3.2.4 Error Code Description​

Map according to actual support situation

errCodeerrMsgDescription
-1requestPayment:fail Payment failedUser payment failed
-1requestPayment:fail internal errorInternal error in the minigame framework
-2requestPayment:fail Payment cancelledUser cancelled payment
3requestPayment:fail error_tip_start_cash_register_failFailed to launch the cashier desk, such as encountering an internal error in the minigame framework
4requestPayment:fail Network errorUser network is abnormal
-15002requestPayment:fail The request parameters are invalidRequest parameters are invalid
-15006requestPayment:fail The app does not have payment permissionsPlease confirm whether to set the game coin exchange rate
-15098requestPayment:fail The current user has not passed real-name authenticationThe current user has not passed real-name authentication
-15099requestPayment:fail The current user's cumulative payment amount exceeds the limitThe cumulative payment amount of the current user exceeds the limit
-15101requestPayment:fail customId is empty or not uniquecustomId is empty or not unique
-16000requestPayment:fail User not logged inUser is not logged in
-20002requestPayment:fail Transaction is at riskThe transaction is risky and has been intercepted by the risk control strategy
21113requestPayment:fail face authentication failedA 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 NameTypeDescription
timestampstringTimestamp
noncestringRandom Number
msgstringPayment result information of Json string type, see 3.3.1.3 PaymentInfo object
signaturestringSignature, see Section 3.3.1.4 Signature for the signature algorithm
3.3.1.3 PaymentInfo​
Parameter NameTypeDescription
appidstringPlatform-side minigame appid
cp_ordernostringDeveloper-defined order number, the customId parameter in the tj.requestPayment method
cp_extrastringExtra parameters passed by the developer, the extra parameter in the tj.requestPayment method
order_no_channelstringMinigame Backend Transaction Order Number
amount_centint64Order amount, in RMB cents
amount_coinint64The quantity of game coins purchased is not involved in the platform's integration process and can be ignored.
currencystringPayment 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 NameTypeDescription
tokenstringThe two parties agree on the server token
ordernostringcp Custom Order Number, passed in when placing an order, the customId parameter in the tj.requestPayment method
3.3.2.3 Response​
Parameter NameTypeDescription
statusstringPayment 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}