Browse Source

♻️ refactor(payment): 优化支付回调处理流程

- 调整微信支付SDK初始化时机,先使用默认租户ID进行初始化以验证签名和解密
- 从解密后的回调数据中获取商户订单号,而非原始回调数据
- 重构日志输出格式,移除冗余的租户ID前缀
- 移动支付记录查询逻辑至签名验证和解密之后

✅ test(payment): 更新集成测试依赖

- 添加SystemConfigMt实体到测试数据库设置中,确保测试环境完整性
yourname 1 tháng trước cách đây
mục cha
commit
6e12c0fa57

+ 39 - 34
packages/mini-payment-mt/src/services/payment.mt.service.ts

@@ -211,35 +211,13 @@ export class PaymentMtService extends GenericCrudService<PaymentMtEntity> {
       rawBody
     });
 
-    // 首先从回调数据中获取商户订单号
-    const outTradeNo = callbackData.out_trade_no;
-    if (!outTradeNo) {
-      console.debug('回调数据中缺少商户订单号,回调数据:', callbackData);
-      throw new Error('回调数据中缺少商户订单号');
-    }
-
-    console.debug(`开始处理支付回调,商户订单号: ${outTradeNo}`);
-
-    // 从数据库中查找支付记录以获取租户ID
-    const paymentRepository = this.dataSource.getRepository(PaymentMtEntity);
-    const payment = await paymentRepository.findOne({
-      where: { outTradeNo }
-    });
-
-    if (!payment) {
-      console.debug(`支付记录不存在,商户订单号: ${outTradeNo}`);
-      throw new Error('支付记录不存在');
-    }
-
-    console.debug(`[租户${payment.tenantId}] 找到支付记录,外部订单ID: ${payment.externalOrderId}, 当前支付状态: ${payment.paymentStatus}`);
-
-    // 重新初始化微信支付SDK
-    console.debug(`[租户${payment.tenantId}] 开始初始化微信支付SDK`);
-    await this.initializeWxPay(payment.tenantId);
-    console.debug(`[租户${payment.tenantId}] 微信支付SDK初始化完成`);
+    // 重新初始化微信支付SDK(先初始化以进行签名验证和解密)
+    console.debug(`开始初始化微信支付SDK`);
+    await this.initializeWxPay(1); // 先使用默认租户ID进行初始化
+    console.debug(`微信支付SDK初始化完成`);
 
     // 验证回调签名
