2022 wechat payment v3 - Native

Introduction to Native payment

Reference documents: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_0.shtml

Native payment refers to the mode in which the merchant system generates a payment QR code according to the wechat payment agreement, and the user uses wechat to "scan" to complete the payment.

Application scenario

Native payment is applicable to PC website, physical store single product or order, media advertising payment and other scenarios

The user scans the QR code displayed by the merchant in various scenarios for payment. The specific operation process is as follows:

Preparation before access

Reference documents: https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_1.shtml#top

Select access mode

  • Direct Mode
  • Service provider model

Parameter application

Note: appid and mchid are required.

Configure API key

API v3 key is mainly used for platform certificate decryption and callback information decryption. Please refer to the interface rules document for specific usage Decryption of certificate and callback message Chapter.

Note: we set the API v3 key here, not the API v2 key.

Download and configure merchant certificate

In the "certificate tool" - "generate certificate" link, the certificate application process has been completed. Click "View Certificate folder" to view the generated certificate file.

Congratulations, everything is ready now!

About API v3

In order to give merchants a simple, consistent and easy-to-use development experience on the premise of ensuring payment security, we launched a new wechat payment API v3.

Compared with the previous wechat payment API, the main differences are:

  • Follow a unified REST design style
  • Use JSON as the format of data interaction instead of XML
  • The digital signature algorithm of SHA256-RSA based on asymmetric key is used, and MD5 or HMAC-SHA256 is no longer used
  • HTTPS client certificate is no longer required (only certificate serial number is required)
  • AES-256-GCM is used to encrypt and protect the key information in the callback

data format

All API requests must use HTTPS.

Wechat payment API v3 usage JSON As the data exchange format of the message body, except for the image upload API. HTTP header must be set for the request:

Content-Type: application/json
Accept: application/json

error message

Wechat payment API v3 uses HTTP status code to represent the result of request processing.

  • If the request is processed successfully, the message body will return 200 if there is a response, and 204 if there is no response.
  • If the pending request has been successfully accepted, 202 will be returned.
  • When the request processing fails, if the necessary input parameters are missing and the balance is insufficient during payment, the error code within 4xx range will be returned.
  • The service system error on wechat payment side occurs during request processing, and the status code of 500 / 501 / 503 will be returned. This is rare.

Wechat payment v3 actual combat

Environmental Science:

  • SpringBoot 2.3.2.RELEASE
  • weixin-java-pay 4.2.0
  • lombok 1.18.22
  • hutool-all 5.7.21

prepare

The following materials need to be prepared in advance

Add dependency

Reference address: https://gitee.com/binary/weixin-java-tools

<!--weixin pay -->
<dependency>
    <groupId>com.github.binarywang</groupId>
    <artifactId>weixin-java-pay</artifactId>
    <version>4.2.0</version>
</dependency>

other

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
    <scope>provided</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.7.21</version>
</dependency>

configuration file

Modify application YML file

wx:
  pay:
    appId: Please fill in your appId
    mchId: Please fill in your mchId
    apiV3Key: Please fill in your apiV3Key
    privateCertPath: Please fill in your apiclient_cert.pem File (absolute path or relative path)
    privateKeyPath: Please fill in your apiclient_key.pem File (absolute path or relative path)
    notifyUrl: Your callback address must be filled in successfully https (and accessible from the public network)

Configure payment environment

Add two configuration files to complete the initialization of payment environment

WxPayPropertiesV3

Read the contents of the configuration file

package com.ray.weixin.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * wxpay pay properties.
 *
 * @author Binary Wang
 */
@Data
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayPropertiesV3 {
    /**
     * Set up appid for WeChat official account or small program.
     */
    private String appId;

    /**
     * Wechat payment merchant No
     */
    private String mchId;

    /**
     * apiV3 Secret key value
     */
    private String apiV3Key;

    /**
     * apiclient_cert.pem The absolute path of the certificate file or the classpath starting with classpath:
     */
    private String privateCertPath;

    /**
     * apiclient_key.pem The absolute path of the certificate file or the classpath starting with classpath:
     */
    private String privateKeyPath;

    /**
     * The link is set through the request parameter "notify_url" in the basic order interface, which must be an https address.
     * Please ensure that the callback URL is externally accessible and cannot carry suffix parameters, otherwise the merchant may not receive the callback notification information of wechat.
     * Example callback URL:“ https://pay.weixin.qq.com/wxpay/pay.action ”
     */
    private String notifyUrl;

}

