SpringBoot实现微信支付

在目前的互联网上,我们已经经常使用微信支付进行各种支付操作。微信支付作为一种移动支付的新时代产品,新颖的功能和稳定的操作流程使得它在用户中深得信任。对于一些企业或者个人,如何实现和使用微信支付成了一个不可避免的问题。为此,本文将介绍如何使用SpringBoot来快速实现微信支付的功能。

准备工作

在实现微信支付之前,需要先确保满足以下条件:

  • 使用微信公众号或者小程序账号,并开通支付功能;
  • 有自己的服务器,能够接收微信支付的通知;
  • 使用Java SpringBoot框架。

如果已经满足以上条件,则可以开始进行以下步骤。

申请微信支付

首先需要前往微信公众平台或者微信开放平台进行注册和登录。在登录之后,在菜单中找到“开发者中心”,并选择“开发设置”,然后找到“微信支付”功能,进入申请流程。

在申请过程中,需要填写一些相关的信息,并上传一些必须的文件(如商户证书等)。在完成审核之后,会获得一些必要的信息,如appidmch_idkey 等。

引入依赖

在SpringBoot项目中,使用微信支付需要引入对应的依赖。在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>    
    <groupId>com.github.wxpay</groupId>    
    <artifactId>wxpay-sdk</artifactId>
    <version>3.0.10</version>
</dependency>

注意:以上依赖中的版本号可能跟您当前使用的版本号不一致,可以根据实际情况进行更改。

配置参数

在项目的配置文件中,需要添加以下配置信息:

#微信支付的相关配置
wxpay.appid=你的appid
wxpay.mchid=你的商户id
wxpay.key=你的商户key
wxpay.notifyurl=你的后台接收微信支付结果通知的url
wxpay.trade_type=JSAPI
# 等等

代码实现

预支付

在使用微信支付之前,需要先生成一个预支付订单,在此之后才能发起支付。以下代码实现了通过预支付生成支付订单并获取支付信息:

/**
 * 创建统一下单接口
 * @param order
 * @return
 * @throws Exception
 */
public Map<String, String> createUnifiedOrder(Order order) throws Exception {
    
    
    // 1.生成随机字符串
    String nonceStr = WXPayUtil.generateNonceStr();
    // 2.生成订单号
    String outTradeNo = order.getOutTradeNo();
    // 3.获取订单金额,单位是分
    String totalFee = order.getTotalFee().toString();
    // 4.获取用户openId(JSAPI支付必需)
    String openid = order.getOpenid();
    // 5.配置统一下单参数
    Map<String, String> data = new HashMap<>();
    data.put("appid", wxpayAppid);
    data.put("mch_id", wxpayMchid);
    data.put("nonce_str", nonceStr);
    if (order.getBody() != null) {
    
    
        data.put("body", order.getBody()); 
    }
    data.put("out_trade_no", outTradeNo);
    data.put("total_fee", totalFee);
    data.put("spbill_create_ip", order.getSpbillCreateIp()); 
    data.put("notify_url", wxpayNotifyurl); 
    data.put("trade_type", wxpayTrade_type); 
    data.put("openid", openid); 
    // 6.生成签名
    String sign = WXPayUtil.generateSignature(data, wxpayKey, WXPayConstants.SignType.MD5);
    data.put("sign", sign);
    // 7.将参数转换为XML格式,通过HTTP请求调用微信支付接口
    String requestXml = WXPayUtil.mapToXml(data);
    WXPay wxPay = new WXPay(wxpayConfig);
    Map<String, String> resultMap = wxPay.unifiedOrder(data);
    // 8.对微信支付接口返回的数据进行处理并返回,包括二次签名和返回给前端的数据格式处理。
    Map<String, String> resultMap = wxPay.unifiedOrder(data);
    String returnCode = resultMap.get("return_code");
    String resultCode = resultMap.get("result_code");
    if(WXPayConstants.SUCCESS.equals(returnCode) && WXPayConstants.SUCCESS.equals(resultCode)) {
    
    
        String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
        String prepayId = resultMap.get("prepay_id");
        // 生成响应给前端的参数列表
        Map<String, String> responseMap = new HashMap<>();
        responseMap.put("timeStamp", timeStamp);
        responseMap.put("nonceStr", nonceStr);
        responseMap.put("signType", WXPayConstants.MD5);
        responseMap.put("package", "prepay_id=" + prepayId);
        // 二次签名
        String responseSign = WXPayUtil.generateSignature(responseMap, wxpayKey, WXPayConstants.SignType.MD5);
        responseMap.put("paySign", responseSign);
        return responseMap;
    } else {
    
    
        return null;
    }
}

