Selaa lähdekoodia

feat(profit-sharing): 扩展分账功能支持课程订单类型

- 添加课程订单类型到分账定时任务查询条件
- 集成微信支付分账接收方企业名称加密解密功能
- 实现分账接收方企业名称的RSA加密传输
- 更新分账请求参数中的应用ID和商户ID配置
- 添加分账结果日志记录和证书文件处理
- 优化分账流程中的接收方信息设置逻辑
wzq 2 päivää sitten
vanhempi
commit
9a09e7155e

+ 38 - 5
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WeChatProfitSharingService.java

@@ -6,6 +6,7 @@ import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
+import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.jeecg.common.constant.CommonConstant;
@@ -24,6 +25,7 @@ import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.NoSuchPaddingException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Type;
@@ -31,12 +33,14 @@ import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
 import java.security.cert.*;
 import java.util.*;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
 
 import static java.lang.Thread.sleep;
+import static org.jeecg.modules.pay.paytest.ServiceProvider.privateKey;
 
 @Slf4j
 @Service
@@ -80,9 +84,13 @@ public class WeChatProfitSharingService {
         log.info("分账接收方:{}", receiverAddForm);
         JSONObject body = wechatPayV3Utils.profitSharingSendPost(WechatUrlConstants.PAY_V3_RECEIVERS_ADD, params);
         log.info("添加分账接收方结果:{}", body);
+        String name1 = body.getString("name");
+        String s = rsaDecryptOAEP(name1, PemUtil.loadPrivateKey(WechatConstants.WECHAT_MCH_PRIVATE_KEY));
+        log.info("企业名称解密:{}",s);
         return body;
     }
 
+
     /**
      * 分账
      *
@@ -129,28 +137,37 @@ public class WeChatProfitSharingService {
                 receiver.setType("MERCHANT_ID")
                         .setAccount(receiverRecord.getMchId())
                         .setAmount(receiverRecord.getPreAmount())
-                        .setDescription("商户:" + receiverRecord.getMchName() + "于订单" + receiverRecord.getOrgCode() + "分账所获金额:" + receiverRecord.getPreAmount());
-                receivers.add(receiver);
+                        .setName(receiverRecord.getMchName())
+                        .setDescription("商户:" + receiverRecord.getMchName() + "于订单" + receiverRecord.getOrderId() + "分账所获金额:" + receiverRecord.getPreAmount());
+                ClassPathResource classPathResource = new ClassPathResource("cert/platform_cert.pem");
+                InputStream certStream = classPathResource.getInputStream();
+                X509Certificate x509Certificate = getCertificate(certStream);
+                String name = WeChatProfitSharingService.rsaEncryptOAEP(receiverRecord.getMchName(), x509Certificate);
+                receiver.setName(name);
+
                 //添加分账接收方
                 ReceiverAddForm receiverAddForm = new ReceiverAddForm();
-                receiverAddForm.setSub_mchid(partyFunding.get(0).getMchId());
+                receiverAddForm.setSub_mchid(receiverRecords.get(0).getMchId());
                 receiverAddForm.setSub_appid(WechatConstants.WECHAT_SUB_APPID);
                 receiverAddForm.setAccount(receiver.getAccount());
                 receiverAddForm.setName(receiverRecord.getMchName());
+                receiverAddForm.setType("MERCHANT_ID");
 
-                receiversAdd(receiverAddForm);
+                JSONObject jsonObject = receiversAdd(receiverAddForm);
+                receivers.add(receiver);
             }
             sleep(1000);
         }
         //构建分账参数
         ProfitSharingRequest profitSharingRequest = new ProfitSharingRequest();
         profitSharingRequest
-                .setAppid(WechatConstants.WECHAT_SP_APPID)
+                .setAppid(WechatConstants.WECHAT_SUB_APPID)
                 .setSub_mchid(receiverRecords.get(0).getMchId())
                 .setTransaction_id(appOrder.getTransactionId())
                 .setOut_order_no(appProfitSharingRecords.getProfitSharingNo())
                 .setReceivers(receivers)
                 .setUnfreeze_unsplit(Boolean.TRUE);
+        log.info("微信服务商分账--------------------------------------------------wechatPay profitSharingRequest:{}", profitSharingRequest);
         try {
             JSONObject res = wechatPayV3Utils.profitSharingSendPost(WechatUrlConstants.PAY_V3_PROFIT_SHARING, JSONObject.from(profitSharingRequest));
             log.info("微信服务商分账--------------------------------------------------wechatPay res:{}", res.toString());
@@ -606,4 +623,20 @@ public class WeChatProfitSharingService {
         }
     }
 
+    public static String rsaDecryptOAEP(String ciphertext, PrivateKey privateKey)
+            throws BadPaddingException, IOException {
+        try {
+            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
+            cipher.init(Cipher.DECRYPT_MODE, privateKey);
+            byte[] data = Base64.getDecoder().decode(ciphertext);
+            return new String(cipher.doFinal(data), "utf-8");
+        } catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
+            throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
+        } catch (InvalidKeyException e) {
+            throw new IllegalArgumentException("无效的私钥", e);
+        } catch (BadPaddingException | IllegalBlockSizeException e) {
+            throw new BadPaddingException("解密失败");
+        }
+    }
+
 }

+ 2 - 2
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/quartz/job/ProfitSharingJonService.java

@@ -42,10 +42,10 @@ public class ProfitSharingJonService {
     public void profitSharingExecute() {
         log.info("开始执行分账定时任务");
         try {
-            //包场和无固定场
+            //包场和无固定场和课程
             List<AppOrder> appOrders = appOrderMapper.selectList(Wrappers.lambdaQuery(AppOrder.class)
                     .eq(AppOrder::getPayStatus, CommonConstant.NUMBER_1)
-                    .in(AppOrder::getOrderType, CommonConstant.ORDER_TYPE_1, CommonConstant.ORDER_TYPE_2)
+                    .in(AppOrder::getOrderType, CommonConstant.ORDER_PRO_INFO_TYPE_1, CommonConstant.ORDER_PRO_INFO_TYPE_2, CommonConstant.ORDER_PRO_INFO_TYPE_5)
             );
             for (AppOrder appOrder : appOrders) {
                 //判断当前订单是否到期,是否进行分账