2022微信支付v3 - Native

Native支付介绍

参考文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_0.shtml

Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。

应用场景

Native支付适用于PC网站、实体店单品或订单、媒体广告支付等场景

用户扫描商户展示在各种场景的二维码进行支付,具体操作流程如下:

接入前准备

参考文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_7_1.shtml#top

选择接入模式

  • 直连模式
  • 服务商模式

参数申请

注意:appid 和 mchid 是必须的。

配置API key

API v3密钥主要用于平台证书解密、回调信息解密,具体使用方式可参见接口规则文档中证书和回调报文解密章节。

img

注意:这里我们设置的是 API v3密钥,不是 API v2密钥。

下载并配置商户证书

在【证书工具】-“生成证书”环节,已完成申请证书流程,点击“查看证书文件夹”,查看已生成的证书文件。

恭喜,到此一切准备就绪!

关于API v3

为了在保证支付安全的前提下,带给商户简单、一致且易用的开发体验,我们推出了全新的微信支付API v3。

相较于之前的微信支付API,主要区别是:

  • 遵循统一的REST的设计风格
  • 使用JSON作为数据交互的格式,不再使用XML
  • 使用基于非对称密钥的SHA256-RSA的数字签名算法,不再使用MD5或HMAC-SHA256
  • 不再要求携带HTTPS客户端证书(仅需携带证书序列号)
  • 使用AES-256-GCM,对回调中的关键信息进行加密保护

数据格式

所有的API请求必须使用HTTPS。

微信支付API v3使用 JSON 作为消息体的数据交换格式,图片上传API除外。请求须设置HTTP头部:

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

错误信息

微信支付API v3使用HTTP状态码来表示请求处理的结果。

  • 处理成功的请求,如果有应答的消息体将返回200,若没有应答的消息体将返回204。
  • 已经被成功接受待处理的请求,将返回202。
  • 请求处理失败时,如缺少必要的入参、支付时余额不足,将会返回4xx范围内的错误码。
  • 请求处理时发生了微信支付侧的服务系统错误,将返回500/501/503的状态码。这种情况比较少见。

微信支付v3 实战

环境:

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

准备

需要提前准备以下的材料

添加依赖

参考地址: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>

其他

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

配置文件

修改 application.yml 文件

wx:
  pay:
    appId: 请填写您的appId
    mchId: 请填写您的mchId
    apiV3Key: 请填写您的apiV3Key
    privateCertPath: 请填写您的apiclient_cert.pem所在文件(绝对路径或相对路径)
    privateKeyPath: 请填写您的apiclient_key.pem所在文件(绝对路径或相对路径)
    notifyUrl: 请填写您的支付成功回调地址(必须https开头且公网可访问)

配置支付环境

新增两个配置文件,完成支付环境初始化

WxPayPropertiesV3

读取配置文件的内容

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 {
    /**
     * 设置微信公众号或者小程序等的appid
     */
    private String appId;

    /**
     * 微信支付商户号
     */
    private String mchId;

    /**
     * apiV3 秘钥值
     */
    private String apiV3Key;

    /**
     * apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径.
     */
    private String privateCertPath;

    /**
     * apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径
     */
    private String privateKeyPath;

    /**
     * 该链接是通过基础下单接口中的请求参数“notify_url”来设置的,要求必须为https地址。
     * 请确保回调URL是外部可正常访问的,且不能携带后缀参数,否则可能导致商户无法接收到微信的回调通知信息。
     * 回调URL示例:“https://pay.weixin.qq.com/wxpay/pay.action”
     */
    private String notifyUrl;

}

WxPayConfiguration

完成支付环境初始化

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()));

        // 可以指定是否使用沙箱环境
        payConfig.setUseSandboxEnv(false);

        // 微信支付接口请求实现类,默认使用Apache HttpClient实现
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }

}

其中 WxPayServiceImpl 是微信支付接口请求实现类,默认使用Apache HttpClient实现。

工具类

微信订单工具类

package com.ray.weixin.utils;

import lombok.extern.slf4j.Slf4j;

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

/**
 * @ClassName: WxOrderUtils
 * @Description: 微信订单工具类
 * @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";

    /**
     * 生成商户订单号
     *
     * @return
     */
    public static String genOutTradeNo() {
        String order = ORDER_PAY_PREFIX + new SimpleDateFormat(FORMAT).format(new Date());
        log.debug("生成商户订单号: [{}]", order);
        return order;
    }

    /**
     * 生成退款订单号
     *
     * @return
     */
    public static String genRefundOrder() {
        String order = ORDER_REFUND_PREFIX + new SimpleDateFormat(FORMAT).format(new Date());
        log.debug("生成退款订单号: [{}]", order);
        return order;
    }
}

