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 | 343 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 275 insertions(+), 68 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 045db5c..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,16 +73,17 @@ private String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmu8n/4yTHWbn7VOrNc9OsLtDL1bEQ8gC1dHkj8Wy5z0mkaOsjJRIG/28ze12M0V8jdCKuuDr5Z1OPKiqf+XO3ypguEh+mYUVMBM/cZodDFQfTY1TKLWjvQCuaqlA+QUTCK6f7T7stsgyQ1o9Jj0rXZDz6PM4QHSTzjrLIBaeqM5WIBvH+fy/X+QG5Utd+/UT0kc0JyvuKhZ65yVUd/C9VcwJJAPliRsAQNrqYterwAJ9zvw9tF11wj9W0XgJ8Ccu4x3gR1vrlLRJJo/OA97RmxPQ+5hSacWQZCUd1dwiBq+YCrKVHGTj14izRHXrLc0yBlRXo7tBOIqcy3IsvKVthQIDAQAB";//支付宝支付公钥 - private String appid = "";//微信appid + private String smid = "2088330203191220";//平台支付宝商户号... - private String appletsAppid = "";//微信小程序appid - private String smid = "2088330203191220";//平台支付宝商户号 + private String appid = "wx41d32f362ba0f911";//微信appid - private String mchId = "";//微信商户号 + private String appSecret = "cf0ebf950f5926a69041a0e2bbe20f3e"; - private String key = "";//微信商户号 + private String mchId = "1501481761";//微信商户号 - private String callbackPath = "http://221.182.45.100:56666/account";//支付回调网关地址 + private String key = "6f5e0c2dcabfa9c27b5da5836a362fef";//微信商户号 + + private String callbackPath = "https://online.daowepark.com:443/account";//支付回调网关地址 private String app_cert_path = "C:/cert/alipay/user/app_cert_path.crt";//应用公钥证书路径 @@ -85,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 (); // //设置网关地址 @@ -168,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 { @@ -299,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("出现问题啦"); + } + } /** * 支付成功后的回调处理逻辑 * @@ -349,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; + } } @@ -408,10 +509,13 @@ } String nonce_str = UUIDUtil.getRandomCode(16); Map<String, Object> map = new HashMap<>(); - map.put("appid", "APP".equals(tradeType) ? appid : appletsAppid); + 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); @@ -502,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); } @@ -1330,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