-    console.debug(`[租户${payment.tenantId}] 开始验证回调签名`);
+    console.debug(`开始验证回调签名`);
     const isValid = await this.wxPay.verifySign({
       timestamp: headers['wechatpay-timestamp'],
       nonce: headers['wechatpay-nonce'],
@@ -248,25 +226,25 @@ export class PaymentMtService extends GenericCrudService<PaymentMtEntity> {
       signature: headers['wechatpay-signature']
     });
 
-    console.debug(`[租户${payment.tenantId}] 回调签名验证结果:`, isValid);
+    console.debug(`回调签名验证结果:`, isValid);
 
     if (!isValid) {
-      console.debug(`[租户${payment.tenantId}] 回调签名验证失败,headers:`, headers);
+      console.debug(`回调签名验证失败,headers:`, headers);
       throw new Error('回调签名验证失败');
     }
 
-    console.debug(`[租户${payment.tenantId}] 回调签名验证成功`);
+    console.debug(`回调签名验证成功`);
 
     // 解密回调数据
-    console.debug(`[租户${payment.tenantId}] 开始解密回调数据`);
+    console.debug(`开始解密回调数据`);
     const decryptedData = this.wxPay.decipher_gcm(
       callbackData.resource.ciphertext,
       callbackData.resource.associated_data || '',
       callbackData.resource.nonce
     );
 
-    console.debug(`[租户${payment.tenantId}] 解密回调数据:`, decryptedData);
-    console.debug(`[租户${payment.tenantId}] 解密回调数据类型:`, typeof decryptedData);
+    console.debug(`解密回调数据:`, decryptedData);
+    console.debug(`解密回调数据类型:`, typeof decryptedData);
 
     // 处理解密后的数据,可能是字符串或对象
     let parsedData;
@@ -276,7 +254,34 @@ export class PaymentMtService extends GenericCrudService<PaymentMtEntity> {
       parsedData = decryptedData;
     }
 
-    console.debug(`[租户${payment.tenantId}] 解析后的回调数据:`, parsedData);
+    console.debug(`解析后的回调数据:`, parsedData);
+
+    // 从解密后的数据中获取商户订单号
+    const outTradeNo = parsedData.out_trade_no;
+    if (!outTradeNo) {
+      console.debug('解密后的回调数据中缺少商户订单号,回调数据:', parsedData);
+      throw new Error('回调数据中缺少商户订单号');
+    }
+
+    console.debug(`开始处理支付回调,商户订单号: ${outTradeNo}`);
+
+    // 从数据库中查找支付记录以获取租户ID
+    const paymentRepository = this.dataSource.getRepository(PaymentMtEntity);
+    const payment = await paymentRepository.findOne({
+      where: { outTradeNo }
+    });
+
+    if (!payment) {
+      console.debug(`支付记录不存在,商户订单号: ${outTradeNo}`);
+      throw new Error('支付记录不存在');
+    }
+
+    console.debug(`[租户${payment.tenantId}] 找到支付记录,外部订单ID: ${payment.externalOrderId}, 当前支付状态: ${payment.paymentStatus}`);
+
+    // 重新使用正确的租户ID初始化微信支付SDK
+    console.debug(`[租户${payment.tenantId}] 重新初始化微信支付SDK`);
+    await this.initializeWxPay(payment.tenantId);
+    console.debug(`[租户${payment.tenantId}] 微信支付SDK重新初始化完成`);
 
     // 根据回调结果更新支付状态
     const originalPaymentStatus = payment.paymentStatus;

+ 7 - 6
packages/mini-payment-mt/tests/integration/payment-callback.integration.test.ts

@@ -15,6 +15,7 @@ import { MerchantMt } from '@d8d/merchant-module-mt';
 import { SupplierMt } from '@d8d/supplier-module-mt';
 import { DeliveryAddressMt } from '@d8d/delivery-address-module-mt';
 import { AreaEntityMt } from '@d8d/geo-areas-mt';
+import { SystemConfigMt } from '@d8d/core-module-mt/system-config-module-mt/entities';
 import { config } from 'dotenv';
 import { resolve } from 'path';
 // 导入微信支付SDK用于模拟
@@ -28,7 +29,7 @@ config({ path: resolve(process.cwd(), '.env.test') });
 vi.mock('wechatpay-node-v3')
 
 // 设置集成测试钩子
-setupIntegrationDatabaseHooksWithEntities([PaymentMtEntity, UserEntityMt, FileMt, RoleMt, OrderMt, MerchantMt, SupplierMt, DeliveryAddressMt, AreaEntityMt])
+setupIntegrationDatabaseHooksWithEntities([PaymentMtEntity, UserEntityMt, FileMt, RoleMt, OrderMt, MerchantMt, SupplierMt, DeliveryAddressMt, AreaEntityMt, SystemConfigMt])
 
 describe('支付回调API集成测试 - 多租户版本', () => {
   let client: ReturnType<typeof testClient<typeof PaymentMtRoutes>>;
@@ -115,7 +116,7 @@ describe('支付回调API集成测试 - 多租户版本', () => {
         const dataSource = await IntegrationTestDatabase.getDataSource();
         const orderRepository = dataSource.getRepository(OrderMt);
         const updatedOrder = await orderRepository.findOne({
-          where: { id: testOrder.id, tenantId: 1 }
+          where: { id: testData.order.id, tenantId: 1 }
         });
 
         expect(updatedOrder).toBeDefined();
@@ -128,7 +129,7 @@ describe('支付回调API集成测试 - 多租户版本', () => {
       const mockWxPay = {
         verifySign: vi.fn().mockResolvedValue(true),
         decipher_gcm: vi.fn().mockReturnValue(JSON.stringify({
-          out_trade_no: testPayment.outTradeNo,
+          out_trade_no: testData.payment.outTradeNo,
           trade_state: 'FAIL',
           transaction_id: null,
           amount: {
@@ -157,7 +158,7 @@ describe('支付回调API集成测试 - 多租户版本', () => {
         const dataSource = await IntegrationTestDatabase.getDataSource();
         const orderRepository = dataSource.getRepository(OrderMt);
         const updatedOrder = await orderRepository.findOne({
-          where: { id: testOrder.id, tenantId: 1 }
+          where: { id: testData.order.id, tenantId: 1 }
         });
 
         expect(updatedOrder).toBeDefined();
@@ -170,7 +171,7 @@ describe('支付回调API集成测试 - 多租户版本', () => {
       const mockWxPay = {
         verifySign: vi.fn().mockResolvedValue(true),
         decipher_gcm: vi.fn().mockReturnValue(JSON.stringify({
-          out_trade_no: testPayment.outTradeNo,
+          out_trade_no: testData.payment.outTradeNo,
           trade_state: 'REFUND',
           transaction_id: 'test_refund_transaction_id',
           amount: {
@@ -199,7 +200,7 @@ describe('支付回调API集成测试 - 多租户版本', () => {
         const dataSource = await IntegrationTestDatabase.getDataSource();
         const orderRepository = dataSource.getRepository(OrderMt);
         const updatedOrder = await orderRepository.findOne({
-          where: { id: testOrder.id, tenantId: 1 }
+          where: { id: testData.order.id, tenantId: 1 }
         });
 
         expect(updatedOrder).toBeDefined();