ApiController.ts 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  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. let extrasArr = extrasParams.split(";")
  372. let serverId = extrasArr[0] //区服id
  373. let orgProductId = extrasArr[1]//商品id
  374. const orderInfo = (await Order.getOrder(orderId))[0]
  375. if (!orderInfo) {
  376. logger.info(`订单${orderId}不存在`)
  377. ret.msg = `订单${orderId}不存在`
  378. return ret
  379. }
  380. if (orderInfo.status == 2) {
  381. logger.info(`订单${orderId}已经重复发货`)
  382. ret.code = 1
  383. ret.msg = `订单${orderId}已经重复发货`
  384. return ret
  385. }
  386. let url = await getServerList(serverId, 'default')
  387. if (!url) {
  388. logger.info(`区服id错误: serverId ${serverId}`)
  389. ret.msg = `区服id错误: serverId ${serverId}`
  390. return ret
  391. }
  392. // 使用 Msg 类的 connect 方法连接到 WebSocket 服务器
  393. let sendMsg = new Msg()
  394. sendMsg.connect(url, Account);
  395. logger.info(`订单${orderId} ${url}`)
  396. // 在适当的时机,调用 CG_ASK_LOGIN 方法
  397. let params = `{"account":"${orgMemId}","order":"${orderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`
  398. return new Promise((resolve) => {
  399. setTimeout(async () => {
  400. console.log("这个消息将在3秒后打印出来");
  401. const send_res = sendMsg.CG_ASK_LOGIN(Account, 0, "", 'cn', 'CN', ctx.request.ip, params);
  402. if (!send_res) {
  403. resolve(ret);
  404. return;
  405. }
  406. const update_time = formatDate(new Date())
  407. const res = await Order.updateOrderStats(
  408. orderId,
  409. 2,
  410. orderNo,
  411. update_time
  412. );
  413. if (res.affectedRows <= 0) {
  414. logger.info(`订单${orderId} 发货失败`)
  415. ret.msg = '发货失败'
  416. resolve(ret);
  417. return;
  418. }
  419. ret.code = 1
  420. ret.msg = '发货成功'
  421. resolve(ret);
  422. }, 1000);
  423. });
  424. }
  425. const CallPay360 = async (ctx) => {
  426. let ret = {
  427. code: 0,
  428. msg: '发货失败'
  429. }
  430. let data = ctx.request.body
  431. let sign = data.sign
  432. let serverId = data.serverId
  433. let orderId = data.cpOrder
  434. let out_trade_no = data.orderId
  435. logger.info("pay callback params:", { "url": ctx.href, "params": data })
  436. const orderInfo = (await Order.getOrder(orderId))[0]
  437. if (!orderInfo) {
  438. logger.info(`订单${orderId}不存在`)
  439. ret.msg = `订单${orderId}不存在`
  440. return ret
  441. }
  442. if (orderInfo.status == 2) {
  443. logger.info(`订单${orderId}已经重复发货`)
  444. ret.code = 1
  445. ret.msg = `订单${orderId}已经重复发货`
  446. return ret
  447. }
  448. //签名参数
  449. let signData = Object.keys(data).sort().filter(key => key !== 'sign');
  450. let signStr = signData.map(key => `${data[key]}`).join('');
  451. signStr += AppSecret360
  452. let newSign = CryptoJS.MD5(signStr).toString();
  453. console.log("signStr:", signStr)
  454. console.log("newSign:", newSign)
  455. if (sign != newSign) {
  456. logger.info(`签名错误: 签名串 ${signStr} newSign ${newSign} sign ${sign}`)
  457. ret.msg = `签名错误`
  458. return ret
  459. }
  460. let url = await getServerList(serverId, 'default')
  461. if (!url) {
  462. logger.info(`区服id错误: serverId ${serverId}`)
  463. ret.msg = `区服id错误: serverId ${serverId}`
  464. return ret
  465. }
  466. //发货
  467. // 使用 Msg 类的 connect 方法连接到 WebSocket 服务器
  468. let sendMsg = new Msg()
  469. sendMsg.connect(url, Account);
  470. logger.info(`订单${orderId} ${url}`)
  471. let orgMemId = data.uid
  472. let orgOderId = data.cpOrder
  473. let orgProductId = orderInfo.product_id
  474. let orgExt = data.cText
  475. let orgProductPrice = data.skuPrice
  476. // 在适当的时机,调用 CG_ASK_LOGIN 方法
  477. let params = `{"account":"${orgMemId}","order":"${orgOderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`
  478. return new Promise((resolve) => {
  479. setTimeout(async () => {
  480. console.log("这个消息将在3秒后打印出来");
  481. const send_res = sendMsg.CG_ASK_LOGIN(Account, 0, "", 'cn', 'CN', ctx.request.ip, params);
  482. if (!send_res) {
  483. resolve(ret);
  484. return;
  485. }
  486. const update_time = formatDate(new Date())
  487. const res = await Order.updateOrderStats(
  488. orderId,
  489. 2,
  490. out_trade_no,
  491. update_time
  492. );
  493. if (res.affectedRows <= 0) {
  494. logger.info(`订单${orderId} 发货失败`)
  495. ret.msg = '发货失败'
  496. resolve(ret);
  497. return;
  498. }
  499. ret.code = 1
  500. ret.msg = '发货成功'
  501. resolve(ret);
  502. }, 1000);
  503. });
  504. }
  505. const testGoogleCallPay = async (ctx) => {
  506. let ret = {
  507. code: 0,
  508. msg: '消费失败'
  509. }
  510. let data = ctx.request.body
  511. logger.info("pay callback params:", { "url": ctx.href, "params": data })
  512. const redisClient = ctx.redis.client;
  513. let access_token = await redisClient.get('access_token');
  514. if (!access_token) {
  515. console.log('请求api获取token')
  516. const apiData = {
  517. "grant_type": "refresh_token",
  518. "client_id": ClientId,
  519. "client_secret": ClientSecret,
  520. "refresh_token": RefreshToken
  521. }
  522. const response = await axios.post('https://accounts.google.com/o/oauth2/token', apiData, {
  523. headers: {
  524. 'Content-Type': 'application/x-www-form-urlencoded'
  525. }
  526. });
  527. logger.info("token params:", { "data": response.data, "params": apiData })
  528. if (!response.data.access_token) {
  529. return ret
  530. }
  531. access_token = response.data.access_token
  532. await redisClient.set('access_token', response.data.access_token);
  533. await redisClient.expire('access_token', 1800);
  534. }
  535. if (!access_token) {
  536. return ret;
  537. }
  538. let googleToken = data.purchaseToken
  539. let product_id = data.orderId
  540. const productId = ProductId + product_id
  541. let apiUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}?access_token=${access_token}`
  542. let maxRetries = 5;
  543. let currentRetry = 0;
  544. let isCheck = false;
  545. // 使用 while 循环进行重试
  546. while (currentRetry < maxRetries) {
  547. try {
  548. // // 尝试执行的操作
  549. const googleRes = await axios.get(apiUrl, {
  550. headers: {
  551. 'Content-Type': 'application/x-www-form-urlencoded'
  552. }
  553. })
  554. console.log(googleRes.data)
  555. // 如果操作成功,退出循环
  556. if (googleRes.data.purchaseState == 0) {
  557. isCheck = true
  558. break;
  559. }
  560. } catch (error) {
  561. // 如果操作失败,记录错误并继续尝试
  562. console.log(error)
  563. }
  564. currentRetry++;
  565. }
  566. if (!isCheck) {
  567. return ret;
  568. }
  569. return new Promise(async (resolve) => {
  570. let acknowledgeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:acknowledge?access_token=${access_token}`
  571. console.log(acknowledgeUrl)
  572. const acknowledgeRes = await axios.post(acknowledgeUrl,
  573. {
  574. developerPayload: ""
  575. }
  576. ,
  577. {
  578. headers: {
  579. 'Content-Type': 'application/json'
  580. }
  581. })
  582. let consumeUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}:consume?access_token=${access_token}`
  583. const consumeRes = await axios.post(consumeUrl,
  584. {
  585. developerPayload: ""
  586. }
  587. ,
  588. {
  589. headers: {
  590. 'Content-Type': 'application/json'
  591. }
  592. })
  593. ret.code = 1
  594. ret.msg = '发货成功'
  595. resolve(ret);
  596. });
  597. }
  598. const checkVersion = async (ctx) => {
  599. let ret = {
  600. code: 0,
  601. msg: '无需更新',
  602. url: '',
  603. }
  604. let data = ctx.request.body
  605. let version = data.version
  606. let tag = data.tag || 'default'
  607. logger.info("checkVersion params:", { "url": ctx.href, "params": data })
  608. const versionInfo = (await Version.getGameVersion(tag))[0]
  609. if (!versionInfo) {
  610. return ret
  611. }
  612. if (compareVersions(versionInfo.version, version) === 1) {
  613. if (versionInfo.download_url) {
  614. ret.code = 1
  615. ret.msg = '需要更新'
  616. ret.url = versionInfo.download_url
  617. }
  618. }
  619. return ret
  620. }
  621. //验证账号
  622. const checkUserToken = async (ctx) => {
  623. }
  624. class ApiController {
  625. async createOrder(ctx) {
  626. let {
  627. uid,
  628. level,
  629. amount,
  630. role_id,
  631. role_name,
  632. product_id,
  633. server_id
  634. } = ctx.request.body
  635. logger.info("create params:", { "params": ctx.request.body })
  636. if (!product_id || !server_id || !role_name || !role_id || !amount || !uid) {
  637. ctx.body = { code: -1, message: '参数错误,创建订单失败!!', data: '' }
  638. return
  639. }
  640. const orderId = generateOrderNumber(); // 生成一个长度为8的订单号
  641. const create_time = formatDate(new Date())
  642. const res = await Order.createOrder(
  643. orderId,
  644. uid,
  645. level,
  646. amount,
  647. role_id,
  648. role_name,
  649. product_id,
  650. server_id,
  651. create_time
  652. );
  653. if (res.affectedRows > 0) {
  654. ctx.body = { code: 0, message: '创建订单成功', data: orderId }
  655. } else {
  656. ctx.body = { code: -1, message: '创建订单失败', data: '' }
  657. }
  658. logger.info("创建订单返回结果:", { "params": ctx.body })
  659. }
  660. async checkUserToken(ctx) {
  661. // const result = await checkUserToken(ctx);
  662. // let data = { "status": false, "sign": "" }
  663. // if (result) {
  664. // data.status = true
  665. // data.sign = result
  666. // }
  667. // ctx.body = data
  668. }
  669. //quick登陆
  670. async quickUserLogin(ctx) {
  671. //sdk参数
  672. let productCode = "68402796563185068148745974229755"
  673. let data = ctx.request.body
  674. let uid = data.uid
  675. let token = data.token
  676. let reqUrl = "http://checkuser.quickapi.net/v2/checkUserInfo?token=" + token + "&uid=" + uid + "product_code=" + productCode
  677. logger.info("quick登陆验证请求", { 'params': data, 'url': reqUrl })
  678. const res = await axios.get(reqUrl)
  679. logger.info("quick req", { "res": res.data })
  680. if (res.data == '1') {
  681. ctx.body = {
  682. code: 200,
  683. msg: 'success'
  684. }
  685. } else {
  686. ctx.body = {
  687. code: 0,
  688. msg: 'fail'
  689. }
  690. }
  691. }
  692. async callPay(ctx) {
  693. console.log(234234234)
  694. let data = ctx.request.body
  695. let platform = '360' // 默认360
  696. if (ctx.query.platform) {
  697. platform = ctx.query.platform
  698. }
  699. if (data.platform) {
  700. platform = data.platform
  701. }
  702. switch (platform) {
  703. case 'google':
  704. var result = await googleCallPay(ctx)
  705. console.log('发货结果', result)
  706. ctx.body = result
  707. break;
  708. case 'apple':
  709. var result = await appleCallPay(ctx)
  710. console.log('发货结果', result)
  711. ctx.body = result
  712. break;
  713. case '360':
  714. var result = await CallPay360(ctx)
  715. console.log('发货结果', result)
  716. ctx.body = result
  717. break;
  718. // case 'testGoogle':
  719. // var result = await testGoogleCallPay(ctx)
  720. // console.log('发货结果', result)
  721. // ctx.body = result
  722. // break;
  723. case 'quick':
  724. var result = await CallPayQuick(ctx)
  725. console.log('发货结果', result)
  726. ctx.body = result
  727. break;
  728. default:
  729. ctx.body = {
  730. code: 0,
  731. msg: '渠道错误'
  732. }
  733. }
  734. }
  735. async checkVersion(ctx) {
  736. var result = await checkVersion(ctx)
  737. console.log('校验版本', result)
  738. ctx.body = result
  739. }
  740. async getServerList(ctx) {
  741. let tag = ctx.query.tag || 'default'
  742. const servers = (await Server.getServerList(tag))
  743. let data = []
  744. let ip = ctx.request.ip
  745. if (ip.startsWith('::ffff:')) {
  746. ip = ip.substring('::ffff:'.length);
  747. }
  748. logger.info("区服接口", { "ip": ctx.request.ip })
  749. if (servers.length > 0) {
  750. servers.forEach(function (element) {
  751. let status = element.status
  752. if ((status == 0 || status == 3) && element.white_list) {
  753. const list = element.white_list.split(",");
  754. if (list.length > 0) {
  755. if (list.includes(ip)) {
  756. status = 1
  757. }
  758. }
  759. }
  760. data.push({
  761. "id": element.id,
  762. "name": element.name,
  763. "ip": element.ip,
  764. "port": element.port,
  765. "tips": element.tips,
  766. "status": status,
  767. })
  768. });
  769. }
  770. ctx.body = data
  771. }
  772. async getAllServerList(ctx) {
  773. let tag = ctx.query.tag || 'default'
  774. let ip = ctx.request.ip
  775. if (ip.startsWith('::ffff:')) {
  776. ip = ip.substring('::ffff:'.length);
  777. }
  778. logger.info("getAllServerList 区服接口", { "ip": ctx.request.ip })
  779. const servers = (await Server.getAllServerList(tag, ip))
  780. ctx.body = servers
  781. }
  782. async enterServer(ctx) {
  783. let ret = {
  784. code: 0,
  785. msg: '请求失败'
  786. }
  787. let {
  788. uid,
  789. server_id
  790. } = ctx.request.body
  791. let url = await getServerList(server_id, 'default')
  792. if (!url) {
  793. ctx.body = { code: -1, message: `区服id错误: serverId ${server_id}`, data: '' }
  794. return
  795. }
  796. logger.info("create params:", { "params": ctx.request.body })
  797. if (!server_id || !uid) {
  798. ctx.body = { code: -1, message: '参数错误!!', data: '' }
  799. return
  800. }
  801. const create_time = formatDate(new Date())
  802. const serverInfo = (await Server.checkEnterServerByUid(uid, server_id))[0]
  803. let res = null
  804. if (serverInfo) {
  805. res = await Server.updateEnterServer(
  806. serverInfo.id,
  807. create_time
  808. );
  809. } else {
  810. res = await Server.enterServer(
  811. uid,
  812. server_id,
  813. create_time
  814. );
  815. }
  816. if (res.affectedRows > 0) {
  817. ctx.body = { code: 0, message: '请求成功', data: '' }
  818. } else {
  819. ctx.body = { code: -1, message: '请求失败', data: '' }
  820. }
  821. }
  822. async getLastServerList(ctx) {
  823. let {
  824. uid,
  825. } = ctx.request.body
  826. let tag = 'default'
  827. let data = [];
  828. let isNewAccount = 1
  829. let enterServerList = (await Server.getEnterServerListByUid(uid))
  830. if (enterServerList.length > 0) {
  831. isNewAccount = 0
  832. const servers = (await Server.getServerList(tag, 1))
  833. enterServerList.forEach(function (element) {
  834. data.push({
  835. "channel": "Thailand", //渠道固定
  836. "minSid": 1, //最小服务器
  837. "maxSid": servers.length, //最大服务器 这里会控制 服务器列表显示的数量
  838. "isNewAccount": isNewAccount, //1为新号 会弹出用户协议
  839. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  840. "sid": element.server_id || 1,
  841. "id": element.server_id || 1,
  842. "name": element.name || "1区",
  843. "tips": element.tips || "",
  844. "server": element.ip ? `ws://${element.ip}:${element.port}` : "",
  845. "status": element.status || 0,
  846. })
  847. });
  848. } else {
  849. const servers = (await Server.getServerList(tag, 1))
  850. if (servers.length > 0) {
  851. const serverInfo = servers[servers.length - 1]
  852. data.push({
  853. "channel": "Thailand", //渠道固定
  854. "minSid": 1, //最小服务器
  855. "maxSid": servers.length, //最大服务器 这里会控制 服务器列表显示的数量
  856. "isNewAccount": isNewAccount, //1为新号 会弹出用户协议
  857. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  858. "sid": serverInfo.id || 1,
  859. "id": serverInfo.id || 1,
  860. "name": serverInfo.name || "1区",
  861. "tips": serverInfo.tips || "",
  862. "server": serverInfo.ip ? `ws://${serverInfo.ip}:${serverInfo.port}` : "",
  863. "status": serverInfo.status || 0,
  864. })
  865. } else {
  866. data.push({
  867. "channel": "Thailand", //渠道固定
  868. "minSid": 1, //最小服务器
  869. "maxSid": 10, //最大服务器 这里会控制 服务器列表显示的数量
  870. "isNewAccount": isNewAccount, //1为新号 会弹出用户协议
  871. //以下是最近登陆的服务器 (不可为空 如果没有参数可以填最后一个区)
  872. "sid": 1,
  873. "id": 1,
  874. "name": "1区",
  875. "tips": "",
  876. "server": "",
  877. "status": 0,
  878. })
  879. }
  880. }
  881. ctx.body = data
  882. }
  883. async getNotice(ctx) {
  884. let data = ctx.request.body
  885. let platform = 'th'
  886. if (ctx.query.platform) {
  887. platform = ctx.query.platform
  888. }
  889. switch (platform) {
  890. case 'th':
  891. ctx.body = th_notice
  892. break;
  893. case '360':
  894. ctx.body = notice
  895. break;
  896. case 'xky':
  897. ctx.body = xky_notice
  898. break;
  899. default:
  900. ctx.body = notice
  901. }
  902. }
  903. async genCDK(ctx) {
  904. /*
  905. data = {
  906. cnt : number -- 生成数量
  907. useCnt : number -- 当前批次最大使用数量
  908. serverList : string -- 区服列表Json字符串
  909. itemList : string -- CDK对应物品列表Json字符串
  910. }
  911. */
  912. let data = ctx.request.body
  913. await CDK.genCDK(ctx, data.cnt, data.useCnt, data.serverList, data.itemList)
  914. ctx.body = {
  915. code: 0,
  916. msg: 'success'
  917. }
  918. return
  919. }
  920. async getCDK(ctx) {
  921. let data = ctx.request.body
  922. let ret = await CDK.getCDK(ctx, data.batch)
  923. if (ret.length <= 0) {
  924. ctx.body = {
  925. code: 1,
  926. msg: "batch invalid"
  927. }
  928. return
  929. }
  930. ctx.body = {
  931. code: 0,
  932. msg: ret
  933. }
  934. }
  935. async useCDK(ctx) {
  936. let data = ctx.request.body
  937. let url = await getServerList(data.serverId, 'default')
  938. let err = ""
  939. if (!url) {
  940. ctx.body = {
  941. code: 1,
  942. msg: `区服id错误: serverId ${data.serverId}`
  943. }
  944. err = "server id invalid"
  945. }
  946. let param: string = ""
  947. // 验证CDK
  948. if (err.length == 0) {
  949. let batchInfo = await CDK.getCDKItemList(ctx, data.code)
  950. if (batchInfo.length <= 0) {
  951. err = "cdk not found"
  952. } else {
  953. err = await CDK.checkCDK(ctx, data.code, data.serverId)
  954. param = JSON.stringify({
  955. type: "UseCDK",
  956. err: err,
  957. batchInfo: batchInfo
  958. })
  959. }
  960. }
  961. // 固定码
  962. if (err == "cdk not found" || err == "server id invalid") {
  963. param = JSON.stringify({
  964. code: data.code,
  965. type: "UseFixCDK"
  966. })
  967. }
  968. // 测试是否可以调用过去
  969. // 通知给服务器,发放道具
  970. // "ws://43.143.193.23:18192"
  971. // Msg.connect(url, Account);
  972. try {
  973. let sendMsg = new Msg()
  974. sendMsg.connect(url, Account);
  975. logger.info(`code ${data.code} id ${data.serverId} ${url}`)
  976. new Promise((resolve) => {
  977. setTimeout(async () => {
  978. sendMsg.CG_TEST_PROTO(data.account, param)
  979. CDK.useCDK(ctx, data.code)
  980. }, 1000);
  981. });
  982. } catch (error) {
  983. console.log(error)
  984. }
  985. ctx.body = {
  986. code: 0,
  987. msg: "success"
  988. }
  989. }
  990. async validCDK(ctx) {
  991. let data = ctx.request.body
  992. if (data.code.length == 10) {
  993. let ret = await CDK.useCDK(ctx, data.code)
  994. if (ret != "success") {
  995. ctx.body = {
  996. code: 1,
  997. msg: ret
  998. }
  999. return
  1000. }
  1001. }
  1002. ctx.body = {
  1003. code: 0,
  1004. msg: "success"
  1005. }
  1006. }
  1007. // 维护服务器,踢掉所有玩家
  1008. async maintenance(ctx) {
  1009. let data = ctx.request.body
  1010. let url = await getServerList(data.serverId, 'default')
  1011. if (!url) {
  1012. ctx.body = {
  1013. code: 1,
  1014. msg: `区服id错误: serverId ${data.serverId}`
  1015. }
  1016. return
  1017. }
  1018. let param = JSON.stringify({
  1019. type: "kickAllUser"
  1020. })
  1021. // Msg.connect(url, Account);
  1022. let sendMsg = new Msg()
  1023. sendMsg.connect(url, Account);
  1024. new Promise((resolve) => {
  1025. setTimeout(async () => {
  1026. sendMsg.CG_TEST_PROTO("test", param)
  1027. }, 1000);
  1028. });
  1029. ctx.body = {
  1030. code: 0,
  1031. msg: "success"
  1032. }
  1033. }
  1034. async sendMail(ctx) {
  1035. let data = ctx.request.body
  1036. let url = await getServerList(data.serverId, 'default')
  1037. if (!url) {
  1038. ctx.body = {
  1039. code: 1,
  1040. msg: `区服id错误: serverId ${data.serverId}`
  1041. }
  1042. return
  1043. }
  1044. let param = JSON.stringify({
  1045. type: "sendMail",
  1046. mail: JSON.stringify({
  1047. uuid: data.uuid,
  1048. title: data.title,
  1049. content: data.content,
  1050. items: JSON.parse(data.items),
  1051. expire: data.expire
  1052. })
  1053. })
  1054. // Msg.connect(url, Account);
  1055. let sendMsg = new Msg()
  1056. sendMsg.connect(url, Account);
  1057. new Promise((resolve) => {
  1058. setTimeout(async () => {
  1059. sendMsg.CG_TEST_PROTO("test", param)
  1060. }, 1000);
  1061. });
  1062. ctx.body = {
  1063. code: 0,
  1064. msg: "success"
  1065. }
  1066. }
  1067. }
  1068. module.exports = new ApiController()