From 5dc40fcd64b0513150f1d8335ab849e6d8cdc28e Mon Sep 17 00:00:00 2001
From: 无关风月 <443237572@qq.com>
Date: 星期五, 04 七月 2025 19:42:49 +0800
Subject: [PATCH] 支付版本更新 根据资金流向使用V2或V3服务商版本支付

---
 cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java |  332 ++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 269 insertions(+), 63 deletions(-)

diff --git a/cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java b/cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java
index 9af98bc..5cd4639 100644
--- a/cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java
+++ b/cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java
@@ -2,6 +2,7 @@
 
 import cn.hutool.core.util.RandomUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alipay.api.AlipayApiException;
 import com.alipay.api.AlipayClient;
@@ -25,6 +26,10 @@
 //import com.github.binarywang.wxpay.service.ProfitSharingV3Service;
 //import com.github.binarywang.wxpay.service.WxPayService;
 
+import com.dsh.account.util.wx.PartnerAppPrepay;
+import com.dsh.account.util.wx.WXPayUtility;
+import com.dsh.account.util.wx.WeChatV3SignUtil;
+import com.dsh.account.util.wx.WxV3PayConfig;
 import org.apache.commons.collections.map.HashedMap;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -36,12 +41,10 @@
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
 
 import javax.annotation.Resource;
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.NoSuchPaddingException;
+import javax.crypto.*;
 import javax.crypto.spec.SecretKeySpec;
 import javax.servlet.http.HttpServletRequest;
 import java.io.*;
@@ -54,6 +57,8 @@
 import java.security.NoSuchProviderException;
 import java.security.Security;
 import java.util.*;