WxPayConfiguration

Complete payment environment initialization

package com.ray.weixin.config;

import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author Binary Wang
 */
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayPropertiesV3.class)
@AllArgsConstructor
public class WxPayConfiguration {
    private WxPayPropertiesV3 properties;

    @Bean
    @ConditionalOnMissingBean
    public WxPayService wxService() {
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
        payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));

        payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiV3Key()));
        payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));
        payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath()));
        payConfig.setNotifyUrl(StringUtils.trimToNull(this.properties.getNotifyUrl()));

        // You can specify whether to use a sandbox environment
        payConfig.setUseSandboxEnv(false);

        // The wechat payment interface request implementation class is implemented by Apache HttpClient by default
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }

}

WxPayServiceImpl is the wechat payment interface request implementation class, which is implemented by Apache HttpClient by default.

Tool class

Wechat order tools

package com.ray.weixin.utils;

import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ClassName: WxOrderUtils
 * @Description: Wechat order tools
 * @Author: Ray
 * @Date: 2022-02-16 9:28
 */
@Slf4j
public class WxOrderUtils {

    public static final String ORDER_PAY_PREFIX = "ray_pay_";
    public static final String ORDER_REFUND_PREFIX = "ray_refund_";
    public static final String FORMAT = "yyyyMMddHHmmssSSS";

    /**
     * Generate merchant order number
     *
     * @return
     */
    public static String genOutTradeNo() {
        String order = ORDER_PAY_PREFIX + new SimpleDateFormat(FORMAT).format(new Date());
        log.debug("Generate merchant order number: [{}]", order);
        return order;
    }

    /**
     * Generate refund order number
     *
     * @return
     */
    public static String genRefundOrder() {
        String order = ORDER_REFUND_PREFIX + new SimpleDateFormat(FORMAT).format(new Date());
        log.debug("Generate refund order number: [{}]", order);
        return order;
    }
}

Request header tool class

package com.ray.weixin.utils;

import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @ClassName: HtmlUtils
 * @Description: Request header tool class
 * @Author: Ray
 * @Date: 2022-02-10 8:48
 */
@Slf4j
public class HtmlUtils {

    /**
     * Get request header information
     *
     * @return
     */
    public static String fetchRequest2Str(HttpServletRequest request) {
        String reqStr = null;
        BufferedReader streamReader = null;
        try {
            streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
            StringBuilder responseStrBuilder = new StringBuilder();
            String inputStr;
            while ((inputStr = streamReader.readLine()) != null) {
                responseStrBuilder.append(inputStr);
            }
            reqStr = responseStrBuilder.toString();
            log.info("Request Received is  \n" + reqStr);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (streamReader != null) {
                    streamReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return reqStr;
    }


    /**
     * Get request header signature
     *
     * @return
     */
    public static SignatureHeader fetchRequest2SignatureHeader(HttpServletRequest request) {
        SignatureHeader signatureHeader = new SignatureHeader();
        signatureHeader.setSignature(request.getHeader("Wechatpay-Signature"));
        signatureHeader.setNonce(request.getHeader("Wechatpay-Nonce"));
        signatureHeader.setSerial(request.getHeader("Wechatpay-Serial"));
        signatureHeader.setTimeStamp(request.getHeader("Wechatpay-TimeStamp"));
        return signatureHeader;
    }
}

Processing notification response class

package com.ray.common.core.domain;

import java.util.HashMap;

/**
 * @Description: Wechat payment V3 notification response
 * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
 * @Author: Ray
 * @Date: 2022-02-13 9:39
 **/
public class WxPayResult extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    private static final String FAIL = "FAIL";
    private static final String SUCCESS = "SUCCESS";

    public static WxPayResult error() {
        WxPayResult r = new WxPayResult();
        r.put("code", FAIL);
        r.put("message", "fail");
        return r;
    }

    public static WxPayResult ok() {
        WxPayResult r = new WxPayResult();
        r.put("code", SUCCESS);
        r.put("message", "success");
        return r;
    }

    @Override
    public WxPayResult put(String key, Object value) {
        super.put(key, value);
        return this;
    }
}

Payment exception class

package com.ray.common.exception;

/**
 * Payment exception class
 *
 * @author Ray
 */
public class WeixinPayException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    private String msg;
    private int code = 500;

