WaterControl/assets/Script/module/Crypto/HttpUtil.ts
2024-07-10 18:35:07 +08:00

222 lines
6.3 KiB
TypeScript

const {ccclass, property} = cc._decorator;
import CryptoJS = require('./crypto-js.min.js'); //引用AES源码js
const BASE_URL = "http://api.sparkus.cn";
//只负责网络接口 次类只负责和后端交互,不负责处理数据 数据处理在GameTool
@ccclass
export default class HttpUtil extends cc.Component {
//排行榜
static async rankData(type,callback,data): Promise<any> {
const time = Math.floor((new Date().getTime()) / 1000)
const url = apiSign(`/api/get/rank/data?gameId=${config.gameId}&dataType=${type}&time=${time}`, data)
this.post(url,data,callback);
}
static async uploadUserLogData(data,callback): Promise<any> {
const url = '/log/collect/data';
this.post(url,data,callback);
}
//暂时用不到
static async getUserRecord(data,callback): Promise<any> {
const time = Math.floor((new Date().getTime()) / 1000)
const url = apiSign(`/api/get/user/data?gameId=${config.gameId}&time=${time}`, data)
this.post(url,data,callback);
}
static async post(url, data, callback) {
const response = await this.fetchData(url, data, 'POST');
callback && callback(response);
}
static async get(url, callback) {
const response = await this.fetchData(url, null, 'GET');
callback && callback(response);
}
static async fetchData(url, data, method) {
const fullUrl = `${BASE_URL}${url}`;
const headers = { 'Content-Type': 'application/json' };
const options = {
method,
headers,
body: data ? JSON.stringify(data) : null,
};
try {
const response = await fetch(fullUrl, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Fetch error:', error);
return null;
}
}
}
function responseHandler(response: { data: any }) {
return response.data
}
// 响应拦截器
// Rq.interceptors.response.use(responseHandler)
const config = {
gameId: "100009",
secretKey: "CMNhOzBA",
EK:"hui231%1"
};
interface CrypotoType {
encryptByDES: any
decryptByDES: any
hmacSha256: any
}
class Crypoto implements CrypotoType {
// 加密的向明值,自己根据项目实际情况定,需要跟后端开发保持一致
private keyHex = this.getHetKey()
private getHetKey() {
return CryptoJS.enc.Utf8.parse(config.EK);
}
/** DES加密 */
encryptByDES(message: string, secret?: string) {
if(!message) {
return message
}
const key = secret? CryptoJS.enc.Utf8.parse(secret): this.keyHex
const encrypted = CryptoJS.DES.encrypt(message, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.toString()
}
/** DES解密 */
decryptByDES(message: string, secret?: string) {
const key = secret? CryptoJS.enc.Utf8.parse(secret): this.keyHex
const decrypted = CryptoJS.DES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(message)
}, key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
return decrypted.toString(CryptoJS.enc.Utf8)
}
/** hmacSHA256加密 */
hmacSha256(message: string, secret?: string) {
const keyHex = secret? CryptoJS.enc.Utf8.parse(secret): this.keyHex
const hash = CryptoJS.HmacSHA256(message, keyHex);
return hash.toString()
}
/** hmacSHA256验证 */
verifyHmacSha256(message: string, signature: string) {
const hash = CryptoJS.HmacSHA256(message, this.keyHex);
return hash.toString() === signature
}
/** CBC加密 */
encryptCBC(word: string) {
if (!word) {
return word;
}
const srcs = CryptoJS.enc.Utf8.parse(word);
const encrypted = CryptoJS.AES.encrypt(srcs, this.keyHex, {
iv: this.keyHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
});
return encrypted.toString();
}
/** CBC解密 */
decryptCBC(word: string) {
if (!word) {
return word;
}
const encryptedHexStr = CryptoJS.enc.Hex.parse(word);
const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
const decrypt = CryptoJS.AES.decrypt(srcs, this.keyHex, {
iv: this.keyHex,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding
});
const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
return decryptedStr.toString();
}
}
const fxCry = new Crypoto();
function isEmpty(data) {
return data === "" || data === null || data === undefined || data.length === 0 || JSON.stringify(data) == "{}"
}
function getQueryString(obj) {
// 首先对对象的键进行排序并过滤空值
const sortedKeys = Object.keys(obj).sort();
const sortedObj = {};
for (let i = 0; i < sortedKeys.length; i++) {
if (isEmpty(obj[sortedKeys[i]])) {
continue;
}
sortedObj[sortedKeys[i]] = obj[sortedKeys[i]];
}
// 然后将排序后的对象转换为查询字符串
const params = [];
for (const key in sortedObj) {
params.push(`${encodeURIComponent(key)}=${encodeURIComponent(sortedObj[key])}`);
}
return params.join('&');
}
/**
* 组装签名字符串
* @param string url: 请求地址
* @param string postStr: post参数的a=1&b=2
* @returns
*/
function genSignStr(url: string, postStr: string): string {
let lessUrl = url.replace('?', '')
lessUrl = lessUrl + "&" + postStr
return encodeURIComponent(fxCry.hmacSha256(lessUrl))
}
// 对参数进行统一urlencode
function urlencode(url: string): string {
const [baseUrl, queryString] = url.split("?", 2);
const params = new URLSearchParams(queryString);
return `${baseUrl}?${params.toString()}`;
}
/**
*
* @param url {string} 接口地址
* @param params {object} 需要加密的参数对象
*/
function apiSign(url: string, params = {}) {
let convertUrl = url.trim()
if (convertUrl.indexOf('?') === -1) {
convertUrl += '?'
}
// 传入参数转换拼接字符串
let postStr = getQueryString(params)
const signedStr = genSignStr(convertUrl, postStr)
const encryptStr = `sign=${signedStr}`
let encryptSignStr = fxCry.encryptByDES(encryptStr, config.secretKey)
encryptSignStr = encodeURIComponent(encryptSignStr)
return `${urlencode(convertUrl)}&_p=${encryptSignStr}`
}