browser-real-pay.mjs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #!/usr/bin/env node
  2. import { chromium } from 'playwright';
  3. const API_BASE = 'https://server.fmode.cn';
  4. const PARSE_BASE = API_BASE + '/parse/functions';
  5. const APP_ID = 'ncloudmaster';
  6. const PAY_COMPANY = '1AiWpTEDH9';
  7. function getArg(name, fallback = '') {
  8. const prefix = `--${name}=`;
  9. const match = process.argv.find(arg => arg.startsWith(prefix));
  10. return match ? match.slice(prefix.length) : fallback;
  11. }
  12. function makeTradeNo(user) {
  13. const now = new Date();
  14. const pad = value => String(value).padStart(2, '0');
  15. return 'Cbr' + user.replace(/[^a-zA-Z0-9]/g, '').slice(0, 8) +
  16. now.getFullYear() +
  17. pad(now.getMonth() + 1) +
  18. pad(now.getDate()) +
  19. pad(now.getHours()) +
  20. pad(now.getMinutes()) +
  21. pad(now.getSeconds()) +
  22. String(now.getMilliseconds()).padStart(3, '0');
  23. }
  24. async function main() {
  25. const user = getArg('user', '2luFP8J1H1');
  26. const authid = getArg('authid', 'd1DOPlTNCb');
  27. const fcompany = getArg('fcompany', PAY_COMPANY);
  28. const apigid = getArg('apigid', 'G0vmsUI44d');
  29. // fun_id 必须是充值云函数 apigRechargeOnPay 的 objectId;voc-e-commerce 是 APIG 的 path,传它会导致回调找不到云函数、不入账
  30. const funId = getArg('fun_id', 'HOkkX72PMF');
  31. const price = Number(getArg('price', '0.01'));
  32. const count = Number(getArg('count', '1'));
  33. const oldCount = Number(getArg('oldCount', '1003'));
  34. const tradeNo = getArg('trade', makeTradeNo(user));
  35. const bodyText = `国内电商数据中台 接口充值(${count} 次)`;
  36. const browser = await chromium.launch({ headless: true });
  37. const page = await browser.newPage();
  38. await page.goto('https://app.fmode.cn/dev/apig-pay/', { waitUntil: 'domcontentloaded' });
  39. const result = await page.evaluate(async ({ API_BASE, PARSE_BASE, APP_ID, PAY_COMPANY, user, authid, fcompany, apigid, funId, price, count, oldCount, tradeNo, bodyText }) => {
  40. async function postJSON(url, body) {
  41. const resp = await fetch(url, {
  42. method: 'POST',
  43. headers: { 'Content-Type': 'application/json' },
  44. body: JSON.stringify(body)
  45. });
  46. const text = await resp.text();
  47. let data;
  48. try {
  49. data = JSON.parse(text);
  50. } catch {
  51. data = text;
  52. }
  53. return { ok: resp.ok, status: resp.status, data };
  54. }
  55. const order = await postJSON(API_BASE + '/api/apig/created-apigorder', {
  56. type: 'wxpay',
  57. user,
  58. authid,
  59. fcompany,
  60. apigid,
  61. oldCount,
  62. params: {
  63. out_trade_no: tradeNo,
  64. total_fee: price,
  65. body: bodyText
  66. },
  67. count
  68. });
  69. const pay = await postJSON(PARSE_BASE + '/pay_code2', {
  70. _ApplicationId: APP_ID,
  71. company: PAY_COMPANY,
  72. out_trade_no: tradeNo,
  73. total_fee: price,
  74. body: bodyText,
  75. fun_id: funId
  76. });
  77. const payResult = pay.data?.result || {};
  78. const nonceStr = Array.isArray(payResult.nonce_str) ? payResult.nonce_str[0] : payResult.nonce_str;
  79. const status = nonceStr
  80. ? await postJSON(PARSE_BASE + '/order_status2', {
  81. _ApplicationId: APP_ID,
  82. out_trade_no: tradeNo,
  83. nonce_str: nonceStr,
  84. company: PAY_COMPANY
  85. })
  86. : null;
  87. return { tradeNo, order, pay, status };
  88. }, { API_BASE, PARSE_BASE, APP_ID, PAY_COMPANY, user, authid, fcompany, apigid, funId, price, count, oldCount, tradeNo, bodyText });
  89. await browser.close();
  90. console.log(JSON.stringify(result, null, 2));
  91. }
  92. main().catch(err => {
  93. console.error('[failed]', err.message);
  94. process.exit(1);
  95. });