【JAVA】汇聚支付支付实现使用

汇聚支付

汇聚支付官网文档
支付
代付

实现

配置信息

joinpay:
  # 商户编号
  user-no: 
  # 报备商户号
  report-user-no: 
  # 商户MD5签名密钥
  private-key: 
  # 产品类型
  product-code: 
  # 是否复核
  is-checked: 
  # 回调通知地址
  callback-url:
  #代付用途
  paid-use: 
  # 支付回调
  notifyUrl: 
  # 退款回调
  refundNotifyUrl: 
  # 代付回调
  paidNotifyUrl: 
@Data
@Configuration
@ConfigurationProperties(prefix = "joinpay")
public class JoinPayConfig {

    private String userNo;
    private String reportUserNo;
    private String productCode;
    private String isChecked;
    private String callbackUrl;
    private String paidUse;
    private String privateKey;
    private String notifyUrl;
    private String refundNotifyUrl;
    private String paidNotifyUrl;

}

工具类

MD5签名&验签

public class Md5_Sign {

public static String SignByMD5(String requestSign, String merchantKey) {
        String reqHmac = "";
        try {
            reqHmac = DigestUtils.md5Hex(requestSign + merchantKey).toUpperCase();
        } catch (Exception e) {}

        return reqHmac;
    }
}

post请求

public class HttpClientUtil {
    public static String sendHttpPost(String url, String body) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
        StringEntity setEntity = new StringEntity(body,"utf-8");
        setEntity.setContentType("application/json");
        setEntity.setContentEncoding("UTF-8");
        httpPost.setEntity(setEntity);


        CloseableHttpResponse response = httpClient.execute(httpPost);
        System.out.println(response.getStatusLine().getStatusCode() + "\n");
        HttpEntity entity = response.getEntity();
        String responseContent = EntityUtils.toString(entity, "UTF-8");
        System.out.println(responseContent);

        response.close();
        httpClient.close();
        return responseContent;
    }
}

工具方法

    //验签
    private static boolean nosign(String hp, String key) throws Exception {
        System.out.println("接收到:" + hp);
        JSONObject myJson = JSONObject.parseObject(hp);
        Map m = myJson;

        // 返回hmac
        String returnHmac = (String) m.remove("hmac");
        String Strmap = CreateLinkStringByGet1.createLinkStringByGet(m);

        // 返回参数组装hmac
        String hmac1 = Md5_Sign.SignByMD5(Strmap, key);
        return hmac1.equalsIgnoreCase(returnHmac);
    }

    //获取请求体
    public String getRequestBody(HttpServletRequest request) throws IOException {
        StringBuilder sb = new StringBuilder();
        String line;
        try (BufferedReader reader = request.getReader()) {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        }
        return sb.toString();
    }

    //获取请求参数
    public Map<String, String> getRequestParamsAsMap(HttpServletRequest request) {
        // 1. 创建一个新的 HashMap 用于存储结果
        Map<String, String> paramMap = new HashMap<>();

        // 2. 获取请求参数的 Map<String, String[]>
        Map<String, String[]> requestParams = request.getParameterMap();

        // 3. 遍历 requestParams 并转换到 paramMap
        requestParams.forEach((name, values) -> {
            // 对于每个参数名 (name),它的值是一个字符串数组 (values)
            // 我们通常取数组的第一个元素作为参数的值
            if (values != null && values.length > 0) {
                paramMap.put(name, values[0]);
            } else {
                paramMap.put(name, null); // 或者空字符串 ""
            }
        });

        // 4. 返回转换后的 Map
        return paramMap;
    }


    //签名
    public static String singlePayGetResponseSign(Map<String, Object> params) {

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(params.get("statusCode")).append(params.get("message")).append(params.get("errorCode"))
                .append(params.get("errorDesc")).append(params.get("userNo")).append(params.get("merchantOrderNo"));

        return stringBuilder.toString();
    }
    //....

