123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- import CodeMgr from "../../scriptMain/CodeMgr"
- import { StringMap } from "../Collections/StringMap"
- import Gamecfg from "../common/gameCfg"
- import { gameMethod } from "../common/gameMethod"
- import { SevBack } from "../common/Xys"
- import Config from "../Config"
- import { GameEvent, NetworkEvent } from "../data/const/EventConst"
- import GameDataCenter from "../data/GameDataCenter"
- import GameController from "../GameController"
- import UIHelp, { DialogParams } from "../logic/ui/UIHelp"
- import EventMng from "../manager/EventMng"
- import { I18n } from "../utils/I18nUtil"
- import NetConfig from "./NetConfig"
- export interface POST_DATA {
- cmdId: number
- url: string,
- body: Object,
- cb1?: (sev: SevBack) => void,
- cb2?: (sev: SevBack) => void,
- deal: number
- postTime?: number
- }
- export default class HttpRequest {
- // 网络请求所需时间
- static netMs: number = 0
- // 网络请求最长时间(超时时间)
- static timeoutMs: number = 15000
- // 请求失败计数
- static errCount: number = 0
- //请求失败的接口
- static errPostMap: StringMap<POST_DATA> = new StringMap<POST_DATA>();
- //当前请求的接口
- static curPostMap: StringMap<POST_DATA> = new StringMap<POST_DATA>();
- static GET(path: string, callback: Function = () => { }) {
- let isJiami = this.isJiamiPlatform();
- let r = new XMLHttpRequest()
- r.open("GET", path + `?x=${isJiami ? 1 : 0}`, true)
- r.timeout = this.timeoutMs
- let isTimeOut = false;
- let isError = false;
- r.onerror = () => {
- isError = true;
- console.log("发生错误,url=", path)
- callback({})
- }
- r.ontimeout = () => {
- isTimeOut = true;
- console.log("超时了,url=", path)
- callback({})
- }
- r.onloadend = function () {
- if (isTimeOut || isError) return;
- let temp = {}
- if (r.status >= 200 && r.status <= 400 && r.readyState == 4) {
- let txt = gameMethod.xorEncrypt(r.response, isJiami);
- temp = JSON.parse(txt)
- }
- callback(temp)
- }
- r.send()
- }
- // 只发送,无需处理回调
- static POST_SIMPLE(url: string, body: Object) {
- let r = new XMLHttpRequest()
- r.open("POST", url, true)
- r.setRequestHeader("Content-Type", "application/json")
- r.send(JSON.stringify(body))
- }
- // 发送业务外,需处理回调
- static POST_SIMPLE_2(url: string, body: Object, callback: Function = () => { }) {
- let r = new XMLHttpRequest()
- r.open("POST", url, true)
- r.setRequestHeader("Content-Type", "application/json")
- r.onreadystatechange = () => {
- if (r.status >= 200 && r.status <= 400 && r.readyState == 4) {
- callback(r.response)
- } else {
- console.error("POST Faile:", r.status)
- }
- }
- r.send(JSON.stringify(body))
- }
- // 业务逻辑协议调用接口
- static POST(path: string, data: { [key: string]: string }, body: Object, callback: Function = () => { }, isLogin: boolean = false) {
- body = body || {}
- if (CC_JSB) {
- if (!gameMethod.isEmpty(GameDataCenter.sevBack) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch.clientLog)) {
- console.warn("C->S:", path, JSON.stringify(body))
- }
- } else {
- if (!gameMethod.isEmpty(GameDataCenter.sevBack) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch.clientLog)) {
- console.warn("C->S:", path, body)
- }
- }
- let delay = new Date().getTime()
- if (NetConfig.needWait(data.url, body)) {
- EventMng.emit(NetworkEvent.WAIT, 1)
- }
- //淘宝需要通过云服务调用服务器
- if (cc.sys.platform == cc.sys.TAOBAO_MINIGAME) {
- this.taoBaoCloudRequest(data, body, callback, isLogin)
- return
- }
- let r = new XMLHttpRequest()
- r.open("POST", path, true)
- r.timeout = this.timeoutMs
- r.setRequestHeader("Content-Type", "application/json")
- let xor: number = this.isJiamiPlatform() ? 1 : 0;//原生端接收到加密数据会不全,所以就不加密了
- // r.onerror = () => {
- // // console.warn("=======https onerror", r.status, r.readyState)
- // callback({ type: 0 })
- // if (isLogin) {
- // EventMng.emit(NetworkEvent.LOGIN_FAILED)
- // return
- // }
- // this.onError(data.url)
- // }
- r.onerror = r.ontimeout = () => {
- // console.warn("=======https ontimeout", r.status, r.readyState)
- this.netMs = r.timeout
- // 超时的时候,先把waiting关掉
- if (NetConfig.needWait(data.url, body)) {
- EventMng.emit(NetworkEvent.WAIT_CLOSE)
- }
- //请求失败时关闭强请求遮罩
- EventMng.emit(NetworkEvent.NETWAIT_MASK, false)
- // 如果是登录过程中出错,特殊处理
- if (isLogin) {
- EventMng.emit(NetworkEvent.LOGIN_FAILED)
- return
- }
- this.onTimeOut(data.url)
- }
- r.onreadystatechange = () => {
- // console.log("=======https onreadystatechange", r.status, r.readyState)
- if (r.readyState == 4) {
- this.netMs = new Date().getTime() - delay
- if (this.netMs > 1000) {
- console.warn("服务器回调时间超过1秒:", path, JSON.stringify(body))
- }
- }
- let temp = {}
- if (r.status >= 200 && r.status <= 400 && r.readyState == 4) {
- this.errCount = 0
- if (r.response == null || r.response == "") {
- EventMng.emit(NetworkEvent.ON_EXCEPTION)
- this.showErrDialog(data.url, data.uuid, data.version, JSON.stringify(body), r.response == null ? "null" : r.response)
- return
- }
- try {
- // temp = JSON.parse(r.response) // gameMethod.jiemi(r.response)
- // let jiemiTime = new Date().getTime()
- let txt = gameMethod.xorEncrypt(r.response, xor == 1);
- temp = JSON.parse(txt)
- // console.log("消息解密耗时:", new Date().getTime() - jiemiTime)
- } catch (error) {
- EventMng.emit(NetworkEvent.ON_EXCEPTION)
- console.error("解析回调数据失败:", r.response)
- this.showErrDialog(data.url, data.uuid, data.version, JSON.stringify(body), r.response == null ? "null" : r.response)
- }
- // try {
- if (temp && Object.keys(temp).length > 0) {
- if (CC_JSB) {
- if (!gameMethod.isEmpty(GameDataCenter.sevBack) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch.clientLog)) {
- console.warn("S->C:", JSON.stringify(temp))
- }
- } else {
- if (!gameMethod.isEmpty(GameDataCenter.sevBack) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch.clientLog)) {
- console.warn("S->C:", temp)
- }
- }
- //请求成功移除缓存的消息请求
- this.errPostMap.Remove(data.url)
- this.curPostMap.Remove(data.url)
- callback(temp)
- }
- // } catch (error) {
- // console.error("服务端回调数据处理时出现异常:", path, error)
- // }
- }
- if (r.readyState == 4 && NetConfig.needWait(data.url, body)) {
- EventMng.emit(NetworkEvent.WAIT, -1)
- }
- if (r.status < 200 || r.status > 400) {
- // 异常情况
- if (isLogin) {
- EventMng.emit(NetworkEvent.LOGIN_FAILED)
- } else {
- this.onTimeOut(data.url)
- }
- }
- };
- // r.send(JSON.stringify({ cs: CodeMgr.jiami(body) }))
- r.send(JSON.stringify({ xor: gameMethod.xorEncrypt(JSON.stringify(body)), x: xor }))
- // r.send(JSON.stringify(body))
- }
- //淘宝云服请求
- static taoBaoCloudRequest(data: { [key: string]: string }, body: Object, callback: Function = () => { }, isLogin: boolean = false) {
- let path = data.url + "?uuid=" + GameDataCenter.user.uuid +
- "&token=" + GameDataCenter.user.token +
- "&version=" + Config.appVersion +
- "&time=" + GameDataCenter.time.sevTime
- let self = this;
- async function taoBaoCloud() {
- let result
- try {
- result = await window['cloud'].application.httpRequest({
- //不需要完整域名,只需要接口访问路径即可
- 'path': path,
- 'method': 'POST',
- 'headers': { "Content-Type": "application/json" },
- 'params': {},
- 'body': { xor: gameMethod.xorEncrypt(JSON.stringify(body)) },
- //cloudAppId 云应用的Id
- 'exts': {
- "cloudAppId": "55088",
- "timeout": 4000,
- //空应用调用需要填写该字段,包括协议头以及端口号(可省略),支持http、https
- "domain": Gamecfg.packageInfo.getItem(Config.pid).wayhttp
- }
- });
- } catch (error) {
- console.log(error)
- }
- // console.log("result:", JSON.stringify(gameMethod.xorEncrypt(result)));
- let temp = {}
- try {
- // temp = JSON.parse(result) // gameMethod.jiemi(r.response)
- temp = JSON.parse(gameMethod.xorEncrypt(result))
- } catch (error) {
- EventMng.emit(NetworkEvent.ON_EXCEPTION)
- console.error("解析回调数据失败:", result)
- // self.showErrDialog(data.url, data.uuid, data.version, JSON.stringify(body), result == null ? "null" : result)
- }
- try {
- if (temp && Object.keys(temp).length > 0) {
- if (CC_JSB) {
- if (!gameMethod.isEmpty(GameDataCenter.sevBack) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch.clientLog)) {
- console.warn("S->C:", JSON.stringify(temp))
- }
- } else {
- if (!gameMethod.isEmpty(GameDataCenter.sevBack) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch) && !gameMethod.isEmpty(GameDataCenter.sevBack.switch.clientLog)) {
- console.warn("S->C:", temp)
- }
- }
- //请求成功移除缓存的消息请求
- self.errPostMap.Remove(data.url);
- self.curPostMap.Remove(data.url);
- callback(temp)
- }
- } catch (error) {
- console.error("服务端回调数据处理时出现异常:", error)
- }
- if (NetConfig.needWait(data.url, body)) {
- EventMng.emit(NetworkEvent.WAIT, -1)
- }
- }
- this.errCount = 0
- let delayTime = new Date().getTime()
- taoBaoCloud().then(res => {
- if (!gameMethod.isEmpty(GameDataCenter.sevBack?.switch?.clientLog)) {
- console.log("net delay time == " + (new Date().getTime() - delayTime))
- }
- });
- }
- // 发生服务器错误时,提示重试
- private static onError(url: string) {
- let dialogParam: DialogParams = {
- content: I18n.getI18nText("http_error", url),
- cbConfirm: () => {
- this.errCount = 0
- GameController.clear()
- cc.game.restart()
- },
- txtConfirm: I18n.getI18nText("http_overtime_confirm_1"),
- onlyConfirm: true
- }
- UIHelp.ShowSystemDialog(dialogParam)
- }
- // 发生服务器错误时,提示重试
- private static onTimeOut(url: string) {
- this.errCount++
- if (this.errCount > 3) {
- // 超过三次重连失败,提示退出游戏
- GameController.network.stopRequest = true
- let dialogParam: DialogParams = {
- content: I18n.getI18nText("http_error", url),
- cbConfirm: () => {
- this.errCount = 0
- GameController.clear()
- cc.game.restart()
- },
- txtConfirm: I18n.getI18nText("http_overtime_confirm_1"),
- onlyConfirm: true
- }
- UIHelp.ShowSystemDialog(dialogParam)
- } else {
- // 提示网络错误并引导重连
- let dialogParam: DialogParams = {
- content: I18n.getI18nText("http_overtime"),
- cbConfirm: () => {
- GameDataCenter.user.sendPlayerReconnect(() => {
- GameController.network.stopRequest = false
- //重连成功,重新发送失败请求
- this.errPostMap.Foreach((key: string, value: POST_DATA) => {
- console.log(`重新发送:${key}`)
- GameController.network.send(value.url, value.body, value.cb1, value.cb2, value.deal)
- })
- this.errPostMap.Clear()
- this.curPostMap.Clear()
- GameController.network.RemoveTimers()
- })
- },
- txtConfirm: I18n.getI18nText("http_overtime_confirm_2"),
- onlyConfirm: true
- }
- UIHelp.ShowSystemDialog(dialogParam)
- }
- }
- private static showErrDialog(url: string, uuid: string, version: string, body: string, response: string) {
- UIHelp.ShowDialog({
- content: "回调数据丢失,请将此界面截图给开发者\n"
- + `url:${url} uuid:${uuid} version:${version}\n`
- + `body:` + JSON.stringify(body) + "\n"
- + `response:${response.slice(0, 200)}`
- })
- }
- static isJiamiPlatform(): boolean {//以下平台不加密,因为以下加密数据会接受不全
- return !cc.sys.isNative && cc.sys.platform != cc.sys.VIVO_GAME && cc.sys.platform != cc.sys.XIAOMI_GAME && cc.sys.platform != cc.sys.OPPO_GAME;
- }
- }
|