ApiController.ts 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  1. import Msg from "../utils/msg";
  2. import {
  3. RefreshToken,
  4. PackageName,
  5. ProductId,
  6. IosUrl,
  7. Account,
  8. ClientSecret,
  9. ClientId,
  10. ORDER_SIGN_KEY,
  11. } from "../config/thirdParams";
  12. import {
  13. generateOrderNumber,
  14. formatDate,
  15. getServerList,
  16. getClientIp,
  17. } from "../utils/common";
  18. import {PaymentHelper} from "../utils/PaymentHelper";
  19. import {SignatureVerifier} from "../utils/SignatureVerifier";
  20. import {ChannelConfigManager} from "../utils/ChannelConfigManager";
  21. import {getRoleInfoByUidAndServerId} from "../mongo/mongodb";
  22. // 导入依赖
  23. const CryptoJS = require("crypto-js");
  24. const Order = require("../model/OrderModel");
  25. const Server = require("../model/ServerModel");
  26. const System = require("../model/SystemModel");
  27. const User = require("../model/UserModel");
  28. const logger = require("../utils/log");
  29. const axios = require("axios");
  30. const {channelFactory} = require("../channels/factory/ChannelFactory");
  31. const {MianyouChannelHandler} = require("../channels/handlers/MianyouChannelHandler");
  32. /**
  33. * Google支付回调处理
  34. */
  35. const googleCallPay = async (ctx, config) => {
  36. let data = ctx.request.body;
  37. let orderId = data.orderId;
  38. let googleToken = data.purchaseToken;
  39. let out_trade_no = "";
  40. logger.info("Google支付回调参数:", {url: ctx.href, params: data});
  41. // 更新订单Token
  42. await Order.updateOrderToken(orderId, googleToken, "google");
  43. // 获取Google访问令牌
  44. const redisClient = ctx.redis.client;
  45. let access_token = await redisClient.get("access_token");
  46. if (!access_token) {
  47. logger.info("请求Google API获取token");
  48. const apiData = {
  49. grant_type: "refresh_token",
  50. client_id: ClientId,
  51. client_secret: ClientSecret,
  52. refresh_token: RefreshToken,
  53. };
  54. try {
  55. const response = await axios.post(
  56. "https://accounts.google.com/o/oauth2/token",
  57. apiData,
  58. {
  59. headers: {
  60. "Content-Type": "application/x-www-form-urlencoded",
  61. },
  62. }
  63. );
  64. logger.info("Google token响应:", {data: response.data});
  65. if (!response.data.access_token) {
  66. return PaymentHelper.DEFAULT_RESULT;
  67. }
  68. access_token = response.data.access_token;
  69. await redisClient.set("access_token", response.data.access_token);
  70. await redisClient.expire("access_token", 1800);
  71. } catch (error) {
  72. logger.error("获取Google token失败:", error);
  73. return PaymentHelper.DEFAULT_RESULT;
  74. }
  75. }
  76. if (!access_token) {
  77. return PaymentHelper.DEFAULT_RESULT;
  78. }
  79. // 验证订单
  80. const validation = await PaymentHelper.validateOrder(orderId);
  81. if (!validation.valid) {
  82. return {
  83. code: validation.message?.includes("重复发货") ? 1 : 0,
  84. msg: validation.message,
  85. };
  86. }
  87. const orderInfo = validation.orderInfo;
  88. // 验证Google订单
  89. const productId = ProductId + orderInfo.product_id;
  90. let apiUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}?access_token=${access_token}`;
  91. let maxRetries = 3;
  92. let currentRetry = 0;
  93. let isCheck = false;
  94. // 使用循环进行重试
  95. while (currentRetry < maxRetries) {
  96. try {
  97. const googleRes = await axios.get(apiUrl, {
  98. headers: {
  99. "Content-Type": "application/x-www-form-urlencoded",
  100. },
  101. });
  102. logger.info("Google验证响应:", googleRes.data);
  103. if (googleRes.data.purchaseState == 0) {
  104. out_trade_no = googleRes.data.orderId;
  105. isCheck = true;
  106. break;
  107. }
  108. } catch (error) {
  109. logger.error("Google验证请求失败:", error);
  110. }
  111. currentRetry++;
  112. }
  113. if (!isCheck) {
  114. return PaymentHelper.DEFAULT_RESULT;
  115. }
  116. // 发货处理
  117. const result = await PaymentHelper.deliverOrder(
  118. orderInfo,
  119. ctx.request.ip,
  120. validation.url,
  121. out_trade_no
  122. );
  123. // 确认和消费Google订单
  124. try {
  125. // 确认订单
  126. let acknowledgeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:acknowledge?access_token=${access_token}`;
  127. await axios.post(
  128. acknowledgeUrl,
  129. {developerPayload: ""},
  130. {headers: {"Content-Type": "application/json"}}
  131. );
  132. // 消费订单
  133. let consumeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:consume?access_token=${access_token}`;
  134. await axios.post(
  135. consumeUrl,
  136. {developerPayload: ""},
  137. {headers: {"Content-Type": "application/json"}}
  138. );
  139. logger.info("Google订单处理完成:", {orderId: orderId});
  140. } catch (error) {
  141. logger.error("Google订单确认/消费失败:", error);
  142. // 即使确认/消费失败,我们仍然返回发货结果,因为发货可能已经成功
  143. }
  144. return result;
  145. };
  146. /**
  147. * Apple支付回调处理
  148. */
  149. const appleCallPay = async (ctx, config) => {
  150. let data = ctx.request.body;
  151. logger.info("Apple支付回调参数:", {url: ctx.href, params: data});
  152. if (!data.purchaseToken || !data.orderId) {
  153. return PaymentHelper.DEFAULT_RESULT;
  154. }
  155. let receipt_data = data.purchaseToken.replace(/ /g, "+");
  156. let orderId = data.orderId;
  157. let out_trade_no = orderId;
  158. // 更新订单Token
  159. await Order.updateOrderToken(orderId, receipt_data, "apple");
  160. // 验证Apple收据
  161. let maxRetries = 5;
  162. let currentRetry = 0;
  163. let isCheck = false;
  164. while (currentRetry < maxRetries) {
  165. try {
  166. const apiData = {
  167. "receipt-data": receipt_data,
  168. };
  169. const response = await axios.post(IosUrl, apiData, {
  170. headers: {
  171. "Content-Type": "application/json",
  172. },
  173. });
  174. logger.info(`Apple验证响应状态:${response.data.status}`);
  175. if (response.data.status == 0) {
  176. isCheck = true;
  177. break;
  178. }
  179. } catch (error) {
  180. logger.error("Apple验证请求失败:", error);
  181. }
  182. currentRetry++;
  183. }
  184. if (!isCheck) {
  185. logger.info(`Apple票据验证失败!`);
  186. return {code: 0, msg: "票据验证失败!"};
  187. }
  188. // 验证订单
  189. const validation = await PaymentHelper.validateOrder(orderId);
  190. if (!validation.valid) {
  191. return {
  192. code: validation.message?.includes("重复发货") ? 1 : 0,
  193. msg: validation.message,
  194. };
  195. }
  196. const orderInfo = validation.orderInfo;
  197. // 发货处理
  198. logger.info(`订单${orderId}通知游戏发货开始`);
  199. const result = await PaymentHelper.deliverOrder(
  200. orderInfo,
  201. ctx.request.ip,
  202. validation.url,
  203. out_trade_no
  204. );
  205. logger.info(`订单${orderId}通知游戏发货结束,结果:`, result);
  206. return result;
  207. };
  208. function splitString(input: string, separator: string): string[] {
  209. return input.split(separator);
  210. }
  211. //验证账号
  212. const checkUserToken = async (ctx) => {
  213. let ip = getClientIp(ctx);
  214. let {
  215. uid,
  216. channel_id,
  217. device_no,
  218. reg_device,
  219. device_type,
  220. device_model,
  221. device_version,
  222. system_version,
  223. } = ctx.request.body;
  224. const create_time = formatDate(new Date());
  225. const accountInfo = (await User.checkAccountIsExist(uid, channel_id))[0];
  226. let accountRes = null;
  227. let res = null;
  228. if (!accountInfo) {
  229. accountRes = await User.createAccount(
  230. uid,
  231. channel_id,
  232. ip,
  233. device_no,
  234. reg_device,
  235. create_time
  236. );
  237. if (accountRes.affectedRows <= 0) {
  238. return ApiController.fail("添加账户失败");
  239. }
  240. }
  241. res = await User.logAccountLogin(
  242. uid,
  243. ip,
  244. device_type,
  245. device_no,
  246. device_model,
  247. device_version,
  248. system_version,
  249. create_time,
  250. channel_id
  251. );
  252. if (res.affectedRows <= 0) {
  253. return ApiController.fail("添加日志失败");
  254. }
  255. return ApiController.success("请求成功", 1, false, {ip: ip});
  256. };
  257. class ApiController {
  258. /**
  259. * 生成成功响应
  260. * @param msg 成功消息
  261. * @param code 成功码,默认为1(部分API使用0表示成功)
  262. * @param useMessage 是否使用message字段而不是msg字段,默认为false
  263. * @param data 响应数据
  264. * @returns 标准化的成功响应对象
  265. */
  266. static success(
  267. msg: string = "请求成功",
  268. code: number = 1,
  269. useMessage: boolean = false,
  270. data: any = null
  271. ) {
  272. return {
  273. code: code,
  274. [useMessage ? "message" : "msg"]: msg,
  275. data: data,
  276. };
  277. }
  278. /**
  279. * 生成失败响应
  280. * @param msg 错误消息
  281. * @param code 错误码,默认为0
  282. * @param data 额外的错误数据
  283. * @param useMessage 是否使用message字段而不是msg字段,默认为false
  284. * @returns 标准化的失败响应对象
  285. */
  286. static fail(
  287. msg: string = "请求失败",
  288. code: number = 0,
  289. data: any = null,
  290. useMessage: boolean = false
  291. ) {
  292. return {
  293. code: code,
  294. [useMessage ? "message" : "msg"]: msg,
  295. data: data,
  296. };
  297. }
  298. async createOrder(ctx) {
  299. let {
  300. uid,
  301. level,
  302. amount,
  303. role_id,
  304. role_name,
  305. product_id,
  306. server_id,
  307. channel_id,
  308. } = ctx.request.body;
  309. logger.info("create params:", {params: ctx.request.body});
  310. if (
  311. !product_id ||
  312. !server_id ||
  313. !role_name ||
  314. !role_id ||
  315. !amount ||
  316. !uid ||
  317. !channel_id
  318. ) {
  319. ctx.body = ApiController.fail("参数错误,创建订单失败!!", -1);
  320. return;
  321. }
  322. const data = ctx.request.body;
  323. if (!SignatureVerifier.verifyMD5Sign(data, ORDER_SIGN_KEY)) {
  324. logger.error("创建订单签名验证失败");
  325. ctx.body = ApiController.fail("签名错误,创建订单失败!!", -1);
  326. return;
  327. }
  328. if (amount <= 0) {
  329. ctx.body = ApiController.fail("金额错误,创建订单失败!!", -1);
  330. return;
  331. }
  332. const orderId = generateOrderNumber(); // 生成一个长度为8的订单号
  333. const create_time = formatDate(new Date());
  334. const res = await Order.createOrder(
  335. orderId,
  336. uid,
  337. level,
  338. amount,
  339. role_id,
  340. role_name,
  341. product_id,
  342. server_id,
  343. channel_id,
  344. create_time
  345. );
  346. if (res.affectedRows > 0) {
  347. ctx.body = ApiController.success("创建订单成功", 0, false, orderId);
  348. } else {
  349. ctx.body = ApiController.fail("创建订单失败", -1, null);
  350. }
  351. logger.info("创建订单返回结果:", {params: ctx.body});
  352. }
  353. async checkUserToken(ctx) {
  354. let {channel_id} = ctx.request.body;
  355. const channelConfig = ChannelConfigManager.getConfig(channel_id);
  356. if (!channelConfig) {
  357. logger.info("未找到渠道配置:", {channel_id});
  358. ctx.body = {
  359. code: 0,
  360. msg: "未知渠道id",
  361. };
  362. return;
  363. }
  364. var result = await checkUserToken(ctx);
  365. ctx.body = result;
  366. }
  367. async thirdLogin(ctx) {
  368. const data = ctx.request.body;
  369. let channelId = parseInt(data.channel_id) || 1;
  370. const platform = data.platform; // 平台参数:ios、Android、miniapp、h5
  371. logger.info("thirdLogin请求参数:", {data, channelId, platform});
  372. // 渠道11和渠道12数据打通,统一使用渠道11
  373. if (channelId === 12) {
  374. channelId = 11;
  375. logger.info("渠道12映射到渠道11,平台参数:", platform);
  376. }
  377. // 获取渠道配置
  378. let channelConfig = ChannelConfigManager.getConfig(channelId);
  379. if (data.is_new == 1) {
  380. if (channelId == 6) {
  381. channelConfig = ChannelConfigManager.getConfig(999);
  382. }
  383. if (channelId == 1) {
  384. channelConfig = ChannelConfigManager.getConfig(9);
  385. }
  386. }
  387. if (!channelConfig) {
  388. logger.info("未找到渠道配置:", {channelId});
  389. ctx.body = ApiController.fail("未知渠道id");
  390. return;
  391. }
  392. // 从工厂获取对应的渠道处理器
  393. const handler = channelFactory.getHandler(channelId);
  394. if (!handler) {
  395. logger.info("未找到渠道处理器:", {channelId});
  396. ctx.body = ApiController.fail("未知渠道id");
  397. return;
  398. }
  399. logger.info("使用渠道处理器处理登录:", {
  400. channelId: channelId,
  401. channelName: channelConfig.name,
  402. platform: platform
  403. });
  404. // 调用渠道处理器的登录方法
  405. const result = await handler.handleLogin(ctx, channelConfig);
  406. // 在返回结果中添加平台信息
  407. if (result && result.data) {
  408. result.data.platform = platform || 'unknown';
  409. }
  410. // 根据不同渠道的返回格式要求处理结果
  411. ctx.body = result;
  412. }
  413. async callPay(ctx) {
  414. const data = ctx.request.body;
  415. let channelId = 1; // 默认渠道ID
  416. //打印回调参数
  417. logger.info("callPay支付回调参数:", {url: ctx.href, params: data, query: ctx.query});
  418. // 从请求中获取渠道ID
  419. if (ctx.query.channel_id) {
  420. channelId = parseInt(ctx.query.channel_id);
  421. }
  422. if (data.channel_id) {
  423. channelId = parseInt(data.channel_id);
  424. }
  425. logger.info("当前支付渠道id:", {channelId});
  426. // 获取渠道配置
  427. let channelConfig = ChannelConfigManager.getConfig(channelId);
  428. if (!channelConfig) {
  429. logger.info("未找到渠道配置:", {channelId});
  430. ctx.body = ApiController.fail("未知渠道id");
  431. return;
  432. }
  433. if (ctx.query.is_new && ctx.query.is_new == 1) {
  434. if (channelId == 6) {
  435. channelConfig = ChannelConfigManager.getConfig(999);
  436. }
  437. if (channelId == 1) {
  438. channelConfig = ChannelConfigManager.getConfig(9);
  439. }
  440. }
  441. const handler = channelFactory.getHandler(channelId);
  442. if (!handler) {
  443. logger.info("未找到渠道处理器:", {channelId});
  444. ctx.body = ApiController.fail("未知渠道id");
  445. return;
  446. }
  447. logger.info("使用渠道处理器处理支付:", {
  448. channelId: channelId,
  449. channelName: channelConfig.name,
  450. });
  451. // 调用渠道处理器的支付方法
  452. const result = await handler.handlePayment(ctx, channelConfig);
  453. // 根据不同渠道的返回格式要求处理结果
  454. switch (channelConfig.channelId) {
  455. case 6:
  456. ctx.body = result.code === 1 ? 1 : result.code;
  457. break;
  458. case 2:
  459. case 3:
  460. case 5:
  461. case 8:
  462. ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
  463. break;
  464. case 7:
  465. ctx.body = result.code === 1 ? "success" : "fail";
  466. break;
  467. case 11:
  468. ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
  469. break;
  470. case 12:
  471. ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
  472. break;
  473. case 13:
  474. //{"status":0,"msg":"status 非 0 时,传入失败信息"}
  475. ctx.body = {status: result.code === 1 ? 0 : -1, msg: result.msg};
  476. break;
  477. case 17:
  478. // 华为渠道:成功返回 {"errCode": 0},失败返回 {"errCode": 1, "errMsg": "..."}
  479. if (result.code === 0 || result.code === 1) {
  480. // 发货成功
  481. ctx.body = {errCode: 0};
  482. } else {
  483. // 发货失败
  484. ctx.body = {errCode: 1, errMsg: result.msg || "发放失败"};
  485. }
  486. break;
  487. case 14:
  488. ctx.body = result.code === 1 ? "SUCCESS" : "Fail";
  489. break;
  490. default:
  491. ctx.body = result;
  492. }
  493. }
  494. async getServerList(ctx) {
  495. let tag = ctx.query.channel_id || 1;
  496. let data = ctx.request.body;
  497. let ip = getClientIp(ctx);
  498. // 尝试从渠道ID获取配置
  499. const channelConfig = ChannelConfigManager.getConfig(1);
  500. const signStr = data.timestamp + channelConfig.loginConfig?.signKey;
  501. let newSign = CryptoJS.MD5(signStr).toString();
  502. if (data.sign != newSign) {
  503. console.log("signStr:", signStr);
  504. logger.info(
  505. `签名错误: 签名串 ${signStr} newSign ${newSign} sign ${data.sign}`
  506. );
  507. ctx.body = ApiController.fail("签名错误");
  508. return;
  509. }
  510. let sort = data.sort == 0 ? "asc" : "desc";
  511. logger.info("区服接口", {ip: ip});
  512. const servers = await Server.getServerList(tag, 0, sort);
  513. let serverList = [];
  514. if (servers.length > 0) {
  515. servers.forEach(function (element) {
  516. let status = element.status;
  517. if ((status == 0 || status == 3) && element.white_list) {
  518. const list = element.white_list.split(",");
  519. if (list.length > 0) {
  520. if (list.includes(ip)) {
  521. status = 1;
  522. }
  523. }
  524. }
  525. serverList.push({
  526. serverId: element.id,
  527. serverName: element.name,
  528. });
  529. });
  530. }
  531. ctx.body = ApiController.success("成功", 1, false, serverList);
  532. }
  533. async getAllServerList(ctx) {
  534. let tag = ctx.query.channel_id || 1;
  535. let uid = ctx.query.uid || ctx.request.body?.uid; // uid是可选参数,支持GET和POST请求
  536. let ip = getClientIp(ctx);
  537. logger.info("getAllServerList 区服接口", {tag: tag, uid: uid, ip: ip});
  538. const servers = await Server.getAllServerList(tag, ip);
  539. // 如果提供了玩家ID,则查询每个服务器的角色信息;否则只返回基本服务器信息
  540. if (uid) {
  541. const {getRoleInfoByUidAndServerId} = require("../mongo/mongodb");
  542. // 为每个服务器添加角色信息
  543. const serversWithRoleInfo = await Promise.all(
  544. servers.map(async (server) => {
  545. try {
  546. const newUniqueTag = `${server.tag}|${server.sid}|${uid}`;
  547. const roleInfo = await getRoleInfoByUidAndServerId(newUniqueTag, server.db_name);
  548. return {
  549. ...server,
  550. roleName: roleInfo?.roleName || null,
  551. roleLevel: roleInfo?.roleLevel || null,
  552. head: roleInfo?.head || null,
  553. hasRole: !!roleInfo
  554. };
  555. } catch (error) {
  556. logger.error(`查询服务器${server.id}角色信息失败:`, error);
  557. return {
  558. ...server,
  559. roleName: null,
  560. roleLevel: null,
  561. head: null,
  562. hasRole: false
  563. };
  564. }
  565. })
  566. );
  567. ctx.body = serversWithRoleInfo;
  568. } else {
  569. ctx.body = servers;
  570. }
  571. }
  572. async enterServer(ctx) {
  573. let {uid, server_id, channel_id} = ctx.request.body;
  574. let url = await getServerList(server_id, channel_id || 1);
  575. if (!url) {
  576. ctx.body = ApiController.fail(`区服id错误: serverId ${server_id}`, -1);
  577. return;
  578. }
  579. logger.info("create params:", {params: ctx.request.body});
  580. if (!server_id || !uid) {
  581. ctx.body = ApiController.fail("参数错误!!", -1);
  582. return;
  583. }
  584. const create_time = formatDate(new Date());
  585. const serverInfo = (
  586. await Server.checkEnterServerByUid(uid, server_id, channel_id)
  587. )[0];
  588. let res = null;
  589. if (serverInfo) {
  590. res = await Server.updateEnterServer(serverInfo.id, create_time);
  591. } else {
  592. res = await Server.enterServer(uid, server_id, create_time, channel_id);
  593. }
  594. if (res.affectedRows > 0) {
  595. ctx.body = ApiController.success("请求成功", 0, true, "");
  596. } else {
  597. ctx.body = ApiController.fail("请求失败", -1, null, true);
  598. }
  599. }
  600. async getLastServerList(ctx) {
  601. let {uid, channel_id} = ctx.request.body;
  602. // uid是可选参数,如果不提供则只返回基本服务器信息
  603. let tag = channel_id || 1;
  604. let data = [];
  605. let isNewAccount = 1;
  606. let enterServerList = [];
  607. let ip = getClientIp(ctx);
  608. logger.info("getLastServerList 区服接口", {uid: uid, ip: ip});
  609. // 获取渠道配置
  610. const channelConfig = ChannelConfigManager.getConfig(tag);
  611. if (!channelConfig) {
  612. logger.info("未找到渠道配置:", {tag});
  613. ctx.body = ApiController.fail("未知渠道id");
  614. return;
  615. }
  616. // 如果提供了uid,查询用户进入过的服务器列表
  617. if (uid) {
  618. enterServerList = await Server.getEnterServerListByUid(uid, channel_id);
  619. }
  620. if (enterServerList.length > 0) {
  621. isNewAccount = 0;
  622. const servers = await Server.getAllServerList(tag, ip);
  623. const {getRoleInfoByUidAndServerId} = require("../mongo/mongodb");
  624. // 为每个进入过的服务器添加角色信息
  625. for (const element of enterServerList) {
  626. let roleInfo = null;
  627. // 只有在提供了uid时才查询角色信息
  628. if (uid) {
  629. try {
  630. const newUniqueTag = `${tag}|${element.server_id}|${uid}`;
  631. roleInfo = await getRoleInfoByUidAndServerId(newUniqueTag, element.db_name);
  632. } catch (error) {
  633. logger.error(`查询服务器${element.server_id}角色信息失败:`, error);
  634. }
  635. }
  636. data.push({
  637. channel: channelConfig.name, //渠道固定
  638. minSid: 1, //最小服务器
  639. maxSid: servers.length, //最大服务器 这里会控制 服务器列表显示的数量
  640. isNewAccount: isNewAccount, //1为新号 会弹出用户协议
  641. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  642. sid: element.server_id || 1,
  643. id: element.server_id || 1,
  644. name: element.name || "1区",
  645. tips: element.tips || "",
  646. server: element.wss
  647. ? element.wss
  648. : `ws://${element.ip}:${element.port}`,
  649. status: element.status || 0,
  650. // 角色信息(只有在提供了uid时才包含)
  651. roleName: roleInfo?.roleName || null,
  652. roleLevel: roleInfo?.roleLevel || null,
  653. head: roleInfo?.head || null,
  654. hasRole: !!roleInfo
  655. });
  656. }
  657. logger.info("getLastServerList 区服接口 enterServerList", {
  658. enterServerList: enterServerList,
  659. });
  660. } else {
  661. const servers = await Server.getAllServerList(tag, ip);
  662. let roleInfo = null;
  663. if (servers.length > 0) {
  664. const serverInfo = servers[servers.length - 1];
  665. logger.info("getLastServerList 区服接口 serverInfo", {
  666. serverInfo: serverInfo,
  667. });
  668. // 只有在提供了uid时才查询最后一个服务器的角色信息
  669. if (uid) {
  670. const {getRoleInfoByUidAndServerId} = require("../mongo/mongodb");
  671. try {
  672. const newUniqueTag = `${serverInfo.tag}|${serverInfo.sid}|${uid}`;
  673. roleInfo = await getRoleInfoByUidAndServerId(newUniqueTag, serverInfo.db_name);
  674. } catch (error) {
  675. logger.error(`查询服务器${serverInfo.id}角色信息失败:`, error);
  676. }
  677. }
  678. data.push({
  679. channel: channelConfig.name, //渠道固定
  680. minSid: 1, //最小服务器
  681. maxSid: servers.length, //最大服务器 这里会控制 服务器列表显示的数量
  682. isNewAccount: isNewAccount, //1为新号 会弹出用户协议
  683. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  684. sid: serverInfo.sid || 1,
  685. id: serverInfo.id || 1,
  686. name: serverInfo.name || "1区",
  687. tips: serverInfo.tips || "",
  688. server: serverInfo.server
  689. ? serverInfo.server
  690. : `ws://${serverInfo.ip}:${serverInfo.port}/`,
  691. status: serverInfo.status || 0,
  692. // 角色信息
  693. roleName: roleInfo?.roleName || null,
  694. roleLevel: roleInfo?.roleLevel || null,
  695. head: roleInfo?.head || null,
  696. hasRole: !!roleInfo
  697. });
  698. } else {
  699. data.push({
  700. channel: "未知", //渠道固定
  701. minSid: 1, //最小服务器
  702. maxSid: 10, //最大服务器 这里会控制 服务器列表显示的数量
  703. isNewAccount: isNewAccount, //1为新号 会弹出用户协议
  704. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  705. sid: 1,
  706. id: 1,
  707. name: "1区",
  708. tips: "",
  709. server: "",
  710. status: 0,
  711. // 角色信息(新用户,无角色)
  712. roleName: null,
  713. roleLevel: null,
  714. head: null,
  715. hasRole: false
  716. });
  717. }
  718. }
  719. ctx.body = data;
  720. // ctx.body = ApiController.success("获取最近服务器列表成功", 1, false, data);
  721. }
  722. async getNotice(ctx) {
  723. let tag = ctx.query.channel_id || 1;
  724. let content = "";
  725. let content_wh = "";
  726. const system = await System.getSystemConfig(tag);
  727. if (system) {
  728. system.forEach((element) => {
  729. if (element.key == "content") {
  730. content = element.value;
  731. }
  732. if (element.key == "content_wh") {
  733. content_wh = element.value;
  734. }
  735. });
  736. }
  737. let notice_data = [
  738. {
  739. status: 1,
  740. content: content,
  741. content_wh: content_wh,
  742. },
  743. ];
  744. ctx.body = notice_data;
  745. // ctx.body = ApiController.success("获取公告成功", 1, false, notice_data);
  746. }
  747. // 维护服务器,踢掉所有玩家
  748. async maintenance(ctx) {
  749. let data = {
  750. channel_id: parseInt(ctx.query.channel_id),
  751. serverId: parseInt(ctx.query.serverId) || "",
  752. };
  753. logger.info("maintenance :", {channelId: data.channel_id});
  754. let url = await getServerList(data.serverId, data.channel_id || 1);
  755. if (!url) {
  756. ctx.body = ApiController.fail(`区服id错误: serverId ${data.serverId}`, 1);
  757. return;
  758. }
  759. let param = JSON.stringify({
  760. type: "kickAllUser",
  761. });
  762. let sendMsg = new Msg();
  763. sendMsg.connect(url, Account);
  764. new Promise((resolve) => {
  765. setTimeout(async () => {
  766. sendMsg.CG_TEST_PROTO("test", param);
  767. }, 1000);
  768. });
  769. ctx.body = ApiController.success("success", 0, false, null);
  770. }
  771. async maintenanceAll(ctx) {
  772. let channelId = parseInt(ctx.query.channel_id);
  773. let isMaintenance = ctx.query.isMaintenance;
  774. let key = ctx.query.key;
  775. logger.info("maintenanceAll :", {
  776. channelId: channelId,
  777. isMaintenance: isMaintenance,
  778. });
  779. if (key != "dsdadsadajkkjkxab") {
  780. ctx.body = ApiController.fail("无权使用", -1);
  781. return;
  782. }
  783. const servers = await Server.getAllServerList(channelId, "");
  784. logger.info("maintenanceAll servers:", {servers: servers});
  785. if (servers.length === 0) {
  786. ctx.body = ApiController.fail("不存在可操作区服", -1);
  787. return;
  788. }
  789. const serversId = servers.map((obj) => obj.id);
  790. if (isMaintenance == "true") {
  791. const res = await Server.updateServerStatus(serversId, 3);
  792. }
  793. servers.forEach(function (element) {
  794. let url = "ws://" + element.ip + ":" + element.port;
  795. if (!url) {
  796. ctx.body = ApiController.fail(`区服id错误: serverId ${element.id}`, 1);
  797. return;
  798. }
  799. let param = JSON.stringify({
  800. type: "kickAllUser",
  801. });
  802. // Msg.connect(url, Account);
  803. let sendMsg = new Msg();
  804. sendMsg.connect(url, Account);
  805. new Promise((resolve) => {
  806. setTimeout(async () => {
  807. sendMsg.CG_TEST_PROTO("test", param);
  808. }, 1000);
  809. });
  810. });
  811. logger.info("maintenanceAll 更新的区服id:", {serversId: serversId});
  812. ctx.body = ApiController.success("success", 0, false, null);
  813. }
  814. async sendMail(ctx) {
  815. let data = ctx.request.body;
  816. let url = await getServerList(data.serverId, data.channel_id || 1);
  817. if (!url) {
  818. ctx.body = ApiController.fail(`区服id错误: serverId ${data.serverId}`, 1);
  819. return;
  820. }
  821. let param = JSON.stringify({
  822. type: "sendMail",
  823. mail: JSON.stringify({
  824. uuid: data.uuid,
  825. title: data.title,
  826. content: data.content,
  827. items: JSON.parse(data.items),
  828. expire: data.expire,
  829. }),
  830. });
  831. // Msg.connect(url, Account);
  832. let sendMsg = new Msg();
  833. sendMsg.connect(url, Account);
  834. new Promise((resolve) => {
  835. setTimeout(async () => {
  836. sendMsg.CG_TEST_PROTO("test", param);
  837. }, 1000);
  838. });
  839. ctx.body = ApiController.success("success", 0, false, null);
  840. }
  841. async sendAllMail(ctx) {
  842. let data = ctx.request.body;
  843. if (!data.server_list || data.server_list.length === 0) {
  844. ctx.body = ApiController.fail("区服不能为空", -1);
  845. return;
  846. }
  847. logger.info("sendAllMail 接口请求 data:", {data: data});
  848. const server_list = data.server_list;
  849. const servers = await Server.getServerList(data.channel_id || 1);
  850. const filteredServer = servers.filter((item) =>
  851. server_list.includes(item.id)
  852. );
  853. filteredServer.forEach(function (element) {
  854. let url = "ws://" + element.ip + ":" + element.port;
  855. if (!url) {
  856. ctx.body = ApiController.fail(
  857. `区服id错误: serverId ${element.server_id}`,
  858. 1
  859. );
  860. return;
  861. }
  862. let param = JSON.stringify({
  863. type: "sendAllMail",
  864. mail: JSON.stringify({
  865. title: data.title,
  866. content: data.content,
  867. items: JSON.parse(data.items),
  868. expire: data.expire,
  869. }),
  870. });
  871. let sendMsg = new Msg();
  872. sendMsg.connect(url, Account);
  873. new Promise((resolve) => {
  874. setTimeout(async () => {
  875. sendMsg.CG_TEST_PROTO("test", param);
  876. }, 1000);
  877. });
  878. });
  879. ctx.body = ApiController.success("success", 0);
  880. }
  881. async useCDKV2(ctx) {
  882. let body = ctx.request.body;
  883. logger.info("useCDKV2接口请求参数:", {data: body});
  884. let data = {
  885. code: body.code,
  886. userId: body.account,
  887. channelId: body.channel_id || 0,
  888. };
  889. if (body.uuid) {
  890. data.userId = body.uuid;
  891. }
  892. let serverUrl = await getServerList(body.serverId, body.channel_id);
  893. let err = "";
  894. if (!serverUrl) {
  895. ctx.body = ApiController.fail(`区服id错误: serverId ${body.serverId}`, 1);
  896. return;
  897. }
  898. let port = 8004;
  899. let host = "127.0.0.1";
  900. let url = "http://" + host + ":" + port + "/api/giftCode/exchange";
  901. logger.info("接口请求后台 data:", {data: data, url: url});
  902. try {
  903. const specialCodes = [
  904. "gfyx555",
  905. "gfyx666",
  906. "gfyx777",
  907. "gfyx1000",
  908. "gfyx2000",
  909. "gfyx3000",
  910. "gfyxrqlb",
  911. "GFYX555",
  912. "GFYX666",
  913. "GFYX777",
  914. "GFYX1000",
  915. "GFYX2000",
  916. "GFYX3000",
  917. "GFYXrqlb",
  918. "GFYX000",
  919. "GFYX222",
  920. "GFYX333",
  921. "GFYX888",
  922. "GFYX1818",
  923. "GQ888",
  924. "ZQ888",
  925. "gfyx8888",
  926. "gfyx6666",
  927. "gfyx7777",
  928. "gfyxxjbc",
  929. "LIDONGLB",
  930. "XIAOXULB",
  931. "GANENLB",
  932. "WANSHLB",
  933. "HERO666",
  934. "HERO777",
  935. "HERO888",
  936. "gfyx9999",
  937. "aiqi6666",
  938. "aiqi7777",
  939. "aiqi8888",
  940. "aiqi9999",
  941. "gf555",
  942. "gf666",
  943. "gf777",
  944. "gf100",
  945. "gf200",
  946. "gf300",
  947. "YDKL888",
  948. "SDKL888",
  949. ];
  950. let param: string = "";
  951. const h5Codes = ["gfyx000", "gfyx222", "gfyx333", "gfyx888", "gfyx1818"];
  952. if (h5Codes.includes(data.code) && body.channel_id != 5) {
  953. ctx.body = ApiController.fail("该激活码无法在h5渠道使用", 1);
  954. }
  955. if (specialCodes.includes(data.code) || h5Codes.includes(data.code)) {
  956. param = JSON.stringify({
  957. code: data.code,
  958. type: "UseFixCDK",
  959. channel_id: body.channel_id,
  960. });
  961. } else {
  962. const response = await axios.post(url, data, {
  963. headers: {
  964. "Content-Type": "application/json",
  965. },
  966. timeout: 10000,
  967. });
  968. logger.info("接口请求后台 接口返回 response:", {data: response.data});
  969. if (response.data.code != 200) {
  970. ctx.body = ApiController.fail(response.data.msg, 1);
  971. return;
  972. }
  973. const result = splitString(response.data.data, ";");
  974. // 重构itemList
  975. let itemList = Array();
  976. for (let i = 0; i < result.length; i++) {
  977. let elem = splitString(result[i], ":");
  978. let output0 = parseInt(elem[0], 10);
  979. let output1 = parseInt(elem[1], 10);
  980. itemList.push([output0, output1]);
  981. }
  982. param = JSON.stringify({
  983. type: "UseCDKV2",
  984. itemList: itemList,
  985. channel_id: body.channel_id,
  986. });
  987. }
  988. let sendMsg = new Msg();
  989. sendMsg.connect(serverUrl, Account);
  990. logger.info("api cdk 发送服务器 param:", {param: param});
  991. new Promise((resolve) => {
  992. setTimeout(async () => {
  993. sendMsg.CG_TEST_PROTO(body.account, param, body.serverId);
  994. }, 1000);
  995. });
  996. } catch (error) {
  997. console.log(error);
  998. }
  999. ctx.body = ApiController.success("success", 0);
  1000. }
  1001. async banUser(ctx) {
  1002. let data = ctx.request.body;
  1003. logger.info("banUser 接口请求 data:", {data: data});
  1004. if (!data.server_tag) {
  1005. ctx.body = ApiController.fail("区服id不能为空", -1, "");
  1006. return;
  1007. }
  1008. let banInfo = {};
  1009. switch (parseInt(data.ban_type)) {
  1010. case 1:
  1011. banInfo = {
  1012. roleBanInfo: {
  1013. channelTag: data.channel_id,
  1014. serverTag: data.server_tag,
  1015. roleTag: data.role_tag,
  1016. banTime: data.ban_time,
  1017. },
  1018. type: "setBan",
  1019. };
  1020. break;
  1021. case 2:
  1022. banInfo = {
  1023. accountBanInfo: {
  1024. channelTag: data.channel_id,
  1025. accountTag: data.account_tag,
  1026. banTime: data.ban_time,
  1027. },
  1028. type: "setBan",
  1029. };
  1030. break;
  1031. case 3:
  1032. banInfo = {
  1033. appBanInfo: {
  1034. appId: data.device_id,
  1035. banTime: data.ban_time,
  1036. },
  1037. type: "setBan",
  1038. };
  1039. break;
  1040. default:
  1041. }
  1042. logger.info("banUser 发送服务器 banInfo:", banInfo);
  1043. let url = await getServerList(data.server_tag, data.channel_id);
  1044. if (!url) {
  1045. ctx.body = ApiController.fail(
  1046. `区服id错误: serverId ${data.server_tag}`,
  1047. 1
  1048. );
  1049. return;
  1050. }
  1051. let param = JSON.stringify(banInfo);
  1052. logger.info("banUser 发送服务器 json字符串: " + param);
  1053. let sendMsg = new Msg();
  1054. sendMsg.connect(url, Account);
  1055. new Promise((resolve) => {
  1056. setTimeout(async () => {
  1057. sendMsg.CG_TEST_PROTO("test", param, data.server_tag);
  1058. // sendMsg.CG_SET_BAN(param);
  1059. }, 1000);
  1060. });
  1061. ctx.body = ApiController.success("success", 0);
  1062. }
  1063. async uicFilter4399(ctx) {
  1064. let body = ctx.request.body;
  1065. let channelConfig = ChannelConfigManager.getConfig(6);
  1066. if (body.is_new == 1) {
  1067. channelConfig = ChannelConfigManager.getConfig(999);
  1068. }
  1069. logger.info("uicFilter4399 body:", {data: body});
  1070. let toCheck = body.toCheck;
  1071. let signStr = channelConfig.loginConfig?.signKey + toCheck;
  1072. logger.info("uicFilter4399 signStr:", {signStr: signStr});
  1073. let apiParams = {
  1074. toCheck: toCheck,
  1075. app: channelConfig.loginConfig.appId,
  1076. byPinyin: true,
  1077. isBatch: false,
  1078. sig: CryptoJS.MD5(signStr).toString(),
  1079. };
  1080. logger.info("uicFilter4399 apiParams:", {data: apiParams});
  1081. const queryStr = Object.entries(apiParams)
  1082. .map(
  1083. ([key, value]) =>
  1084. `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
  1085. )
  1086. .join("&");
  1087. let url = "https://wo.webgame138.com/test/matchService.do" + "?" + queryStr;
  1088. // let url = "https://wo.webgame138.com/test/matchService.do";
  1089. logger.info("uicFilter4399 url:", {url: url});
  1090. try {
  1091. // let response = await axios.get(url, {
  1092. // timeout: 10000, // 设置10秒超时
  1093. // });
  1094. const response = await axios.post(url, apiParams, {
  1095. headers: {
  1096. "Content-Type": "application/json",
  1097. },
  1098. });
  1099. logger.info("uicFilter4399 接口返回 response:", {data: response.data});
  1100. ctx.body = ApiController.success("success", 0, false, response.data);
  1101. } catch (error) {
  1102. console.log(error);
  1103. ctx.body = ApiController.fail(error.message || "请求失败", 1);
  1104. }
  1105. }
  1106. async roleList4399(ctx) {
  1107. let body = ctx.request.body;
  1108. logger.info("RoleList4399 请求参数:", {body: body});
  1109. let data = {
  1110. userId: body.userId,
  1111. server: body.server,
  1112. is_new: ctx.query.is_new || 0
  1113. };
  1114. let port = 8004;
  1115. let host = "127.0.0.1";
  1116. let url = "http://" + host + ":" + port + "/api/roleList/checkBy4399";
  1117. logger.info("RoleList4399 url:", {url: url});
  1118. try {
  1119. const response = await axios.post(url, data, {
  1120. headers: {
  1121. "Content-Type": "application/json",
  1122. },
  1123. });
  1124. logger.info("RoleList4399 返回 response:", {data: response.data});
  1125. ctx.body = response.data;
  1126. } catch (error) {
  1127. console.log(error);
  1128. }
  1129. }
  1130. async cdkBy4399(ctx) {
  1131. let body = ctx.request.body;
  1132. logger.info("cdkBy4399:", {data: body});
  1133. let server = body.server || 1;
  1134. let channel = 5;
  1135. let data = {
  1136. code: body.giftId,
  1137. userId: body.userId,
  1138. channelId: channel,
  1139. };
  1140. if (body.uuid) {
  1141. data.userId = body.uuid;
  1142. }
  1143. let serverUrl = await getServerList(server, channel);
  1144. let err = "";
  1145. if (!serverUrl) {
  1146. ctx.body = ApiController.fail(`区服id错误: serverId ${body.serverId}`, 1);
  1147. return;
  1148. }
  1149. let port = 8004;
  1150. let host = "127.0.0.1";
  1151. let url = "http://" + host + ":" + port + "/api/giftCode/exchange";
  1152. logger.info("cdkBy4399接口请求后台 data:", {data: data, url: url});
  1153. try {
  1154. const response = await axios.post(url, data, {
  1155. headers: {
  1156. "Content-Type": "application/json",
  1157. },
  1158. timeout: 10000,
  1159. });
  1160. logger.info("cdkBy4399接口请求后台 接口返回 response:", {
  1161. data: response.data,
  1162. });
  1163. if (response.data.code != 200) {
  1164. ctx.body = ApiController.fail(response.data.msg, 10004);
  1165. return;
  1166. }
  1167. const result = splitString(response.data.data, ";");
  1168. // 重构itemList
  1169. let itemList = Array();
  1170. for (let i = 0; i < result.length; i++) {
  1171. let elem = splitString(result[i], ":");
  1172. let output0 = parseInt(elem[0], 10);
  1173. let output1 = parseInt(elem[1], 10);
  1174. itemList.push([output0, output1]);
  1175. }
  1176. let param = JSON.stringify({
  1177. type: "UseCDKV2",
  1178. itemList: itemList,
  1179. channel_id: channel,
  1180. });
  1181. let sendMsg = new Msg();
  1182. sendMsg.connect(serverUrl, Account);
  1183. logger.info("cdkBy4399 cdk 发送服务器 param:", {param: param});
  1184. new Promise((resolve) => {
  1185. setTimeout(async () => {
  1186. sendMsg.CG_TEST_PROTO("test", param, server);
  1187. }, 1000);
  1188. });
  1189. } catch (error) {
  1190. console.log(error);
  1191. }
  1192. ctx.body = ApiController.success("success", 10000);
  1193. }
  1194. async roleListYfy(ctx) {
  1195. let gameCode = ctx.query.gameCode;
  1196. let timestamp = ctx.query.timestamp;
  1197. let uid = ctx.query.uid;
  1198. let sign = ctx.query.sign;
  1199. let AppSecret = "H1EqhbpA80jt0Jw6Q3T2";
  1200. logger.info("roleListYfy 请求参数:", {
  1201. uid: uid,
  1202. gameCode: gameCode,
  1203. timestamp: timestamp,
  1204. });
  1205. const signStr = `gameCode-${gameCode}&timestamp=${timestamp}&uid=${uid}${AppSecret}`;
  1206. const newSign = CryptoJS.MD5(signStr).toString();
  1207. if (newSign != sign) {
  1208. logger.info("roleListYfy 签名错误:", {
  1209. signStr: signStr,
  1210. sign: sign,
  1211. newSign: newSign,
  1212. });
  1213. ctx.body = ApiController.fail("签名错误!!", -1);
  1214. }
  1215. let port = 8004;
  1216. let host = "127.0.0.1";
  1217. let url = "http://" + host + ":" + port + "/api/roleList/checkByYfy";
  1218. logger.info("roleListYfy url:", {url: url});
  1219. try {
  1220. const response = await axios.post(
  1221. url,
  1222. {
  1223. userId: uid,
  1224. },
  1225. {
  1226. headers: {
  1227. "Content-Type": "application/json",
  1228. },
  1229. }
  1230. );
  1231. logger.info("roleListYfy 返回 response:", {data: response.data});
  1232. ctx.body = response.data;
  1233. } catch (error) {
  1234. console.log(error);
  1235. }
  1236. }
  1237. async getQuickSign(ctx) {
  1238. let data = ctx.request.body;
  1239. logger.info("getQuickSign 请求参数:", {body: data});
  1240. if (!SignatureVerifier.verifyMD5Sign(data, ORDER_SIGN_KEY)) {
  1241. logger.error("签名验证失败");
  1242. ctx.body = ApiController.fail("签名错误!!", -1);
  1243. return;
  1244. }
  1245. let key = "H1EqhbpA80jt0Jw6Q3T2";
  1246. let signStr =
  1247. "uid=" +
  1248. data.uid +
  1249. "&username=" +
  1250. data.username +
  1251. "&serverId=" +
  1252. data.serverId +
  1253. "&serverName=" +
  1254. data.serverName +
  1255. "&userRoleId=" +
  1256. data.userRoleId +
  1257. "&userRoleName=" +
  1258. data.userRoleName +
  1259. "&userRoleLevel=" +
  1260. data.userRoleLevel +
  1261. "&vipLevel=" +
  1262. data.vipLevel +
  1263. "&gameRolePower=" +
  1264. data.gameRolePower +
  1265. "&key=" +
  1266. key;
  1267. logger.info("getQuickSign signStr:", {signStr: signStr});
  1268. data.sign = CryptoJS.MD5(signStr).toString();
  1269. ctx.body = ApiController.success("success", 0, false, data);
  1270. }
  1271. /**
  1272. * mianyou开服同步处理
  1273. * @param ctx Koa上下文
  1274. */
  1275. async mianyouSyncServer(ctx) {
  1276. try {
  1277. const data = ctx.request.body;
  1278. logger.info("mianyou开服同步请求参数:", {data});
  1279. // 验证必要参数
  1280. const {serverId, gameServerId, serverName, startTime, channelId} = data;
  1281. if (!serverId || !gameServerId || !serverName || !startTime) {
  1282. logger.warn("mianyou开服同步失败: 缺少必要参数", {data});
  1283. ctx.body = ApiController.fail("缺少必要参数: serverId, gameServerId, serverName, startTime");
  1284. return;
  1285. }
  1286. // 获取渠道配置
  1287. const channelConfig = ChannelConfigManager.getConfig(channelId || 1);
  1288. if (!channelConfig) {
  1289. logger.error("mianyou开服同步失败: 未找到渠道配置", {channelId});
  1290. ctx.body = ApiController.fail("未找到渠道配置");
  1291. return;
  1292. }
  1293. // 创建MianyouChannelHandler实例
  1294. const mianyouHandler = new MianyouChannelHandler();
  1295. // 调用开服同步方法
  1296. const result = await mianyouHandler.openServer(
  1297. parseInt(serverId),
  1298. gameServerId,
  1299. serverName,
  1300. startTime,
  1301. channelConfig
  1302. );
  1303. logger.info("mianyou开服同步结果:", {result});
  1304. // 根据返回结果设置响应
  1305. if (result.status === 0) {
  1306. ctx.body = ApiController.success("开服同步成功", 0, false, result);
  1307. } else {
  1308. ctx.body = ApiController.fail(result.msg || "开服同步失败", result.status);
  1309. }
  1310. } catch (error) {
  1311. logger.error("mianyou开服同步异常:", error);
  1312. ctx.body = ApiController.fail("服务器内部错误", -1);
  1313. }
  1314. }
  1315. }
  1316. module.exports = new ApiController();