支付&支付回调

    //支付接口
    public JSONObject uniPay(String orderNumber, BigDecimal orderPrice, String goodsName, String miniOpenid) throws Exception {

        String key = joinPayConfig.getPrivateKey();
        Map<String, String> map = new HashMap<String, String>();
        map.put("p0_Version", "2.6");// 版本号
        map.put("p1_MerchantNo", joinPayConfig.getUserNo());// 商户编号
        map.put("p2_OrderNo", orderNumber);  // 商户订单号
        map.put("p3_Amount", String.valueOf(orderPrice));//订单金额
        map.put("p4_Cur", "1"); //交易币种,人民币1
        map.put("p5_ProductName", goodsName); // 商品名称
        map.put("p6_ProductDesc", "");
        map.put("p9_NotifyUrl", joinPayConfig.getNotifyUrl()); // 服务器异步通知地址
        map.put("q1_FrpCode", "WEIXIN_XCX"); // 交易类型
        map.put("q5_OpenId", miniOpenid); // openid
        map.put("q7_AppId", wechatPayConfig.getAppId()); // appid
        map.put("qa_TradeMerchantNo", joinPayConfig.getReportUserNo()); // 报备商户号
        map.put("qi_FqSellerPercen", "0");

        String Strmap = CreateLinkStringByGet1.createLinkStringByGet(map);

        // 签名
        String sign = "";
        sign = Md5_Sign.SignByMD5(Strmap, key);
        map.put("hmac", sign);/** 签名数据 */
        System.out.println("发送:" + JSON.toJSONString(map).toString());

        // post请求参数内容

        StringBuffer param = new StringBuffer();
        for (String k : map.keySet()) {
            param.append("&");
            param.append(k).append("=").append(map.get(k));
        }
        HttpResponse response = HttpRequest.post("https://trade.joinpay.com/tradeRt/uniPay")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .body(param.toString())
                .execute();

        System.out.println("接收返回参数:" + response.body());
        boolean yesorno = nosign(response.body(), key);
        if (yesorno) {
             System.out.println("支付验签成功");
            JSONObject jsonObject = JSONObject.parseObject(response.body());
            return jsonObject.getJSONObject("rc_Result");
        } else {
             System.out.println("支付验签失败");
        }
        return new JSONObject();
    }

    //支付回调
    public void payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String key = joinPayConfig.getPrivateKey();
        response.setContentType("text/plain;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        try {
            Map<String, String> requestParamsAsMap = getRequestParamsAsMap(request);

            String r2_OrderNo = requestParamsAsMap.get("r2_OrderNo");

            Map<String, String> map = new HashMap<String, String>();
            map.put("p0_Version", "2.6");/** 版本号 */
            map.put("p1_MerchantNo", joinPayConfig.getUserNo());/** 商户编号 */
            map.put("p2_OrderNo", r2_OrderNo); /**商户订单号*/

            String Strmap = CreateLinkStringByGet1.createLinkStringByGet(map);

            // 签名
            String sign = "";
            sign = Md5_Sign.SignByMD5(Strmap, key);
            map.put("hmac", sign);/** 签名数据 */
            System.out.println("查询订单状态发送:" + JSON.toJSONString(map).toString());

            // post请求参数内容
            StringBuffer param = new StringBuffer();
            for (String k : map.keySet()) {
                param.append("&");
                param.append(k).append("=").append(map.get(k));
            }
            HttpResponse resp = HttpRequest.post("https://trade.joinpay.com/tradeRt/queryOrder")
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .body(param.toString())
                    .execute();

            System.out.println("接收返回参数:" + resp.body());
            boolean yesorno = nosign(resp.body(), key);
            if (yesorno) {
                JSONObject resData = JSONObject.parseObject(resp.body());
                Map mp = resData;
                if(mp.get("ra_Status").equals("100")){
                    response.setStatus(200);
                    response.getWriter().write("success");
                    response.getWriter().flush();
                    response.getWriter().close();
                }
            } else {
                System.out.println("订单查询验签失败");
            }
        } catch (Exception e) {
            log.error("支付回调处理失败:" + e.getMessage());
            response.setStatus(500);
            response.getWriter().flush();
            response.getWriter().close();
        }
    }

