02/25/2025 15:42:56
Login module development
I. Plugin development
MSDK's login function provides a convenient login method for games. Players can use a third-party channel's account to log into a game.
1.1 Login status caching
Under normal circumstances, the MSDK client and the third-party channel SDK both cache the data of the previous login status to reduce operations such as launching app popups and user confirmation and entering account passwords. However, this logic may also bring other side effects, as shown in the following two application scenarios:
The user wants to switch a login account
In general, if the user encounters such a scenario, the problem can be solved by setting the
Logout
interface in the UI[info] Suggestions Due to the differences in the implementation of channels, it is recommended to perform targeted testing on the channels
When the user changes the password on the channel App, the data is not cached synchronically this time.
Generally, this can lead to hacking. After the user changes the password, if the channel SDK does not bind the local cache validity, hackers can still log in the channel.
[info] Suggestions Add the corresponding logic and then test it
1.2 Automatic login
Under normal circumstances, MSDK's automatic login logic does not call plug-ins. MSDK will verify whether the local login status is valid. If it is valid, MSDK client will directly send a request to the backend to verify it. After the verification is passed, automatic login will be allowed.
Some special channels require some logical processing during automatic login, otherwise some functions may fail. Therefore, MSDK provides a capability which allows automatic login to call plugins. The channel login needs to implement the AutoLoginInterface interface and implement the autoLogin method.
II. Client Plugin Development
2.1 Android Platform
2.1.1 Class implementation rules
- Package naming rule: fixed as
com.tencent.gcloud.msdk.login
- Class naming rule:
channel + Login
, such as:GarenaLogin
- Must implement
LoginInterface
interface:- login function is used to implement the channel login function
- logout function is used to implement the channel logout function
- Optionally implement the 'AutoLoginInterface' interface:
- autoLogin function is used to support some channels to call relevant plugins in case of autoLogin
- Must implement a
public CLASSNAME (String seqID)
constructor, which is usually used for function initialization
2.1.2 Description of callback fields
As for the description of the callback function, please refer to Client Plugin Development Rules
observerID
callback function IDMSDKObserverID.MSDK_LOGIN_OBSERVER_LOGIN_RET
is used for direct return when login or automatic login failsMSDKObserverID.MSDK_LOGIN_OBSERVER_LOGIN_PLUGIN
is used to notify the game of the data when login or automatic login is successful. The current process continues runningMSDKObserverID.MSDK_LOGIN_OBSERVER_LOGOUT_PLUGIN
is used to notify that the current process continues running in case of logout.
ret
return struct must be a subclass ofMSDKRet
- In the login or automatic login method, the return result is
MSDKLoginRet
. If a plugin needs to pass its self-defined data, it needs to be placed in theMSDKLoginRet.pluginData
struct, where its type is a JSON string - In the logout method, the return result is
MSDKRet
- In the login or automatic login method, the return result is
methodNameID
is the function ID defined by MSDK and is used to define callback methods. It is recommended to uniformly useMSDKBaseParams.methodID
2.1.3 LoginInterface interface
Login function
Call the channel login interface and return the necessary channel login authentication data required for login authentication
Logout function
Call the logout function of the channel and return "success" or "failure".
2.1.4 AutoLoginInterface interface
autoLogin function
The automatic login interface is used to support some channels to call relevant plugins in case of autoLogin if needed
2.1.5 Code example
package com.tencent.gcloud.msdk.login;
public class GarenaLogin implements LoginInterface, AutoLoginInterface {
public GarenaLogin(String seqID) {
MSDKLog.d("[ " + seqID + "] Garena Login initialize start ");
// TODO Initialize the Garena environment
...
}
@Override
public void login(final MSDKLoginParams params) {
// TODO Garena login logic
...
// When MSDK data is returned, channel and channelID must be returned. Their definition must be consistent with that in the MSDK backend. They are generally applied and confirmed at the time of access to the corresponding channel
MSDKLoginPluginInfo pluginResult = new MSDKLoginPluginInfo(params.methodId);
pluginResult.channel = GarenaConst.Channel.CHANNEL;
pluginResult.channelID = GarenaConst.Channel.CHANNEL_ID;
// channelOpenID is the channel user ID. If it can be obtained, please try to assign a value to it
pluginResult.channelOpenID = (session == null ? "" : session.getOpenId());
// The returns data assembly struct, in JSON format. These data can be added by following the channel characteristics and backend requirements
try {
JSONObject params = new JSONObject();
params.put("uid", session.getOpenId());
params.put("token", session.getTokenValue().getAuthToken());
params.put("channel", session.getSessionProvider().getValue());
params.put("platform",session.getPlatform());
if (session.getSessionProvider() == GGLoginSession.SessionProvider.FACEBOOK) {
params.put("facebook_token", GGPlatform.GGGetFacebookAccessToken());
}
MSDKLog.d(params.toString());
// Key steps to assign values
pluginResult.pluginData = params.toString();
} catch (JSONException e) {
// TODO Here, 'catch' is to ensure robustness. The game can also handle exceptions as needed
MSDKLog.e("[ " + params.seqID + " ] catch exception : " + e.getMessage());
}
MSDKLog.d("[ " + params.seqID + " ] pluginResult = " + pluginResult.toString());
// Send the data to MSDK server
IT.onPluginRetCallback(MSDKObserverID.MSDK_LOGIN_OBSERVER_LOGIN_PLUGIN, pluginResult, params.seqID);
}
@Override
public void autoLogin(MSDKLoginParams params) {
// TODO Determine if there is currently Garena login status
// TODO Call Garena's automatic login logic
// TODO Refer to the login method to call back the automatic login data
}
@Override
public void logout(MSDKBaseParams params) {
// Garena logout logic
GGLoginSession.clearSession();
MSDKLog.d("[ " + params.seqID + " ] logout success" );
// Directly return successfully
IT.onPluginRetCallback(MSDKObserverID.MSDK_LOGIN_OBSERVER_LOGOUT_PLUGIN,
new MSDKRet(MSDKMethodNameID.MSDK_METHOD_LOGOUT, MSDKErrorCode.SUCCESS),
params.seqID);
}
}
[info] For details, please refer to Demo Code
2.2 iOS Platform
2.2.1 Class implementation rules
- Naming rules: Fixed as
MSDKLogin + channel
, such as:MSDKLoginGarena
- Must implement the
MSDKLoginDelegate
protocol - Must implement the singleton module. It is recommended to use the
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER
+SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER
macro processing
2.2.2 Description of callback fields
As for the description of the callback function, please refer to Client Plugin Development Rules
observerID
callback function IDkObserverIDLoginRet
is used for direct return when login or automatic login failskObserverIDLoginPlugin
is used to notify the game of the data when login or automatic login is successful. The current process continues runningkObserverIDLogoutPlugin
is used to notify that the current process continues running in case of logout.
ret
return struct- In the login or automatic login method, the return result is
InnerLoginPluginRet
. If a plugin needs to pass its self-defined data, it needs to be placed in theInnerLoginPluginRet.pluginData
struct, where its type is a JSON string - In the logout method, the return result is
InnerBaseRet
- In the login or automatic login method, the return result is
methodNameID
is the function ID defined by MSDK and is used to define callback methods. It is recommended to uniformly use MSDKBaseParams.methodID
2.2.3 MSDKLoginDelegate protocol
Description of Login function
The Login function calls the channel login interface and returns the necessary channel login authentication data required for login authentication
Function prototype:
- (void)login:(const MSDKLoginParams &)params;
[Optional implementation] autoLogin function description
The automatic login interface is used to support some channels to call relevant plugins in case of autoLogin if needed
Function prototype:
- (void)autoLogin:(const MSDKLoginParams &)params;
Description of Logout function
The Logout function calls the channel's logout function and returns "success" or "failure".
Function prototype:
- (void)logout:(const MSDKBaseParams &)params;
[Optional implementation] Description of the channel installation judgment function
Function prototype:
- (BOOL)isChannelInstall;
Used to determine whether the channel is installed. If the channel has an interface or scheme to implement this logic, it is needed to implement it
[Optional implementation] Description of the QR code scan login function or interface
Function prototype:
- (void)qrCodeLogin:(const MSDKLoginParams &)params info:(const MSDKQRCodeInfo &)qrinfo;
Currently applied to WeChat QR code scan login. Common channels do not need to implement it
[Optional implementation] Description of the interface of checking if a channel supports the function of automatically refreshing the channel token
Function prototype:
- (BOOL)checkAutoRefresh;
It is used to determine whether a channel supports the automatic refresh of the channel token. Common channels do not have an automatic token refresh mechanism, so it is generally not necessary to implement it.
2.2.4 Code example
- (void)login:(const MSDKLoginParams &)params {
// TODO Garena login logic
...
// Garena login return data processing
InnerLoginPluginRet ret;
ret.methodNameID = params.methodID;
// When MSDK data is returned, channel and channelID must be returned. Their definition must be consistent with that in the MSDK backend. They are generally applied and confirmed at the time of access to the corresponding channel
ret.channelID = GARENA_CHANNEL_ID;
ret.channel = GARENA_CHANNEL;
// channelOpenID is the channel user ID. If it can be obtained, please try to assign a value to it
ret.channelOpenID = loginRet.openID;
// The returns data assembly struct, in JSON format. These data can be added by following the channel characteristics and backend requirements
MSDKJsonWriter jsonWriter;
jsonWriter.StartJsonConvert();
jsonWriter.convert("uid", loginRet.openID);
// Garena Token processing, including two types of Token: Login Token and Refresh Token
for (int i=0; i<loginRet.token.size(); i++) {
GG::TokenRet* pToken = &loginRet.token[i];
if (pToken->type == GG::eToken_BT_Access) {
jsonWriter.convert("token", pToken->value);
} else {
jsonWriter.convert("refresh_token", pToken->value);
}
}
jsonWriter.convert("platform", loginRet.platform);
if(loginRet.platform == GG::ePlatform_FB) {
jsonWriter.convert("facebook_token", GG::GGPlatform::GetInstance()->GGGetFacebookAccessToken().c_str() ? : "");
}
jsonWriter.EndJsonConvert();
ret.pluginData = jsonWriter.GetJsonString().c_str();
LOG_DEBUG("[ %s ] plugin data %s", params.seqID.c_str(), ret.pluginData.c_str());
// Send the data to MSDK server
MSDKInnerObserverHolder<InnerLoginPluginRet>::CommitToTaskQueue(ret, kObserverIDLoginPlugin, params.seqID);
}
- (void)autoLogin:(const MSDKLoginParams &)params {
// TODO Determine if there is currently Garena login status
// TODO Call Garena's automatic login logic
// TODO Refer to the login method to call back the automatic login data
}
- (void)logout:(const MSDKBaseParams &)params {
bool success = GG::GGPlatform::GetInstance()->GGGetLogout();
InnerBaseRet innerRet = InnerBaseRet(MSDKError::SUCCESS);
if (!success) {
innerRet = InnerBaseRet(MSDKError::THIRD_ERROR);
innerRet.thirdCode = MSDKError::NO_ASSIGN;
innerRet.thirdMsg = "GGGetLogout return false";
}
MSDKInnerObserverHolder<InnerBaseRet>::CommitToTaskQueue(innerRet, kObserverIDLogoutPlugin, params.seqID);
}
[info] For details, please refer to Demo Code
III. Plugin server development
For the login process, the game needs to implement the following server interfaces:
- Login interface, which is one of the client login's core interfaces and is used for user login implementation and channel data return
- [Optional] Login verification interface, which is one of the client login's core interfaces and is used to verify the validity of the token returned by the login interface
- [Optional] Personal information interface, which mainly provides the basic information query capabilities for the user
Domestic and overseas games need to make choices when accessing the MSDK platform
3.1 Login interface
3.1.1 Interface name
Interface name (/auth/login/
can be configured in the management console)
3.1.2 Request parameters
Parameter | Type | Description | Optional or required |
---|---|---|---|
appid | string | App ID | Required |
channel_info | json | Value of the channel_info field in the client's input parameters | Required |
3.1.3 Return parameters
Parameter | Type | Description | Optional or required |
---|---|---|---|
ret | uint | Return code, 0-success, other-failure | Required |
msg | string | Detailed description of the return result | Required |
uid | string | Third-party channel's user identifier | Required |
token | string | third-party channel's token | Required |
expires_in | uint | How many seconds are left before the third-party channel token expires, in seconds | Required |
gender | uint | Gender, 0-Undefined, 1-Male, 2-Female | Optional |
birthdate | string | Date of birth, format "YYYY-MM-DD" | Optional |
user_name | string | The user's nickname | Optional |
picture_url | string | Avatar address | Optional |
extraJson | json | Additional information | Optional |
3.1.4 Request example
Request
POST /auth/login/?channelid=101&gameid=10&os=1&sig=0764cfef18e9b877b1805ede000eda38 HTTP/1.1 Host: openplatformtest.com Content-Type: application/json Content-Length: 308 { "appid": "xxxxx", "channel_info": { "access_token": "EAAGBC9HZB9l4BAEWkk4T3b4d2gZCTrQVFmmtPZA6SoH4VCPO0XKkce47LUaOMMdzuo6q7JWM2RDLjyT1nehQWTTLcwyjyvKxy2AeNzPRTkI9dpBz78s5KOYf8omVMfMzrykdKcnQSYuRJ0zaCyaHJ1ZCeOg5HBnc8XnHwYk5EUp9htCFXw7RbTBVNU0rGxAkurqnnMLZC92N5gTbYF4NOUMZBd2iJDa7dmE6RNOb3gPAZDZD" } }
Response
{ "ret": 0, "msg": "success", "uid": "openplatformtestloginuid", "token": "openplatformtestlogintokentest", "expires_in": 5184000, "user_name": "tamywang", "gender": 1, "birthdate": "1999-09-09", "picture_url": "http://exmaple.com/example.jpg", "extraJson": { "example": "self defined login extra info" } }
3.2 Login verification interface
3.2.1 Interface name
Interface name (/auth/verify_login/
can be configured in the management console)
3.2.2 Request parameters
Parameter | Type | Description | Optional or required |
---|---|---|---|
appid | string | App ID | Required |
uid | string | Third-party channel's user identifier | Required |
token | string | third-party channel's token | Required |
extraJson | json | Additional information | Optional |
3.2.3 Return parameters
Parameter | Type | Description | Optional or required |
---|---|---|---|
ret | uint | Return code, 0-success, other-failure | Required |
msg | string | Detailed description of the return result | Required |
3.2.4 Request example
Request
POST /auth/verify_login/?channelid=101&gameid=10&os=1&sig=6e2cf8d1e6f560f9eecffc18251a544e HTTP/1.1 Host: openplatformtest.com Content-Type: application/json Content-Length: 142 { "appid": "xxxxx", "uid": "openplatformtestloginuid", "token": "openplatformtestlogintokentest", "extraJson": { "example": "example" } }
Response
{ "ret": 0, "msg": "success" }
3.3 Personal information interface
3.3.1 Interface name
Interface name (/profile/userinfo/
can be configured in the management console)
3.3.2 Request parameters
Parameter | Type | Description | Optional or required |
---|---|---|---|
appid | string | App ID | Required |
uid | string | Third-party channel's user identifier | Required |
token | string | third-party channel's token | Required |
extraJson | json | Additional information | Optional |
3.3.3 Return parameters
Parameter | Type | Description | Optional or required |
---|---|---|---|
ret | uint | Return code, 0-success, other-failure | Required |
msg | string | Detailed description of the return result | Required |
gender | uint | Gender, 0-Undefined, 1-Male, 2-Female | Optional |
birthdate | string | Date of birth, format "YYYY-MM-DD" | Optional |
user_name | string | The user's nickname | Required |
picture_url | string | Avatar address | Required |
extraJson | json | Additional information | Optional |
3.3.4 Request example
Request
POST /profile/userinfo/?channelid=101&gameid=10&os=1&sig=5b4ad2242a4cb680dc373aae5ba5e7e7 HTTP/1.1 Host: openplatformtest.com Content-Type: application/json Content-Length: 142 { "appid": "xxxxx", "uid": "openplatformtestloginuid", "token": "openplatformtestlogintokentest", "extraJson": { "example": "example" } }
Response
{ "ret": 0, "msg": "success", "user_name": "tamywang", "gender": 1, "birthdate": "1999-09-09", "picture_url": "http://exmaple.com/example.jpg", "extraJson": { "example": "login extra info" } }
All rights reserved.