支付结果回调

支付结果回调通知是微信支付中非常重要的一步,因为它能够实时地将支付的结果反馈给我们的服务端。当用户支付成功后,微信会通过POST方式把相关支付通知发送到我们所设定的回调URL上,我们需要在回调URL所在的服务中对支付结果进行处理。

/**
 * 微信支付结果通知接口(POST方式)
 * @param request
 * @param response
 * @return
 */
@ResponseBody
@PostMapping(value="/wxpay/notify")
public String handleWxPayNotify(HttpServletRequest request, HttpServletResponse response) {
    
    
    try {
    
    
        ServletInputStream inputStream = request.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        String result = "";
        while((line = bufferedReader.readLine()) != null){
    
    
            result += line;
        }
        // 此处 result 就是接受到的微信支付异步通知报文,直接使用WXPayUtil工具解析xml报文内容即可
        Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
        // 通过微信支付通知的返回结果,校验是否支付成功
        String returnCode = resultMap.get("return_code");
        String resultCode = resultMap.get("result_code");
        if(WXPayConstants.SUCCESS.equals(returnCode) && WXPayConstants.SUCCESS.equals(resultCode)) {
    
    
            String outTradeNo = resultMap.get("out_trade_no");
            //... 业务逻辑处理
            // 返回给微信支付结果通知接收服务器的信息
            String returnMsg = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
            return returnMsg;
        } else {
    
    
            String returnMsg = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[支付失败]]></return_msg>" + "</xml>";
            return returnMsg;
        }
    } catch (Exception e) {
    
    
        logger.error("微信支付结果回调出现异常:{}", e.getMessage());
        return null;
    }
}

完整的控制器代码如下:

package com.example.demo.controller;

import com.example.demo.config.WxpayConfig;
import com.example.demo.dto.Order;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

@RestController
public class WxPayController {
    
    

    private static final Logger logger = LoggerFactory.getLogger(WxPayController.class);

    @Autowired
    private WxpayConfig wxpayConfig;

    @Value("${wxpay.appid}")
    private String wxpayAppid;

    @Value("${wxpay.mchid}")
    private String wxpayMchid;

    @Value("${wxpay.key}")
    private String wxpayKey;

    @Value("${wxpay.notifyurl}")
    private String wxpayNotifyurl;

    @Value("${wxpay.trade_type}")
    private String wxpayTrade_type;