    public WeixinPayException() {
        super("Payment exception, please contact the administrator");
    }

    public WeixinPayException(String msg) {
        super(msg);
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}

Native order

Reference documents: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml

The merchant background system calls wechat payment first Native order Interface, wechat background system returns link parameter code_url, the merchant background system will code_ The URL value generates a QR code image, and the user initiates payment after scanning the code with the wechat client.

be careful

code_ The validity period of the URL is 2 hours. After expiration, scanning the code can no longer initiate payment.

Therefore, when processing orders, if it is a duplicate order, we can directly return the QR code within the validity period without requesting again.

Business process sequence diagram

Service layer

package com.ray.weixin.service;

import com.ray.weixin.utils;
import com.ray.common.utils.StringUtils;
import com.ray.qhummingbird.domain.PayOrder.PayOrderEntity;
import com.ray.qhummingbird.domain.UserPayOrder.UserPayOrderCreateInfoVo;
import com.ray.qhummingbird.domain.UserPayOrder.UserPayOrderEntity;
import com.ray.qhummingbird.domain.UserPayOrderLog.UserPayOrderLogEntity;
import com.ray.weixin.config.WxPayPropertiesV3;
import com.ray.weixin.domain.UserPayOrderLogRefundDto;
import com.ray.weixin.utils.HtmlUtils;
import com.ray.weixin.utils.WxOrderUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName: WxPayRemoteService
 * @Description: Wechat payment remote service
 * @Author: Ray
 * @Date: 2022-02-10 14:09
 */
@Service
@Slf4j
public class WxPayRemoteService {

    @Autowired
    private WxPayService wxService;
    @Autowired
    private WxPayPropertiesV3 properties;

    /**
     * @Description: Call order API
     * @Author: Ray
     * @Date: 2022-02-10 14:54
     **/
    public Map<String, Object> createOrderV3() throws WxPayException {
        log.debug("Create order >>>>> ");
		// Product description
        String description = "Custom item description";
        // Merchant order number
        String outTradeNo = WxOrderUtils.genOutTradeNo();
        // Total amount in minutes
        Integer total = 1;
        
        WxPayUnifiedOrderV3Request request = this.genWxPayUnifiedOrderV3Request(description, outTradeNo, total);
        String qrCode = wxService.createOrderV3(TradeTypeEnum.NATIVE, request);

        // Return the required information
        HashMap<String, Object> map = new HashMap<>();;
        map.put("qrCode", qrCode);
        map.put("outTradeNo", outTradeNo);
        return map;
    }

    /**
     * @Description: Assembly request data
     * @Author: Ray
     * @Date: 2022-02-10 14:30
     **/
    private WxPayUnifiedOrderV3Request genWxPayUnifiedOrderV3Request(String description, String outTradeNo, Integer total) {
        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
        // Product description
        request.setDescription(description);
        // Merchant order number
        request.setOutTradeNo(outTradeNo);

        // Notification address
        request.setNotifyUrl(properties.getNotifyUrl());
        // Order amount
        WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
        // Total amount in minutes
        amount.setTotal(total);
        // Currency type, optional
        amount.setCurrency("CNY");
        request.setAmount(amount);
        return request;
    }
}

Request layer

package com.ray.weixin.feign;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.ray.common.core.controller.BaseController;
import com.ray.common.core.domain.R;
import com.ray.common.core.domain.WxPayResult;
import com.ray.common.exception.WeixinPayException;
import com.ray.common.utils.StringUtils;
import com.ray.weixin.service.WxPayRemoteService;
import com.ray.weixin.utils.WxOrderUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName: WxPayFeign
 * @Description: Wechat payment interface
 * @Author: Ray
 * @Date: 2022-02-08 15:10
 */
@RestController
@RequestMapping("/feign/wxPay")
public class WxPayFeign extends BaseController {

