import { game } from "cc"; import { HTTP_SITE_ID, SERVER_LIST, GAME_VER } from "../setting/ServerConfig"; import { Tools } from "../tools/Tools"; import { app } from "../../app/app"; import { CHANNELDATA } from "../data/ChannelData"; import { EDITOR } from "cc/env"; var urls: any = {}; // 当前请求地址集合 var reqparams: any = {}; // 请求参数 /** * 登录token类,全局唯一 */ export class LoginToken{ private static instance: LoginToken | null = null; public access_token: string = ""; public refresh_token: string = ""; public appId: string = ""; public appKey: string = ""; private constructor(){} static get Instance(){ if(LoginToken.instance == null){ LoginToken.instance = new LoginToken(); } return LoginToken.instance; } public setToken(access_token: string, refresh_token: string, appID: string, appKey: string){ this.access_token = access_token; this.refresh_token = refresh_token; this.appId = appID this.appKey = appKey } } /** 当前保存的token */ export const LOGIN_TOKEN : LoginToken = LoginToken.Instance; export enum HttpEvent { NO_NETWORK = "http_request_no_network", // 断网 UNKNOWN_ERROR = "http_request_unknown_error", // 未知错误 TIMEOUT = "http_request_timout" // 请求超时 } export class HttpRequest { /** 服务器地址 */ public server: string = SERVER_LIST /** 请求超时时间 */ public timeout: number = 10000; public lobbyUrl = "" public setUrl (url:string) { this.server = "http://" + url + "/" } /** * HTTP GET请求 * 例: * * Get var complete = function(response){ LogWrap.log(response); } var error = function(response){ LogWrap.log(response); } this.get(name, complete, error); */ public get(name: string, completeCallback: Function, errorCallback?: Function) { this.sendRequest(name, null, false, completeCallback, errorCallback) } public getWithParams(name: string, params: any, completeCallback: Function, errorCallback?: Function) { this.sendRequest(name, params, false, completeCallback, errorCallback) } public getByArraybuffer(name: string, completeCallback: Function, errorCallback?: Function) { this.sendRequest(name, null, false, completeCallback, errorCallback, 'arraybuffer', false); } public getWithParamsByArraybuffer(name: string, params: any, completeCallback: Function, errorCallback?: Function) { this.sendRequest(name, params, false, completeCallback, errorCallback, 'arraybuffer', false); } /** * HTTP POST请求 * 例: * * Post var param = '{"LoginCode":"donggang_dev","Password":"e10adc3949ba59abbe56e057f20f883e"}' var complete = function(response){ var jsonData = JSON.parse(response); var data = JSON.parse(jsonData.Data); LogWrap.log(data.Id); } var error = function(response){ LogWrap.log(response); } this.post(name, param, complete, error); */ public post(name: string, params: any, completeCallback?: Function, errorCallback?: Function) { this.sendRequest(name, params, true, completeCallback, errorCallback); } /** 取消请求中的请求 */ public abort(name: string) { var xhr = urls[this.server + name]; if (xhr) { xhr.abort(); } } /** * 获得字符串形式的参数 */ private getParamString(params: any) { var result = ""; for (var name in params) { let data = params[name]; if (data instanceof Object) { for (var key in data) result += `${key}=${data[key]}&`; } else { result += `${name}=${data}&`; } } return result.substring(0, result.length - 1); } /** * Http请求 * @param name(string) 请求地址 * @param params(JSON) 请求参数 * @param isPost(boolen) 是否为POST方式 * @param callback(function) 请求成功回调 * @param errorCallback(function) 请求失败回调 * @param responseType(string) 响应类型 */ private async sendRequest( name: string, params: any, isPost: boolean, completeCallback?: Function, errorCallback?: Function, responseType?: string, isOpenTimeout = true, timeout: number = this.timeout ) { if (!name) { console.log("请求地址不能为空"); return; } let url: string, newUrl: string, paramsStr: string; if (name.toLocaleLowerCase().indexOf("http") === 0) { url = name; } else { url = this.server + name; } if (params) { paramsStr = this.getParamString(params); if (url.indexOf("?") > -1) newUrl = url + "&" + encodeURIComponent(paramsStr); else newUrl = url + "?" + paramsStr; } else { newUrl = url; } if (urls[newUrl] != null && reqparams[newUrl] === paramsStr!) { console.log(`地址【${url}】已正在请求中,不能重复请求`); return; } const xhr = new XMLHttpRequest(); urls[newUrl] = xhr; reqparams[newUrl] = paramsStr!; if (isPost) { xhr.open("POST", url); } else { xhr.open("GET", newUrl); } if (LOGIN_TOKEN.access_token !== "") { xhr.setRequestHeader("Authorization", "Bearer " + LOGIN_TOKEN.access_token); } xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); // 加密设置 const time = Math.floor(Date.now() / 1000); xhr.setRequestHeader("Lang", CHANNELDATA.lang); if (!params) params = {}; let _params = params; _params.appId = LOGIN_TOKEN.appId; _params.nonceStr = Tools.getRandomStr(6); _params.timestamp = time; let sha256DDD: string; try { sha256DDD = await Tools.generateSignNative(_params, LOGIN_TOKEN.appKey); } catch (err) { console.error("生成签名失败:", err); this.deleteCache(newUrl); const data: any = { url, params, event: HttpEvent.UNKNOWN_ERROR }; if (errorCallback) errorCallback(data); return; // 出错直接返回,避免继续执行 } // xhr.setRequestHeader("appId", LOGIN_TOKEN.appId); // xhr.setRequestHeader("timestamp", _params.timestamp.toString()); // xhr.setRequestHeader("signature", sha256DDD); // xhr.setRequestHeader("nonceStr", _params.nonceStr); // xhr.setRequestHeader("Site-Id", HTTP_SITE_ID); // const v = app.lib.storage.get("CURR_VERSION") || "100"; // xhr.setRequestHeader("app-version-key", v.toString()); // xhr.setRequestHeader("system-key", "android"); // xhr.setRequestHeader("Client-Version", GAME_VER); xhr.setRequestHeader("X-Domain", LOGIN_TOKEN.appId); xhr.setRequestHeader("X-Locale", LOGIN_TOKEN.appKey); const data: any = { url, params }; // 请求超时 if (isOpenTimeout) { xhr.timeout = timeout; xhr.ontimeout = () => { this.deleteCache(newUrl); data.event = HttpEvent.TIMEOUT; if (errorCallback) errorCallback(data); }; } xhr.onloadend = () => { if (xhr.status === 500) { this.deleteCache(newUrl); data.event = HttpEvent.NO_NETWORK; if (errorCallback) errorCallback(data); } }; xhr.onerror = () => { this.deleteCache(newUrl); if (!errorCallback) return; if (xhr.readyState === 0 || xhr.readyState === 1 || xhr.status === 0) { data.event = HttpEvent.NO_NETWORK; } else { data.event = HttpEvent.UNKNOWN_ERROR; } errorCallback(data); }; xhr.onreadystatechange = () => { if (xhr.readyState !== 4) return; this.deleteCache(newUrl); if (xhr.status === 200) { if (completeCallback) { if (responseType === "arraybuffer") { xhr.responseType = responseType; completeCallback(xhr.response); } else { try { const resp: any = JSON.parse(xhr.response); if (resp.status === "success") { const isDevelopment = EDITOR || (typeof window !== 'undefined' && (window.location.hostname.includes('localhost') || window.location.hostname.includes('127.0.0.1'))); if (isDevelopment) { console.log("data:", resp.data); } completeCallback(resp.data); } else { app.manager.ui.showToast(Tools.GetLocalized(resp.msg)); if (errorCallback) errorCallback(resp.data); } // if (Number(resp.code) === 200 || Number(resp.code) === 406) { // const isDevelopment = EDITOR || (typeof window !== 'undefined' && (window.location.hostname.includes('localhost') || window.location.hostname.includes('127.0.0.1'))); // if (isDevelopment) { // console.log("data:", resp.data); // } // completeCallback(resp.data); // } else { // app.manager.ui.showToast(Tools.GetLocalized(resp.msg)); // if (errorCallback) errorCallback(resp.data); // } } catch (error) { console.log("解析响应失败:", error); if (errorCallback) errorCallback({ event: HttpEvent.UNKNOWN_ERROR }); } } } } }; if (!paramsStr) { xhr.send(); } else { xhr.send(paramsStr!); } } private deleteCache(url: string) { delete urls[url]; delete reqparams[url]; } } export let httpRequest = new HttpRequest()