+
+import static com.dsh.account.util.akeylogin.Md5Util.byteArrayToHexString;
 
 /**
  * 第三方支付工具类
@@ -68,7 +73,7 @@
 
     private String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmu8n/4yTHWbn7VOrNc9OsLtDL1bEQ8gC1dHkj8Wy5z0mkaOsjJRIG/28ze12M0V8jdCKuuDr5Z1OPKiqf+XO3ypguEh+mYUVMBM/cZodDFQfTY1TKLWjvQCuaqlA+QUTCK6f7T7stsgyQ1o9Jj0rXZDz6PM4QHSTzjrLIBaeqM5WIBvH+fy/X+QG5Utd+/UT0kc0JyvuKhZ65yVUd/C9VcwJJAPliRsAQNrqYterwAJ9zvw9tF11wj9W0XgJ8Ccu4x3gR1vrlLRJJo/OA97RmxPQ+5hSacWQZCUd1dwiBq+YCrKVHGTj14izRHXrLc0yBlRXo7tBOIqcy3IsvKVthQIDAQAB";//支付宝支付公钥
 
-    private String smid = "2088330203191220";//平台支付宝商户号
+    private String smid = "2088330203191220";//平台支付宝商户号...
 
     private String appid = "wx41d32f362ba0f911";//微信appid
 
@@ -78,7 +83,7 @@
 
     private String key = "6f5e0c2dcabfa9c27b5da5836a362fef";//微信商户号
 
-    private String callbackPath = "http://221.182.45.100:56666/account";//支付回调网关地址
+    private String callbackPath = "https://online.daowepark.com:443/account";//支付回调网关地址
 
     private String app_cert_path = "C:/cert/alipay/user/app_cert_path.crt";//应用公钥证书路径
 
@@ -86,13 +91,102 @@
 
     private String alipay_root_cert_path = "C:/cert/alipay/user/alipay_root_cert_path.crt";//支付宝CA根证书文件路径
 
-    private String certPath = "C:\\cert\\1523106371_20211206_cert\\apiclient_cert.p12";//微信证书
+    private String certPath = "/usr/playpai/cert/weixin/apiclient_cert.p12";//微信证书
 
+
+//    public static void main(String[] args) {
+//        Map<String, Object> body = new HashMap<>();
+//        body.put("type", "MERCHANT_ID");
+//        body.put("account", "1231232121");
+//        body.put("amount", "asda");
+//        body.put("description", "订单分账");
+//        JSONObject jsonObject = new JSONObject(body);
+//        JSONArray objects = new JSONArray();
+//        objects.add(jsonObject);
+//        System.err.println(objects);
+//        System.err.println(objects.toJSONString());
+//    }
+    /**
+     * 发起分账
+     * @param order 微信订单号
+     * @return
+     */
+    public ResultUtil fenzhang(String order,BigDecimal amount,String merchantNumber,String description) throws Exception {
+        Map<String, Object> map = new HashMap<>();
+        map.put("mch_id", mchId);
+        map.put("appid", appid);
+        String nonce_str = UUIDUtil.getRandomCode(16);
+        String out_order_no = UUIDUtil.getRandomCode(16);
+        map.put("out_order_no", out_order_no);
+        map.put("nonce_str", nonce_str);
+
+        map.put("transaction_id", order);
+        // 将这个字符串使用json格式拼接起来
+        Map<String, Object> body = new HashMap<>();
+        body.put("type", "MERCHANT_ID");
+        body.put("account", merchantNumber);
+        int i = amount.multiply(new BigDecimal("100")).intValue();
+        body.put("amount", i);
+        body.put("description", description);
+        JSONObject jsonObject = new JSONObject(body);
+        JSONArray objects = new JSONArray();
+        objects.add(jsonObject);
+        map.put("receivers",objects.toJSONString());
+        String s = this.weixinSignature1(map);
+        map.put("sign", s);
+        String url = "https://api.mch.weixin.qq.com/secapi/pay/profitsharing";
+        //设置请求头
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_XML);
+        StringBuffer xmlString = new StringBuffer();
+        Set<String> strings = map.keySet();
+        String[] keys = {};
+        keys = strings.toArray(keys);
+        Arrays.sort(keys);
+        xmlString.append("<xml>");
+        for (int l = 0; l < keys.length; l++) {
+            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
+        }
+        xmlString.append("</xml>");
+
+        Map<String, String> map1 = null;
+        String body1 = null;
+        try {
+            body1 = HttpClientUtil.pushHttpsRequsetXml1(url, xmlString.toString(), new HashMap<>(), mchId, certPath, "PKCS12");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        System.err.println("分账请求"+body1);
+        //将结果xml解析成map
+        body1 = body1.replaceAll("<!\\[CDATA\\[", "");
+        body1 = body1.replaceAll("]]>", "");
+        try {
+            map1 = this.xmlToMap(body1, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        } catch (DocumentException e) {
+            e.printStackTrace();
+        }
+        String return_code = map1.get("return_code");
+        if ("SUCCESS".equals(return_code)) {
+            String result_code = map1.get("result_code");
+            if ("SUCCESS".equals(result_code)) {
+                return ResultUtil.success();
+            } else {
+//                System.err.println(map1.get("err_code_des"));
+                return ResultUtil.error(map1.get("err_code_des"));
+            }
+        } else {
+//            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
+            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
+        }
+    }
 
     /**
      * 支付宝支付
      */
-    public ResultUtil  alipay(String smid,String body, String subject, String passbackParams, String outTradeNo, String amount, String notifyUrl) {
+    public ResultUtil  alipay(String smid,String body, String subject,
+                              String passbackParams, String outTradeNo, String amount, String notifyUrl) {
 //        //构造client
 //        CertAlipayRequest certAlipayRequest = new CertAlipayRequest ();
 //        //设置网关地址
@@ -169,47 +263,7 @@
         SubMerchant subMerchant = new SubMerchant();
         subMerchant.setMerchantId(smid);
         model.setSubMerchant(subMerchant);
-        ExtendParams extendParams = new ExtendParams();
-        extendParams.setRoyaltyFreeze("true");// 冻结资金 用于后续分账处理
-        model.setExtendParams(extendParams);
-        //分账
-//        Integer    coursePackagePayments = coursePackageClient.queryByCode(outTradeNo);
-//        Integer paymentCompetitions = competitionsClient.queryByCode(outTradeNo);
-//        Integer siteBookings = siteClient.queryByCode(outTradeNo);
-//        List<Integer> stores = new ArrayList<>();
-//        stores.add(coursePackagePayments);
-//        stores.add(paymentCompetitions);
-//        stores.add(siteBookings);
-//
-//        OperatorUser operatorUser = siteClient.queryOperator(stores);
-//
-//        String alipayProportion = operatorUser.getAlipayProportion();
-//        String alipayNum = operatorUser.getAlipayNum();
-//
-//        ExtendParams extendParams = new ExtendParams();
-////        extendParams.setSysServiceProviderId("YOUR_SERVICE_PROVIDER_ID");
-//        model.setExtendParams(extendParams);
-//
-//        RoyaltyInfo royaltyInfo = new RoyaltyInfo();
-////        royaltyInfo.setRoyaltyType("transfer");
-//
-//
-//        RoyaltyDetailInfos royaltyDetailInfo1 = new RoyaltyDetailInfos();
-//        royaltyDetailInfo1.setTransOutType("userId");
-//        royaltyDetailInfo1.setTransOut(aliAppid);
-//        royaltyDetailInfo1.setTransInType("loginName");
-//        royaltyDetailInfo1.setTransIn("18398968484");
-//
-//        royaltyDetailInfo1.setDesc("分账描述1");
-//        royaltyDetailInfo1.setAmountPercentage(alipayProportion);
-//        List<RoyaltyDetailInfos> royaltyDetailInfos = new ArrayList<>();
-//
-//
-//
-//        royaltyInfo.setRoyaltyDetailInfos(royaltyDetailInfos);
-//        model.setRoyaltyInfo(royaltyInfo);
-//        System.err.println("=================="+royaltyInfo);
-        //
+
         request.setBizModel(model);
         request.setNotifyUrl(callbackPath + notifyUrl);
         try {
@@ -300,7 +354,47 @@
             return ResultUtil.error("出现问题啦");
         }
     }
-
+    // 资金冻结 做分账处理
+    public ResultUtil confirm1(String smid,String code, String outTradeNo, String amount) {
+        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
+                aliAppid,
+                appPrivateKey,
+                "json",
+                "GBK",
+                alipay_public_key,
+                "RSA2");
+        AlipayTradeSettleConfirmRequest request = new AlipayTradeSettleConfirmRequest();
+        request.setBizContent("{" +
+                "  \"out_request_no\":\""+code+"\"," +
+                "  \"trade_no\":\""+outTradeNo+"\"," +
+                "  \"settle_info\":{" +
+                "    \"settle_detail_infos\":[" +
+                "      {" +
+                "        \"trans_in_type\":\"defaultSettle\"," +
+                "        \"settle_entity_id\":\""+smid+"\"," +
+                "        \"settle_entity_type\":\"SecondMerchant\"," +
+                "        \"amount\":"+amount+"," +
+                "      }" +
+                "    ]" +
+                "  }," +
+                "  \"extend_params\":{" +
+                "    \"royalty_freeze\":\"true\"" +
+                "  }" +
+                "}");
+        AlipayTradeSettleConfirmResponse response = null;
+        try {
+            response = alipayClient.execute(request);
+        } catch (AlipayApiException e) {
+            e.printStackTrace();
+        }
+        if(response.isSuccess()){
+            System.out.println("调用成功");
+            return ResultUtil.success();
+        } else {
+            System.out.println("调用失败");
+            return ResultUtil.error("出现问题啦");
+        }
+    }
     /**
      * 支付成功后的回调处理逻辑
      *
@@ -350,17 +444,23 @@
 
 
         Map<String, String> map = new HashMap<>();
-        String out_trade_no = params.get("out_trade_no");
-        String subject = params.get("subject");
-        String total_amount = params.get("total_amount");
-        String trade_no = params.get("trade_no");
-        String passback_params = params.get("passback_params");
-        map.put("out_trade_no", out_trade_no);//商家订单号
-        map.put("subject", subject);
-        map.put("total_amount", total_amount);
-        map.put("trade_no", trade_no);//支付宝交易号
-        map.put("passback_params", passback_params);//回传参数
-        return map;
+        System.err.println("返回码"+params);
+        if (params.get("trade_status").equals("TRADE_SUCCESS")){
+            String out_trade_no = params.get("out_trade_no");
+            String subject = params.get("subject");
+            String total_amount = params.get("total_amount");
+            String trade_no = params.get("trade_no");
+            String passback_params = params.get("passback_params");
+            map.put("out_trade_no", out_trade_no);//商家订单号
+            map.put("subject", subject);
+            map.put("total_amount", total_amount);
+            map.put("trade_no", trade_no);//支付宝交易号
+            map.put("passback_params", passback_params);//回传参数
+            System.err.println("回调map");
+            return map;
+        }else{
+            return null;
+        }
     }
 
 
@@ -412,7 +512,10 @@
         map.put("appid", appid);
         map.put("mch_id", mchId);
         map.put("nonce_str", nonce_str);
-        map.put("body", body);
+
+            map.put("body", body);
+
+
         map.put("attach", attach);//存储订单id
         map.put("out_trade_no", out_trade_no);//存储的订单code
         map.put("total_fee", i);
@@ -503,6 +606,62 @@
             System.err.println(map1.get("return_msg") + appid + "----" + mchId);
             return ResultUtil.error(map1.get("return_msg"), new JSONObject());
         }
+    }
+    public ResultUtil weixinpayV3(String subMchid,String description, String outTradeNo, String notifyUrl, String totalFee) throws Exception {
+        int i = new BigDecimal(totalFee).multiply(new BigDecimal("100")).intValue();
+        // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
+        PartnerAppPrepay client = new PartnerAppPrepay(
+//                "1681873607",                  // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考https://pay.weixin.qq.com/doc/v3/partner/4013080340
+//                "55714944F7A7E52526F708280B176DCC838F371A",       // 商户API证书序列号,如何获取请参考https://pay.weixin.qq.com/doc/v3/partner/4013058924
+//                "E:\\wanpai\\1681873607_20250424_cert\\apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径
+//                "PUB_KEY_ID_0116818736072025042400351694002605",          // 微信支付公钥ID,如何获取请参考https://pay.weixin.qq.com/doc/v3/partner/4013038589
+//                "E:\\wanpai\\pub_key.pem"     // 微信支付公钥文件路径,本地文件路径
+
+                "1681873607",                  // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考https://pay.weixin.qq.com/doc/v3/partner/4013080340
+                "55714944F7A7E52526F708280B176DCC838F371A",       // 商户API证书序列号,如何获取请参考https://pay.weixin.qq.com/doc/v3/partner/4013058924
+                "/usr/playpai/server/wxV3/1681873607_20250424_cert/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径
+                "PUB_KEY_ID_0116818736072025042400351694002605",          // 微信支付公钥ID,如何获取请参考https://pay.weixin.qq.com/doc/v3/partner/4013038589
+                "/usr/playpai/server/wxV3/pub_key.pem"     // 微信支付公钥文件路径,本地文件路径
+        );
+
+        PartnerAppPrepay.PartnerAPIv3CommonPrepayRequest request = new PartnerAppPrepay.PartnerAPIv3CommonPrepayRequest();
+        request.spAppid = appid;// appid
+        request.spMchid = WxV3PayConfig.Mch_ID;// 服务商商户号
+        request.subMchid = subMchid;// 子商户号
+        request.description = description;// 描述
+        request.outTradeNo = outTradeNo;// 订单号
+        request.notifyUrl = callbackPath+notifyUrl;// 回调地址
+        request.amount = new PartnerAppPrepay.CommonAmountInfo();
+        request.amount.total = (long) i;// 金额 单位分
+        request.amount.currency = "CNY";
+        String prepayId ="";
+        Map<String, Object> map3 = new HashMap<>();
+        try {
+            PartnerAppPrepay.PartnerAPIv3AppPrepayResponse response = client.run(request);
+            // TODO: 请求成功,继续业务逻辑
+            System.err.println("微信申请成功,预支付ID: " + response.prepayId);
+            prepayId = response.prepayId;
+        } catch (WXPayUtility.ApiException e) {
+            // TODO: 请求失败,根据状态码执行不同的逻辑
+            e.printStackTrace();
+        }
+        map3.put("appid", appid);
+        map3.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
+        String nonce_str = UUIDUtil.getRandomCode(16);
+        map3.put("noncestr", nonce_str);
+        map3.put("prepayid", prepayId);
+        // 构造待签名字符串
+        String message = WeChatV3SignUtil.buildSignMessage(map3);
+        // 私钥路径(pem 文件)
+        String privateKeyPath = "/usr/playpai/server/wxV3/1681873607_20250424_cert/apiclient_key.pem";
+//      String privateKeyPath = "E:\\wanpai\\1681873607_20250424_cert\\apiclient_key.pem";
+        // 生成签名
+        String sign = WeChatV3SignUtil.signWithPrivateKey(message, privateKeyPath);
+        map3.put("sign", sign);
+        map3.put("package", "Sign=WXPay");
+        map3.put("partnerid", WxV3PayConfig.Mch_ID);// 服务商商户号
+        System.err.println(map3);
+        return ResultUtil.success(map3);
     }
 
 
@@ -1331,7 +1490,54 @@
         }
         return null;
     }
-
+    private String weixinSignature1(Map<String, Object> map) {
+        try {
+            Set<Map.Entry<String, Object>> entries = map.entrySet();
+            List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries);
+            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
+            Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
+                public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
+                    return (o1.getKey()).toString().compareTo(o2.getKey());
+                }
+            });
+            // 构造签名键值对的格式
+            StringBuilder sb = new StringBuilder();
+            for (Map.Entry<String, Object> item : infoIds) {
+                if (item.getKey() != null || item.getKey() != "") {
+                    String key = item.getKey();
+                    Object val = item.getValue();
+                    if (!(val == "" || val == null)) {
+                        sb.append(key + "=" + val + "&");
+                    }
+                }
+            }
+            sb.append("key=" + key);
+            String sign = sha256_HMAC(sb.toString(), key).toUpperCase();
+            return sign;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    /**
+     * sha256_HMAC加密
+     * @param message 消息
+     * @param secret  秘钥
+     * @return 加密后字符串
+     */
+    public  String sha256_HMAC(String message, String secret) {
+        String hash = "";
+        try {
+            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
+            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
+            sha256_HMAC.init(secret_key);
+            byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
+            hash = byteArrayToHexString(bytes);
+        } catch (Exception e) {
+            System.out.println("Error HmacSHA256 ===========" + e.getMessage());
+        }
+        return hash;
+    }
 
     /**
      * 微信退款成功后的解密

--
Gitblit v1.7.1