Java对接微信支付(史上最详细)

Java对接微信支付(史上最详细)

本文将介绍如何使用Java对接微信支付,包括获取支付参数、支付回调处理等步骤。本文适用于已经熟悉微信支付基本原理的读者。

开发环境

  • JDK 1.8
  • Maven
  • Spring Boot 2.x
  • 微信支付开发文档

第一步:获取支付参数

为了进行支付,我们需要先获取微信支付的参数信息,包括appid、商户id、支付密钥等。

配置文件

我们可以将这些参数信息放在一个配置文件中,以便后续使用。在Spring Boot中,可以通过application.yml或者application.properties文件配置。

wechat:
  appid: xxx # 微信公众号appid
  mchid: xxx # 商户id
  key: xxx # 支付密钥
  notifyUrl: xxx # 支付回调地址

获取签名

获取到参数信息后,我们需要对其进行签名,以确保支付安全性。签名算法具体可以参考微信官方文档。

public static String sign(Map<String, String> params, String key) {
    
    
    String signStr = SignUtil.createLinkString(params) + "&key=" + key;
    return MD5Util.md5(signStr).toUpperCase();
}

其中,createLinkString方法用于将参数按照字典序拼接为一个字符串,MD5Util.md5方法用于生成MD5签名,toUpperCase方法用于将签名转换成大写。

第二步:生成支付参数

获取到签名后,我们需要根据支付金额、订单号等信息生成一个可以供客户端调用的支付参数。

统一下单接口

我们可以通过微信提供的统一下单接口生成支付参数。

public static Map<String, String> unifiedOrder(String appid, String mchId, String key, String body, String outTradeNo, int totalFee, String spBillCreateIp, String notifyUrl, String tradeType, String openid) throws Exception {
    
    
    Map<String, String> params = new HashMap<>();
    params.put("appid", appid);
    params.put("mch_id", mchId);
    params.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
    params.put("body", body);
    params.put("out_trade_no", outTradeNo);
    params.put("total_fee", String.valueOf(totalFee));
    params.put("spbill_create_ip", spBillCreateIp);
    params.put("notify_url", notifyUrl);
    params.put("trade_type", tradeType);
    params.put("openid", openid);
    params.put("sign", SignUtil.sign(params, key));
    String xml = HttpUtil.post(UNIFIED_ORDER_URL, XmlUtil.mapToXml(params));
    Map<String, String> result = XmlUtil.xmlToMap(xml);
    if ("SUCCESS".equals(result.get("return_code")) && "SUCCESS".equals(result.get("result_code"))) {
    
    
        return result;
    } else {
    
    
        throw new Exception(result.get("return_msg"));
    }
}

其中,UNIFIED_ORDER_URL为统一下单接口地址。HttpUtil.post方法用于发送POST请求并获取响应结果,XmlUtil.mapToXml和XmlUtil.xmlToMap方法用于将Map对象和XML字符串互相转换。

生成支付参数

统一下单接口返回的结果中包含了prepay_id,我们需要将其作为参数再次签名生成支付参数。

public static String createPayParams(String appId, String prepayId, String key) {
    
    
    Map<String, String> params = new HashMap<>();
    params.put("appId", appId);
    params.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
    params.put("nonceStr", UUID.randomUUID().toString().replaceAll("-", ""));
    params.put("package", "prepay_id=" + prepayId);
    params.put("signType", "MD5");
    params.put("paySign", SignUtil.sign(params, key));
    return JsonUtil.toJson(params);
}

其中,JsonUtil.toJson方法用于将Map对象转换成JSON字符串。

第三步:处理支付回调

当客户端支付完成后,微信会回调我们预先设置的支付回调地址,我们需要在该地址上接收并处理回调信息。

支付回调接口

我们可以将支付回调信息封装成一个实体类,用于接收并处理回调信息。

@Data
public class PayNotify {
    
    
    private String return_code;
    private String return_msg;
    private String appid;
    private String mch_id;
    private String nonce_str;
    private String sign;
    private String result_code;
    private String openid;
    private String trade_type;
    private String bank_type;
    private Integer total_fee;
    private String fee_type;
    private String transaction_id;
    private String out_trade_no;
    private String attach;
    private String time_end;
}

处理支付结果

接收到支付回调信息后,我们需要校验签名并处理支付结果。

@PostMapping("/pay/notify")
public String payNotify(@RequestBody PayNotify payNotify) {
    
    
    Map<String, String> params = new HashMap<>();
    params.put("appid", payNotify.getAppid());
    params.put("mch_id", payNotify.getMch_id());
    params.put("nonce_str", payNotify.getNonce_str());
    params.put("result_code", payNotify.getResult_code());
    params.put("openid", payNotify.getOpenid());
    params.put("trade_type", payNotify.getTrade_type());
    params.put("bank_type", payNotify.getBank_type());
    params.put("total_fee", payNotify.getTotal_fee().toString());
    params.put("fee_type", payNotify.getFee_type());
    params.put("transaction_id", payNotify.getTransaction_id());
    params.put("out_trade_no", payNotify.getOut_trade_no());
    params.put("attach", payNotify.getAttach());
    params.put("time_end", payNotify.getTime_end());
    String sign = SignUtil.sign(params, key);
    if (!sign.equals(payNotify.getSign())) {
    
    
        return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名错误]]></return_msg></xml>";
    }
    // 处理支付结果
    return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
}

其中,key为支付密钥。

总结

本文介绍了使用Java对接微信支付的步骤,包括获取支付参数、生成支付参数、处理支付回调等。希望对大家有所帮助。

猜你喜欢

转载自blog.csdn.net/Ellis_li/article/details/131010470
今日推荐