package com.ruoyi.errand.utils; import cn.hutool.http.*; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.utils.StringUtils; import lombok.extern.slf4j.Slf4j; import java.util.*; @Slf4j public class PaymentUtil { //微信公众号、微信小程序、微信 APP+/H5、云微小程序支付 private static final String appId = "wxdeed472c98e42a54"; /** * 商户密钥 */ private static final String key = "925899fcc374430f9e4b4ba3db05b448"; /** * 商户号 */ private static final String merchantNo = "888122600004175"; /** * 平台-报备商户号 */ private static final String sysTradeMerchantNo = "777168500885852"; /** * 支付回调地址 */ private static final String callbackUrl = "https://www.qijisheng.top"; /** * 支付 * @param orderNo 商户订单号 * @param amount 订单金额 * @param productName 商品名称 * @param productDesc 商品描述 * @param mp 公用回传参数 * @param notifyUrl 服务器异步通知地址 * @param openId 微信 Openid * @param tradeMerchantNo 报备商户号 * @return */ public static UniPayResult uniPay(String orderNo, Double amount, String productName, String productDesc, String mp, String notifyUrl, String openId, String tradeMerchantNo){ String url = "https://trade.joinpay.com/tradeRt/uniPay"; HttpRequest post = HttpUtil.createPost(url); post.header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded"); JSONObject body = new JSONObject(); //版本号 body.put("p0_Version", "2.5"); //商户编号 body.put("p1_MerchantNo", merchantNo); //商户订单号 body.put("p2_OrderNo", orderNo); //订单金额 body.put("p3_Amount", amount); //交易币种 body.put("p4_Cur", "1"); //商品名称 body.put("p5_ProductName", productName); //商品描述 body.put("p6_ProductDesc", productDesc); //公用回传参数 body.put("p7_Mp", mp); //服务器异步通知地址 body.put("p9_NotifyUrl", callbackUrl + notifyUrl); //交易类型 body.put("q1_FrpCode", FrpCodeEnum.WEIXIN_XCX.getCode()); //微信 Openid body.put("q5_OpenId", openId); //APPID body.put("q7_AppId", appId); //报备商户号 body.put("qa_TradeMerchantNo", StringUtils.isNotEmpty(tradeMerchantNo) ? tradeMerchantNo : sysTradeMerchantNo); String sign = null; try { sign = sign(body); } catch (Exception e) { throw new RuntimeException(e); } body.put("hmac", sign); post.form(body); log.info("支付接口请求参数:" + body); HttpResponse execute = post.execute(); log.info("支付接口请求响应:" + execute.body()); if(200 != execute.getStatus()){ log.error("支付接口异常:" + execute.body()); return null; } UniPayResult uniPayResult = JSON.parseObject(execute.body(), UniPayResult.class); return uniPayResult; } /** * 查询支付订单 * @param orderNo 订单号 * @return */ public static QueryOrderResult queryOrder(String orderNo){ String url = "https://trade.joinpay.com/tradeRt/queryOrder"; HttpRequest post = HttpUtil.createPost(url); post.header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded"); JSONObject body = new JSONObject(); //版本号 body.put("p0_Version", "2.5"); //商户编号 body.put("p1_MerchantNo", merchantNo); //商户订单号 body.put("p2_OrderNo", orderNo); String sign = null; try { sign = sign(body); } catch (Exception e) { throw new RuntimeException(e); } body.put("hmac", sign); post.form(body); log.info("查询支付接口请求参数:" + body); HttpResponse execute = post.execute(); log.info("查询支付接口请求响应:" + execute.body()); if(200 != execute.getStatus()){ log.error("查询支付接口异常:" + execute.body()); return null; } QueryOrderResult uniPayResult = JSON.parseObject(execute.body(), QueryOrderResult.class); return uniPayResult; } /** * 退款 * @param orderNo 支付订单号 * @param refundOrderNo 退款订单号 * @param refundAmount 退款金额 * @param notifyUrl 异步通知地址 * @return */ public static RefundResult refund(String orderNo, String refundOrderNo, Double refundAmount, String notifyUrl){ String url = "https://trade.joinpay.com/tradeRt/refund"; HttpRequest post = HttpUtil.createPost(url); post.header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded"); JSONObject body = new JSONObject(); //版本号 body.put("p0_Version", "2.3"); //商户编号 body.put("p1_MerchantNo", merchantNo); //商户订单号 body.put("p2_OrderNo", orderNo); //商户退款订单号 body.put("p3_RefundOrderNo", refundOrderNo); //退款金额 body.put("p4_RefundAmount", refundAmount); //服务器异步通知地址 body.put("p6_NotifyUrl", callbackUrl + notifyUrl); String sign = null; try { sign = sign(body); } catch (Exception e) { throw new RuntimeException(e); } body.put("hmac", sign); post.form(body); log.info("退款接口请求参数:" + body); HttpResponse execute = post.execute(); log.info("退款接口请求响应:" + execute.body()); if(200 != execute.getStatus()){ log.error("退款接口异常:" + execute.body()); return null; } RefundResult uniPayResult = JSON.parseObject(execute.body(), RefundResult.class); return uniPayResult; } /** * 查询退款订单 * @param refundOrderNo 退款订单号 * @return */ public static QueryRefundResult queryRefund(String refundOrderNo){ String url = "https://trade.joinpay.com/tradeRt/refund"; HttpRequest post = HttpUtil.createPost(url); post.header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded"); JSONObject body = new JSONObject(); //版本号 body.put("p0_Version", "2.3"); //商户编号 body.put("p1_MerchantNo", merchantNo); //商户退款订单号 body.put("p2_RefundOrderNo", refundOrderNo); String sign = null; try { sign = sign(body); } catch (Exception e) { throw new RuntimeException(e); } body.put("hmac", sign); post.form(body); log.info("退款接口请求参数:" + body); HttpResponse execute = post.execute(); log.info("退款接口请求响应:" + execute.body()); if(200 != execute.getStatus()){ log.error("退款接口异常:" + execute.body()); return null; } QueryRefundResult uniPayResult = JSON.parseObject(execute.body(), QueryRefundResult.class); return uniPayResult; } /** * 关闭订单(仅支持微信和支付宝) * @param orderNo 订单号 * @return */ public static CloseOrderResult closeOrder(String orderNo){ String url = "https://www.joinpay.com/trade/closeOrder.action"; HttpRequest post = HttpUtil.createPost(url); post.header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded"); JSONObject body = new JSONObject(); //商户编号 body.put("p1_MerchantNo", merchantNo); //商户订单号 body.put("p2_OrderNo", orderNo); //交易类型 body.put("p3_FrpCode", FrpCodeEnum.WEIXIN_XCX.getCode()); String sign = null; try { sign = sign(body); } catch (Exception e) { throw new RuntimeException(e); } body.put("hmac", sign); post.form(body); log.info("关闭订单接口请求参数:" + body); HttpResponse execute = post.execute(); log.info("关闭订单接口请求响应:" + execute.body()); if(200 != execute.getStatus()){ log.error("关闭订单接口异常:" + execute.body()); return null; } CloseOrderResult uniPayResult = JSON.parseObject(execute.body(), CloseOrderResult.class); return uniPayResult; } public static String sign(JSONObject body) { Set> entries = body.entrySet(); List> infoIds = new ArrayList>(entries); // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) Collections.sort(infoIds, new Comparator>() { public int compare(Map.Entry o1, Map.Entry o2) { return (o1.getKey()).compareTo(o2.getKey()); } }); // 构造签名键值对的格式 StringBuilder sb = new StringBuilder(); for (Map.Entry item : infoIds) { if (item.getKey() != null || item.getKey() != "") { Object val = item.getValue(); if (!(val == "" || val == null)) { sb.append(val); } } } sb.append(key); log.info("待签名串:{}", sb.toString()); return MD5AndKL.MD5(sb.toString()); } public static void main(String[] args) { // UniPayResult uniPayResult = PaymentUtil.uniPay("852963742", 0.01D, "测试商品", "这是用于对接支付测试的商品描述", // "", "/order/shopping-cart/shoppingCartPaymentCallback", "ooOrs64zHLuInkZ_GF0LpIN9_Rxc", "777168500885852"); // PaymentUtil.queryOrder("852963742"); // PaymentUtil.closeOrder("852963742"); } }