退款&退款回调

    //退款
    public String refund(String orderNumber , EsOrder esOrder , BigDecimal returnPrice) throws Exception {
        String key = joinPayConfig.getPrivateKey();
        Map<String, String> map = new HashMap<String, String>();
        map.put("p0_version", "2.3"); // 接口版本号
        map.put("p1_MerchantNo", joinPayConfig.getUserNo());//商户编号
        map.put("p2_OrderNo", orderNumber); //商户原支付订单号
        map.put("p3_RefundOrderNo", orderNumber);// 商户退款订单号
        map.put("p4_RefundAmount", String.valueOf(returnPrice)); //退款金额
        map.put("p5_RefundReason", ""); // 退款原因描述
        map.put("p6_NotifyUrl", joinPayConfig.getRefundNotifyUrl()); // 异步地址

        String Strmap = CreateLinkStringByGet1.createLinkStringByGet(map);
        // 签名
        String sign = Md5_Sign.SignByMD5(Strmap, key);
        map.put("hmac", sign);

        // post请求参数内容
        StringBuffer param = new StringBuffer();
        for (String k : map.keySet()) {
            param.append("&");
            param.append(k).append("=").append(map.get(k));
        }
        HttpResponse response = HttpRequest.post("https://trade.joinpay.com/tradeRt/refund")
                .header("Content-Type", "application/x-www-form-urlencoded")
                .body(param.toString())
                .execute();

        boolean yesorno = nosign(response.body(), key);
        if (yesorno) {
            System.out.println("验签成功");
            JSONObject myJson = JSONObject.parseObject(response.body());
            Map m = myJson;
            if (m.get("rb_Code").equals("100")) {
                //...
            }else{
                //...
            }
            Object rcCodeMsg = m.get("rc_CodeMsg");
            return rcCodeMsg.toString();
        } else {
            System.out.println("验签失败");
             return "退款发起失败";
        }
    }
    //退款回调
    public void refundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {

        String key = joinPayConfig.getPrivateKey();
        response.setContentType("text/plain;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        try {
            Map<String, String> requestParamsAsMap = getRequestParamsAsMap(request);

            String r2_RefundOrderNo = requestParamsAsMap.get("r3_RefundOrderNo");

            Map<String, String> map = new HashMap<String, String>();
            map.put("p0_Version", "2.3"); // 接口版本号
            map.put("p1_MerchantNo", joinPayConfig.getUserNo());//商户编号
            map.put("p2_RefundOrderNo", r2_RefundOrderNo);// 商户退款订单号
            String Strmap = CreateLinkStringByGet1.createLinkStringByGet(map);

            // 签名
            String sign = "";
            sign = Md5_Sign.SignByMD5(Strmap, key);
            map.put("hmac", sign);/** 签名数据 */
            System.out.println("发送:" + JSON.toJSONString(map).toString());

            // post请求参数内容
            StringBuffer param = new StringBuffer();
            for (String k : map.keySet()) {
                param.append("&");
                param.append(k).append("=").append(map.get(k));
            }
            HttpResponse resp = HttpRequest.post("https://trade.joinpay.com/tradeRt/queryRefund")
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .body(param.toString())
                    .execute();
            System.out.println("接收返回参数:" + resp.body());
            boolean yesorno = nosign(resp.body(), key);
            if (yesorno) {
                System.out.println("退款查询验签成功");
                JSONObject resData = JSONObject.parseObject(resp.body());
                Map mp = resData;
                if(mp.get("ra_Status").equals("100")){
                    response.setStatus(200);
                    response.getWriter().write("success");
                    response.getWriter().flush();
                    response.getWriter().close();
                }
            } else {
                System.out.println("退款查询验签失败");
            }
        } catch (Exception e) {
            log.error("退款回调处理失败:" + e.getMessage());
            response.setStatus(500);
            response.getWriter().flush();
            response.getWriter().close();
        }

    }

