SpringBoot implements WeChat payment

On the current Internet, we have often used WeChat payment for various payment operations. As a product of the new era of mobile payment, WeChat Pay has won the trust of users for its novel functions and stable operation process. For some enterprises or individuals, how to implement and use WeChat payment has become an inevitable problem. To this end, this article will introduce how to use SpringBoot to quickly realize the function of WeChat payment.

Preparation

Before implementing WeChat payment, you need to ensure that the following conditions are met:

  • Use the WeChat official account or Mini Program account, and activate the payment function;
  • Has its own server and can receive WeChat payment notifications;
  • Use the Java Spring Boot framework.

If the above conditions have been met, you can start the following steps.

Apply for WeChat Pay

First, you need to go to the WeChat public platform or WeChat open platform to register and log in. After logging in, find "Developer Center" in the menu, select "Development Settings", and then find the "WeChat Payment" function to enter the application process.

During the application process, you need to fill in some relevant information and upload some necessary documents (such as merchant certificate, etc.). After completing the review, you will get some necessary information, such as appid, mch_id, keyand so on.

Introduce dependencies

In the SpringBoot project, the use of WeChat payment requires the introduction of corresponding dependencies. pom.xmlAdd the following dependencies to the file :

<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>

Note: The version number in the above dependencies may be inconsistent with the version number you are currently using, and can be changed according to the actual situation.

configuration parameters

In the configuration file of the project, the following configuration information needs to be added:

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

Code

advance payment

Before using WeChat Pay, you need to generate a prepaid order first, and then you can initiate payment. The following code realizes the generation of payment order and acquisition of payment information through prepayment:

/**
 * 创建统一下单接口
 * @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;
    }
}

Payment result callback

The payment result callback notification is a very important step in WeChat Pay, because it can feed back the payment result to our server in real time. When the user's payment is successful, WeChat will send the relevant payment notification to the callback URL we set by POST, and we need to process the payment result in the service where the callback URL is located.

/**
 * 微信支付结果通知接口(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;
    }
}

The complete controller code is as follows:

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;
        }
    }
}

Summarize

Through the above steps, we have successfully implemented the function of SpringBoot to realize WeChat payment. In actual use, you can adjust the code according to specific needs to enhance the usability of payment. At the same time, we also need to pay attention to data security and reliability of message delivery during the payment process.

I hope this article is helpful to you, thank you for reading.

Guess you like

Origin blog.csdn.net/weixin_65950231/article/details/130824233