/** * 登录数据管理 */ let LoginMgr = { //* ************* 初始化 ************* *// /** * 初始化 * */ init () { if (CC_EDITOR) { return; } // 注册消息 G.PublicMgr.on(JMC.PUBLIC_MSG.SWITCH_ACCOUNT, JMC.PUBLIC_MSG_ORDER.LOGIN, this.handleDidSwitchAccount, this); G.PublicMgr.on(JMC.PUBLIC_MSG.LOGIN_SUCCESS, JMC.PUBLIC_MSG_ORDER.LOGIN, this.handleDidLoginSuccess, this); G.PublicMgr.on(JMC.PUBLIC_MSG.DISCONNECTED, JMC.PUBLIC_MSG_ORDER.LOGIN, this.handleDidDisconnected, this); this._initEventListener(); this._initPublishListener(); cc.game.on('e_mgr_load_config_done', this.initLocalConfig, this); cc.game.on('e_middle_auth_logout_result', this._handleAuthLogoutResult, this); }, /** * 初始化事件侦听 * */ _initEventListener () { cc.game.on('e_socket_on_connected', this._handleSocketOnConected, this); cc.game.on('e_socket_on_closed', this._handleSocketOnClosed, this); cc.game.on('e_mgr_conf_download_result', this.handleConfDownloadResult, this); }, /** * 初始化服务器请求事件侦听 * */ _initPublishListener () { }, /** * 初始化本地配置 * */ initLocalConfig () { }, /** * 离线 * */ offline () { // 容错:避免前面没有关闭socket,这里再关闭一次 // closeSocket有非空判断,正常情况下不会有任何效果 G.NetworkMgr.closeSocket(); // 向各个Mgr发送断线消息 G.PublicMgr.emit(JMC.PUBLIC_MSG.DISCONNECTED); }, //* ************* 登录数据获取 ************* *// getPassWord () { if (this.loginData) { return this.loginData.password; } return ""; }, //* ************* 事件侦听 ************* *// _handleSocketOnConected () { this._stopKeepalive(); // 请求授权令牌 this.requestAuthToken(); }, /** * 收到登录成功事件 * */ handleDidLoginSuccess () { // 标记在线状态 this.isOnline = true; // 重连计数重置 this.reconnectTimes = 0; // h5user_self_info on_h5user_system_info都收到 cc.game.emit('e_socket_on_logined'); }, /** * 收到断网事件 * */ handleDidDisconnected () { this.isOnline = false; }, /** * 收到切换账号事件 * */ handleDidSwitchAccount () { }, /** * 中间层注销账号 * */ _handleAuthLogoutResult (eventData) { // eventData.data // 授权信息 // 关闭websocket链接 this.offline(); cc.director.loadScene('scene_login'); }, //* ************* 客户端请求/响应 ************* *// /** * 请求注册 * */ // #注册 // usr_register 1001 { // request { // version 1: string # 版本号 // uuid 2: string # UUID // device 3: string # 设备名称 // sysVer 4: string # 设备信息 // channel 5: integer # 渠道号 // apn 6: string # 玩家网络状态 // operator 7: string # 运营商类型字段 // platform 8: string # 登录平台 // udid 9: string # UDID // appVerison 10: string # 对内版本号 // deviceId 11: string # 设备号 // } // response { // code 0: integer // sysTime 1: integer # 服务器时间 // ip 2: string # Socket连接的IP // port 3: integer # Socket连接的Port // token 4: string # token // uid 5: integer # // password 6: string # 密码 // http 7: integer # HTTP PORT // registerTime 8: integer # 注册时间 // errorMsg 9: string # 登陆失败错误信息 // isGuest 10: boolean # 是否游客 // wsPort 11: integer # websocket连接端口 // uuid 12: string # UUID // configVersion 13: string # configVersion // } // } requestRegister () { let info = { version: G.MiddleMgr.getVersion(), uuid: G.MiddleMgr.getUUID(), device: G.MiddleDevice.getDeviceName() + G.FuncUtils.randomInt(100000, 999999), sysVer: G.MiddleDevice.getDeviceInfo(), channel: G.MiddleDevice.getChannelId(), apn: G.MiddleDevice.getApnType(), operator: G.MiddleDevice.getOperator(), platform: cc.sys.platform, udid: G.MiddleMgr.getUDID(), appVerison: G.APP_VERSION, deviceId: G.MiddleMgr.getIDFAEncode(), }; G.NetworkMgr.sendHttpRequestToLoginServer('usr_register', info, this._responseLogin.bind(this)); }, // # 注册 - 手机号 // usr_register_by_phone 1002 { // request { // version 1: string # 必填 - 版本号 // channel 2: integer # 必填 - 渠道号 // device 3: string # 选填 - 设备名称 // sysVer 4: string # 选填 - 设备信息 // apn 5: string # 选填 - 玩家网络状态 // operator 6: string # 选填 - 运营商类型字段 // platform 7: string # 选填 - 登录平台 // deviceId 8: string # 选填 - 设备号 // phone 30: string # 必填 - 手机号 // vcode 31: string # 必填 - 验证码 // password 32: string # 必填 - 密码 // nickname 33: string # 选填 - 昵称 - 空:手机号作为昵称 // sharecode 34: string # 选填 - 邀请码 // } // response { // code 0: integer // sysTime 1: integer # 服务器时间 // ip 2: string # 游戏服网关地址 // port 3: integer # 网关Socket连接的Port // wsPort 4: integer # 网关websocket连接端口 // httpPort 5: integer # 网关HTTP PORT // token 6: string # token // uid 7: integer # 玩家id // registerTime 8: integer # 注册时间 // errorMsg 9: string # 登陆失败错误信息 // configVersion 10: string # configVersion // } // } requestRegisterByPhone (phone, password, nickname, sharecode) { let info = { version: G.MiddleMgr.getVersion(), channel: G.MiddleDevice.getChannelId(), phone: phone, vcode: "", password: password, nickname: nickname ? nickname : "", sharecode: sharecode ? sharecode : "" }; G.NetworkMgr.sendHttpRequestToLoginServer('usr_register_by_phone', info, this._responseLogin.bind(this)); }, /** * 请求登录 * * @param {string} uid 用户ID * @param {string} password 用户密码 */ // #登录 // usr_login 1000 { // request { // uid 0: integer // version 1: string # 版本号 // password 2: string # 密码 // channel 3: integer # 渠道号 // apn 4: string # 玩家网络状态 // operator 5: string # 运营商类型字段 // platform 6: string # 登录平台 // appVerison 7: string # 对内版本号 // uuid 8: string # UUID // udid 9: string # UDID // sysVer 10: string # 设备信息 // } // response { // code 0: integer // sysTime 1: integer # 服务器时间 // ip 2: string # Socket连接的IP // port 3: integer # Socket连接的Port // token 4: string # token // http 5: integer # HTTP PORT // registerTime 6: integer # 注册时间 // errorMsg 7: string # 登陆失败错误信息 // isGuest 8: boolean # 是否游客 // wsPort 9: integer # websocket连接端口 // uuid 10: string # UUID // configVersion 11: string # configVersion // } // } requestLogin (uid, password) { let info = { uid: uid, version: G.MiddleMgr.getVersion(), password: password, channel: G.MiddleDevice.getChannelId(), apn: G.MiddleDevice.getApnType(), operator: G.MiddleDevice.getOperator(), platform: cc.sys.platform, appVerison: G.APP_VERSION, udid: G.MiddleMgr.getUDID(), uuid: G.MiddleMgr.getUUID(), sysVer: G.MiddleDevice.getDeviceInfo(), }; G.NetworkMgr.sendHttpRequestToLoginServer('usr_login', info, this._responseLogin.bind(this)); }, // # 登录 - 手机号 // usr_login_by_phone 1003 { // request { // version 1: string # 必填 - 版本号 // channel 2: integer # 必填 - 渠道号 // device 3: string # 选填 - 设备名称 // sysVer 4: string # 选填 - 设备信息 // apn 5: string # 选填 - 玩家网络状态 // operator 6: string # 选填 - 运营商类型字段 // platform 7: string # 选填 - 登录平台 // deviceId 8: string # 选填 - 设备号 // phone 30: string # 必填 - 手机号 // vcode 31: string # vcode/password必填 - 验证码 - 优先校验vcode // password 32: string # vcode/password必填 - 密码 // } // response { // code 0: integer // sysTime 1: integer # 服务器时间 // ip 2: string # 游戏服网关地址 // port 3: integer # 网关Socket连接的Port // wsPort 4: integer # 网关websocket连接端口 // httpPort 5: integer # 网关HTTP PORT // token 6: string # token // uid 7: integer # 玩家id // registerTime 8: integer # 注册时间 // errorMsg 9: string # 登陆失败错误信息 // configVersion 10: string # configVersion // } // } requestLoginByPhone (phone, password) { let info = { version: G.MiddleMgr.getVersion(), channel: G.MiddleDevice.getChannelId(), phone: phone, password: password }; G.NetworkMgr.sendHttpRequestToLoginServer('usr_login_by_phone', info, this._responseLogin.bind(this)); }, /** * 注册和登录的回调 * 登录和注册返回的数据唯一不同是 * 注册多了uid 和 password * * @author libo * @date 2019-06-19 * @param {object} data */ _responseLogin (data) { let requestInfo = data.requestInfo; let responseInfo = data.responseInfo; switch (responseInfo.code) { case 200: // 成功d case 2010: // 已经注册了的用户 { if (responseInfo.sysTime && responseInfo.sysTime > 0) { G.TimeUtils.synTime(responseInfo.sysTime); } // 记录登录成功时间 this.loginTimestamp = G.TimeUtils.getCurrentTime(); // 特殊处理uid和password let uid = (responseInfo.uid) ? responseInfo.uid : requestInfo.uid; let password = (responseInfo.password) ? responseInfo.password : requestInfo.password; this.loginData = responseInfo; this.loginData.uid = uid; this.loginData.password = password; this._connectGameServer(responseInfo.ip, responseInfo.wsPort || responseInfo.http); break; } case 2004: // 密码错误 { break; } case 2009: // 账号被封杀 { break; } default: // 参数错误 或 未知错误 { // 连接错误或者连接错误会返回 400 break; } } // 将消息下发到ctrl中处理 cc.game.emit('e_nwk_usr_login', data); }, /** * 请求授权令牌 * * @author Wetion * @date 2019-03-26 */ requestAuthToken () { let info = { uid: this.loginData.uid, token: this.loginData.token }; G.NetworkMgr.sendSocketRequest('usr_auth_token', info, this._responseAuthToken.bind(this)); }, _responseAuthToken (data) { let responseInfo = data.responseInfo; if (responseInfo.code === 200) { this.keepaliveTime = this.loginData.sysTime; this._startKeepalive(); G.UserMgr.requestSelfInfo(); } }, // 启动心跳,4 * 30秒后发出第一条心跳 _startKeepalive () { this._stopKeepalive(); this.keepaliveTimeoutCount = 0; this._keepaliveIntervalId = setInterval(() => { this.keepaliveTimeoutCount++; /** * 定时器30秒执行一次 * 4 * 30秒间隔发一次保活请求 * 发送保活请求后30秒没返回断开当前连接进行重连 */ if (this.keepaliveTimeoutCount == 4) { // G.LogUtils.log('发送心跳'); this._requestKeepalive(); } else if (this.keepaliveTimeoutCount == 5) { // G.LogUtils.log('心跳不通'); // 清空心跳定时器 clearInterval(this._keepaliveIntervalId); this._keepaliveIntervalId = undefined; // 断开网络并且弹出重连窗口 G.NetworkMgr.closeSocket(); G.AppUtils.getSceneCtrl().showOfflineAlert(); } }, 30 * 1000); }, /** * 连接保活, 客户端主动60s发送一次 * * @author Wetion * @date 2019-03-26 */ _requestKeepalive () { G.NetworkMgr.sendSocketRequest('h5user_keepalive', undefined, this._responseKeepalive.bind(this)); }, _responseKeepalive (data) { let responseInfo = data.responseInfo; if (responseInfo && responseInfo.systemTime) { this.keepaliveTime = responseInfo.systemTime; // 间隔多少秒请求一次保活 this.keepaliveTimeoutCount = 0; } }, // 重置心跳定时器 _stopKeepalive () { if (this._keepaliveIntervalId) { clearInterval(this._keepaliveIntervalId); this._keepaliveIntervalId = undefined; } }, _connectGameServer (host, port) { // 链接SOCKET G.NetworkMgr.connectSocket(host, port); // 增加HTTP_GAME连接 G.NetworkMgr.addConnection({ alias: '游戏服', name: 'HTTP_GAME', host: host, port: port, path: 'pb' }); }, } module.exports = LoginMgr;