ApiController.ts 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. import Msg from '../msg'; // 确保路径是正确的
  2. const CryptoJS = require("crypto-js");
  3. const AppKey = "57afbdc608db9aa423e1b15b321d7de0"
  4. const Account = "H1EqhbpA80jt0Jw6Q3T2"//ws请求密钥
  5. const Order = require('../model/OrderModel')
  6. const Server = require('../model/ServerModel')
  7. const Version = require('../model/VersionModel')
  8. const logger = require('../log')
  9. const axios = require('axios');
  10. const ClientId = "849706610247-rok24bfm4sapiggunbuirugf2n31c3ho.apps.googleusercontent.com"
  11. const ClientSecret = "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"
  12. const RefreshToken = '1//06IooeZBqGqUsCgYIARAAGAYSNwF-L9Ir7cRRL3vBcSsZcQunM2NF6H6rwBjE-WJ_sLIiVyvVCE1iWj4QHOUDGUE0FlA05d8LtPU'
  13. const PackageName = "com.ultimategame.sso"
  14. const ProductId = "com.ultimategame.sso.aos."
  15. //根据区服id获取地址
  16. const getServerList = async (serverId, tag) => {
  17. const servers = (await Server.getServerList(tag))
  18. for (let i = 0; i < servers.length; i++) {
  19. if (servers[i].id == serverId) {
  20. return 'ws://' + servers[i].ip + ':' + servers[i].port
  21. }
  22. }
  23. }
  24. const callPay = async (ctx) => {
  25. let ret = {
  26. code: 0,
  27. msg: '发货失败'
  28. }
  29. const redisClient = ctx.redis.client;
  30. let access_token = await redisClient.get('access_token');
  31. if (!access_token) {
  32. console.log('请求api获取token')
  33. const apiData = {
  34. "grant_type": "refresh_token",
  35. "client_id": ClientId,
  36. "client_secret": ClientSecret,
  37. "refresh_token": RefreshToken
  38. }
  39. const response = await axios.post('https://accounts.google.com/o/oauth2/token', apiData, {
  40. headers: {
  41. 'Content-Type': 'application/x-www-form-urlencoded'
  42. }
  43. });
  44. logger.info("token params:", { "data": response.data, "params": apiData })
  45. if (!response.data.access_token) {
  46. return ret
  47. }
  48. access_token = response.data.access_token
  49. await redisClient.set('access_token', response.data.access_token);
  50. await redisClient.expire('access_token', 1800);
  51. }
  52. if (!access_token) {
  53. return ret;
  54. }
  55. let data = ctx.request.body
  56. let orderId = data.orderId
  57. let googleToken = data.purchaseToken
  58. let out_trade_no = ''
  59. logger.info("pay callback params:", { "url": ctx.href, "params": data })
  60. const orderInfo = (await Order.getOrder(orderId))[0]
  61. if (!orderInfo) {
  62. logger.info(`订单${orderId}不存在`)
  63. ret.msg = `订单${orderId}不存在`
  64. return ret
  65. }
  66. if (orderInfo.status == 2) {
  67. logger.info(`订单${orderId}已经重复发货`)
  68. ret.code = 1
  69. ret.msg = `订单${orderId}已经重复发货`
  70. return ret
  71. }
  72. let url = await getServerList(orderInfo.server_id, 'default')
  73. if (!url) {
  74. logger.info(`区服id错误: serverId ${orderInfo.server_id}`)
  75. ret.msg = `区服id错误: serverId ${orderInfo.server_id}`
  76. return ret
  77. }
  78. const productId = ProductId + orderInfo.product_id
  79. let apiUrl = `https://androidpublisher.googleapis.com/androidpublisher/v3/applications/${PackageName}/purchases/products/${productId}/tokens/${googleToken}?access_token=${access_token}`
  80. let maxRetries = 5;
  81. let currentRetry = 0;
  82. let isCheck = false;
  83. // 使用 while 循环进行重试
  84. while (currentRetry < maxRetries) {
  85. try {
  86. // // 尝试执行的操作
  87. const googleRes = await axios.get(apiUrl, {
  88. headers: {
  89. 'Content-Type': 'application/x-www-form-urlencoded'
  90. }
  91. })
  92. console.log(googleRes.data)
  93. // 如果操作成功,退出循环
  94. if (googleRes.data.purchaseState == 0) {
  95. out_trade_no = googleRes.data.orderId
  96. isCheck = true
  97. break;
  98. }
  99. } catch (error) {
  100. // 如果操作失败,记录错误并继续尝试
  101. console.log(error)
  102. }
  103. currentRetry++;
  104. }
  105. if (!isCheck) {
  106. return ret;
  107. }
  108. Msg.connect(url, Account);
  109. let orgMemId = orderInfo.uid
  110. let orgOderId = orderId
  111. let orgProductId = orderInfo.product_id
  112. let orgProductPrice = orderInfo.amount
  113. // 在适当的时机,调用 CG_ASK_LOGIN 方法
  114. let params = `{"account":"${orgMemId}","order":"${orgOderId}","id":${orgProductId},"cnt":100,"money":${orgProductPrice}}`
  115. return new Promise((resolve) => {
  116. setTimeout(async () => {
  117. const send_res = Msg.CG_ASK_LOGIN(Account, 0, "", 'cn', 'CN', ctx.request.ip, params);
  118. if (!send_res) {
  119. resolve(ret);
  120. return;
  121. }
  122. const update_time = formatDate(new Date())
  123. const res = await Order.updateOrderStats(
  124. orderId,
  125. 2,
  126. out_trade_no,
  127. update_time
  128. );
  129. if (res.affectedRows <= 0) {
  130. logger.info(`订单${orderId} 发货失败`)
  131. ret.msg = '发货失败'
  132. resolve(ret);
  133. return;
  134. }
  135. ret.code = 1
  136. ret.msg = '发货成功'
  137. resolve(ret);
  138. }, 2000);
  139. });
  140. }
  141. const compareVersions = (v1: string, v2: string) => {
  142. const parts1 = v1.split('.').map(Number);
  143. const parts2 = v2.split('.').map(Number);
  144. for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
  145. const num1 = parts1[i] || 0;
  146. const num2 = parts2[i] || 0;
  147. if (num1 > num2) return 1;
  148. if (num1 < num2) return -1;
  149. }
  150. return 0;
  151. }
  152. const checkVersion = async (ctx) => {
  153. let ret = {
  154. code: 0,
  155. msg: '无需更新',
  156. url: '',
  157. }
  158. let data = ctx.request.body
  159. let version = data.version
  160. let tag = data.tag || 'default'
  161. logger.info("checkVersion params:", { "url": ctx.href, "params": data })
  162. const versionInfo = (await Version.getGameVersion(tag))[0]
  163. if (!versionInfo) {
  164. return ret
  165. }
  166. if (compareVersions(versionInfo.version, version) === 1) {
  167. if (versionInfo.download_url) {
  168. ret.code = 1
  169. ret.msg = '需要更新'
  170. ret.url = versionInfo.download_url
  171. }
  172. }
  173. return ret
  174. }
  175. //验证账号
  176. const checkUserToken = async (ctx) => {
  177. let data = ctx.request.body
  178. //签名参数
  179. let signData = Object.keys(data).filter(key => key !== 'sign');
  180. let signStr = signData.map(key => `${data[key]}`).join('');
  181. signStr += AppKey
  182. let newSign = CryptoJS.MD5(signStr).toString();
  183. console.log("signStr:", signStr)
  184. console.log("newSign:", newSign)
  185. if (data.sign != newSign) {
  186. console.log("签名错误:", signStr, newSign, data.sign)
  187. return false
  188. }
  189. return data.sign
  190. }
  191. const generateOrderNumber = () => {
  192. const date = new Date();
  193. const year = date.getFullYear();
  194. const month = (date.getMonth() + 1).toString().padStart(2, '0');
  195. const day = date.getDate().toString().padStart(2, '0');
  196. const hours = date.getHours().toString().padStart(2, '0');
  197. const minutes = date.getMinutes().toString().padStart(2, '0');
  198. const seconds = date.getSeconds().toString().padStart(2, '0');
  199. const dateString = `${year}${month}${day}${hours}${minutes}${seconds}`;
  200. const randomString1 = Math.floor(Math.random() * 1090000000800)
  201. .toString()
  202. .slice(0, 4);
  203. const randomString2 = Math.floor(Math.random() * 1090000000800)
  204. .toString()
  205. .slice(0, 4);
  206. return "CP" + dateString + randomString1 + randomString2;
  207. }
  208. const formatDate = (date: Date) => {
  209. const year = date.getFullYear();
  210. const month = (date.getMonth() + 1).toString().padStart(2, '0');
  211. const day = date.getDate().toString().padStart(2, '0');
  212. return `${year}-${month}-${day}`;
  213. }
  214. class ApiController {
  215. async createOrder(ctx) {
  216. let {
  217. uid,
  218. level,
  219. amount,
  220. role_id,
  221. role_name,
  222. product_id,
  223. server_id
  224. } = ctx.request.body
  225. logger.info("create params:", { "params": ctx })
  226. logger.info("create params:", { "params": ctx.request.body })
  227. if (!product_id || !server_id || !role_name || !role_id || !amount || !uid) {
  228. ctx.body = { code: -1, message: '参数错误,创建订单失败!!', data: '' }
  229. return
  230. }
  231. const orderId = generateOrderNumber(); // 生成一个长度为8的订单号
  232. const create_time = formatDate(new Date())
  233. const res = await Order.createOrder(
  234. orderId,
  235. uid,
  236. level,
  237. amount,
  238. role_id,
  239. role_name,
  240. product_id,
  241. server_id,
  242. create_time
  243. );
  244. if (res.affectedRows > 0) {
  245. ctx.body = { code: 0, message: '创建订单成功', data: orderId }
  246. } else {
  247. ctx.body = { code: -1, message: '创建订单失败', data: '' }
  248. }
  249. logger.info("创建订单返回结果:", { "params": ctx.body })
  250. }
  251. async checkUserToken(ctx) {
  252. const result = await checkUserToken(ctx);
  253. let data = { "status": false, "sign": "" }
  254. if (result) {
  255. data.status = true
  256. data.sign = result
  257. }
  258. ctx.body = data
  259. }
  260. async callPay(ctx) {
  261. var result = await callPay(ctx)
  262. console.log('发货结果', result)
  263. ctx.body = result
  264. }
  265. async checkVersion(ctx) {
  266. var result = await checkVersion(ctx)
  267. console.log('校验版本', result)
  268. ctx.body = result
  269. }
  270. async getServerList(ctx) {
  271. let tag = ctx.query.tag || 'default'
  272. const servers = (await Server.getServerList(tag))
  273. ctx.body = servers
  274. }
  275. }
  276. module.exports = new ApiController()