OrderPayment.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. const crypto = require('crypto')
  2. const config = require('../config.json')
  3. const { normalizePayBaseUrl } = require('./PaymentClient')
  4. const { getRuntimeConfig } = require('./RuntimeConfig')
  5. const DEFAULT_PAYMENT_METHODS = [
  6. { type: 'alipay', name: '支付宝' },
  7. { type: 'wxpay', name: '微信支付' }
  8. ]
  9. async function getPaymentMethods() {
  10. const paymentConfig = await getRuntimeConfig('pay', {
  11. required: false,
  12. defaultValue: { methods: DEFAULT_PAYMENT_METHODS }
  13. })
  14. const methods = paymentConfig?.methods
  15. if (!Array.isArray(methods)) {
  16. return DEFAULT_PAYMENT_METHODS
  17. }
  18. return methods
  19. .filter(method => method && method.enabled !== false && typeof method.type === 'string' && method.type.trim())
  20. .map(method => ({
  21. type: method.type.trim(),
  22. name: String(method.name || method.type).trim()
  23. }))
  24. }
  25. async function isSupportedPaymentMethod(payType) {
  26. return (await getPaymentMethods()).some(method => method.type === payType)
  27. }
  28. function generatePaymentSign(params, key) {
  29. const query = Object.keys(params)
  30. .sort()
  31. .map(keyName => `${keyName}=${params[keyName]}`)
  32. .join('&') + key
  33. return crypto.createHash('md5').update(query, 'utf8').digest('hex')
  34. }
  35. async function buildPaymentSession({ orderId, gatewayOrderNo = orderId, payType, goodsName, price, deviceType }) {
  36. const paymentConfig = await getRuntimeConfig('pay')
  37. if (!paymentConfig.pid || !paymentConfig.url || !paymentConfig.key || !paymentConfig.return_url) {
  38. throw new Error('支付配置错误,请联系管理员')
  39. }
  40. if (!await isSupportedPaymentMethod(payType)) {
  41. throw new Error('不支持的支付方式')
  42. }
  43. const isUniapp = deviceType === 'RunForge Uniapp Client'
  44. const returnBaseUrl = isUniapp ? paymentConfig.uni_return_url : paymentConfig.return_url
  45. if (!returnBaseUrl) {
  46. throw new Error('支付返回地址配置错误,请联系管理员')
  47. }
  48. const payData = {
  49. pid: paymentConfig.pid,
  50. type: payType,
  51. out_trade_no: gatewayOrderNo,
  52. notify_url: `${config.url}/Order/CallBack`,
  53. return_url: `${returnBaseUrl}${orderId}`,
  54. name: goodsName,
  55. money: String(price)
  56. }
  57. payData.sign = generatePaymentSign(payData, paymentConfig.key)
  58. payData.sign_type = 'MD5'
  59. return {
  60. payUrl: `${normalizePayBaseUrl(paymentConfig.url)}/submit.php`,
  61. payData,
  62. // 客户端收到后应以 payData 创建并自动提交一个 POST 表单,进入支付网关。
  63. autoSubmit: true
  64. }
  65. }
  66. module.exports = {
  67. buildPaymentSession,
  68. getPaymentMethods,
  69. isSupportedPaymentMethod
  70. }