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-activity/src/main/java/com/dsh/activity/util/PayMoneyUtil.java | 174 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 136 insertions(+), 38 deletions(-) diff --git a/cloud-server-activity/src/main/java/com/dsh/activity/util/PayMoneyUtil.java b/cloud-server-activity/src/main/java/com/dsh/activity/util/PayMoneyUtil.java index 65fc4d2..d2986c1 100644 --- a/cloud-server-activity/src/main/java/com/dsh/activity/util/PayMoneyUtil.java +++ b/cloud-server-activity/src/main/java/com/dsh/activity/util/PayMoneyUtil.java @@ -11,6 +11,7 @@ import com.alipay.api.request.*; import com.alipay.api.response.*; import com.dsh.activity.util.httpClinet.HttpClientUtil; +import com.dsh.activity.util.wx.*; import org.apache.commons.collections.map.HashedMap; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.dom4j.Document; @@ -29,6 +30,7 @@ import java.math.BigDecimal; import java.net.InetAddress; import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; @@ -61,8 +63,8 @@ private String key = "6f5e0c2dcabfa9c27b5da5836a362fef";//微信商户号 -// private String callbackPath = "https://online.daowepark.com:443/activity";//支付回调网关地址 - private String callbackPath = "http://vbef9arg13uu.guyubao.com/activity";//支付回调网关地址 + private String callbackPath = "https://online.daowepark.com:443/activity";//支付回调网关地址 +// private String callbackPath = "http://vbef9arg13uu.guyubao.com/activity";//支付回调网关地址 private String app_cert_path = "C:/cert/alipay/user/app_cert_path.crt";//应用公钥证书路径 @@ -70,9 +72,10 @@ private String alipay_root_cert_path = "C:/cert/alipay/user/alipay_root_cert_path.crt";//支付宝CA根证书文件路径 - private String certPath = "/usr/playpai/cert/weixin/apiclient_cert.p12";//微信证书 + // private String certPath = "/usr/playpai/cert/weixin/apiclient_cert.p12";//微信证书 + private String certPath = "E:\\wanpaiapiclient_cert.p12";//微信证书 - public ResultUtil confirm(String smid,String code, String outTradeNo, String amount) { + public ResultUtil confirm(String smid, String code, String outTradeNo, String amount) { AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, @@ -82,15 +85,15 @@ "RSA2"); AlipayTradeSettleConfirmRequest request = new AlipayTradeSettleConfirmRequest(); request.setBizContent("{" + - " \"out_request_no\":\""+code+"\"," + - " \"trade_no\":\""+outTradeNo+"\"," + + " \"out_request_no\":\"" + code + "\"," + + " \"trade_no\":\"" + outTradeNo + "\"," + " \"settle_info\":{" + " \"settle_detail_infos\":[" + " {" + " \"trans_in_type\":\"defaultSettle\"," + - " \"settle_entity_id\":\""+smid+"\"," + + " \"settle_entity_id\":\"" + smid + "\"," + " \"settle_entity_type\":\"SecondMerchant\"," + - " \"amount\":"+amount+"," + + " \"amount\":" + amount + "," + " }" + " ]" + " }," + @@ -104,7 +107,7 @@ } catch (AlipayApiException e) { e.printStackTrace(); } - if(response.isSuccess()){ + if (response.isSuccess()) { System.out.println("调用成功"); return ResultUtil.success(); } else { @@ -112,8 +115,9 @@ return ResultUtil.error("出现问题啦"); } } + // 属于平台的运营商 因为无需分账不冻结资金 - public ResultUtil confirm1(String smid,String code, String outTradeNo, String amount) { + public ResultUtil confirm1(String smid, String code, String outTradeNo, String amount) { AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, @@ -123,15 +127,15 @@ "RSA2"); AlipayTradeSettleConfirmRequest request = new AlipayTradeSettleConfirmRequest(); request.setBizContent("{" + - " \"out_request_no\":\""+code+"\"," + - " \"trade_no\":\""+outTradeNo+"\"," + + " \"out_request_no\":\"" + code + "\"," + + " \"trade_no\":\"" + outTradeNo + "\"," + " \"settle_info\":{" + " \"settle_detail_infos\":[" + " {" + " \"trans_in_type\":\"defaultSettle\"," + - " \"settle_entity_id\":\""+smid+"\"," + + " \"settle_entity_id\":\"" + smid + "\"," + " \"settle_entity_type\":\"SecondMerchant\"," + - " \"amount\":"+amount+"," + + " \"amount\":" + amount + "," + " }" + " ]" + " }," + @@ -145,7 +149,7 @@ } catch (AlipayApiException e) { e.printStackTrace(); } - if(response.isSuccess()){ + if (response.isSuccess()) { System.out.println("调用成功"); return ResultUtil.success(); } else { @@ -156,7 +160,10 @@ /** * 支付宝支付 */ - 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 (); // //设置网关地址 @@ -207,6 +214,8 @@ // } catch (AlipayApiException e ) { // e.printStackTrace(); // } + + //实例化客户端 AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipay_public_key, "RSA2"); //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay @@ -232,11 +241,10 @@ SubMerchant subMerchant = new SubMerchant(); subMerchant.setMerchantId(smid); model.setSubMerchant(subMerchant); - ExtendParams extendParams = new ExtendParams(); - extendParams.setRoyaltyFreeze("false");// 冻结资金 用于后续分账处理 - model.setExtendParams(extendParams); + request.setBizModel(model); - request.setNotifyUrl(callbackPath + notifyUrl); + request.setNotifyUrl("http://8.137.22.229:5002" + notifyUrl); + try { //这里和普通的接口调用不同,使用的是sdkExecute AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); @@ -334,8 +342,8 @@ Map<String, String> map = new HashMap<>(); - System.err.println("返回码"+params); - if (params.get("trade_status").equals("TRADE_SUCCESS")){ + 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"); @@ -348,7 +356,7 @@ map.put("passback_params", passback_params);//回传参数 System.err.println("回调map"); return map; - }else{ + } else { return null; } } @@ -376,6 +384,62 @@ } } + 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); + } /** * 微信统一下单 @@ -400,18 +464,11 @@ Map<String, Object> map = new HashMap<>(); map.put("appid", appid); map.put("mch_id", mchId); +// map.put("sub_mch_id", "123456"); map.put("nonce_str", nonce_str); String temp = ""; - if (body.split("-").length>1){ - temp = body.split("-")[1]; - map.put("body", body.split("-")[0]); - }else{ - map.put("body", body); - } - if (StringUtils.hasLength(temp) && temp.equals("1")){ - // 添加分账标识 - map.put("profit_sharing", "Y"); - } + map.put("body", body); + map.put("attach", attach);//存储订单id map.put("out_trade_no", out_trade_no);//存储的订单code map.put("total_fee", i); @@ -501,8 +558,6 @@ return ResultUtil.error(map1.get("return_msg"), new JSONObject()); } } - - /** @@ -1141,6 +1196,46 @@ return sb.toString(); } + public String weixinSignatureWithSHA256(Map<String, Object> map, String key) { + try { + Set<Map.Entry<String, Object>> entries = map.entrySet(); + List<Map.Entry<String, Object>> infoIds = new ArrayList<>(entries); + + // 按 key 的 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().isEmpty()) { + String keyName = item.getKey(); + Object val = item.getValue(); + if (val != null && !val.toString().isEmpty()) { + sb.append(keyName).append("=").append(val).append("\n"); + } + } + } + + sb.deleteCharAt(sb.length() - 1); // 删除最后一个 & + + // 使用 SHA256-HMAC 加密 + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + sha256_HMAC.init(secretKey); + byte[] hashBytes = sha256_HMAC.doFinal(sb.toString().getBytes(StandardCharsets.UTF_8)); + String sign = byteArrayToHexString(hashBytes).toUpperCase(); + + return sign; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + /** * 微信下单的签名算法 @@ -1177,6 +1272,7 @@ } return null; } + private String weixinSignature1(Map<String, Object> map) { try { Set<Map.Entry<String, Object>> entries = map.entrySet(); @@ -1198,21 +1294,23 @@ } } } - sb.append("key=" + key); - String sign = sha256_HMAC(sb.toString(), key).toUpperCase(); + sb.append("key=" + "1skiujh28376shznxmslwosiusytersq"); + String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式 return sign; } catch (Exception e) { e.printStackTrace(); } return null; } + /** * sha256_HMAC加密 + * * @param message 消息 * @param secret 秘钥 * @return 加密后字符串 */ - public String sha256_HMAC(String message, String secret) { + public String sha256_HMAC(String message, String secret) { String hash = ""; try { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); -- Gitblit v1.7.1