    @Autowired
    private WxPayRemoteService wxPayRemoteService;

    /**
     * Generate merchant order number
     */
    @GetMapping("genOutTradeNo")
    public String genOutTradeNo() {
        return WxOrderUtils.genOutTradeNo();
    }

    /**
     * Generate refund order
     */
    @GetMapping("genOutRefundNo")
    public String genOutRefundNo() {
        return WxOrderUtils.genRefundOrder();
    }

    /**
     * Call unified ordering interface
     *
     */
    @GetMapping("createOrderV3")
    public R createOrderV3() {
        try {
            logger.debug("Call unified ordering interface >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            // Query the data first. If it exists and the QR code is within the validity period, it will be returned directly (omitted)

            // Call order API
            HashMap<String, Object> map = wxPayRemoteService.createOrderV3();
            // Item order number
            String outTradeNo = map.get("outTradeNo");
            // QR code
            String qrCode = map.get("qrCode");

            // Save data (omitted)
            
            // Return data
            return R.data(map);
        } catch (WxPayException e) {
            e.printStackTrace();
            throw new WeixinPayException(e.getErrCodeDes());
        } 
        return R.error();
    }
}

Payment notification API

Document address: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml

Wechat payment notifies the merchant of the user's payment success message through the payment notification interface

tip: if there is no public address, you can use intranet penetration.

be careful:

• the same notification may be sent to the merchant system multiple times. The merchant system must be able to correctly handle duplicate notifications. It is recommended that when the merchant system receives the notice for processing, it first checks the status of the corresponding business data and determines whether the notice has been processed. If it is not processed, it shall be processed again; If it has been processed, the result will be returned directly. Before checking and processing the status of business data, data lock should be used for concurrency control to avoid data confusion caused by function reentry.

• if no wechat callback is received after all notification frequencies, the merchant shall call the query order interface to confirm the order status.

**Special reminder: * * the merchant system must verify the signature of the content of the opening result notice, and verify whether the information in the notice is consistent with the information on the merchant side, so as to prevent data leakage from causing "false notice" and capital loss.

Notification response

The payment notice will be deemed to be received normally only when the HTTP response code is 200 or 204. When the callback handles exceptions, the HTTP status code of the response should be 500 or 4xx.

The return parameters of payment notice are as follows:

Service layer

/**
 * @ClassName: WxPayRemoteService
 * @Description: Wechat payment remote service
 * @Author: Ray
 * @Date: 2022-02-10 14:09
 */
@Service
@Slf4j
public class WxPayRemoteService {

    @Autowired
    private WxPayService wxService;
    @Autowired
    private WxPayPropertiesV3 properties;
    
    // Ignore partial code

    /**
     * @Description: Resolve payment result v3 notification
     * @Author: Ray
     * @Date: 2022-02-10 14:10
     **/
    public WxPayOrderNotifyV3Result parseOrderNotifyV3Result(HttpServletRequest request) throws WxPayException {
        // Resolve payment result v3 notification
        return wxService.parseOrderNotifyV3Result(
                HtmlUtils.fetchRequest2Str(request),
                HtmlUtils.fetchRequest2SignatureHeader(request)
        );
    }

}

Request layer

/**
 * @ClassName: WxPayFeign
 * @Description: Wechat payment interface
 * @Author: Ray
 * @Date: 2022-02-08 15:10
 */
@RestController
@RequestMapping("/feign/wxPay")
public class WxPayFeign extends BaseController {

    @Autowired
    private WxPayRemoteService wxPayRemoteService;

