无关风月
20 小时以前 5dc40fcd64b0513150f1d8335ab849e6d8cdc28e
cloud-server-course/src/main/java/com/dsh/course/util/PayMoneyUtil.java
@@ -1,6 +1,7 @@
package com.dsh.course.util;
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;
@@ -10,6 +11,10 @@
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.dsh.course.util.httpClinet.HttpClientUtil;
import com.dsh.course.util.wx.PartnerAppPrepay;
import com.dsh.course.util.wx.WXPayUtility;
import com.dsh.course.util.wx.WeChatV3SignUtil;
import com.dsh.course.util.wx.WxV3PayConfig;
import org.apache.commons.collections.map.HashedMap;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.Document;
@@ -20,11 +25,9 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
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.*;
@@ -37,6 +40,8 @@
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.*;
import static com.dsh.course.util.akeylogin.Md5Util.byteArrayToHexString;
/**
 * 第三方支付工具类
@@ -61,7 +66,7 @@
    private String key = "6f5e0c2dcabfa9c27b5da5836a362fef";//微信商户号
    private String callbackPath = "http://221.182.45.100:56666/course";//支付回调网关地址
    private String callbackPath = "https://online.daowepark.com:443/course";//支付回调网关地址
    private String app_cert_path = "C:/cert/alipay/user/app_cert_path.crt";//应用公钥证书路径
@@ -69,7 +74,7 @@
    private String alipay_root_cert_path = "C:/cert/alipay/user/alipay_root_cert_path.crt";//支付宝CA根证书文件路径
    private String certPath = "C:\\Users\\Admin\\Desktop\\weixin_cert\\apiclient_cert.p12";//微信证书
    private String certPath = "/usr/playpai/cert/weixin/apiclient_cert.p12";//微信证书
    public ResultUtil confirm(String smid,String code, String outTradeNo, String amount) {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
@@ -95,6 +100,47 @@
                "  }," +
                "  \"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("出现问题啦");
        }
    }
    // 属于平台的运营商 因为无需分账不冻结资金
    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\":\"false\"" +
                "  }" +
                "}");
        AlipayTradeSettleConfirmResponse response = null;
@@ -190,9 +236,6 @@
        SubMerchant subMerchant = new SubMerchant();
        subMerchant.setMerchantId(smid);
        model.setSubMerchant(subMerchant);
        ExtendParams extendParams = new ExtendParams();
        extendParams.setRoyaltyFreeze("true");// 冻结资金 用于后续分账处理
        model.setExtendParams(extendParams);
        request.setBizModel(model);
        request.setNotifyUrl(callbackPath + notifyUrl);
        try {
@@ -292,17 +335,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;
        }
    }
@@ -353,7 +402,9 @@
        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);
@@ -443,7 +494,139 @@
            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
        }
    }
    public ResultUtil weixinpayV3(String subMchid,String description, String outTradeNo, String notifyUrl, String totalFee, String attach) 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";
        request.attach = attach;
        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);
    }
    /**
     * 发起分账
     * @param order 微信订单号
     * @return
     */
    public ResultUtil fenzhang(String order,BigDecimal amount,String merchantNumber,String nonceStr) throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("mch_id", mchId);
        map.put("appid", appid);
        map.put("nonce_str", nonceStr);
        map.put("transaction_id", order);
        String out_order_no = UUIDUtil.getRandomCode(16);
        map.put("out_order_no", out_order_no);
        // 将这个字符串使用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", "购买课包分账");
        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(map1.get("order_id"));
            } 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());
        }
    }
    /**
     * 微信支付成功后的回调处理
@@ -1117,7 +1300,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;
    }
    /**
     * 微信下单的签名算法