app.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. const dataJson = {"meta":{"success":true,"code":"0000","message":"Request Success"},"data":{"merchantNo":"AC202299319","merchantOrderNo":"DS202412311005240317","orderNo":"R08OC0241231100525384624557803","currency":"JPY","payType":"JAPAN_PAY","orderAmount":10000,"paidAmount":null,"orderFee":700,"payModel":"BankTransfer","orderStatus":"PENDING","webUrl":null,"page":null,"orderTime":1735610725000,"finishTime":0,"sign":"V0EZCULoPBG7q8CuWxSnAkTnigjPbX49IquVzqH8TZ2Kp+SYJmXAmAWPLKPWWTQdvAw99T3PrkEMmutKfCE2zEay5uKhtHU8BY4T0phLr8cU3G9MTWNjp3AJ/dtJ6nh19/L20vis5anvj0aC4ShnEcIzfVeWtWszT+meu7LC4Js52C9vmGGKtPWUUbD6zV/+3YYnNxf/BIEBLOewWIaHccne6E37wbzjbHWczAPecka/E7KOGPyG2PPa67Y5ixsGUjhSD6RHHjbXKJatD8+vTa4BpwieQ4FZTF1dF2oCWJjVOLiB4ZSwMs4vRf9bb0GhWmJuf1N45eWWJkMRJ+392A==","remark":"","errorMessage":null,"descriptor":null},"sign":"589092dbe5aca882cfcc409d1f868d0e"}
  2. const express = require('express');
  3. const bodyParser = require('body-parser');
  4. const fs = require('fs');
  5. const path = require('path');
  6. const { createVerify } = require('crypto');
  7. const logger = console;
  8. // 创建Express应用
  9. const app = express();
  10. app.use(bodyParser.urlencoded({ extended: true }));
  11. app.use(bodyParser.json());
  12. // 加载配置
  13. const configPath = path.join(__dirname, '../config.ini');
  14. const config = fs.existsSync(configPath) ? fs.readFileSync(configPath, 'utf8') : null;
  15. // 模拟解析配置文件
  16. const PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n" + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK/q2uuuf+s4pd2gkVAyhHkpog1o4RL5+Dm2ZOe5i7O/ELKJvj/9JIrNO1abNNuG8g2nvBnOeJ5uii1q83Qy9C4aaey1UjqYd3iVupuO8Xfmr/3sHTec6R8X0HZnuQ/fsU8uREYEQFUfBFcZtiNz2TqXfjJXMXAeTpXc6CbKOLe3AgMBAAECgYAYDVvWSnsJ7apb9Ya4uNd8+3DBNZxEbHIAbgw41Jkhv9doGcYt2I4k/i+FRV5CP56buFnTC3RZcRKqaAuWURsqcnDG8ufFIhoSEiD11FcFrXanFdixfj9gijuPiTE4w9f07eDVEfdQjFMSO8tYDbsMUoaMPUTOoreqyy86uW0G0QJBAN5zaUsxjgtJhqO3OsoHXpu+67bsM2ounuoHWq7KehiVeb9ykrS6quZ1+r5+0SIMEFkKZKbpwfIG+Hi9NII85/ECQQDKctaP1WQzuLQvm97lfQEfgY/JWL9RZuWriGd7fDT7Nrl0FTK5O9q22HvJdwIQktaTOQca28KzHucIxa7ouYInAkB1KehteF5OR52ooRtPyW3lLjvMjr/Nz1xX+yOiKHcCd8g2M8xdcGwPEljM+NKB0kTSAQ1edIR4S3+XaGA9sIKhAkEAsfVaqJry9wgw0/zXZbGJsDFKvLpXiu3BjBReqszXIdDMGr+bk/qKWtpXjhQf64O4PTgPB8wQDTZn7m0fQJH5VwJBAIDnGXiaoMRammmmOl6sYwar8APUMhRkCNqxzwiEokmwRsrR0GKuKtLKpRg/jNAAQbj2ajVihhgR7F3/04kc/jE=\n" + "-----END RSA PRIVATE KEY-----\n"; // 从配置文件中获取私钥
  17. // 创建排序后的数据字符串
  18. function createSortedDataString(data) {
  19. const validKeys = ['merchantNo', 'merchantOrderNo', 'orderNo', 'currency', 'orderAmount',
  20. 'orderFee', 'payModel', 'orderStatus', 'payType'];
  21. const sortedData = Object.keys(data)
  22. .filter(key => validKeys.includes(key))
  23. .sort()
  24. .map(key => `${key}=${data[key]}`)
  25. .join('&');
  26. return sortedData;
  27. }
  28. // 验证Webhook
  29. function verifyWebhook(data) {
  30. const sign = data.sign;
  31. if (!sign) {
  32. logger.warn("No signature found in the data");
  33. return { isValid: false, message: "No signature found" };
  34. }
  35. delete data.sign;
  36. const signStr = createSortedDataString(data);
  37. logger.info(`String to be signed: ${signStr}`);
  38. // Verify the signature using RSA
  39. const verify = createVerify('SHA256');
  40. verify.update(signStr);
  41. verify.end();
  42. try {
  43. const isVerified = verify.verify(PRIVATE_KEY, sign, 'base64');
  44. if (isVerified) {
  45. logger.info("Verification passed");
  46. return { isValid: true, message: "Verification passed" };
  47. } else {
  48. logger.warn("Verification failed");
  49. return { isValid: false, message: "Verification failed" };
  50. }
  51. } catch (error) {
  52. logger.error(`Verification error: ${error.message}`);
  53. return { isValid: false, message: `Verification error: ${error.message}` };
  54. }
  55. }
  56. // 处理Webhook请求
  57. app.post('/webhook', (req, res) => {
  58. logger.info("Received a webhook POST request");
  59. const data = req.body.data;
  60. if (!data) {
  61. logger.error("Invalid data format received");
  62. return res.status(400).json({ status: "error", message: "Invalid data format" });
  63. }
  64. logger.info(`Received data: ${JSON.stringify(data, null, 2)}`);
  65. const { isValid, message } = verifyWebhook(data);
  66. if (isValid) {
  67. logger.info("Webhook verified successfully");
  68. res.status(200).json({ status: "success", message });
  69. } else {
  70. logger.warn(`Webhook verification failed: ${message}`);
  71. res.status(400).json({ status: "error", message });
  72. }
  73. });
  74. // 启动服务器
  75. const PORT = 5000;
  76. app.listen(PORT, () => {
  77. logger.info(`Server is running on http://127.0.0.1:${PORT}`);
  78. });