Partner.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import crypto from "crypto";
  2. import axios from "axios";
  3. import path from "node:path";
  4. import { fileURLToPath } from "node:url";
  5. import { getData } from "../libs/cache.js";
  6. import Logs from "../libs/logs.js";
  7. const __filename = fileURLToPath(import.meta.url);
  8. const __dirname = path.dirname(__filename);
  9. const IS_DEV = process.env.NODE_ENV == 'development';
  10. const IS_BID = process.env.PPAI_RUN_MODE == 'BID';
  11. const PARTNER_DATA_FILE = path.join(__dirname, '../data/partner.json');
  12. /**
  13. * Partner API environment variables
  14. */
  15. const PARTNER_API_BASE = 'https://dev.api.ppai.win/api/p/gate';
  16. const { PARTNER_APP_ID, PARTNER_APP_KEY } = process.env;
  17. const PARTNER_DATA = {};
  18. /**
  19. * QBoss API environment variables
  20. */
  21. const QBOSS_API_BASE = IS_DEV ? 'https://cb.long.bid/api' : 'http://172.27.74.243/api';
  22. /**
  23. * axios instance
  24. */
  25. const axiosInstance = axios.create({
  26. proxy: false,
  27. });
  28. /**
  29. *
  30. */
  31. /**
  32. * 加载本地数据
  33. */
  34. const loadLocalData = async () => {
  35. const data = await getData(PARTNER_DATA_FILE);
  36. Object.assign(PARTNER_DATA, data);
  37. }
  38. loadLocalData().catch(error => {
  39. Logs.out('not load partner data', error.message);
  40. });
  41. /**
  42. * 生成SHA256
  43. */
  44. const generateSHA256 = (message) => {
  45. return crypto.createHash('sha256').update(message).digest('hex');
  46. }
  47. /**
  48. * 生成随机 nonce
  49. */
  50. const generateNonce = () => {
  51. return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
  52. }
  53. /**
  54. * 生成签名
  55. */
  56. const generateSignature = (appKey, action, timestamp, nonce) => {
  57. return generateSHA256(`${appKey}${action}${timestamp}${nonce}`);
  58. }
  59. /**
  60. * 获取时间戳 秒级
  61. */
  62. const getTimestamp = () => {
  63. return Math.floor(Date.now() / 1000);
  64. }
  65. /**
  66. * 时间窗口校验
  67. */
  68. const isTimestampValid = (timestamp, window=300) => {
  69. const now = getTimestamp();
  70. return Math.abs(now - timestamp) <= window;
  71. }
  72. /**
  73. * 请求Partner数据接口
  74. */
  75. export const requestData = async (action, data={}) => {
  76. const timestamp = getTimestamp();
  77. const nonce = generateNonce();
  78. const sign = generateSignature(PARTNER_APP_KEY, action, timestamp, nonce);
  79. const appid = PARTNER_APP_ID;
  80. const requestData = { action, appid, nonce, sign, timestamp };
  81. if (Object.keys(data).length > 0) {
  82. requestData.params = data;
  83. }
  84. return axiosInstance.post(PARTNER_API_BASE, requestData).then(res => res.data);
  85. }
  86. /**
  87. * 更新策略
  88. * @param {*} solutions
  89. * @returns
  90. */
  91. export const updateSolutions = async (solutions) => {
  92. if (process.env.NODE_ENV == 'development') {
  93. return Promise.resolve({ message: 'development mode' });
  94. }
  95. return requestData('opps.soccer', solutions);
  96. }
  97. /**
  98. * 获取关联比赛
  99. * @returns
  100. */
  101. export const getSoccerGames = async () => {
  102. return requestData('game.soccer');
  103. }
  104. /**
  105. * 获取QBoss赔率数据
  106. * le listEvents
  107. * lo listOdds
  108. * lp listPC
  109. * hb hideBase
  110. * hh hideHalf
  111. * @returns
  112. */
  113. export const getObossOdds = async () => {
  114. return axiosInstance.get(`${QBOSS_API_BASE}/pstery/get_games_relation`, {
  115. params: { lo: true, lp: true, hb: true, hh: true, ho: IS_BID },
  116. }).then(res => res.data);
  117. }
  118. /**
  119. * 接收Partner数据
  120. */
  121. export const receivePartnerData = async (data) => {
  122. const { action, appid, nonce, sign, timestamp, params } = data;
  123. if (!isTimestampValid(timestamp)) {
  124. return Promise.reject(new Error('timestamp invalid'));
  125. }
  126. const partnerData = PARTNER_DATA[appid];
  127. if (!partnerData) {
  128. return Promise.reject(new Error('appid invalid'));
  129. }
  130. const newSign = generateSignature(partnerData.appkey, action, timestamp, nonce);
  131. if (newSign !== sign) {
  132. return Promise.reject(new Error('sign invalid'));
  133. }
  134. return Promise.resolve({ action, params });
  135. }
  136. export default { updateSolutions, getSoccerGames, getObossOdds, receivePartnerData };