ApiController.ts 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278
  1. import Msg from '../utils/msg'; // 确保路径是正确的
  2. import QuickAsy from '../utils/quickAsy';
  3. import { parseString } from 'xml2js';
  4. import {
  5. RefreshToken,
  6. PackageName,
  7. ProductId,
  8. IosUrl,
  9. SandboxIosUrl,
  10. Account,
  11. ClientSecret,
  12. ClientId,
  13. AppSecret360
  14. } from '../config/thirdParams'
  15. import {
  16. compareVersions,
  17. generateOrderNumber,
  18. formatDate,
  19. getServerList
  20. } from '../utils/common'
  21. const CryptoJS = require("crypto-js");
  22. const Order = require('../model/OrderModel')
  23. const Server = require('../model/ServerModel')
  24. const Version = require('../model/VersionModel')
  25. const CDK = require("../model/CDK")
  26. const notice = require("../json/notice.json")
  27. const th_notice = require("../json/th_notice.json")
  28. const xky_notice = require("../json/xky_notice.json")
  29. const logger = require('../utils/log')
  30. const axios = require('axios');
  31. const googleCallPay = async (ctx) => {
  32. let ret = {
  33. code: 0,
  34. msg: '发货失败'
  35. }
  36. let data = ctx.request.body
  37. let orderId = data.orderId
  38. let googleToken = data.purchaseToken
  39. let out_trade_no = ''
  40. logger.info("pay callback params:", { "url": ctx.href, "params": data })
  41. const res = await Order.updateOrderToken(
  42. orderId,
  43. googleToken,
  44. 'google',
  45. );
  46. const redisClient = ctx.redis.client;
  47. let access_token = await redisClient.get('access_token');
  48. if (!access_token) {
  49. console.log('请求api获取token')
  50. const apiData = {
  51. "grant_type": "refresh_token",
  52. "client_id": ClientId,
  53. "client_secret": ClientSecret,
  54. "refresh_token": RefreshToken
  55. }
  56. const response = await axios.post('https://accounts.google.com/o/oauth2/token', apiData, {
  57. headers: {
  58. 'Content-Type': 'application/x-www-form-urlencoded'
  59. }
  60. });
  61. logger.info("token params:", { "data": response.data, "params": apiData })
  62. if (!response.data.access_token) {
  63. return ret
  64. }
  65. access_token = response.data.access_token
  66. await redisClient.set('access_token', response.data.access_token);
  67. await redisClient.expire('access_token', 1800);
  68. }
  69. if (!access_token) {
  70. return ret;
  71. }
  72. const orderInfo = (await Order.getOrder(orderId))[0]
  73. if (!orderInfo) {
  74. logger.info(`订单${orderId}不存在`)
  75. ret.msg = `订单${orderId}不存在`
  76. return ret
  77. }
  78. if (orderInfo.status == 2) {
  79. logger.info(`订单${orderId}已经重复发货`)
  80. ret.code = 1
  81. ret.msg = `订单${orderId}已经重复发货`
  82. return ret
  83. }
  84. let url = await getServerList(orderInfo.server_id, 'default')
  85. if (!url) {
  86. logger.info(`区服id错误: serverId ${orderInfo.server_id}`)
  87. ret.msg = `区服id错误: serverId ${orderInfo.server_id}`
  88. return ret
  89. }
  90. const productId = ProductId + orderInfo.product_id
  91. let apiUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}?access_token=${access_token}`
  92. let maxRetries = 3;
  93. let currentRetry = 0;
  94. let isCheck = false;
  95. // 使用 while 循环进行重试
  96. while (currentRetry < maxRetries) {
  97. try {
  98. // // 尝试执行的操作
  99. const googleRes = await axios.get(apiUrl, {
  100. headers: {
  101. 'Content-Type': 'application/x-www-form-urlencoded'
  102. }
  103. })
  104. console.log(googleRes.data)
  105. // 如果操作成功,退出循环
  106. if (googleRes.data.purchaseState == 0) {
  107. out_trade_no = googleRes.data.orderId
  108. isCheck = true
  109. break;
  110. }
  111. } catch (error) {
  112. // 捕获请求中的错误
  113. if (error.response) {
  114. // 请求已发出,服务器用状态码响应
  115. console.error(error.response.data);
  116. console.error(error.response.status);
  117. console.error(error.response.headers);
  118. } else if (error.request) {
  119. // 请求已发出但没有收到响应
  120. // 这通常是网络错误
  121. console.error(error.request);
  122. } else {
  123. // 在设置请求时出现错误
  124. console.error('Error', error.message);
  125. }
  126. }
  127. currentRetry++;
  128. }
  129. if (!isCheck) {
  130. return ret;
  131. }
  132. let sendMsg = new Msg()
  133. sendMsg.connect(url, Account);
  134. let orgMemId = orderInfo.uid
  135. let orgOderId = orderId
  136. let orgProductId = orderInfo.product_id
  137. let orgProductPrice = orderInfo.amount
  138. // 在适当的时机,调用 CG_ASK_LOGIN 方法
  139. let params = `{"account":"${orgMemId}","order":"${orgOderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`
  140. return new Promise((resolve) => {
  141. setTimeout(async () => {
  142. const send_res = sendMsg.CG_ASK_LOGIN(Account, 0, "", 'cn', 'CN', ctx.request.ip, params);
  143. if (!send_res) {
  144. resolve(ret);
  145. return;
  146. }
  147. try {
  148. let acknowledgeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:acknowledge?access_token=${access_token}`
  149. const acknowledgeRes = await axios.post(acknowledgeUrl,
  150. {
  151. developerPayload: ""
  152. }
  153. ,
  154. {
  155. headers: {
  156. 'Content-Type': 'application/json'
  157. }
  158. })
  159. } catch (error) {
  160. // 捕获请求中的错误
  161. if (error.response) {
  162. // 请求已发出,服务器用状态码响应
  163. console.error(error.response.data);
  164. console.error(error.response.status);
  165. console.error(error.response.headers);
  166. } else if (error.request) {
  167. // 请求已发出但没有收到响应
  168. // 这通常是网络错误
  169. console.error(error.request);
  170. } else {
  171. // 在设置请求时出现错误
  172. console.error('Error', error.message);
  173. }
  174. ret.msg = '请求第三方失败'
  175. resolve(ret);
  176. }
  177. try {
  178. let consumeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:consume?access_token=${access_token}`
  179. const consumeRes = await axios.post(consumeUrl,
  180. {
  181. developerPayload: ""
  182. }
  183. ,
  184. {
  185. headers: {
  186. 'Content-Type': 'application/json'
  187. }
  188. })
  189. } catch (error) {
  190. // 捕获请求中的错误
  191. if (error.response) {
  192. // 请求已发出,服务器用状态码响应
  193. console.error(error.response.data);
  194. console.error(error.response.status);
  195. console.error(error.response.headers);
  196. } else if (error.request) {
  197. // 请求已发出但没有收到响应
  198. // 这通常是网络错误
  199. console.error(error.request);
  200. } else {
  201. // 在设置请求时出现错误
  202. console.error('Error', error.message);
  203. }
  204. ret.msg = '请求第三方失败'
  205. resolve(ret);
  206. }
  207. logger.info("谷歌 pass :", { "orderId": orderId })
  208. const update_time = formatDate(new Date())
  209. const res = await Order.updateOrderStats(
  210. orderId,
  211. 2,
  212. out_trade_no,
  213. update_time
  214. );
  215. if (res.affectedRows <= 0) {
  216. logger.info(`订单${orderId} 发货失败`)
  217. ret.msg = '发货失败'
  218. resolve(ret);
  219. return;
  220. }
  221. ret.code = 1
  222. ret.msg = '发货成功'
  223. resolve(ret);
  224. }, 1000);
  225. });
  226. }
  227. const appleCallPay = async (ctx) => {
  228. let ret = {
  229. code: 0,
  230. msg: '发货失败'
  231. }
  232. let data = ctx.request.body
  233. logger.info("pay callback params:", { "url": ctx.href, "params": data })
  234. if (!data.purchaseToken || !data.orderId) {
  235. return ret;
  236. }
  237. let receipt_data = data.purchaseToken.replace(/ /g, '+')
  238. let orderId = data.orderId
  239. let maxRetries = 5;
  240. let currentRetry = 0;
  241. let isCheck = false;
  242. let out_trade_no = orderId
  243. const res = await Order.updateOrderToken(
  244. orderId,
  245. receipt_data,
  246. 'apple',
  247. );
  248. // 使用 while 循环进行重试
  249. while (currentRetry < maxRetries) {
  250. try {
  251. const apiData = {
  252. "receipt-data": receipt_data,
  253. }
  254. const response = await axios.post(IosUrl, apiData, {
  255. headers: {
  256. 'Content-Type': 'application/json'
  257. }
  258. });
  259. logger.info(`苹果返回的状态:${response.data.status}`)
  260. // 如果操作成功,退出循环
  261. if (response.data.status == 0) {
  262. isCheck = true
  263. break;
  264. }
  265. } catch (error) {
  266. // 如果操作失败,记录错误并继续尝试
  267. console.log(error)
  268. }
  269. currentRetry++;
  270. }
  271. if (!isCheck) {
  272. logger.info(`票据验证失败!`)
  273. ret.msg = `票据验证失败!`
  274. return ret;
  275. }
  276. const orderInfo = (await Order.getOrder(orderId))[0]
  277. if (!orderInfo) {
  278. logger.info(`订单${orderId}不存在`)
  279. ret.msg = `订单${orderId}不存在`
  280. return ret
  281. }
  282. if (orderInfo.status == 2) {
  283. logger.info(`订单${orderId}已经重复发货`)
  284. ret.code = 1
  285. ret.msg = `订单${orderId}已经重复发货`
  286. return ret
  287. }
  288. let url = await getServerList(orderInfo.server_id, 'default')
  289. if (!url) {
  290. logger.info(`区服id错误: serverId ${orderInfo.server_id}`)
  291. ret.msg = `区服id错误: serverId ${orderInfo.server_id}`
  292. return ret
  293. }
  294. let sendMsg = new Msg()
  295. sendMsg.connect(url, Account);
  296. let orgMemId = orderInfo.uid
  297. let orgOderId = orderId
  298. let orgProductId = orderInfo.product_id
  299. let orgProductPrice = orderInfo.amount
  300. // 在适当的时机,调用 CG_ASK_LOGIN 方法
  301. let params = `{"account":"${orgMemId}","order":"${orgOderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`
  302. return new Promise((resolve) => {
  303. setTimeout(async () => {
  304. logger.info(`订单${orderId}通知游戏发货开始`)
  305. const send_res = sendMsg.CG_ASK_LOGIN(Account, 0, "", 'cn', 'CN', ctx.request.ip, params);
  306. if (!send_res) {
  307. resolve(ret);
  308. return;
  309. }
  310. logger.info(`订单${orderId}通知游戏发货结束`)
  311. const update_time = formatDate(new Date())
  312. const res = await Order.updateOrderStats(
  313. orderId,
  314. 2,
  315. out_trade_no,
  316. update_time
  317. );
  318. if (res.affectedRows <= 0) {
  319. logger.info(`订单${orderId} 发货失败`)
  320. ret.msg = '发货失败'
  321. resolve(ret);
  322. return;
  323. }
  324. ret.code = 1
  325. ret.msg = '发货成功'
  326. resolve(ret);
  327. }, 1000);
  328. });
  329. }
  330. //qucik发货
  331. //扩展参数格式为${serverId};${productId}
  332. const CallPayQuick = async (ctx) => {
  333. let ret = {
  334. code: 0,
  335. msg: '发货失败'
  336. }
  337. //sdk参数
  338. let md5Key = "gaug5awijz5kdqfkzdmikjfrt4jbpv5f"
  339. let callbackKey = "19404462610366331550315911887318"
  340. let data = ctx.request.body
  341. logger.info("qucik 回调参数", { "data": data })
  342. let md5Sign = data.md5Sign
  343. let ntData = data.nt_data
  344. let verifySignData = QuickAsy.getSign(data, md5Key)
  345. if (verifySignData != md5Sign) {
  346. logger.error("quick 调用md5Sign错误", { '$verifySignData': verifySignData, 'md5Sign': md5Sign })
  347. return ret
  348. }
  349. let xmlData = QuickAsy.decode(ntData, callbackKey)
  350. const result = await new Promise((resolve, reject) => {
  351. parseString(xmlData, (err, result) => {
  352. if (err) {
  353. return reject(err);
  354. }
  355. resolve(result);
  356. });
  357. });
  358. const message = (result as any).quicksdk_message.message[0];
  359. const channel = message.channel[0];
  360. const orgMemId = message.channel_uid[0];
  361. const channelOrder = message.channel_order[0];
  362. const orderId = message.game_order[0];//cp单号
  363. const orderNo = message.order_no[0];//sdk订单号
  364. const payTime = message.pay_time[0];
  365. const orgProductPrice = message.amount[0]; //充值成功的金额
  366. const status = message.status[0];//0成功
  367. const extrasParams = message.extras_params[0];
  368. if (status == 1) {
  369. return
  370. }
  371. const orderInfo = (await Order.getOrder(orderId))[0]
  372. if (!orderInfo) {
  373. logger.info(`订单${orderId}不存在`)
  374. ret.msg = `订单${orderId}不存在`
  375. return ret
  376. }
  377. let serverId = orderInfo.server_id//区服id
  378. let orgProductId = orderInfo.product_id//商品id
  379. if (orderInfo.status == 2) {
  380. logger.info(`订单${orderId}已经重复发货`)
  381. ret.code = 1
  382. ret.msg = `订单${orderId}已经重复发货`
  383. return ret
  384. }
  385. let url = await getServerList(serverId, 'default')
  386. if (!url) {
  387. logger.info(`区服id错误: serverId ${serverId}`)
  388. ret.msg = `区服id错误: serverId ${serverId}`
  389. return ret
  390. }
  391. // 使用 Msg 类的 connect 方法连接到 WebSocket 服务器
  392. let sendMsg = new Msg()
  393. sendMsg.connect(url, Account);
  394. logger.info(`订单${orderId} ${url}`)
  395. // 在适当的时机,调用 CG_ASK_LOGIN 方法
  396. let params = `{"account":"${orgMemId}","order":"${orderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`
  397. return new Promise((resolve) => {
  398. setTimeout(async () => {
  399. console.log("这个消息将在3秒后打印出来");
  400. const send_res = sendMsg.CG_ASK_LOGIN(Account, 0, "", 'cn', 'CN', ctx.request.ip, params);
  401. if (!send_res) {
  402. resolve(ret);
  403. return;
  404. }
  405. const update_time = formatDate(new Date())
  406. const res = await Order.updateOrderStats(
  407. orderId,
  408. 2,
  409. orderNo,
  410. update_time
  411. );
  412. if (res.affectedRows <= 0) {
  413. logger.info(`订单${orderId} 发货失败`)
  414. ret.msg = '发货失败'
  415. resolve(ret);
  416. return;
  417. }
  418. ret.code = 1
  419. ret.msg = '发货成功'
  420. resolve(ret);
  421. }, 1000);
  422. });
  423. }
  424. const CallPay360 = async (ctx) => {
  425. let ret = {
  426. code: 0,
  427. msg: '发货失败'
  428. }
  429. let data = ctx.request.body
  430. let sign = data.sign
  431. let serverId = data.serverId
  432. let orderId = data.cpOrder
  433. let out_trade_no = data.orderId
  434. logger.info("pay callback params:", { "url": ctx.href, "params": data })
  435. const orderInfo = (await Order.getOrder(orderId))[0]
  436. if (!orderInfo) {
  437. logger.info(`订单${orderId}不存在`)
  438. ret.msg = `订单${orderId}不存在`
  439. return ret
  440. }
  441. if (orderInfo.status == 2) {
  442. logger.info(`订单${orderId}已经重复发货`)
  443. ret.code = 1
  444. ret.msg = `订单${orderId}已经重复发货`
  445. return ret
  446. }
  447. //签名参数
  448. let signData = Object.keys(data).sort().filter(key => key !== 'sign');
  449. let signStr = signData.map(key => `${data[key]}`).join('');
  450. signStr += AppSecret360
  451. let newSign = CryptoJS.MD5(signStr).toString();
  452. console.log("signStr:", signStr)
  453. console.log("newSign:", newSign)
  454. if (sign != newSign) {
  455. logger.info(`签名错误: 签名串 ${signStr} newSign ${newSign} sign ${sign}`)
  456. ret.msg = `签名错误`
  457. return ret
  458. }
  459. let url = await getServerList(serverId, 'default')
  460. if (!url) {
  461. logger.info(`区服id错误: serverId ${serverId}`)
  462. ret.msg = `区服id错误: serverId ${serverId}`
  463. return ret
  464. }
  465. //发货
  466. // 使用 Msg 类的 connect 方法连接到 WebSocket 服务器
  467. let sendMsg = new Msg()
  468. sendMsg.connect(url, Account);
  469. logger.info(`订单${orderId} ${url}`)
  470. let orgMemId = data.uid
  471. let orgOderId = data.cpOrder
  472. let orgProductId = orderInfo.product_id
  473. let orgExt = data.cText
  474. let orgProductPrice = data.skuPrice
  475. // 在适当的时机,调用 CG_ASK_LOGIN 方法
  476. let params = `{"account":"${orgMemId}","order":"${orgOderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`
  477. return new Promise((resolve) => {
  478. setTimeout(async () => {
  479. console.log("这个消息将在3秒后打印出来");
  480. const send_res = sendMsg.CG_ASK_LOGIN(Account, 0, "", 'cn', 'CN', ctx.request.ip, params);
  481. if (!send_res) {
  482. resolve(ret);
  483. return;
  484. }
  485. const update_time = formatDate(new Date())
  486. const res = await Order.updateOrderStats(
  487. orderId,
  488. 2,
  489. out_trade_no,
  490. update_time
  491. );
  492. if (res.affectedRows <= 0) {
  493. logger.info(`订单${orderId} 发货失败`)
  494. ret.msg = '发货失败'
  495. resolve(ret);
  496. return;
  497. }
  498. ret.code = 1
  499. ret.msg = '发货成功'
  500. resolve(ret);
  501. }, 1000);
  502. });
  503. }
  504. const testGoogleCallPay = async (ctx) => {
  505. let ret = {
  506. code: 0,
  507. msg: '消费失败'
  508. }
  509. let data = ctx.request.body
  510. logger.info("pay callback params:", { "url": ctx.href, "params": data })
  511. const redisClient = ctx.redis.client;
  512. let access_token = await redisClient.get('access_token');
  513. if (!access_token) {
  514. console.log('请求api获取token')
  515. const apiData = {
  516. "grant_type": "refresh_token",
  517. "client_id": ClientId,
  518. "client_secret": ClientSecret,
  519. "refresh_token": RefreshToken
  520. }
  521. const response = await axios.post('https://accounts.google.com/o/oauth2/token', apiData, {
  522. headers: {
  523. 'Content-Type': 'application/x-www-form-urlencoded'
  524. }
  525. });
  526. logger.info("token params:", { "data": response.data, "params": apiData })
  527. if (!response.data.access_token) {
  528. return ret
  529. }
  530. access_token = response.data.access_token
  531. await redisClient.set('access_token', response.data.access_token);
  532. await redisClient.expire('access_token', 1800);
  533. }
  534. if (!access_token) {
  535. return ret;
  536. }
  537. let googleToken = data.purchaseToken
  538. let product_id = data.orderId
  539. const productId = ProductId + product_id
  540. let apiUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}?access_token=${access_token}`
  541. let maxRetries = 5;
  542. let currentRetry = 0;
  543. let isCheck = false;
  544. // 使用 while 循环进行重试
  545. while (currentRetry < maxRetries) {
  546. try {
  547. // // 尝试执行的操作
  548. const googleRes = await axios.get(apiUrl, {
  549. headers: {
  550. 'Content-Type': 'application/x-www-form-urlencoded'
  551. }
  552. })
  553. console.log(googleRes.data)
  554. // 如果操作成功,退出循环
  555. if (googleRes.data.purchaseState == 0) {
  556. isCheck = true
  557. break;
  558. }
  559. } catch (error) {
  560. // 如果操作失败,记录错误并继续尝试
  561. console.log(error)
  562. }
  563. currentRetry++;
  564. }
  565. if (!isCheck) {
  566. return ret;
  567. }
  568. return new Promise(async (resolve) => {
  569. let acknowledgeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:acknowledge?access_token=${access_token}`
  570. console.log(acknowledgeUrl)
  571. const acknowledgeRes = await axios.post(acknowledgeUrl,
  572. {
  573. developerPayload: ""
  574. }
  575. ,
  576. {
  577. headers: {
  578. 'Content-Type': 'application/json'
  579. }
  580. })
  581. let consumeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:consume?access_token=${access_token}`
  582. const consumeRes = await axios.post(consumeUrl,
  583. {
  584. developerPayload: ""
  585. }
  586. ,
  587. {
  588. headers: {
  589. 'Content-Type': 'application/json'
  590. }
  591. })
  592. ret.code = 1
  593. ret.msg = '发货成功'
  594. resolve(ret);
  595. });
  596. }
  597. const checkVersion = async (ctx) => {
  598. let ret = {
  599. code: 0,
  600. msg: '无需更新',
  601. url: '',
  602. }
  603. let data = ctx.request.body
  604. let version = data.version
  605. let tag = data.tag || 'default'
  606. logger.info("checkVersion params:", { "url": ctx.href, "params": data })
  607. const versionInfo = (await Version.getGameVersion(tag))[0]
  608. if (!versionInfo) {
  609. return ret
  610. }
  611. if (compareVersions(versionInfo.version, version) === 1) {
  612. if (versionInfo.download_url) {
  613. ret.code = 1
  614. ret.msg = '需要更新'
  615. ret.url = versionInfo.download_url
  616. }
  617. }
  618. return ret
  619. }
  620. //验证账号
  621. const checkUserToken = async (ctx) => {
  622. }
  623. class ApiController {
  624. async createOrder(ctx) {
  625. let {
  626. uid,
  627. level,
  628. amount,
  629. role_id,
  630. role_name,
  631. product_id,
  632. server_id
  633. } = ctx.request.body
  634. logger.info("create params:", { "params": ctx.request.body })
  635. if (!product_id || !server_id || !role_name || !role_id || !amount || !uid) {
  636. ctx.body = { code: -1, message: '参数错误,创建订单失败!!', data: '' }
  637. return
  638. }
  639. const orderId = generateOrderNumber(); // 生成一个长度为8的订单号
  640. const create_time = formatDate(new Date())
  641. const res = await Order.createOrder(
  642. orderId,
  643. uid,
  644. level,
  645. amount,
  646. role_id,
  647. role_name,
  648. product_id,
  649. server_id,
  650. create_time
  651. );
  652. if (res.affectedRows > 0) {
  653. ctx.body = { code: 0, message: '创建订单成功', data: orderId }
  654. } else {
  655. ctx.body = { code: -1, message: '创建订单失败', data: '' }
  656. }
  657. logger.info("创建订单返回结果:", { "params": ctx.body })
  658. }
  659. async checkUserToken(ctx) {
  660. // const result = await checkUserToken(ctx);
  661. // let data = { "status": false, "sign": "" }
  662. // if (result) {
  663. // data.status = true
  664. // data.sign = result
  665. // }
  666. // ctx.body = data
  667. }
  668. //quick登陆
  669. async quickUserLogin(ctx) {
  670. //sdk参数
  671. let productCode = "68402796563185068148745974229755"
  672. let data = ctx.request.body
  673. let uid = data.uid
  674. let token = data.token
  675. let reqUrl = "http://checkuser.quickapi.net/v2/checkUserInfo?token=" + token + "&uid=" + uid + "product_code=" + productCode
  676. logger.info("quick登陆验证请求", { 'params': data, 'url': reqUrl })
  677. const res = await axios.get(reqUrl)
  678. logger.info("quick req", { "res": res.data })
  679. if (res.data == '1') {
  680. ctx.body = {
  681. code: 200,
  682. msg: 'success'
  683. }
  684. } else {
  685. ctx.body = {
  686. code: 0,
  687. msg: 'fail'
  688. }
  689. }
  690. }
  691. async callPay(ctx) {
  692. console.log(234234234)
  693. let data = ctx.request.body
  694. let platform = '360' // 默认360
  695. if (ctx.query.platform) {
  696. platform = ctx.query.platform
  697. }
  698. if (data.platform) {
  699. platform = data.platform
  700. }
  701. switch (platform) {
  702. case 'google':
  703. var result = await googleCallPay(ctx)
  704. console.log('发货结果', result)
  705. ctx.body = result
  706. break;
  707. case 'apple':
  708. var result = await appleCallPay(ctx)
  709. console.log('发货结果', result)
  710. ctx.body = result
  711. break;
  712. case '360':
  713. var result = await CallPay360(ctx)
  714. console.log('发货结果', result)
  715. ctx.body = result
  716. break;
  717. // case 'testGoogle':
  718. // var result = await testGoogleCallPay(ctx)
  719. // console.log('发货结果', result)
  720. // ctx.body = result
  721. // break;
  722. case 'quick':
  723. var result = await CallPayQuick(ctx)
  724. console.log('发货结果', result)
  725. if((result as any).code == 1){
  726. ctx.body = 'SUCCESS'
  727. }else{
  728. ctx.body = 'Fail'
  729. }
  730. break;
  731. default:
  732. ctx.body = {
  733. code: 0,
  734. msg: '渠道错误'
  735. }
  736. }
  737. }
  738. async checkVersion(ctx) {
  739. var result = await checkVersion(ctx)
  740. console.log('校验版本', result)
  741. ctx.body = result
  742. }
  743. async getServerList(ctx) {
  744. let tag = ctx.query.tag || 'default'
  745. const servers = (await Server.getServerList(tag))
  746. let data = []
  747. let ip = ctx.request.ip
  748. if (ip.startsWith('::ffff:')) {
  749. ip = ip.substring('::ffff:'.length);
  750. }
  751. logger.info("区服接口", { "ip": ctx.request.ip })
  752. if (servers.length > 0) {
  753. servers.forEach(function (element) {
  754. let status = element.status
  755. if ((status == 0 || status == 3) && element.white_list) {
  756. const list = element.white_list.split(",");
  757. if (list.length > 0) {
  758. if (list.includes(ip)) {
  759. status = 1
  760. }
  761. }
  762. }
  763. data.push({
  764. "id": element.id,
  765. "name": element.name,
  766. "ip": element.ip,
  767. "port": element.port,
  768. "tips": element.tips,
  769. "status": status,
  770. })
  771. });
  772. }
  773. ctx.body = data
  774. }
  775. async getAllServerList(ctx) {
  776. let tag = ctx.query.tag || 'default'
  777. let ip = ctx.request.ip
  778. if (ip.startsWith('::ffff:')) {
  779. ip = ip.substring('::ffff:'.length);
  780. }
  781. logger.info("getAllServerList 区服接口", { "ip": ctx.request.ip })
  782. const servers = (await Server.getAllServerList(tag, ip))
  783. ctx.body = servers
  784. }
  785. async enterServer(ctx) {
  786. let ret = {
  787. code: 0,
  788. msg: '请求失败'
  789. }
  790. let {
  791. uid,
  792. server_id
  793. } = ctx.request.body
  794. let url = await getServerList(server_id, 'default')
  795. if (!url) {
  796. ctx.body = { code: -1, message: `区服id错误: serverId ${server_id}`, data: '' }
  797. return
  798. }
  799. logger.info("create params:", { "params": ctx.request.body })
  800. if (!server_id || !uid) {
  801. ctx.body = { code: -1, message: '参数错误!!', data: '' }
  802. return
  803. }
  804. const create_time = formatDate(new Date())
  805. const serverInfo = (await Server.checkEnterServerByUid(uid, server_id))[0]
  806. let res = null
  807. if (serverInfo) {
  808. res = await Server.updateEnterServer(
  809. serverInfo.id,
  810. create_time
  811. );
  812. } else {
  813. res = await Server.enterServer(
  814. uid,
  815. server_id,
  816. create_time
  817. );
  818. }
  819. if (res.affectedRows > 0) {
  820. ctx.body = { code: 0, message: '请求成功', data: '' }
  821. } else {
  822. ctx.body = { code: -1, message: '请求失败', data: '' }
  823. }
  824. }
  825. async getLastServerList(ctx) {
  826. let {
  827. uid,
  828. } = ctx.request.body
  829. let tag = 'default'
  830. let data = [];
  831. let isNewAccount = 1
  832. let enterServerList = (await Server.getEnterServerListByUid(uid))
  833. let ip = ctx.request.ip
  834. if (ip.startsWith('::ffff:')) {
  835. ip = ip.substring('::ffff:'.length);
  836. }
  837. logger.info("getLastServerList 区服接口", { "ip": ctx.request.ip })
  838. if (enterServerList.length > 0) {
  839. isNewAccount = 0
  840. // const servers = (await Server.getServerList(tag, 1))
  841. const servers = (await Server.getAllServerList(tag, ip))
  842. enterServerList.forEach(function (element) {
  843. data.push({
  844. "channel": "Thailand", //渠道固定
  845. "minSid": 1, //最小服务器
  846. "maxSid": servers.length, //最大服务器 这里会控制 服务器列表显示的数量
  847. "isNewAccount": isNewAccount, //1为新号 会弹出用户协议
  848. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  849. "sid": element.server_id || 1,
  850. "id": element.server_id || 1,
  851. "name": element.name || "1区",
  852. "tips": element.tips || "",
  853. "server": element.ip ? `ws://${element.ip}:${element.port}` : "",
  854. "status": element.status || 0,
  855. })
  856. });
  857. } else {
  858. // const servers = (await Server.getServerList(tag, 1))
  859. const servers = (await Server.getAllServerList(tag, ip))
  860. if (servers.length > 0) {
  861. const serverInfo = servers[servers.length - 1]
  862. data.push({
  863. "channel": "Thailand", //渠道固定
  864. "minSid": 1, //最小服务器
  865. "maxSid": servers.length, //最大服务器 这里会控制 服务器列表显示的数量
  866. "isNewAccount": isNewAccount, //1为新号 会弹出用户协议
  867. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  868. "sid": serverInfo.id || 1,
  869. "id": serverInfo.id || 1,
  870. "name": serverInfo.name || "1区",
  871. "tips": serverInfo.tips || "",
  872. "server": serverInfo.ip ? `ws://${serverInfo.ip}:${serverInfo.port}` : "",
  873. "status": serverInfo.status || 0,
  874. })
  875. } else {
  876. data.push({
  877. "channel": "Thailand", //渠道固定
  878. "minSid": 1, //最小服务器
  879. "maxSid": 10, //最大服务器 这里会控制 服务器列表显示的数量
  880. "isNewAccount": isNewAccount, //1为新号 会弹出用户协议
  881. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  882. "sid": 1,
  883. "id": 1,
  884. "name": "1区",
  885. "tips": "",
  886. "server": "",
  887. "status": 0,
  888. })
  889. }
  890. }
  891. ctx.body = data
  892. }
  893. async getNotice(ctx) {
  894. let data = ctx.request.body
  895. let platform = 'th'
  896. if (ctx.query.platform) {
  897. platform = ctx.query.platform
  898. }
  899. switch (platform) {
  900. case 'th':
  901. ctx.body = th_notice
  902. break;
  903. case '360':
  904. ctx.body = notice
  905. break;
  906. case 'xky':
  907. ctx.body = xky_notice
  908. break;
  909. default:
  910. ctx.body = notice
  911. }
  912. }
  913. async genCDK(ctx) {
  914. /*
  915. data = {
  916. cnt : number -- 生成数量
  917. useCnt : number -- 当前批次最大使用数量
  918. serverList : string -- 区服列表Json字符串
  919. itemList : string -- CDK对应物品列表Json字符串
  920. }
  921. */
  922. let data = ctx.request.body
  923. await CDK.genCDK(ctx, data.cnt, data.useCnt, data.serverList, data.itemList)
  924. ctx.body = {
  925. code: 0,
  926. msg: 'success'
  927. }
  928. return
  929. }
  930. async getCDK(ctx) {
  931. let data = ctx.request.body
  932. let ret = await CDK.getCDK(ctx, data.batch)
  933. if (ret.length <= 0) {
  934. ctx.body = {
  935. code: 1,
  936. msg: "batch invalid"
  937. }
  938. return
  939. }
  940. ctx.body = {
  941. code: 0,
  942. msg: ret
  943. }
  944. }
  945. async useCDK(ctx) {
  946. let data = ctx.request.body
  947. let url = await getServerList(data.serverId, 'default')
  948. let err = ""
  949. if (!url) {
  950. ctx.body = {
  951. code: 1,
  952. msg: `区服id错误: serverId ${data.serverId}`
  953. }
  954. err = "server id invalid"
  955. }
  956. let param: string = ""
  957. // 验证CDK
  958. if (err.length == 0) {
  959. let batchInfo = await CDK.getCDKItemList(ctx, data.code)
  960. if (batchInfo.length <= 0) {
  961. err = "cdk not found"
  962. } else {
  963. err = await CDK.checkCDK(ctx, data.code, data.serverId)
  964. param = JSON.stringify({
  965. type: "UseCDK",
  966. err: err,
  967. batchInfo: batchInfo
  968. })
  969. }
  970. }
  971. // 固定码
  972. if (err == "cdk not found" || err == "server id invalid") {
  973. param = JSON.stringify({
  974. code: data.code,
  975. type: "UseFixCDK"
  976. })
  977. }
  978. // 测试是否可以调用过去
  979. // 通知给服务器,发放道具
  980. // "ws://43.143.193.23:18192"
  981. // Msg.connect(url, Account);
  982. try {
  983. let sendMsg = new Msg()
  984. sendMsg.connect(url, Account);
  985. logger.info(`code ${data.code} id ${data.serverId} ${url}`)
  986. new Promise((resolve) => {
  987. setTimeout(async () => {
  988. sendMsg.CG_TEST_PROTO(data.account, param)
  989. CDK.useCDK(ctx, data.code)
  990. }, 1000);
  991. });
  992. } catch (error) {
  993. console.log(error)
  994. }
  995. ctx.body = {
  996. code: 0,
  997. msg: "success"
  998. }
  999. }
  1000. async validCDK(ctx) {
  1001. let data = ctx.request.body
  1002. if (data.code.length == 10) {
  1003. let ret = await CDK.useCDK(ctx, data.code)
  1004. if (ret != "success") {
  1005. ctx.body = {
  1006. code: 1,
  1007. msg: ret
  1008. }
  1009. return
  1010. }
  1011. }
  1012. ctx.body = {
  1013. code: 0,
  1014. msg: "success"
  1015. }
  1016. }
  1017. // 维护服务器,踢掉所有玩家
  1018. async maintenance(ctx) {
  1019. let data = ctx.request.body
  1020. let url = await getServerList(data.serverId, 'default')
  1021. if (!url) {
  1022. ctx.body = {
  1023. code: 1,
  1024. msg: `区服id错误: serverId ${data.serverId}`
  1025. }
  1026. return
  1027. }
  1028. let param = JSON.stringify({
  1029. type: "kickAllUser"
  1030. })
  1031. // Msg.connect(url, Account);
  1032. let sendMsg = new Msg()
  1033. sendMsg.connect(url, Account);
  1034. new Promise((resolve) => {
  1035. setTimeout(async () => {
  1036. sendMsg.CG_TEST_PROTO("test", param)
  1037. }, 1000);
  1038. });
  1039. ctx.body = {
  1040. code: 0,
  1041. msg: "success"
  1042. }
  1043. }
  1044. async maintenanceAll(ctx) {
  1045. let data = ctx.request.body
  1046. const servers = (await Server.getServerList('default'))
  1047. servers.forEach(function (element) {
  1048. let url = 'ws://' + element.ip + ':' + element.port
  1049. if (!url) {
  1050. ctx.body = {
  1051. code: 1,
  1052. msg: `区服id错误: serverId ${element.server_id}`
  1053. }
  1054. return
  1055. }
  1056. let param = JSON.stringify({
  1057. type: "kickAllUser"
  1058. })
  1059. // Msg.connect(url, Account);
  1060. let sendMsg = new Msg()
  1061. sendMsg.connect(url, Account);
  1062. new Promise((resolve) => {
  1063. setTimeout(async () => {
  1064. sendMsg.CG_TEST_PROTO("test", param)
  1065. }, 1000);
  1066. });
  1067. });
  1068. ctx.body = {
  1069. code: 0,
  1070. msg: "success"
  1071. }
  1072. }
  1073. async sendMail(ctx) {
  1074. let data = ctx.request.body
  1075. let url = await getServerList(data.serverId, 'default')
  1076. if (!url) {
  1077. ctx.body = {
  1078. code: 1,
  1079. msg: `区服id错误: serverId ${data.serverId}`
  1080. }
  1081. return
  1082. }
  1083. let param = JSON.stringify({
  1084. type: "sendMail",
  1085. mail: JSON.stringify({
  1086. uuid: data.uuid,
  1087. title: data.title,
  1088. content: data.content,
  1089. items: JSON.parse(data.items),
  1090. expire: data.expire
  1091. })
  1092. })
  1093. // Msg.connect(url, Account);
  1094. let sendMsg = new Msg()
  1095. sendMsg.connect(url, Account);
  1096. new Promise((resolve) => {
  1097. setTimeout(async () => {
  1098. sendMsg.CG_TEST_PROTO("test", param)
  1099. }, 1000);
  1100. });
  1101. ctx.body = {
  1102. code: 0,
  1103. msg: "success"
  1104. }
  1105. }
  1106. }
  1107. module.exports = new ApiController()