请求头工具类

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: 请求头工具类
 * @Author: Ray
 * @Date: 2022-02-10 8:48
 */
@Slf4j
public class HtmlUtils {

    /**
     * 获取请求头信息
     *
     * @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;
    }


    /**
     * 获取请求头签名
     *
     * @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;
    }
}

处理通知应答类

package com.ray.common.core.domain;

import java.util.HashMap;

/**
 * @Description: 微信支付V3 通知应答
 * 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", "失败");
        return r;
    }

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

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

支付异常类

package com.ray.common.exception;

/**
 * 支付异常类
 *
 * @author Ray
 */
public class WeixinPayException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    private String msg;
    private int code = 500;

    public WeixinPayException() {
        super("支付异常,请联系管理员");
    }

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

参考文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml

商户后台系统先调用微信支付的Native下单接口,微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。

注意

code_url有效期为2小时,过期后扫码不能再发起支付。

所以我们在处理订单的时候,如果是重复的订单,可以直接返回有效期内的二维码,不用再次请求。

业务流程时序图

服务层

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: 微信支付远程服务
 * @Author: Ray
 * @Date: 2022-02-10 14:09
 */
@Service
@Slf4j
public class WxPayRemoteService {

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

    /**
     * @Description: 调用下单API
     * @Author: Ray
     * @Date: 2022-02-10 14:54
     **/
    public Map<String, Object> createOrderV3() throws WxPayException {
        log.debug("创建订单 >>>>> ");
		// 商品描述
        String description = "自定义商品描述";
        // 商户订单号
        String outTradeNo = WxOrderUtils.genOutTradeNo();
        // 总金额,单位分
        Integer total = 1;
        
        WxPayUnifiedOrderV3Request request = this.genWxPayUnifiedOrderV3Request(description, outTradeNo, total);
        String qrCode = wxService.createOrderV3(TradeTypeEnum.NATIVE, request);

        // 返回需要的信息
        HashMap<String, Object> map = new HashMap<>();;
        map.put("qrCode", qrCode);
        map.put("outTradeNo", outTradeNo);
        return map;
    }

    /**
     * @Description: 组装请求数据
     * @Author: Ray
     * @Date: 2022-02-10 14:30
     **/
    private WxPayUnifiedOrderV3Request genWxPayUnifiedOrderV3Request(String description, String outTradeNo, Integer total) {
        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
        // 商品描述
        request.setDescription(description);
        // 商户订单号
        request.setOutTradeNo(outTradeNo);

        // 通知地址
        request.setNotifyUrl(properties.getNotifyUrl());
        // 订单金额
        WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
        // 总金额,单位分
        amount.setTotal(total);
        // 货币类型,选填
        amount.setCurrency("CNY");
        request.setAmount(amount);
        return request;
    }
}

请求层

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: 微信支付接口
 * @Author: Ray
 * @Date: 2022-02-08 15:10
 */
@RestController
@RequestMapping("/feign/wxPay")
public class WxPayFeign extends BaseController {

    @Autowired
    private WxPayRemoteService wxPayRemoteService;

    /**
     * 生成商户订单号
     */
    @GetMapping("genOutTradeNo")
    public String genOutTradeNo() {
        return WxOrderUtils.genOutTradeNo();
    }

    /**
     * 生成退款订单
     */
    @GetMapping("genOutRefundNo")
    public String genOutRefundNo() {
        return WxOrderUtils.genRefundOrder();
    }

    /**
     * 调用统一下单接口
     *
     */
    @GetMapping("createOrderV3")
    public R createOrderV3() {
        try {
            logger.debug("调用统一下单接口 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            // 先查询数据,如果存在并且二维码在有效期内,则直接返回(省略)

            // 调用下单API
            HashMap<String, Object> map = wxPayRemoteService.createOrderV3();
            // 商品订单号
            String outTradeNo = map.get("outTradeNo");
            // 二维码
            String qrCode = map.get("qrCode");

            // 保存数据(省略)
            
            // 返回数据
            return R.data(map);
        } catch (WxPayException e) {
            e.printStackTrace();
            throw new WeixinPayException(e.getErrCodeDes());
        } 
        return R.error();
    }
}

支付通知API

文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml

微信支付通过支付通知接口将用户支付成功消息通知给商户

tip: 如果没有公网地址的,可以使用内网穿透。

注意:

• 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是,当商户系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。

• 如果在所有通知频率后没有收到微信侧回调,商户应调用查询订单接口确认订单状态。

**特别提醒:**商户系统对于开启结果通知的内容一定要做签名验证,并校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。

通知应答

支付通知http应答码为200或204才会当作正常接收,当回调处理异常时,应答的HTTP状态码应为500,或者4xx。

支付通知的返回参数如下:

服务层

/**
 * @ClassName: WxPayRemoteService
 * @Description: 微信支付远程服务
 * @Author: Ray
 * @Date: 2022-02-10 14:09
 */
@Service
@Slf4j
public class WxPayRemoteService {

