import Msg from "../utils/msg"; // 确保路径是正确的 import QuickAsy from "../utils/quickAsy"; import { parseString } from "xml2js"; import { RefreshToken, PackageName, ProductId, IosUrl, AppSecretSanLi, Account, ClientSecret, ClientId, AppSecret360, } from "../config/thirdParams"; import { generateOrderNumber, formatDate, getServerList, } from "../utils/common"; const CryptoJS = require("crypto-js"); const Order = require("../model/OrderModel"); const Server = require("../model/ServerModel"); const System = require("../model/SystemModel"); const User = require("../model/UserModel"); const Version = require("../model/VersionModel"); const CDK = require("../model/CDK"); const notice = require("../json/notice.json"); const th_notice = require("../json/th_notice.json"); const xky_notice = require("../json/xky_notice.json"); const logger = require("../utils/log"); const axios = require("axios"); const googleCallPay = async (ctx) => { let ret = { code: 0, msg: "发货失败", }; let data = ctx.request.body; let orderId = data.orderId; let googleToken = data.purchaseToken; let out_trade_no = ""; logger.info("pay callback params:", { url: ctx.href, params: data }); const res = await Order.updateOrderToken(orderId, googleToken, "google"); const redisClient = ctx.redis.client; let access_token = await redisClient.get("access_token"); if (!access_token) { console.log("请求api获取token"); const apiData = { grant_type: "refresh_token", client_id: ClientId, client_secret: ClientSecret, refresh_token: RefreshToken, }; const response = await axios.post( "https://accounts.google.com/o/oauth2/token", apiData, { headers: { "Content-Type": "application/x-www-form-urlencoded", }, } ); logger.info("token params:", { data: response.data, params: apiData }); if (!response.data.access_token) { return ret; } access_token = response.data.access_token; await redisClient.set("access_token", response.data.access_token); await redisClient.expire("access_token", 1800); } if (!access_token) { return ret; } const orderInfo = (await Order.getOrder(orderId))[0]; if (!orderInfo) { logger.info(`订单${orderId}不存在`); ret.msg = `订单${orderId}不存在`; return ret; } if (orderInfo.status == 2) { logger.info(`订单${orderId}已经重复发货`); ret.code = 1; ret.msg = `订单${orderId}已经重复发货`; return ret; } let url = await getServerList(orderInfo.server_id, "default"); if (!url) { logger.info(`区服id错误: serverId ${orderInfo.server_id}`); ret.msg = `区服id错误: serverId ${orderInfo.server_id}`; return ret; } const productId = ProductId + orderInfo.product_id; let apiUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}?access_token=${access_token}`; let maxRetries = 3; let currentRetry = 0; let isCheck = false; // 使用 while 循环进行重试 while (currentRetry < maxRetries) { try { // // 尝试执行的操作 const googleRes = await axios.get(apiUrl, { headers: { "Content-Type": "application/x-www-form-urlencoded", }, }); console.log(googleRes.data); // 如果操作成功,退出循环 if (googleRes.data.purchaseState == 0) { out_trade_no = googleRes.data.orderId; isCheck = true; break; } } catch (error) { // 捕获请求中的错误 if (error.response) { // 请求已发出,服务器用状态码响应 console.error(error.response.data); console.error(error.response.status); console.error(error.response.headers); } else if (error.request) { // 请求已发出但没有收到响应 // 这通常是网络错误 console.error(error.request); } else { // 在设置请求时出现错误 console.error("Error", error.message); } } currentRetry++; } if (!isCheck) { return ret; } let sendMsg = new Msg(); sendMsg.connect(url, Account); let orgMemId = orderInfo.uid; let orgOderId = orderId; let orgProductId = orderInfo.product_id; let orgProductPrice = orderInfo.amount; const accountInfo = (await User.checkAccountIsExist(orgMemId))[0]; // 在适当的时机,调用 CG_ASK_LOGIN 方法 let params = `{"account":"${orgMemId}","channel_id":${accountInfo.channel_id},"order":"${orgOderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`; return new Promise((resolve) => { setTimeout(async () => { const send_res = sendMsg.CG_ASK_LOGIN( Account, 0, "", "cn", "CN", ctx.request.ip, params, orderInfo.server_id ); if (!send_res) { resolve(ret); return; } try { let acknowledgeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:acknowledge?access_token=${access_token}`; const acknowledgeRes = await axios.post( acknowledgeUrl, { developerPayload: "", }, { headers: { "Content-Type": "application/json", }, } ); } catch (error) { // 捕获请求中的错误 if (error.response) { // 请求已发出,服务器用状态码响应 console.error(error.response.data); console.error(error.response.status); console.error(error.response.headers); } else if (error.request) { // 请求已发出但没有收到响应 // 这通常是网络错误 console.error(error.request); } else { // 在设置请求时出现错误 console.error("Error", error.message); } ret.msg = "请求第三方失败"; resolve(ret); } try { let consumeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:consume?access_token=${access_token}`; const consumeRes = await axios.post( consumeUrl, { developerPayload: "", }, { headers: { "Content-Type": "application/json", }, } ); } catch (error) { // 捕获请求中的错误 if (error.response) { // 请求已发出,服务器用状态码响应 console.error(error.response.data); console.error(error.response.status); console.error(error.response.headers); } else if (error.request) { // 请求已发出但没有收到响应 // 这通常是网络错误 console.error(error.request); } else { // 在设置请求时出现错误 console.error("Error", error.message); } ret.msg = "请求第三方失败"; resolve(ret); } logger.info("谷歌 pass :", { orderId: orderId }); const update_time = formatDate(new Date()); const res = await Order.updateOrderStats( orderId, 2, out_trade_no, update_time, orderInfo.uid ); if (res.affectedRows <= 0) { logger.info(`订单${orderId} 发货失败`); ret.msg = "发货失败"; resolve(ret); return; } ret.code = 1; ret.msg = "发货成功"; resolve(ret); }, 1000); }); }; const appleCallPay = async (ctx) => { let ret = { code: 0, msg: "发货失败", }; let data = ctx.request.body; logger.info("pay callback params:", { url: ctx.href, params: data }); if (!data.purchaseToken || !data.orderId) { return ret; } let receipt_data = data.purchaseToken.replace(/ /g, "+"); let orderId = data.orderId; let maxRetries = 5; let currentRetry = 0; let isCheck = false; let out_trade_no = orderId; const res = await Order.updateOrderToken(orderId, receipt_data, "apple"); // 使用 while 循环进行重试 while (currentRetry < maxRetries) { try { const apiData = { "receipt-data": receipt_data, }; const response = await axios.post(IosUrl, apiData, { headers: { "Content-Type": "application/json", }, }); logger.info(`苹果返回的状态:${response.data.status}`); // 如果操作成功,退出循环 if (response.data.status == 0) { isCheck = true; break; } } catch (error) { // 如果操作失败,记录错误并继续尝试 console.log(error); } currentRetry++; } if (!isCheck) { logger.info(`票据验证失败!`); ret.msg = `票据验证失败!`; return ret; } const orderInfo = (await Order.getOrder(orderId))[0]; if (!orderInfo) { logger.info(`订单${orderId}不存在`); ret.msg = `订单${orderId}不存在`; return ret; } if (orderInfo.status == 2) { logger.info(`订单${orderId}已经重复发货`); ret.code = 1; ret.msg = `订单${orderId}已经重复发货`; return ret; } let url = await getServerList(orderInfo.server_id, "default"); if (!url) { logger.info(`区服id错误: serverId ${orderInfo.server_id}`); ret.msg = `区服id错误: serverId ${orderInfo.server_id}`; return ret; } let sendMsg = new Msg(); sendMsg.connect(url, Account); let orgMemId = orderInfo.uid; let orgOderId = orderId; let orgProductId = orderInfo.product_id; let orgProductPrice = orderInfo.amount; const accountInfo = (await User.checkAccountIsExist(orgMemId))[0]; // 在适当的时机,调用 CG_ASK_LOGIN 方法 let params = `{"account":"${orgMemId}","channel_id":${accountInfo.channel_id},"order":"${orgOderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`; return new Promise((resolve) => { setTimeout(async () => { logger.info(`订单${orderId}通知游戏发货开始`); const send_res = sendMsg.CG_ASK_LOGIN( Account, 0, "", "cn", "CN", ctx.request.ip, params, orderInfo.server_id ); if (!send_res) { resolve(ret); return; } logger.info(`订单${orderId}通知游戏发货结束`); const update_time = formatDate(new Date()); const res = await Order.updateOrderStats( orderId, 2, out_trade_no, update_time, orderInfo.uid ); if (res.affectedRows <= 0) { logger.info(`订单${orderId} 发货失败`); ret.msg = "发货失败"; resolve(ret); return; } ret.code = 1; ret.msg = "发货成功"; resolve(ret); }, 1000); }); }; //qucik发货 //扩展参数格式为${serverId};${productId} const CallPayQuick = async (ctx) => { let ret = { code: 0, msg: "发货失败", }; //sdk参数 let md5Key = "q97tvr1yqpum8y2h7d0mhvosffrplwlm"; let callbackKey = "77410735093537425113205417841669"; let data = ctx.request.body; logger.info("qucik 回调参数", { data: data }); let md5Sign = data.md5Sign; let ntData = data.nt_data; let verifySignData = QuickAsy.getSign(data, md5Key); if (verifySignData != md5Sign) { logger.error("quick 调用md5Sign错误", { $verifySignData: verifySignData, md5Sign: md5Sign, }); return ret; } let xmlData = QuickAsy.decode(ntData, callbackKey); const result = await new Promise((resolve, reject) => { parseString(xmlData, (err, result) => { if (err) { return reject(err); } resolve(result); }); }); const message = (result as any).quicksdk_message.message[0]; const channel = message.channel[0]; const orgMemId = message.channel_uid[0]; const channelOrder = message.channel_order[0]; const orderId = message.game_order[0]; //cp单号 const orderNo = message.order_no[0]; //sdk订单号 const payTime = message.pay_time[0]; const orgProductPrice = message.amount[0]; //充值成功的金额 const status = message.status[0]; //0成功 const extrasParams = message.extras_params[0]; if (status == 1) { return; } const orderInfo = (await Order.getOrder(orderId))[0]; if (!orderInfo) { logger.info(`订单${orderId}不存在`); ret.msg = `订单${orderId}不存在`; return ret; } let serverId = orderInfo.server_id; //区服id let orgProductId = orderInfo.product_id; //商品id if (orderInfo.status == 2) { logger.info(`订单${orderId}已经重复发货`); ret.code = 1; ret.msg = `订单${orderId}已经重复发货`; return ret; } let url = await getServerList(serverId, "default"); if (!url) { logger.info(`区服id错误: serverId ${serverId}`); ret.msg = `区服id错误: serverId ${serverId}`; return ret; } // 使用 Msg 类的 connect 方法连接到 WebSocket 服务器 let sendMsg = new Msg(); sendMsg.connect(url, Account); logger.info(`订单${orderId} ${url}`); const accountInfo = (await User.checkAccountIsExist(orgMemId))[0]; // 在适当的时机,调用 CG_ASK_LOGIN 方法 let params = `{"account":"${orgMemId}","order":"${orderId}","channel_id":${accountInfo.channel_id},"id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`; return new Promise((resolve) => { setTimeout(async () => { console.log("这个消息将在3秒后打印出来"); const send_res = sendMsg.CG_ASK_LOGIN( Account, 0, "", "cn", "CN", ctx.request.ip, params, serverId ); if (!send_res) { resolve(ret); return; } const update_time = formatDate(new Date()); const res = await Order.updateOrderStats( orderId, 2, orderNo, update_time, orderInfo.uid ); if (res.affectedRows <= 0) { logger.info(`订单${orderId} 发货失败`); ret.msg = "发货失败"; resolve(ret); return; } ret.code = 1; ret.msg = "发货成功"; resolve(ret); }, 1000); }); }; const CallPay360 = async (ctx) => { let ret = { code: 0, msg: "发货失败", }; let data = ctx.request.body; let sign = data.sign; let serverId = data.serverId; let orderId = data.cpOrder; let out_trade_no = data.orderId; logger.info("pay callback params:", { url: ctx.href, params: data }); const orderInfo = (await Order.getOrder(orderId))[0]; if (!orderInfo) { logger.info(`订单${orderId}不存在`); ret.msg = `订单${orderId}不存在`; return ret; } if (orderInfo.status == 2) { logger.info(`订单${orderId}已经重复发货`); ret.code = 1; ret.msg = `订单${orderId}已经重复发货`; return ret; } //签名参数 let signData = Object.keys(data) .sort() .filter((key) => key !== "sign"); let signStr = signData.map((key) => `${data[key]}`).join(""); signStr += AppSecret360; let newSign = CryptoJS.MD5(signStr).toString(); console.log("signStr:", signStr); console.log("newSign:", newSign); if (sign != newSign) { logger.info(`签名错误: 签名串 ${signStr} newSign ${newSign} sign ${sign}`); ret.msg = `签名错误`; return ret; } let url = await getServerList(serverId, "default"); if (!url) { logger.info(`区服id错误: serverId ${serverId}`); ret.msg = `区服id错误: serverId ${serverId}`; return ret; } //发货 // 使用 Msg 类的 connect 方法连接到 WebSocket 服务器 let sendMsg = new Msg(); sendMsg.connect(url, Account); logger.info(`订单${orderId} ${url}`); let orgMemId = data.uid; let orgOderId = data.cpOrder; let orgProductId = orderInfo.product_id; let orgExt = data.cText; let orgProductPrice = data.skuPrice; const accountInfo = (await User.checkAccountIsExist(orgMemId))[0]; // 在适当的时机,调用 CG_ASK_LOGIN 方法 let params = `{"account":"${orgMemId}","order":"${orgOderId}","id":${orgProductId},"channel_id":${accountInfo.channel_id},"cnt":100,"money":${orgProductPrice}}`; return new Promise((resolve) => { setTimeout(async () => { console.log("这个消息将在3秒后打印出来"); const send_res = sendMsg.CG_ASK_LOGIN( Account, 0, "", "cn", "CN", ctx.request.ip, params, serverId ); if (!send_res) { resolve(ret); return; } const update_time = formatDate(new Date()); const res = await Order.updateOrderStats( orderId, 2, out_trade_no, update_time, orderInfo.uid ); if (res.affectedRows <= 0) { logger.info(`订单${orderId} 发货失败`); ret.msg = "发货失败"; resolve(ret); return; } ret.code = 1; ret.msg = "发货成功"; resolve(ret); }, 1000); }); }; const CallPaySanLi = async (ctx) => { let ret = { code: 1, msg: "发货失败", }; let data = ctx.request.body; let sign = data.sign; let serverId = data.serverId; let orderId = data.exts; let out_trade_no = data.orderId; logger.info("pay callback params:", { url: ctx.href, params: data }); const orderInfo = (await Order.getOrder(orderId))[0]; if (!orderInfo) { logger.info(`订单${orderId}不存在`); ret.msg = `订单${orderId}不存在`; return ret; } if (orderInfo.status == 2) { logger.info(`订单${orderId}已经重复发货`); ret.code = 1; ret.msg = `订单${orderId}已经重复发货`; return ret; } //签名参数 let signData = Object.keys(data) .sort() .filter((key) => key !== "sign"); let signStr = signData .map((key) => { return `${key}=${data[key]}`; }) .join("&"); signStr += "&key=" + AppSecretSanLi; let newSign = CryptoJS.MD5(signStr).toString(); console.log("signStr:", signStr); console.log("newSign:", newSign); if (sign != newSign) { logger.info(`签名错误: 签名串 ${signStr} newSign ${newSign} sign ${sign}`); ret.msg = `签名错误`; return ret; } let url = await getServerList(serverId, "default"); if (!url) { logger.info(`区服id错误: serverId ${serverId}`); ret.msg = `区服id错误: serverId ${serverId}`; return ret; } //发货 // 使用 Msg 类的 connect 方法连接到 WebSocket 服务器 let sendMsg = new Msg(); sendMsg.connect(url, Account); logger.info(`订单${orderId} ${url}`); let orgMemId = data.userId; let orgOderId = data.exts; let orgProductId = orderInfo.productId; let orgExt = data.exts; let orgProductPrice = data.orderAmount / 100; const accountInfo = (await User.checkAccountIsExist(orgMemId))[0]; // 在适当的时机,调用 CG_ASK_LOGIN 方法 let params = `{"account":"${orgMemId}","order":"${orgOderId}","id":${orgProductId},"channel_id":${accountInfo.channel_id},"cnt":100,"money":${orgProductPrice}}`; return new Promise((resolve) => { setTimeout(async () => { console.log("这个消息将在3秒后打印出来"); const send_res = sendMsg.CG_ASK_LOGIN( Account, 0, "", "cn", "CN", ctx.request.ip, params, serverId ); if (!send_res) { resolve(ret); return; } const update_time = formatDate(new Date()); const res = await Order.updateOrderStats( orderId, 2, out_trade_no, update_time, orderInfo.uid ); if (res.affectedRows <= 0) { logger.info(`订单${orderId} 发货失败`); ret.msg = "发货失败"; resolve(ret); return; } ret.code = 200; ret.msg = "发货成功"; resolve(ret); }, 1000); }); }; const testGoogleCallPay = async (ctx) => { let ret = { code: 0, msg: "消费失败", }; let data = ctx.request.body; logger.info("pay callback params:", { url: ctx.href, params: data }); const redisClient = ctx.redis.client; let access_token = await redisClient.get("access_token"); if (!access_token) { console.log("请求api获取token"); const apiData = { grant_type: "refresh_token", client_id: ClientId, client_secret: ClientSecret, refresh_token: RefreshToken, }; const response = await axios.post( "https://accounts.google.com/o/oauth2/token", apiData, { headers: { "Content-Type": "application/x-www-form-urlencoded", }, } ); logger.info("token params:", { data: response.data, params: apiData }); if (!response.data.access_token) { return ret; } access_token = response.data.access_token; await redisClient.set("access_token", response.data.access_token); await redisClient.expire("access_token", 1800); } if (!access_token) { return ret; } let googleToken = data.purchaseToken; let product_id = data.orderId; const productId = ProductId + product_id; let apiUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}?access_token=${access_token}`; let maxRetries = 5; let currentRetry = 0; let isCheck = false; // 使用 while 循环进行重试 while (currentRetry < maxRetries) { try { // // 尝试执行的操作 const googleRes = await axios.get(apiUrl, { headers: { "Content-Type": "application/x-www-form-urlencoded", }, }); console.log(googleRes.data); // 如果操作成功,退出循环 if (googleRes.data.purchaseState == 0) { isCheck = true; break; } } catch (error) { // 如果操作失败,记录错误并继续尝试 console.log(error); } currentRetry++; } if (!isCheck) { return ret; } return new Promise(async (resolve) => { let acknowledgeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:acknowledge?access_token=${access_token}`; console.log(acknowledgeUrl); const acknowledgeRes = await axios.post( acknowledgeUrl, { developerPayload: "", }, { headers: { "Content-Type": "application/json", }, } ); let consumeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:consume?access_token=${access_token}`; const consumeRes = await axios.post( consumeUrl, { developerPayload: "", }, { headers: { "Content-Type": "application/json", }, } ); ret.code = 1; ret.msg = "发货成功"; resolve(ret); }); }; function splitString(input: string, separator: string): string[] { return input.split(separator); } function extractIPAddresses(text: string): string[] { // 正则表达式匹配IP地址 const ipRegex = /(?:(?:\d{1,3}\.){3}\d{1,3})/g; // 使用正则表达式执行匹配并返回结果 return text.match(ipRegex) || []; } //验证账号 const checkUserToken = async (ctx) => { let ret = { code: 0, data: { ip: "", }, msg: "请求失败", }; let ip = ctx.request.ip; if (ip.startsWith("::ffff:")) { ip = ip.substring("::ffff:".length); } if (ip == "127.0.0.1") { const forwardedIps = ctx.get("X-Forwarded-For")?.split(","); const clientIP = forwardedIps ? forwardedIps[0].trim() : null; // 若 X-Forwarded-For 不存在,尝试 X-Real-IP ip = clientIP || ctx.get("X-Real-IP") || ctx.ip; } let { uid, channel_id, device_no, reg_device, device_type, device_model, device_version, system_version, } = ctx.request.body; const create_time = formatDate(new Date()); const accountInfo = (await User.checkAccountIsExist(uid))[0]; let accountRes = null; let res = null; if (!accountInfo) { accountRes = await User.createAccount( uid, channel_id, ip, device_no, reg_device, create_time ); if (accountRes.affectedRows <= 0) { ret.msg = "添加账户失败"; return ret; } } res = await User.logAccountLogin( uid, ip, device_type, device_no, device_model, device_version, system_version, create_time ); if (res.affectedRows <= 0) { ret.msg = "添加日志失败"; return ret; } ret.code = 1; ret.msg = "请求成功"; ret.data.ip = ip; return ret; }; class ApiController { async createOrder(ctx) { let { uid, level, amount, role_id, role_name, product_id, server_id } = ctx.request.body; logger.info("create params:", { params: ctx.request.body }); if ( !product_id || !server_id || !role_name || !role_id || !amount || !uid ) { ctx.body = { code: -1, message: "参数错误,创建订单失败!!", data: "" }; return; } const data = ctx.request.body; const sign = data.sign; //签名参数 let signData = Object.keys(data) .sort() .filter((key) => key !== "sign"); let signStr = signData.map((key) => `${data[key]}`).join(""); signStr += "q97tvr1yqpum8y2h7d0mhvosffrplwlm"; let newSign = CryptoJS.MD5(signStr).toString(); console.log("signStr:", signStr); console.log("newSign:", newSign); if (sign != newSign) { logger.info( `签名错误: 签名串 ${signStr} newSign ${newSign} sign ${sign}` ); ctx.body = { code: -1, message: "签名错误,创建订单失败!!", data: "", }; return; } if (amount < 1) { ctx.body = { code: -1, message: "金额错误,创建订单失败!!", data: "", }; return; } const orderId = generateOrderNumber(); // 生成一个长度为8的订单号 const create_time = formatDate(new Date()); const res = await Order.createOrder( orderId, uid, level, amount, role_id, role_name, product_id, server_id, create_time ); if (res.affectedRows > 0) { ctx.body = { code: 0, message: "创建订单成功", data: orderId }; } else { ctx.body = { code: -1, message: "创建订单失败", data: "" }; } logger.info("创建订单返回结果:", { params: ctx.body }); } async checkUserToken(ctx) { let data = ctx.request.body; let platform = "360"; // 默认360 if (ctx.query.platform) { platform = ctx.query.platform; } if (data.platform) { platform = data.platform; } switch (platform) { case "360": var result = await checkUserToken(ctx); ctx.body = result; break; case "th": var result = await checkUserToken(ctx); ctx.body = result; break; case "sanli": var result = await checkUserToken(ctx); ctx.body = result; break; case "quick": var result = await checkUserToken(ctx); ctx.body = result; break; default: ctx.body = { code: 0, msg: "渠道错误", }; } } //quick登陆 async quickUserLogin(ctx) { //sdk参数 let productCode = "40202114039243214268433998697181"; let data = ctx.request.body; let uid = data.uid; let token = data.token; let reqUrl = "http://checkuser.quickapi.net/v2/checkUserInfo?token=" + token + "&uid=" + uid + "product_code=" + productCode; logger.info("quick登陆验证请求", { params: data, url: reqUrl }); const res = await axios.get(reqUrl); logger.info("quick req", { res: res.data }); if (res.data == "1") { ctx.body = { code: 200, msg: "success", }; } else { ctx.body = { code: 0, msg: "fail", }; } } async sanLiUserLogin(ctx) { let ret = { code: 0, msg: "fail", }; let data = ctx.request.body; const sign = data.sign; //签名参数 let signData = Object.keys(data) .sort() .filter((key) => key !== "sign"); let signStr = signData .map((key) => { return `${key}=${data[key]}`; }) .join("&"); signStr += "&key=" + AppSecretSanLi; let newSign = CryptoJS.MD5(signStr).toString(); console.log("signStr:", signStr); console.log("newSign:", newSign); if (sign != newSign) { logger.info( `签名错误: 签名串 ${signStr} newSign ${newSign} sign ${sign}` ); ret.msg = `签名错误`; ctx.body = ret; } else { ret.code = 1; ret.msg = "success"; ctx.body = ret; } } async callPay(ctx) { console.log(234234234); let data = ctx.request.body; let platform = "360"; // 默认360 if (ctx.query.platform) { platform = ctx.query.platform; } if (data.platform) { platform = data.platform; } switch (platform) { case "google": var result = await googleCallPay(ctx); console.log("发货结果", result); ctx.body = result; break; case "apple": var result = await appleCallPay(ctx); console.log("发货结果", result); ctx.body = result; break; case "360": var result = await CallPay360(ctx); console.log("发货结果", result); ctx.body = result; break; case "sanli": var result = await CallPaySanLi(ctx); console.log("发货结果", result); ctx.body = result; break; // case 'testGoogle': // var result = await testGoogleCallPay(ctx) // console.log('发货结果', result) // ctx.body = result // break; case "quick": var result = await CallPayQuick(ctx); console.log("发货结果", result); if ((result as any).code == 1) { ctx.body = "SUCCESS"; } else { ctx.body = "Fail"; } break; default: ctx.body = { code: 0, msg: "渠道错误", }; } } async getServerList(ctx) { let tag = ctx.query.tag || "default"; const servers = await Server.getServerList(tag); let data = []; let ip = ctx.request.ip; if (ip.startsWith("::ffff:")) { ip = ip.substring("::ffff:".length); } logger.info("区服接口", { ip: ctx.request.ip }); if (servers.length > 0) { servers.forEach(function (element) { let status = element.status; if ((status == 0 || status == 3) && element.white_list) { const list = element.white_list.split(","); if (list.length > 0) { if (list.includes(ip)) { status = 1; } } } data.push({ id: element.id, name: element.name, ip: element.ip, port: element.port, tips: element.tips, status: status, }); }); } ctx.body = data; } async getAllServerList(ctx) { let tag = ctx.query.tag || "default"; let ip = ctx.request.ip; if (ip.startsWith("::ffff:")) { ip = ip.substring("::ffff:".length); } logger.info("getAllServerList 区服接口", { ip: ctx.request.ip }); const servers = await Server.getAllServerList(tag, ip); ctx.body = servers; } async enterServer(ctx) { let ret = { code: 0, msg: "请求失败", }; let { uid, server_id } = ctx.request.body; let url = await getServerList(server_id, "default"); if (!url) { ctx.body = { code: -1, message: `区服id错误: serverId ${server_id}`, data: "", }; return; } logger.info("create params:", { params: ctx.request.body }); if (!server_id || !uid) { ctx.body = { code: -1, message: "参数错误!!", data: "" }; return; } const create_time = formatDate(new Date()); const serverInfo = (await Server.checkEnterServerByUid(uid, server_id))[0]; let res = null; if (serverInfo) { res = await Server.updateEnterServer(serverInfo.id, create_time); } else { res = await Server.enterServer(uid, server_id, create_time); } if (res.affectedRows > 0) { ctx.body = { code: 0, message: "请求成功", data: "" }; } else { ctx.body = { code: -1, message: "请求失败", data: "" }; } } async getLastServerList(ctx) { let { uid } = ctx.request.body; let tag = "default"; let data = []; let isNewAccount = 1; let enterServerList = await Server.getEnterServerListByUid(uid); let ip = ctx.request.ip; if (ip.startsWith("::ffff:")) { ip = ip.substring("::ffff:".length); } logger.info("getLastServerList 区服接口", { ip: ctx.request.ip }); if (enterServerList.length > 0) { isNewAccount = 0; // const servers = (await Server.getServerList(tag, 1)) const servers = await Server.getAllServerList(tag, ip); enterServerList.forEach(function (element) { data.push({ channel: "Thailand", //渠道固定 minSid: 1, //最小服务器 maxSid: servers.length, //最大服务器 这里会控制 服务器列表显示的数量 isNewAccount: isNewAccount, //1为新号 会弹出用户协议 //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区) sid: element.server_id || 1, id: element.server_id || 1, name: element.name || "1区", tips: element.tips || "", server: element.ip ? `ws://${element.ip}:${element.port}` : "", status: element.status || 0, }); }); } else { // const servers = (await Server.getServerList(tag, 1)) const servers = await Server.getAllServerList(tag, ip); if (servers.length > 0) { const serverInfo = servers[servers.length - 1]; data.push({ channel: "Thailand", //渠道固定 minSid: 1, //最小服务器 maxSid: servers.length, //最大服务器 这里会控制 服务器列表显示的数量 isNewAccount: isNewAccount, //1为新号 会弹出用户协议 //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区) sid: serverInfo.id || 1, id: serverInfo.id || 1, name: serverInfo.name || "1区", tips: serverInfo.tips || "", server: serverInfo.ip ? `ws://${serverInfo.ip}:${serverInfo.port}` : "", status: serverInfo.status || 0, }); } else { data.push({ channel: "Thailand", //渠道固定 minSid: 1, //最小服务器 maxSid: 10, //最大服务器 这里会控制 服务器列表显示的数量 isNewAccount: isNewAccount, //1为新号 会弹出用户协议 //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区) sid: 1, id: 1, name: "1区", tips: "", server: "", status: 0, }); } } ctx.body = data; } async getNotice(ctx) { let data = ctx.request.body; let platform = "th"; if (ctx.query.platform) { platform = ctx.query.platform; } let content = ""; let content_wh = ""; const system = await System.getSystemConfig(); if (system) { system.forEach((element) => { if (element.key == "content") { content = element.value; } if (element.key == "content_wh") { content_wh = element.value; } }); } let notice_data = [ { status: 1, content: content, content_wh: content_wh, }, ]; if (notice_data[0].content == "") { switch (platform) { case "th": notice_data = th_notice; break; case "360": notice_data = notice; break; case "xky": notice_data = xky_notice; break; default: notice_data = notice; } } ctx.body = notice_data; } // 维护服务器,踢掉所有玩家 async maintenance(ctx) { let data = ctx.request.body; let url = await getServerList(data.serverId, "default"); if (!url) { ctx.body = { code: 1, msg: `区服id错误: serverId ${data.serverId}`, }; return; } let param = JSON.stringify({ type: "kickAllUser", }); // Msg.connect(url, Account); let sendMsg = new Msg(); sendMsg.connect(url, Account); new Promise((resolve) => { setTimeout(async () => { sendMsg.CG_TEST_PROTO("test", param); }, 1000); }); ctx.body = { code: 0, msg: "success", }; } async maintenanceAll(ctx) { let data = ctx.request.body; const servers = await Server.getServerList("default"); const serversId = []; servers.forEach(function (element) { let url = "ws://" + element.ip + ":" + element.port; if (!url) { ctx.body = { code: 1, msg: `区服id错误: serverId ${element.id}`, }; return; } serversId.push(element.id); let param = JSON.stringify({ type: "kickAllUser", }); // Msg.connect(url, Account); let sendMsg = new Msg(); sendMsg.connect(url, Account); new Promise((resolve) => { setTimeout(async () => { sendMsg.CG_TEST_PROTO("test", param); }, 1000); }); }); const res = await Server.updateServerStatus(serversId, 3); ctx.body = { code: 0, msg: "success", }; } async sendMail(ctx) { let data = ctx.request.body; let url = await getServerList(data.serverId, "default"); if (!url) { ctx.body = { code: 1, msg: `区服id错误: serverId ${data.serverId}`, }; return; } let param = JSON.stringify({ type: "sendMail", mail: JSON.stringify({ uuid: data.uuid, title: data.title, content: data.content, items: JSON.parse(data.items), expire: data.expire, }), }); // Msg.connect(url, Account); let sendMsg = new Msg(); sendMsg.connect(url, Account); new Promise((resolve) => { setTimeout(async () => { sendMsg.CG_TEST_PROTO("test", param); }, 1000); }); ctx.body = { code: 0, msg: "success", }; } async sendAllMail(ctx) { let data = ctx.request.body; if (!data.server_list || data.server_list.length === 0) { ctx.body = { code: -1, message: "区服不能为空", data: "" }; return; } logger.info("sendAllMail 接口请求 data:", { data: data }); const server_list = data.server_list; const servers = await Server.getServerList("default"); const filteredServer = servers.filter((item) => server_list.includes(item.id) ); filteredServer.forEach(function (element) { let url = "ws://" + element.ip + ":" + element.port; if (!url) { ctx.body = { code: 1, msg: `区服id错误: serverId ${element.server_id}`, }; return; } let param = JSON.stringify({ type: "sendAllMail", mail: JSON.stringify({ title: data.title, content: data.content, items: JSON.parse(data.items), expire: data.expire, }), }); let sendMsg = new Msg(); sendMsg.connect(url, Account); new Promise((resolve) => { setTimeout(async () => { sendMsg.CG_TEST_PROTO("test", param); }, 1000); }); }); ctx.body = { code: 0, msg: "success", }; } async useCDKV2(ctx) { let body = ctx.request.body; let data = { code: body.code, userId: body.account, }; if (body.uuid) { data.userId = body.uuid; } const accountInfo = (await User.checkAccountIsExist(body.account))[0]; logger.info("api cdk 接口请求 data:", { data: data }); let serverUrl = await getServerList(body.serverId, "default"); let err = ""; if (!serverUrl) { ctx.body = { code: 1, msg: `区服id错误: serverId ${body.serverId}`, }; return; } let port = 8004; // let host = extractIPAddresses(serverUrl)[0] let host = "127.0.0.1"; let url = "http://" + host + ":" + port + "/api/giftCode/exchange"; try { const response = await axios.post(url, data, { headers: { "Content-Type": "application/json", }, }); let param: string = ""; logger.info("api cdk 接口返回 response:", { data: response.data }); if (response.data.code != 200) { // 可能是固定码 ,游戏再去检测一下 param = JSON.stringify({ code: data.code, type: "UseFixCDK", channel_id: accountInfo.channel_id, }); } else { const result = splitString(response.data.data, ";"); // 重构itemList let itemList = Array(); for (let i = 0; i < result.length; i++) { let elem = splitString(result[i], ":"); let output0 = parseInt(elem[0], 10); let output1 = parseInt(elem[1], 10); itemList.push([output0, output1]); } param = JSON.stringify({ type: "UseCDKV2", itemList: itemList, channel_id: accountInfo.channel_id, }); } let sendMsg = new Msg(); sendMsg.connect(serverUrl, Account); logger.info("api cdk 发送服务器 param:", { param: param }); new Promise((resolve) => { setTimeout(async () => { sendMsg.CG_TEST_PROTO(body.account, param, body.serverId); }, 1000); }); } catch (error) { console.log(error); } ctx.body = { code: 0, msg: "success", }; } } module.exports = new ApiController();