test 7 kuukautta sitten
vanhempi
sitoutus
14fe5ce8f8
3 muutettua tiedostoa jossa 61 lisäystä ja 40 poistoa
  1. 11 4
      src/comm/utils.ts
  2. 15 6
      src/modules/dj/controller/admin/open.ts
  3. 35 30
      src/modules/dj/service/channels/ach.ts

+ 11 - 4
src/comm/utils.ts

@@ -7,7 +7,6 @@ import * as NodeRSA from 'node-rsa';
 import * as crypto from 'crypto'
 import * as  speakeasy from 'speakeasy';
 import { BinaryToTextEncoding } from 'crypto';
-
 /**
  * 帮助类
  */
@@ -224,10 +223,18 @@ export class Utils {
     return hmac.sign(privateKey, 'base64');
   }
 
+  decryptByMD5WithRSA(data, privateKey) {
+    return crypto.privateDecrypt({
+      key: privateKey,
+      padding: crypto.constants.RSA_PKCS1_PADDING
+    }, data);
+  }
+
   verifyByMD5WithRSA(data, sign, publicKey) {
-    const key = new NodeRSA(publicKey);
-    key.setOptions({ signingScheme: 'pkcs1-sha256' });
-    return key.verify(data, sign);
+    console.log(data, sign, publicKey)
+    const hmac = crypto.createVerify('md5WithRSAEncryption');
+    hmac.update(data);
+    return hmac.verify(publicKey, sign, 'base64');
   }
 
   signBySha256(data, secretKey, format: BinaryToTextEncoding = 'hex') {

+ 15 - 6
src/modules/dj/controller/admin/open.ts

@@ -118,7 +118,7 @@ export class PayOpenController extends BaseController {
   @CoolTag(TagTypes.IGNORE_TOKEN)
   @Post('/notifyTest', { summary: '回调通知' })
   public async notifyTest(@Body(ALL) payload: any) {
-    this.logger.error('收到测试回调数据', JSON.stringify(payload));
+    this.logger.warn('收到测试回调数据', JSON.stringify(payload));
     console.log('收到测试回调数据', payload);
     this.ctx.body = 'success';
   }
@@ -127,7 +127,7 @@ export class PayOpenController extends BaseController {
   @Post('/SunCard/notifyOrder', { summary: '交易订单回调通知' })
   public async notifySunCardOrderGet(@Body(ALL) payload: any) {
     const headers = this.ctx.headers;
-    this.logger.error('SunCard收到交易订单回调数据', JSON.stringify(payload), headers);
+    this.logger.warn('SunCard收到交易订单回调数据', JSON.stringify(payload), headers);
     await this.orderService.handleNotify('SUN_CARD', payload, headers);
     this.ctx.body = {
       "is_success": "true",
@@ -139,7 +139,7 @@ export class PayOpenController extends BaseController {
   @Post('/hambit/bra/notifyOrder', { summary: '巴西交易订单回调通知' })
   public async hambitBraNotifyOrderGet(@Body(ALL) payload: any) {
     const headers = this.ctx.headers;
-    this.logger.error('hambit收到交易订单回调数据', JSON.stringify(payload), headers);
+    this.logger.warn('hambit收到交易订单回调数据', JSON.stringify(payload), headers);
     await this.orderService.handleNotify('HB_BRA', payload, headers);
     this.ctx.body = {
       "code": "200",
@@ -151,7 +151,7 @@ export class PayOpenController extends BaseController {
   @Post('/hambit/bra/notifyWithdraw', { summary: '巴西交易订单回调通知' })
   public async hambitBraNotifyWithdraw(@Body(ALL) payload: any) {
     const headers = this.ctx.headers;
-    this.logger.error('hambit收到代付订单回调数据', JSON.stringify(payload), headers);
+    this.logger.warn('hambit收到代付订单回调数据', JSON.stringify(payload), headers);
     await this.withdrawService.handleWithdrawNotify('HB_BRA', payload, headers);
     this.ctx.body = {
       "code": "200",
@@ -163,7 +163,7 @@ export class PayOpenController extends BaseController {
   @Post('/hambit/inr/notifyOrder', { summary: '印度交易订单回调通知' })
   public async hambitInrNotifyOrderGet(@Body(ALL) payload: any) {
     const headers = this.ctx.headers;
-    this.logger.error('hambit收到交易订单回调数据', JSON.stringify(payload), headers);
+    this.logger.warn('hambit收到交易订单回调数据', JSON.stringify(payload), headers);
     await this.orderService.handleNotify('HB_INR', payload, headers);
     this.ctx.body = {
       "code": "200",
@@ -175,7 +175,7 @@ export class PayOpenController extends BaseController {
   @Post('/hambit/inr/notifyWithdraw', { summary: '巴西交易订单回调通知' })
   public async hambitInrNotifyWithdraw(@Body(ALL) payload: any) {
     const headers = this.ctx.headers;
-    this.logger.error('hambit收到代付订单回调数据', JSON.stringify(payload), headers);
+    this.logger.warn('hambit收到代付订单回调数据', JSON.stringify(payload), headers);
     await this.withdrawService.handleWithdrawNotify('HB_INR', payload, headers);
     this.ctx.body = {
       "code": "200",
@@ -183,6 +183,15 @@ export class PayOpenController extends BaseController {
     };
   }
 
+  @CoolTag(TagTypes.IGNORE_TOKEN)
+  @Post('/ach/notifyOrder', { summary: 'ACH订单回调通知' })
+  public async achNotifyOrderGet(@Body(ALL) payload: any) {
+    const headers = this.ctx.headers;
+    this.logger.warn('ach收到交易订单回调数据', JSON.stringify(payload), headers);
+    await this.orderService.handleNotify('ACH', payload, headers);
+    this.ctx.body = 'success';
+  }
+
   @CoolTag(TagTypes.IGNORE_TOKEN)
   @Post('/kyc/level', { summary: 'kyc level 查询' })
   public async kycLevel(@Body(ALL) payload: any) {

+ 35 - 30
src/modules/dj/service/channels/ach.ts

@@ -9,8 +9,8 @@ import { ILogger } from '@midwayjs/logger';
 const HOST = "https://payment.alchemytech.cc";
 const MCH_ID = 'AC202299319';
 const KEY = 'r1t8hnmj86i1zt7ywbin';
-const PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIiPOgAEa8cMN08+sGKsu9lcm61aZmIXh/Yqfc4S2P234uN8MjAhzINVmYDDXSc0oSQkmqwOoUaf3uRDUUTkAVYzNcYg/IPuStsgEtbinsZSFJ5/+zhW82qd/AOsMxgcN3Jm5sNZa87Yu+E+tEUOXMRmxu4PTBA2lyBjN3D8sGsDAgMBAAECgYBEDXg+dPWO4rAXfiqhaepNJmDwUUoPXSGk08UQ8oSPX9miOwy5vsYvtvNB31nnRUt+ev1XfAzz6IzHnSJ9XdCp/Xv+BjGmD5JK3Li0wcpBuVCcd4GbwMto1+TTw3AXa9QXAnwWTUwHWPBCQAhhPUGxp5BdJ6ut2qX9h3GLqcZISQJBAMAW5M3w8YCzhRBbAJkSIg8fhQA+A9mdRw6gS0rMZiKHEudh7mvoFXWEQsy04OSrKvfQ1HBR+zkuG1+mcoTDTtkCQQC1/pnyKxumd9d/aF/5RJAiwSHinN2O16cROXYGoAndWVQJp7rvtu2AdTFC3S2eL3pQEN/g9ljGNorfKfzw/dc7AkAeGfhVBXLy9i7d90TKt/q6X/gZp5421dyywA/Mcud2dbBSrhgMtNvYBJfrOFUdwG0FVKZVy6MQvNbxUEYV4/1RAkEAjizuGw+uNCgfQ7tIbrUvXNdAH4aoVzUFoSEgoSBZVIC6dCiCk0520Am9iBy9zHwOs4nbPCV3SLHHX3uvzJyhjQJAUurBjyMEzomk8yjkcqIu4LCHKWEjsInJPeWTJ/uNEXwEqaS6wXpcJdSNWehFFr1kgSxsldod2r43XuvwiyC8Dw==\n" + "-----END RSA PRIVATE KEY-----"
-const PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUgjXpKpG6+o/uoJqRdpVaQae5IKgtXtEqoZXNQnAFk+wk/toyDxPmQNn5+Uj2pdwFBOzKTuvfKDVZHnLTgRz6mHfKrNboBwqHCj4WCzDj02P30QArr2KbuY+kfRdD8ckuFUlmMDXCFcqa+XZaCiZAcepDQ/RH7l6mL7A4/FdgMwIDAQAB';
+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"
+const PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCv6trrrn/rOKXdoJFQMoR5KaINaOES+fg5tmTnuYuzvxCyib4//SSKzTtWmzTbhvINp7wZzniebootavN0MvQuGmnstVI6mHd4lbqbjvF35q/97B03nOkfF9B2Z7kP37FPLkRGBEBVHwRXGbYjc9k6l34yVzFwHk6V3Ogmyji3twIDAQAB" + "\n-----END PUBLIC KEY-----";
 const PAY_URL = '/nh-gateway/card/payment';
 const QUERY_URL = '/nh-gateway/card/query'
 // const BALANCE_URL = '/api/v3/bra/query/balance'
@@ -145,12 +145,11 @@ export class AchService extends BaseService {
 
   async query(payload) {
     const param: any = {
-      merchantNo: 'AC202299319',
-      timeStamp: 1735185420342,
-      merchantOrderNo: 'DS202412251203055901',
+      merchantNo: MCH_ID,
+      timeStamp: +moment(),
+      merchantOrderNo: payload.orderNo,
     };
     const signStr = this.utils.signSort(param);
-    console.log(param, signStr)
     param.sign = this.utils.signByMD5WithRSA(signStr, PRIVATE_KEY);
     const res = await this.httpService.postForm(HOST + QUERY_URL, param);
     this.logger.info('查询接口返回', param, JSON.stringify(res.data));
@@ -173,30 +172,36 @@ export class AchService extends BaseService {
     }
   }
 
-  // async handleOrderNotify(payload, headers) {
-  //   const sign = headers['sign'];
-  //   const timestamp = headers['timestamp'];
-  //   const nonce = headers['nonce'];
-  //   const signStr = this.utils.signSort({
-  //     timestamp,
-  //     nonce,
-  //     access_key: ACCESS_KEY,
-  //     ...payload
-  //   });
-  //   const validSign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
-  //   if (sign !== validSign) {
-  //     throw new Error('sign error');
-  //   }
-  //   if (+payload.orderStatusCode !== 2) {
-  //     throw new Error('order no success');
-  //   }
-  //   return {
-  //     date: new Date(),
-  //     orderNo: payload.externalOrderId,
-  //     traceNo: payload.orderId,
-  //     status: 1,
-  //   };
-  // }
+  async handleOrderNotify(payload, headers) {
+    const { data = "" } = payload;
+    const jsonData = JSON.parse(data);
+    const signData = {
+      merchantNo: jsonData.merchantNo,
+      merchantOrderNo: jsonData.merchantOrderNo,
+      orderNo: jsonData.orderNo,
+      currency: jsonData.currency,
+      orderAmount: jsonData.orderAmount,
+      orderFee: jsonData.orderFee,
+      payType: jsonData.payType,
+      payModel: jsonData.payModel,
+      orderStatus: jsonData.orderStatus,
+    }
+    const signStr = this.utils.signSort(signData);
+    console.log(this.utils.decryptByMD5WithRSA(jsonData.sign, PRIVATE_KEY))
+    const valid = this.utils.verifyByMD5WithRSA(signStr, jsonData.sign, PUBLIC_KEY);
+    if (!valid) {
+      throw new Error('sign error');
+    }
+    if (payload.orderStatus !== 'SUCCESS' && payload.orderStatus !== 'FAIL' && payload.orderStatus !== 'CANCEL') {
+      throw new Error('order no result');
+    }
+    return {
+      date: new Date(),
+      orderNo: payload.merchantOrderNo,
+      traceNo: payload.orderNo,
+      status: payload.orderStatus === 'SUCCESS' ? 1 : 3,
+    };
+  }
 
   // async queryBalance() {
   //   const param = {};