    @Autowired
    private WxPayService wxService;
    @Autowired
    private WxPayPropertiesV3 properties;
    
    // 忽略部分代码

    /**
     * @Description: 解析支付结果v3通知
     * @Author: Ray
     * @Date: 2022-02-10 14:10
     **/
    public WxPayOrderNotifyV3Result parseOrderNotifyV3Result(HttpServletRequest request) throws WxPayException {
        // 解析支付结果v3通知
        return wxService.parseOrderNotifyV3Result(
                HtmlUtils.fetchRequest2Str(request),
                HtmlUtils.fetchRequest2SignatureHeader(request)
        );
    }

}

请求层

/**
 * @ClassName: WxPayFeign
 * @Description: 微信支付接口
 * @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();

    // 忽略部分代码

    /**
     * @Description: 支付成功异步通知
     * @Author: Ray
     * @Date: 2022-02-13 9:37
     **/
    @PostMapping("/native/notify")
    public WxPayResult nativeNotify(HttpServletRequest request) {
        logger.debug("支付成功异步通知 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        if (lock.tryLock()) {
            try {
                // 解析支付结果v3通知
                WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = wxPayRemoteService.parseOrderNotifyV3Result(request);

                // 获取基本信息
                String tradeState = wxPayOrderNotifyV3Result.getResult().getTradeState();
                String tradeStateDesc = wxPayOrderNotifyV3Result.getResult().getTradeStateDesc();
                String outTradeNo = wxPayOrderNotifyV3Result.getResult().getOutTradeNo();

                // 获取用户支付订单信息(省略)
                
                // 如果已经处理,直接返回成功标识
                if (StringUtils.isNotBlank(user.getTradeState()) &&
                        WxPayConstants.WxpayTradeStatus.SUCCESS.equals(user.getTradeState())) {
                    // 返回成功标识
                    return WxPayResult.ok();
                }

                // 业务逻辑...(省略)

                // 返回成功标识
                return WxPayResult.ok();

            } catch (WxPayException e) {
                logger.error(e.getMessage());
                // 返回失败标识
                return WxPayResult.error();
            } finally {
                lock.unlock();
            }
        }
        // 返回失败标识
        return WxPayResult.error();
    }
}

查询订单API

参考文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_2.shtml

商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。

注意

查询订单可通过微信支付订单号商户订单号两种方式查询,两种查询方式返回结果相同

服务层

/**
 * @ClassName: WxPayRemoteService
 * @Description: 微信支付远程服务
 * @Author: Ray
 * @Date: 2022-02-10 14:09
 */
@Service
@Slf4j
public class WxPayRemoteService {

    @Autowired
    private WxPayService wxService;
    @Autowired
    private WxPayPropertiesV3 properties;
    
    // 忽略部分代码

    /**
     * @Description: 查询订单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("查询订单结果 >>>>> " + wxPayOrderQueryV3Result);
        return wxPayOrderQueryV3Result;
    }  
}

请求层

/**
 * @ClassName: WxPayFeign
 * @Description: 微信支付接口
 * @Author: Ray
 * @Date: 2022-02-08 15:10
 */
@RestController
@RequestMapping("/feign/wxPay")
public class WxPayFeign extends BaseController {

    @Autowired
    private WxPayRemoteService wxPayRemoteService;

    // 忽略部分代码

    /**
     * 调用查询订单接口
     *
     */
    @GetMapping("queryOrderV3/{outTradeNo}")
    public R queryOrderV3(@PathVariable("outTradeNo") String outTradeNo) {
        try {
            logger.debug("调用查询订单接口 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            // 查询订单
            WxPayOrderQueryV3Result wxPayOrderQueryV3Result = wxPayRemoteService.queryOrderV3("", outTradeNo);

            // 保存数据(省略)
            
            // 返回数据
            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();
    }
}

结语

其他接口的使用方法相似,这里就不演示了。

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值