代付&代付回调

    //代付接口
    public void singlePay(EsDistributionWithdrawDepositRecord record) throws Exception {

        String key = joinPayConfig.getPrivateKey();

        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String nowStr = now.format(formatter);

        Map<String, Object> map = new HashMap<>();
        map.put("userNo", joinPayConfig.getUserNo());// 商户编号
        map.put("productCode", joinPayConfig.getProductCode());//产品类型
        map.put("requestTime", nowStr); // 交易请求时间

        map.put("merchantOrderNo", record.getWithdrawDepositRecordNumber());//商户订单号
        map.put("receiverAccountNoEnc", record.getBankCardNumber()); // 收款账户号
        map.put("receiverNameEnc", record.getBankCardHolder()); // 收款人
        map.put("receiverAccountType", record.getCarType());//账户类型
        if(record.getRoutingNumber() == null){
            record.setRoutingNumber("");
        }
        map.put("receiverBankChannelNo", record.getRoutingNumber()); // 收款账户联行号
        map.put("paidAmount", record.getWithdrawDepositAmount()); //交易金额

        map.put("currency", "201");//币种,201人民币
        map.put("isChecked", joinPayConfig.getIsChecked());//是否复核
        map.put("paidDesc", "其他");//代付说明
        map.put("paidUse", joinPayConfig.getPaidUse());//代付用途
        map.put("callbackUrl", joinPayConfig.getPaidNotifyUrl());//商户通知地址
        map.put("firstProductCode", "");//优先使用产品

        String reqSign = getRequestSign(map);
        // 签名
        String hmac = Md5_Sign.SignByMD5(reqSign, key);
        map.put("hmac", hmac);

        // post请求参数内容
        String reqBodyJson = JSON.toJSONString(map);
        System.out.println("reqBodyJson:" + reqBodyJson);
        String httpResponseJson = HttpClientUtil
                .sendHttpPost("https://www.joinpay.com/payment/pay/singlePay",reqBodyJson);

        doResponseInfo(httpResponseJson, key , record);

    }
    //代付回调
    public void singlePayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {


        String key = joinPayConfig.getPrivateKey();
        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        try {

            String jsonBody = getRequestBody(request);
            ObjectMapper mapper = new ObjectMapper();
            singPayDTO singPayDTO = mapper.readValue(jsonBody, singPayDTO.class);

            String merchantOrderNo = singPayDTO.getMerchantOrderNo();

            Map<String, Object> map = new HashMap<>();
            map.put("userNo", joinPayConfig.getUserNo());// 商户编号
            map.put("merchantOrderNo", merchantOrderNo);//商户订单号

            String reqSignSend = singlePaySearchGetRequestSign(map);
            // 签名
            String hmac = Md5_Sign.SignByMD5(reqSignSend, key);
            map.put("hmac", hmac);

            // Map转json字符串
            String reqBodyJson = JSON.toJSONString(map);
            String httpResponseJson = HttpClientUtil
                    .sendHttpPost("https://www.joinpay.com/payment/pay/singlePayQuery",reqBodyJson);
            // 响应信息map集合
            Map<String, Object> httpResponseMap = (Map<String, Object>) JSONObject.parse(httpResponseJson);
            // 业务数据map集合
            Map<String, Object> dataMap = (Map<String, Object>) httpResponseMap.get("data");
            dataMap.put("statusCode", httpResponseMap.get("statusCode"));
            dataMap.put("message", httpResponseMap.get("message"));
            // 响应签名串
            String respSign = singlePaySearchGetResponseSign(dataMap);
            // 请求数据的加密签名
            String reqHmac = Md5_Sign.SignByMD5(respSign, key);
            // 请求数据的加密签名
            String respHmac = (String) dataMap.get("hmac");
            System.out.println("reqHmac:" + reqHmac);
            System.out.println("respSign:" + respHmac);

            reqHmac=reqHmac.toUpperCase();
            respHmac=respHmac.toUpperCase();
            boolean isMatch = reqHmac.equals(respHmac);
            if (isMatch) {
                System.out.println("代查询验签成功");
                System.out.println("代付查询返回参数:" + dataMap);
                String statusCode = dataMap.get("status").toString();
                response.getWriter().print("{\"statusCode\": \"2001\", \"message\": \"成功\"}");
                response.setStatus(200);
                response.getWriter().flush();
                response.getWriter().close();
            } else {
                System.out.println("代付查询验签失败");
            }

        } catch (Exception e) {
            log.error("代付回调处理失败:" + e.getMessage());
            response.setStatus(500);
            response.getWriter().flush();
            response.getWriter().close();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值