    /**
     * 创建统一下单接口
     * @param order
     * @return
     * @throws Exception
     */
    public Map<String, String> createUnifiedOrder(Order order) throws Exception {
    
    
        // 1.生成随机字符串
        String nonceStr = WXPayUtil.generateNonceStr();
        // 2.生成订单号
        String outTradeNo = order.getOutTradeNo();
        // 3.获取订单金额,单位是分
        String totalFee = order.getTotalFee().toString();
        // 4.获取用户openId(JSAPI支付必需)
        String openid = order.getOpenid();
        // 5.配置统一下单参数
        Map<String, String> data = new HashMap<>();
        data.put("appid", wxpayAppid);
        data.put("mch_id", wxpayMchid);
        data.put("nonce_str", nonceStr);
        if (order.getBody() != null) {
    
    
            data.put("body", order.getBody()); 
        }
        data.put("out_trade_no", outTradeNo);
        data.put("total_fee", totalFee);
        data.put("spbill_create_ip", order.getSpbillCreateIp()); 
        data.put("notify_url", wxpayNotifyurl); 
        data.put("trade_type", wxpayTrade_type); 
        data.put("openid", openid); 
        // 6.生成签名
        String sign = WXPayUtil.generateSignature(data, wxpayKey, WXPayConstants.SignType.MD5);
        data.put("sign", sign);
        // 7.将参数转换为XML格式,通过HTTP请求调用微信支付接口
        String requestXml = WXPayUtil.mapToXml(data);
        WXPay wxPay = new WXPay(wxpayConfig);
        Map<String, String> resultMap = wxPay.unifiedOrder(data);
        // 8.对微信支付接口返回的数据进行处理并返回,包括二次签名和返回给前端的数据格式处理。
        Map<String, String> resultMap = wxPay.unifiedOrder(data);
        String returnCode = resultMap.get("return_code");
        String resultCode = resultMap.get("result_code");
        if(WXPayConstants.SUCCESS.equals(returnCode) && WXPayConstants.SUCCESS.equals(resultCode)) {
    
    
            String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
            String prepayId = resultMap.get("prepay_id");
            // 生成响应给前端的参数列表
            Map<String, String> responseMap = new HashMap<>();
            responseMap.put("timeStamp", timeStamp);
            responseMap.put("nonceStr", nonceStr);
            responseMap.put("signType", WXPayConstants.MD5);
            responseMap.put("package", "prepay_id=" + prepayId);
            // 二次签名
            String responseSign = WXPayUtil.generateSignature(responseMap, wxpayKey, WXPayConstants.SignType.MD5);
            responseMap.put("paySign", responseSign);
            return responseMap;
        } else {
    
    
            return null;
        }
    }

    /**
     * 微信支付结果通知接口(POST方式)
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @PostMapping(value="/wxpay/notify")
    public String handleWxPayNotify(HttpServletRequest request, HttpServletResponse response) {
    
    
        try {
    
    
            ServletInputStream inputStream = request.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            String result = "";
            while((line = bufferedReader.readLine()) != null){
    
    
                result += line;
            }
            // 此处 result 就是接受到的微信支付异步通知报文,直接使用WXPayUtil工具解析xml报文内容即可
            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
            // 通过微信支付通知的返回结果,校验是否支付成功
            String returnCode = resultMap.get("return_code");
            String resultCode = resultMap.get("result_code");
            if(WXPayConstants.SUCCESS.equals(returnCode) && WXPayConstants.SUCCESS.equals(resultCode)) {
    
    
                String outTradeNo = resultMap.get("out_trade_no");
                //... 业务逻辑处理
                // 返回给微信支付结果通知接收服务器的信息
                String returnMsg = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml>";
                return returnMsg;
            } else {
    
    
                String returnMsg = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[支付失败]]></return_msg>" + "</xml>";
                return returnMsg;
            }
        } catch (Exception e) {
    
    
            logger.error("微信支付结果回调出现异常:{}", e.getMessage());
            return null;
        }
    }

    /**
     * 发起微信支付
     * @param order
     * @return
     * @throws Exception
     */
    @PostMapping("/wxpay")
    public Map<String, String> wxPay(@RequestBody Order order) throws Exception {
    
    
        // 生成微信支付订单并获取支付信息
        Map<String, String> result = createUnifiedOrder(order);
        if(result != null) {
    
    
            return result;
        } else {
    
    
            return null;
        }
    }
}

总结

通过以上步骤,我们已经成功地实现了SpringBoot实现微信支付的功能。在实际使用中,您可以根据具体需求对代码进行调整,增强支付的可用性。同时我们也需要注意,支付过程中需要注意数据安全性和消息传递的可靠性。

希望本文对您有所帮助,谢谢阅读。

猜你喜欢

转载自blog.csdn.net/weixin_65950231/article/details/130824233