    private final ReentrantLock lock = new ReentrantLock();

    // Ignore partial code

    /**
     * @Description: Asynchronous notification of payment success
     * @Author: Ray
     * @Date: 2022-02-13 9:37
     **/
    @PostMapping("/native/notify")
    public WxPayResult nativeNotify(HttpServletRequest request) {
        logger.debug("Asynchronous notification of payment success >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        if (lock.tryLock()) {
            try {
                // Resolve payment result v3 notification
                WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = wxPayRemoteService.parseOrderNotifyV3Result(request);

                // Get basic information
                String tradeState = wxPayOrderNotifyV3Result.getResult().getTradeState();
                String tradeStateDesc = wxPayOrderNotifyV3Result.getResult().getTradeStateDesc();
                String outTradeNo = wxPayOrderNotifyV3Result.getResult().getOutTradeNo();

                // Get user payment order information (omitted)
                
                // If it has been processed, the success id is returned directly
                if (StringUtils.isNotBlank(user.getTradeState()) &&
                        WxPayConstants.WxpayTradeStatus.SUCCESS.equals(user.getTradeState())) {
                    // Return success identification
                    return WxPayResult.ok();
                }

                // Business logic (omitted)

                // Return success identification
                return WxPayResult.ok();

            } catch (WxPayException e) {
                logger.error(e.getMessage());
                // Return failure ID
                return WxPayResult.error();
            } finally {
                lock.unlock();
            }
        }
        // Return failure ID
        return WxPayResult.error();
    }
}

Query order API

Reference documents: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_2.shtml

Merchants can actively query the order status through the order query interface to complete the next business logic.

be careful

The order can be queried through Wechat payment order No and Merchant order number The two query methods return the same results

Service layer

/**
 * @ClassName: WxPayRemoteService
 * @Description: Wechat payment remote service
 * @Author: Ray
 * @Date: 2022-02-10 14:09
 */
@Service
@Slf4j
public class WxPayRemoteService {

    @Autowired
    private WxPayService wxService;
    @Autowired
    private WxPayPropertiesV3 properties;
    
    // Ignore partial code

    /**
     * @Description: Query order API
     * @Author: Ray
     * @Date: 2022-02-10 15:18
     **/
    public WxPayOrderQueryV3Result queryOrderV3(String transactionId, String outTradeNo) throws WxPayException {
        WxPayOrderQueryV3Result wxPayOrderQueryV3Result = this.wxService.queryOrderV3(transactionId, outTradeNo);
        log.debug("Query order results >>>>> " + wxPayOrderQueryV3Result);
        return wxPayOrderQueryV3Result;
    }  
}

Request layer

/**
 * @ClassName: WxPayFeign
 * @Description: Wechat payment interface
 * @Author: Ray
 * @Date: 2022-02-08 15:10
 */
@RestController
@RequestMapping("/feign/wxPay")
public class WxPayFeign extends BaseController {

    @Autowired
    private WxPayRemoteService wxPayRemoteService;

    // Ignore partial code

    /**
     * Call order query interface
     *
     */
    @GetMapping("queryOrderV3/{outTradeNo}")
    public R queryOrderV3(@PathVariable("outTradeNo") String outTradeNo) {
        try {
            logger.debug("Call order query interface >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            // Query order
            WxPayOrderQueryV3Result wxPayOrderQueryV3Result = wxPayRemoteService.queryOrderV3("", outTradeNo);

            // Save data (omitted)
            
            // Return data
            HashMap<String, Object> map = new HashMap<>();
            map.put("tradeState", wxPayOrderQueryV3Result.getTradeState());
            map.put("tradeStateDesc", wxPayOrderQueryV3Result.getTradeStateDesc());
            return R.data(map);
        } catch (WxPayException e) {
            e.printStackTrace();
            throw new WeixinPayException(e.getErrCodeDes());
        } 
        return R.error();
    }
}

epilogue

The use methods of other interfaces are similar, which will not be demonstrated here.

Keywords: Java wechat

Added by Druid on Sun, 20 Feb 2022 04:06:14 +0200