From a7eddd2ed0e23844b791e516fd70be33408d32ac Mon Sep 17 00:00:00 2001 From: HongchengQ <121159914+HongchengQ@users.noreply.github.com> Date: Sun, 7 Dec 2025 18:54:37 +0800 Subject: [PATCH] Support CN Client - Add Chinese region server key configuration - Rename UserLoginEntity to OverseaUserLoginEntity and adjust package path - Add ChinaUserLoginEntity entity class to support Chinese region user data structure - Modify CommonConfigHandler to distinguish between Chinese and overseas configuration returns - Update HandlerPlayerLoginReq to be compatible with Chinese region login token parsing - Add /user/set-info and /user/send-sms interfaces in HttpServer - Modify UserLoginHandler to support both Chinese and overseas user login logic - Add mobile phone number + verification code login method support - Add channel recognition logic to return corresponding regional user data --- src/main/java/emu/nebula/GameConstants.java | 3 + .../java/emu/nebula/server/HttpServer.java | 2 + .../handlers/HandlerPlayerLoginReq.java | 10 +- .../server/routes/CommonConfigHandler.java | 37 +++- .../server/routes/UserLoginHandler.java | 191 +++++++++++++----- .../routes/entity/ChinaUserLoginEntity.java | 56 +++++ .../OverseaUserLoginEntity.java} | 4 +- src/main/java/emu/nebula/util/AeadHelper.java | 4 + 8 files changed, 248 insertions(+), 59 deletions(-) create mode 100644 src/main/java/emu/nebula/server/routes/entity/ChinaUserLoginEntity.java rename src/main/java/emu/nebula/server/routes/{UserLoginEntity.java => entity/OverseaUserLoginEntity.java} (94%) diff --git a/src/main/java/emu/nebula/GameConstants.java b/src/main/java/emu/nebula/GameConstants.java index 2426efa..fd5b2e4 100644 --- a/src/main/java/emu/nebula/GameConstants.java +++ b/src/main/java/emu/nebula/GameConstants.java @@ -22,6 +22,9 @@ public class GameConstants { RegionConfig.getRegion("tw") .setDataVersion(64); + + RegionConfig.getRegion("cn") + .setDataVersion(64); } public static final ZoneId UTC_ZONE = ZoneId.of("UTC"); diff --git a/src/main/java/emu/nebula/server/HttpServer.java b/src/main/java/emu/nebula/server/HttpServer.java index acb1eb7..d3c4a0a 100644 --- a/src/main/java/emu/nebula/server/HttpServer.java +++ b/src/main/java/emu/nebula/server/HttpServer.java @@ -164,6 +164,8 @@ public class HttpServer { getApp().post("/user/set", new UserSetDataHandler()); getApp().post("/user/login", new UserLoginHandler()); getApp().post("/user/quick-login", new UserLoginHandler()); + getApp().post("/user/set-info", new HttpJsonResponse("{\"Code\":200,\"Data\":{},\"Msg\":\"OK\"}")); + getApp().post("/user/send-sms", new HttpJsonResponse("{\"Code\":200,\"Data\":{},\"Msg\":\"OK\"}")); getApp().post("/yostar/get-auth", new GetAuthHandler()); getApp().post("/yostar/send-code", new HttpJsonResponse("{\"Code\":200,\"Data\":{},\"Msg\":\"OK\"}")); // Dummy handler diff --git a/src/main/java/emu/nebula/server/handlers/HandlerPlayerLoginReq.java b/src/main/java/emu/nebula/server/handlers/HandlerPlayerLoginReq.java index 7be8ea1..a20e0a7 100644 --- a/src/main/java/emu/nebula/server/handlers/HandlerPlayerLoginReq.java +++ b/src/main/java/emu/nebula/server/handlers/HandlerPlayerLoginReq.java @@ -19,7 +19,15 @@ public class HandlerPlayerLoginReq extends NetHandler { public byte[] handle(GameSession session, byte[] message) throws Exception { // Parse request var req = LoginReq.parseFrom(message); - var loginToken = req.getOfficialOverseas().getToken(); + + // os + String loginToken = req.getOfficialOverseas().getToken(); + + if (loginToken == null || loginToken.isEmpty()) { + // cn + loginToken = req.getOfficial().getToken(); + } + // Login boolean result = session.login(loginToken); diff --git a/src/main/java/emu/nebula/server/routes/CommonConfigHandler.java b/src/main/java/emu/nebula/server/routes/CommonConfigHandler.java index 48985ff..cab42d2 100644 --- a/src/main/java/emu/nebula/server/routes/CommonConfigHandler.java +++ b/src/main/java/emu/nebula/server/routes/CommonConfigHandler.java @@ -1,5 +1,6 @@ package emu.nebula.server.routes; +import emu.nebula.util.JsonUtils; import org.jetbrains.annotations.NotNull; import emu.nebula.server.HttpServer; @@ -10,21 +11,47 @@ import lombok.Getter; @Getter public class CommonConfigHandler implements Handler { + private String osConfig = "{\"Code\":200,\"Data\":{\"AppConfig\":{\"ACCOUNT_RETRIEVAL\":{\"FIRST_LOGIN_POPUP\":false,\"LOGIN_POPUP\":false,\"PAGE_URL\":\"\"},\"AGREEMENT_POPUP_TYPE\":\"Browser\",\"APPLE_CURRENCY_BLOCK_LIST\":null,\"APPLE_TYPE_KEY\":\"apple_hk\",\"APP_CLIENT_LANG\":[\"en\"],\"APP_DEBUG\":0,\"APP_GL\":\"en\",\"BIND_METHOD\":[\"google\",\"apple_hk\",\"facebook\"],\"CAPTCHA_ENABLED\":false,\"CLIENT_LOG_REPORTING\":{\"ENABLE\":false},\"CREDIT_INVESTIGATION\":\"0.0\",\"DESTROY_USER_DAYS\":15,\"DESTROY_USER_ENABLE\":1,\"DETECTION_ADDRESS\":{\"AUTO\":{\"DNS\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"HTTP\":[\"${url}\",\"${url}\",\"${url}\"],\"MTR\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"PING\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"TCP\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"]},\"ENABLE\":true,\"ENABLE_MANUAL\":true,\"INTERNET\":\"https://www.google.com\",\"INTERNET_ADDRESS\":\"https://www.google.com\",\"NETWORK_ENDPORINT\":\"\",\"NETWORK_PROJECT\":\"\",\"NETWORK_SECRET_KEY\":\"\"},\"ENABLE_AGREEMENT\":true,\"ENABLE_MULTI_LANG_AGREEMENT\":false,\"ENABLE_TEXT_REVIEW\":true,\"ERROR_CODE\":\"4.4\",\"FILE_DOMAIN\":\"\",\"GEETEST_ENABLE\":false,\"GEETEST_ID\":\"\",\"GOOGLE_ANALYTICS_MEASUREMENT_ID\":\"\",\"MIGRATE_POPUP\":true,\"NICKNAME_REG\":\"^[A-Za-z0-9]{2,20}$\",\"POPUP\":{\"Data\":[{\"Lang\":\"ja\",\"Text\":\"YostarIDを作成\"},{\"Lang\":\"en\",\"Text\":\"CreateaYostaraccount\"},{\"Lang\":\"kr\",\"Text\":\"YOSTAR계정가입하기\"},{\"Lang\":\"fr\",\"Text\":\"CréezvotrecompteYostar\"},{\"Lang\":\"de\",\"Text\":\"EinenYostar-Accounterstellen\"}],\"Enable\":true},\"PRIVACY_AGREEMENT\":\"0.1\",\"RECHARGE_LIMIT\":{\"Enable\":false,\"IsOneLimit\":false,\"Items\":[],\"OneLimitAmount\":0},\"SHARE\":{\"CaptureScreen\":{\"AutoCloseDelay\":0,\"Enabled\":false},\"Facebook\":{\"AppID\":\"\",\"Enabled\":false},\"Instagram\":{\"Enabled\":false},\"Kakao\":{\"AppKey\":\"\",\"Enabled\":false},\"Naver\":{\"Enabled\":false},\"Twitter\":{\"Enabled\":false}},\"SLS\":{\"ACCESS_KEY_ID\":\"7b5d0ffd0943f26704fc547a871c68b1b5d56b5c9caeb354205b81f445d7af59\",\"ACCESS_KEY_SECRET\":\"4a5e9cc8a50819290c9bfa1fedc79da7c50e85189a05eb462a3d28a7688eabb0\",\"ENABLE\":false},\"SURVEY_POPUP_TYPE\":\"Browser\",\"UDATA\":{\"Enable\":false,\"URL\":\"${url}\"},\"USER_AGREEMENT\":\"0.1\",\"YOSTAR_PREFIX\":\"yoyo\"},\"EuropeUnion\":false,\"StoreConfig\":{\"ADJUST_APPID\":\"\",\"ADJUST_CHARGEEVENTTOKEN\":\"\",\"ADJUST_ENABLED\":0,\"ADJUST_EVENTTOKENS\":null,\"ADJUST_ISDEBUG\":0,\"AIRWALLEX_ENABLED\":false,\"AI_HELP\":{\"AihelpAppID\":\"yostar1_platform_2db52a57068b1ee3fe3652c8b53d581b\",\"AihelpAppKey\":\"YOSTAR1_app_bc226f4419a7447c9de95711f8a2d3d9\",\"AihelpDomain\":\"yostar1.aihelp.net\",\"CustomerServiceURL\":\"\",\"CustomerWay\":1,\"DisplayType\":\"Browser\",\"Enable\":1,\"Mode\":\"robot\"},\"APPLEID\":\"\",\"CODA_ENABLED\":false,\"ENABLED_PAY\":{\"AIRWALLEX_ENABLED\":false,\"CODA_ENABLED\":false,\"GMOAlipay\":false,\"GMOAu\":false,\"GMOCreditcard\":false,\"GMOCvs\":false,\"GMODocomo\":false,\"GMOPaypal\":false,\"GMOPaypay\":false,\"GMOSoftbank\":false,\"MYCARD_ENABLED\":false,\"PAYPAL_ENABLED\":true,\"RAZER_ENABLED\":false,\"STEAM_ENABLED\":false,\"STRIPE_ENABLED\":true,\"TOSS_ENABLED\":false,\"WEBMONEY_ENABLED\":false},\"FACEBOOK_APPID\":\"\",\"FACEBOOK_CLIENT_TOKEN\":\"\",\"FACEBOOK_SECRET\":\"\",\"FIREBASE_ENABLED\":0,\"GMO_CC_JS\":\"https://\",\"GMO_CC_KEY\":\"\",\"GMO_CC_SHOPID\":\"\",\"GMO_PAY_CHANNEL\":{\"GMOAlipay\":false,\"GMOAu\":false,\"GMOCreditcard\":false,\"GMOCvs\":false,\"GMODocomo\":false,\"GMOPaypal\":false,\"GMOPaypay\":false,\"GMOSoftbank\":false},\"GMO_PAY_ENABLED\":false,\"GOOGLE_CLIENT_ID\":\"\",\"GOOGLE_CLIENT_SECRET\":\"\",\"GUEST_CREATE_METHOD\":0,\"GUIDE_POPUP\":{\"DATA\":null,\"ENABLE\":0},\"LOGIN\":{\"DEFAULT\":\"yostar\",\"ICON_SIZE\":\"big\",\"SORT\":[\"google\",\"apple\",\"device\"]},\"MYCARD_ENABLED\":false,\"ONE_STORE_LICENSE_KEY\":\"\",\"PAYPAL_ENABLED\":false,\"RAZER_ENABLED\":false,\"REMOTE_CONFIG\":[],\"SAMSUNG_SANDBOX_MODE\":false,\"STEAM_APPID\":\"\",\"STEAM_ENABLED\":false,\"STEAM_PAY_APPID\":\"\",\"STRIPE_ENABLED\":false,\"TOSS_ENABLED\":false,\"TWITTER_KEY\":\"\",\"TWITTER_SECRET\":\"\",\"WEBMONEY_ENABLED\":false}},\"Msg\":\"OK\"}"; + private String cnConfig = "{\"Code\":200,\"Data\":{\"AppConfig\":{\"AppropriateAge\":{\"Level\":\"18+\",\"Msg\":\"《星塔旅人》游戏适龄提示\\n1、本游戏是一款玩法简单的角色扮演游戏,适用于年满18周岁及以上的用户。\\n2、本游戏基于架空的故事背景和幻想世界观,剧情简单且积极向上,没有基于真实历史和现实事件的改编内容。游戏玩法基于肢体操作,鼓励玩家通过训练达成目标。游戏中有少量自定义文字系统,该社交系统遵循相关法律法规进行管理。\\n3、本游戏中有用户实名认证系统,对年满18周岁及以上的用户开放,使用18周岁以下的身份信息认证账号将无法进入游戏。\"},\"Captcha\":{\"AppID\":191947906,\"Enable\":true},\"DestroyUser\":{\"Days\":15,\"Enable\":true},\"DetectionAddress\":{\"Auto\":{\"DNS\":[\"${url}/meta/serverlist.html\",\"${url}\"],\"HTTP\":[\"${url}/meta/serverlist.html\",\"${url}\"],\"MTR\":[\"${url}/meta/serverlist.html\",\"${url}\"],\"PING\":[\"${url}/meta/serverlist.html\",\"${url}\"],\"TCP\":[\"${url}/meta/serverlist.html\",\"${url}\"]},\"Enable\":true,\"Internet\":\"https://www.baidu.com\"},\"EnableTextReview\":true,\"NicknameReg\":\"^[A-Za-z0-9一-龥]{2,16}$\",\"Passport\":{\"AuthCodeCoolDownDays\":90,\"AuthCodeValidHour\":48,\"DestroyDays\":15,\"ModifyEmailDays\":30,\"ModifyMobileDays\":30,\"Prefix\":\"YS\"},\"PassportPopup\":{\"Enable\":false,\"Text\":\"\"},\"SLS\":{\"AccessKeyID\":\"7b5d0ffd0943f26704fc547a871c68b1b5d56b5c9caeb354205b81f445d7af59\",\"AccessKeySecret\":\"4a5e9cc8a50819290c9bfa1fedc79da7c50e85189a05eb462a3d28a7688eabb0\",\"ENABLE\":true},\"Share\":{\"CaptureScreen\":{\"AutoCloseDelay\":0,\"Enabled\":false},\"PengYouQuan\":{\"AppID\":\"\",\"Enabled\":false,\"UniversalLink\":\"\"},\"QQ\":{\"AppID\":\"\",\"Enabled\":false,\"UniversalLink\":\"\"},\"Qzone\":{\"AppID\":\"\",\"Enabled\":false,\"UniversalLink\":\"\"},\"Sort\":null,\"WeiXin\":{\"AppID\":\"\",\"Enabled\":false,\"UniversalLink\":\"\"},\"Weibo\":{\"AppKey\":\"\",\"Enabled\":false,\"RedirectURL\":\"\",\"UniversalLink\":\"\"}},\"ThirdInfoShareList\":\"https://${url}/cn-nova/shared_list\",\"Version\":{\"ChildPrivacyAgreement\":\"0.1\",\"ErrorCode\":\"5.3\",\"PassportPrivacyAgreement\":\"0.1\",\"PassportUserAgreement\":\"0.1\",\"PrivacyAgreement\":\"0.1\",\"UserAgreement\":\"0.1\",\"UserDestroy\":\"0.1\"}},\"ChannelConfig\":{\"Adjust\":{\"AppID\":\"\",\"Debug\":false,\"Enable\":false,\"EventTokens\":null},\"AiHelp\":{\"DisplayType\":\"WebView\",\"Enable\":true,\"ServiceInterfaceURL\":\"https://customer.yostar.net/\",\"ServiceURL\":\"https://customer-pc.yostar.net/#/\"},\"AntiAddiction\":{\"Enable\":true},\"Debug\":1,\"JPush\":{\"Debug\":false,\"Key\":\"\"},\"Login\":{\"Default\":\"mobile\",\"EnableList\":[\"mobile\",\"taptap\"]},\"OneKeyLoginSecret\":\"5c222d7c997339c921bd4fdcb7549ab4\",\"Taptap\":{\"ClientID\":\"9aeghiagor7hp43smv\",\"ClientPublicKey\":\"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwp10sKQjAn+kxSxZebHBgl3Tuqjapxdtqzy68y2CPzELHVeBQpK6jPnHyjvZcpgsW3/Rr4hyzPsxMHp7akNRfkOy2jqEGl/2hDeYpSsvK4vw9triXz4DTLESpU+RWfTglf3LRHB76RJggcGw0Pt+QAItHlOMQH+9LBuWtnS+bcf2YD+kC4jTmvr2dB6i3dhyaorVuT2OfnTRDZREU0WauWdACWHyaUELwA/JfZW+ir88k++qEjxaq76avRXzfJ0SuA8lqJKRirBc4dgMLvpjpjy1mVV3us64fSyAYwqUFCFNT5HT4/MMCbD4YZs20pgT8sUG04kbxlA1qu6sIh2BHwIDAQAB\",\"ClientToken\":\"ENWpPiooc3lI3ZNVNQNOXWZ7dE4YrVOsbMY7b1Li\"},\"Udata\":{\"Enable\":true}}},\"Msg\":\"OK\"}"; + private HttpServer server; - private String json; public CommonConfigHandler(HttpServer server) { this.server = server; - this.json = "{\"Code\":200,\"Data\":{\"AppConfig\":{\"ACCOUNT_RETRIEVAL\":{\"FIRST_LOGIN_POPUP\":false,\"LOGIN_POPUP\":false,\"PAGE_URL\":\"\"},\"AGREEMENT_POPUP_TYPE\":\"Browser\",\"APPLE_CURRENCY_BLOCK_LIST\":null,\"APPLE_TYPE_KEY\":\"apple_hk\",\"APP_CLIENT_LANG\":[\"en\"],\"APP_DEBUG\":0,\"APP_GL\":\"en\",\"BIND_METHOD\":[\"google\",\"apple_hk\",\"facebook\"],\"CAPTCHA_ENABLED\":false,\"CLIENT_LOG_REPORTING\":{\"ENABLE\":false},\"CREDIT_INVESTIGATION\":\"0.0\",\"DESTROY_USER_DAYS\":15,\"DESTROY_USER_ENABLE\":1,\"DETECTION_ADDRESS\":{\"AUTO\":{\"DNS\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"HTTP\":[\"${url}\",\"${url}\",\"${url}\"],\"MTR\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"PING\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"TCP\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"]},\"ENABLE\":true,\"ENABLE_MANUAL\":true,\"INTERNET\":\"https://www.google.com\",\"INTERNET_ADDRESS\":\"https://www.google.com\",\"NETWORK_ENDPORINT\":\"\",\"NETWORK_PROJECT\":\"\",\"NETWORK_SECRET_KEY\":\"\"},\"ENABLE_AGREEMENT\":true,\"ENABLE_MULTI_LANG_AGREEMENT\":false,\"ENABLE_TEXT_REVIEW\":true,\"ERROR_CODE\":\"4.4\",\"FILE_DOMAIN\":\"\",\"GEETEST_ENABLE\":false,\"GEETEST_ID\":\"\",\"GOOGLE_ANALYTICS_MEASUREMENT_ID\":\"\",\"MIGRATE_POPUP\":true,\"NICKNAME_REG\":\"^[A-Za-z0-9]{2,20}$\",\"POPUP\":{\"Data\":[{\"Lang\":\"ja\",\"Text\":\"YostarIDを作成\"},{\"Lang\":\"en\",\"Text\":\"CreateaYostaraccount\"},{\"Lang\":\"kr\",\"Text\":\"YOSTAR계정가입하기\"},{\"Lang\":\"fr\",\"Text\":\"CréezvotrecompteYostar\"},{\"Lang\":\"de\",\"Text\":\"EinenYostar-Accounterstellen\"}],\"Enable\":true},\"PRIVACY_AGREEMENT\":\"0.1\",\"RECHARGE_LIMIT\":{\"Enable\":false,\"IsOneLimit\":false,\"Items\":[],\"OneLimitAmount\":0},\"SHARE\":{\"CaptureScreen\":{\"AutoCloseDelay\":0,\"Enabled\":false},\"Facebook\":{\"AppID\":\"\",\"Enabled\":false},\"Instagram\":{\"Enabled\":false},\"Kakao\":{\"AppKey\":\"\",\"Enabled\":false},\"Naver\":{\"Enabled\":false},\"Twitter\":{\"Enabled\":false}},\"SLS\":{\"ACCESS_KEY_ID\":\"7b5d0ffd0943f26704fc547a871c68b1b5d56b5c9caeb354205b81f445d7af59\",\"ACCESS_KEY_SECRET\":\"4a5e9cc8a50819290c9bfa1fedc79da7c50e85189a05eb462a3d28a7688eabb0\",\"ENABLE\":false},\"SURVEY_POPUP_TYPE\":\"Browser\",\"UDATA\":{\"Enable\":false,\"URL\":\"${url}\"},\"USER_AGREEMENT\":\"0.1\",\"YOSTAR_PREFIX\":\"yoyo\"},\"EuropeUnion\":false,\"StoreConfig\":{\"ADJUST_APPID\":\"\",\"ADJUST_CHARGEEVENTTOKEN\":\"\",\"ADJUST_ENABLED\":0,\"ADJUST_EVENTTOKENS\":null,\"ADJUST_ISDEBUG\":0,\"AIRWALLEX_ENABLED\":false,\"AI_HELP\":{\"AihelpAppID\":\"yostar1_platform_2db52a57068b1ee3fe3652c8b53d581b\",\"AihelpAppKey\":\"YOSTAR1_app_bc226f4419a7447c9de95711f8a2d3d9\",\"AihelpDomain\":\"yostar1.aihelp.net\",\"CustomerServiceURL\":\"\",\"CustomerWay\":1,\"DisplayType\":\"Browser\",\"Enable\":1,\"Mode\":\"robot\"},\"APPLEID\":\"\",\"CODA_ENABLED\":false,\"ENABLED_PAY\":{\"AIRWALLEX_ENABLED\":false,\"CODA_ENABLED\":false,\"GMOAlipay\":false,\"GMOAu\":false,\"GMOCreditcard\":false,\"GMOCvs\":false,\"GMODocomo\":false,\"GMOPaypal\":false,\"GMOPaypay\":false,\"GMOSoftbank\":false,\"MYCARD_ENABLED\":false,\"PAYPAL_ENABLED\":true,\"RAZER_ENABLED\":false,\"STEAM_ENABLED\":false,\"STRIPE_ENABLED\":true,\"TOSS_ENABLED\":false,\"WEBMONEY_ENABLED\":false},\"FACEBOOK_APPID\":\"\",\"FACEBOOK_CLIENT_TOKEN\":\"\",\"FACEBOOK_SECRET\":\"\",\"FIREBASE_ENABLED\":0,\"GMO_CC_JS\":\"https://\",\"GMO_CC_KEY\":\"\",\"GMO_CC_SHOPID\":\"\",\"GMO_PAY_CHANNEL\":{\"GMOAlipay\":false,\"GMOAu\":false,\"GMOCreditcard\":false,\"GMOCvs\":false,\"GMODocomo\":false,\"GMOPaypal\":false,\"GMOPaypay\":false,\"GMOSoftbank\":false},\"GMO_PAY_ENABLED\":false,\"GOOGLE_CLIENT_ID\":\"\",\"GOOGLE_CLIENT_SECRET\":\"\",\"GUEST_CREATE_METHOD\":0,\"GUIDE_POPUP\":{\"DATA\":null,\"ENABLE\":0},\"LOGIN\":{\"DEFAULT\":\"yostar\",\"ICON_SIZE\":\"big\",\"SORT\":[\"google\",\"apple\",\"device\"]},\"MYCARD_ENABLED\":false,\"ONE_STORE_LICENSE_KEY\":\"\",\"PAYPAL_ENABLED\":false,\"RAZER_ENABLED\":false,\"REMOTE_CONFIG\":[],\"SAMSUNG_SANDBOX_MODE\":false,\"STEAM_APPID\":\"\",\"STEAM_ENABLED\":false,\"STEAM_PAY_APPID\":\"\",\"STRIPE_ENABLED\":false,\"TOSS_ENABLED\":false,\"TWITTER_KEY\":\"\",\"TWITTER_SECRET\":\"\",\"WEBMONEY_ENABLED\":false}},\"Msg\":\"OK\"}"; - + String address = server.getServerConfig().getDisplayAddress(); - this.json = this.json.replaceAll("\\$\\{url}", address); + this.osConfig = this.osConfig.replaceAll("\\$\\{url}", address); + this.cnConfig = this.cnConfig.replaceAll("\\$\\{url}", address); } @Override public void handle(@NotNull Context ctx) throws Exception { ctx.contentType(ContentType.APPLICATION_JSON); - ctx.result(this.json); + + String Channel = ""; + var req = JsonUtils.decode(ctx.header("Authorization"), authDataJson.class); + + if (req != null) { + Channel = req.Head.Channel; + } + + if (Channel != null && Channel.equals("official")) { + // cn + ctx.result(cnConfig); + return; + } + + ctx.result(osConfig); + } + + @SuppressWarnings("unused") + private static class authDataJson { + public handJson Head; + public String Sign; + + protected static class handJson { + public String Channel; + } } } diff --git a/src/main/java/emu/nebula/server/routes/UserLoginHandler.java b/src/main/java/emu/nebula/server/routes/UserLoginHandler.java index d7fba3b..f8442a9 100644 --- a/src/main/java/emu/nebula/server/routes/UserLoginHandler.java +++ b/src/main/java/emu/nebula/server/routes/UserLoginHandler.java @@ -2,14 +2,13 @@ package emu.nebula.server.routes; import java.util.ArrayList; +import emu.nebula.Nebula; +import emu.nebula.server.routes.entity.ChinaUserLoginEntity; +import emu.nebula.server.routes.entity.OverseaUserLoginEntity; import org.jetbrains.annotations.NotNull; import emu.nebula.game.account.Account; import emu.nebula.game.account.AccountHelper; -import emu.nebula.server.routes.UserLoginEntity.LoginYostarJson; -import emu.nebula.server.routes.UserLoginEntity.UserDetailJson; -import emu.nebula.server.routes.UserLoginEntity.UserInfoJson; -import emu.nebula.server.routes.UserLoginEntity.UserKeyJson; import emu.nebula.util.JsonUtils; import io.javalin.http.ContentType; import io.javalin.http.Context; @@ -29,54 +28,120 @@ public class UserLoginHandler implements Handler { account = this.getAccountFromBody(ctx); } - // Check - if (account == null) { - ctx.contentType(ContentType.APPLICATION_JSON); - ctx.result("{\"Code\":100403,\"Data\":{},\"Msg\":\"Error\"}"); // TOKEN_AUTH_FAILED - return; - } - - // Create response - var response = new UserLoginEntity(); - - response.Code = 200; - response.Msg = "OK"; - response.Data = new UserDetailJson(); - response.Data.Keys = new ArrayList<>(); - response.Data.UserInfo = new UserInfoJson(); - response.Data.Yostar = new LoginYostarJson(); - - response.Data.UserInfo.ID = account.getUid(); - response.Data.UserInfo.UID2 = 0; - response.Data.UserInfo.PID = "NEBULA"; - response.Data.UserInfo.Token = account.getLoginToken(); - response.Data.UserInfo.Birthday = ""; - response.Data.UserInfo.RegChannel = "pc"; - response.Data.UserInfo.TransCode = ""; - response.Data.UserInfo.State = 1; - response.Data.UserInfo.DeviceID = ""; - response.Data.UserInfo.CreatedAt = account.getCreatedAt(); - - response.Data.Yostar.ID = account.getUid(); - response.Data.Yostar.Country = "US"; - response.Data.Yostar.Nickname = account.getNickname(); - response.Data.Yostar.Picture = account.getPicture(); - response.Data.Yostar.State = 1; - response.Data.Yostar.AgreeAd = 0; - response.Data.Yostar.CreatedAt = account.getCreatedAt(); - - var key = new UserKeyJson(); - key.ID = account.getUid(); - key.Type = "yostar"; - key.Key = account.getEmail(); - key.NickName = account.getEmail(); - key.CreatedAt = account.getCreatedAt(); - - response.Data.Keys.add(key); - // Result ctx.contentType(ContentType.APPLICATION_JSON); - ctx.result(JsonUtils.encode(response, true)); + ctx.result(getJsonResult(ctx, account)); + } + + private String getJsonResult(Context ctx, Account account) { + if (account == null) { + return "{\"Code\":100403,\"Data\":{},\"Msg\":\"Error\"}"; + } + + String Channel = ""; + var req = JsonUtils.decode(ctx.header("Authorization"), UserAuthDataJson.class); + + if (req != null) { + Channel = req.Head.Channel; + } + + String token = account.getLoginToken(); + if (token == null || token.isEmpty()) { + account.generateLoginToken(); + } + + String nickName = account.getNickname(); + if (nickName == null || nickName.isEmpty()) { + account.setNickname(account.getEmail()); + } + + // Check if it's a CN channel + // The data required by CN channels is somewhat different from other regional servers + if (Channel != null && Channel.equals("official")) { + // CN + var response = new ChinaUserLoginEntity(); + + response.Code = 200; + response.Msg = "OK"; + response.Data = new ChinaUserLoginEntity.UserDetailJson(); + response.Data.IsNew = false; + response.Data.IsTestAccount = false; + response.Data.Keys = new ArrayList<>(); + response.Data.User = new ChinaUserLoginEntity.UserJson(); + response.Data.Yostar = new ChinaUserLoginEntity.LoginYostarJson(); + response.Data.Identity = new ChinaUserLoginEntity.IdentityJson(); + response.Data.TaptapProfile = null; + + response.Data.User.ID = Long.parseLong(account.getUid()); + response.Data.User.PID = "NEBULA"; + response.Data.User.Token = account.getLoginToken(); + response.Data.User.State = 1; + response.Data.User.RegChannel = "pc_official"; + response.Data.User.DestroyState = 0; + + response.Data.Yostar.ID = Long.parseLong(account.getUid()); + response.Data.Yostar.NickName = account.getNickname(); + response.Data.Yostar.Picture = account.getPicture(); + response.Data.Yostar.State = 1; + response.Data.Yostar.CreatedAt = account.getCreatedAt(); + response.Data.Yostar.DefaultNickName = ""; + + response.Data.Identity.Type = 0; + response.Data.Identity.RealName = "***"; + response.Data.Identity.IDCard = "******************"; + response.Data.Identity.Underage = false; + response.Data.Identity.PI = ""; + response.Data.Identity.BirthDate = ""; + response.Data.Identity.State = 1; + + var key = new ChinaUserLoginEntity.UserKeyJson(); + key.Type = "mobile"; + key.NickName = account.getEmail(); + key.NickNameEnc = ""; + + response.Data.Keys.add(key); + return JsonUtils.encode(response, true); + } else { + // OS + var response = new OverseaUserLoginEntity(); + + response.Code = 200; + response.Msg = "OK"; + response.Data = new OverseaUserLoginEntity.UserDetailJson(); + response.Data.Keys = new ArrayList<>(); + response.Data.UserInfo = new OverseaUserLoginEntity.UserInfoJson(); + response.Data.Yostar = new OverseaUserLoginEntity.LoginYostarJson(); + + response.Data.UserInfo.ID = account.getUid(); + response.Data.UserInfo.UID2 = 0; + response.Data.UserInfo.PID = "NEBULA"; + response.Data.UserInfo.Token = account.getLoginToken(); + response.Data.UserInfo.Birthday = ""; + response.Data.UserInfo.RegChannel = "pc"; + response.Data.UserInfo.TransCode = ""; + response.Data.UserInfo.State = 1; + response.Data.UserInfo.DeviceID = ""; + response.Data.UserInfo.CreatedAt = account.getCreatedAt(); + + response.Data.Yostar.ID = account.getUid(); + response.Data.Yostar.Country = "US"; + response.Data.Yostar.Nickname = account.getNickname(); + response.Data.Yostar.Picture = account.getPicture(); + response.Data.Yostar.State = 1; + response.Data.Yostar.AgreeAd = 0; + response.Data.Yostar.CreatedAt = account.getCreatedAt(); + + var key = new OverseaUserLoginEntity.UserKeyJson(); + key.ID = account.getUid(); + key.Type = "yostar"; + key.Key = account.getEmail(); + key.NickName = account.getEmail(); + key.CreatedAt = account.getCreatedAt(); + + response.Data.Keys.add(key); + + return JsonUtils.encode(response, true); + } } protected Account getAccountFromBody(Context ctx) { @@ -86,9 +151,32 @@ public class UserLoginHandler implements Handler { if (req == null || req.OpenID == null || req.Token == null) { return null; } + + Account account = AccountHelper.getAccountByLoginToken(req.Token); + + if (account != null) return account; + + // In CN region, login method is mobile phone + MFA verification code + // OpenID is mobile phone number, Token is a six-digit verification code + // These are stored in the body + { + // CN region requires an OpenID query + account = AccountHelper.getAccountByEmail(req.OpenID); + if (account == null) { + // Create an account if were allowed to + if (Nebula.getConfig().getServerOptions().isAutoCreateAccount()) { + account = AccountHelper.createAccount(req.OpenID, null, 0); + } + } else { + // Check passcode sent by email + if (!account.verifyCode(req.Token)) { + account = null; + } + } + } // Get account - return AccountHelper.getAccountByLoginToken(req.Token); + return account; } protected Account getAccountFromHeader(Context ctx) { @@ -121,6 +209,7 @@ public class UserLoginHandler implements Handler { protected static class UserAuthHeadJson { public String UID; public String Token; + public String Channel; } } diff --git a/src/main/java/emu/nebula/server/routes/entity/ChinaUserLoginEntity.java b/src/main/java/emu/nebula/server/routes/entity/ChinaUserLoginEntity.java new file mode 100644 index 0000000..d871dd2 --- /dev/null +++ b/src/main/java/emu/nebula/server/routes/entity/ChinaUserLoginEntity.java @@ -0,0 +1,56 @@ +package emu.nebula.server.routes.entity; + +import java.util.List; + +public class ChinaUserLoginEntity { + public int Code; + public UserDetailJson Data; + public String Msg; + + public static class UserDetailJson { + public Object Destroy; + public Object YostarDestroy; + + public boolean IsNew; + public boolean IsTestAccount; + public List Keys; + public UserJson User; + public LoginYostarJson Yostar; + public Object TaptapProfile; + public IdentityJson Identity; + } + + public static class UserJson { + public long ID; + public String PID; + public String Token; + public int State; + public String RegChannel; + public int DestroyState; + } + + public static class UserKeyJson { + public String Type; + public String NickName; + public String NickNameEnc; + } + + public static class LoginYostarJson { + public long ID; + public String NickName; + public String Picture; + public int State; + public long CreatedAt; + public String DefaultNickName; + } + + public static class IdentityJson { + public int Type; + public String RealName; + public String IDCard; + public boolean Underage; + public String PI; + public String BirthDate; + public int State; + } +} diff --git a/src/main/java/emu/nebula/server/routes/UserLoginEntity.java b/src/main/java/emu/nebula/server/routes/entity/OverseaUserLoginEntity.java similarity index 94% rename from src/main/java/emu/nebula/server/routes/UserLoginEntity.java rename to src/main/java/emu/nebula/server/routes/entity/OverseaUserLoginEntity.java index d3e264f..83d7e2b 100644 --- a/src/main/java/emu/nebula/server/routes/UserLoginEntity.java +++ b/src/main/java/emu/nebula/server/routes/entity/OverseaUserLoginEntity.java @@ -1,8 +1,8 @@ -package emu.nebula.server.routes; +package emu.nebula.server.routes.entity; import java.util.List; -public class UserLoginEntity { +public class OverseaUserLoginEntity { public int Code; public UserDetailJson Data; public String Msg; diff --git a/src/main/java/emu/nebula/util/AeadHelper.java b/src/main/java/emu/nebula/util/AeadHelper.java index 089bfaf..2cf898e 100644 --- a/src/main/java/emu/nebula/util/AeadHelper.java +++ b/src/main/java/emu/nebula/util/AeadHelper.java @@ -49,6 +49,10 @@ public class AeadHelper { RegionConfig.getRegion("tw") .setServerMetaKey("owGYVDmfHrxi^4pm") .setServerGarbleKey("N&mfco452ZH5!nE3s&o5uxB57UGPENVo"); + + RegionConfig.getRegion("cn") + .setServerMetaKey("Xf&FRcsYm48cJ2A@") + .setServerGarbleKey("QW*Wi7fKjLk!T82Qf2nEGZA%nSC!D9qV"); } public static void loadKeys() {