| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614 |
- 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();
|