侧边栏壁纸
博主头像
杨不易呀

你的压力来源于无法自律,只是假装努力,现状跟不上内心欲望,所以你焦虑又恐慌。——杨不易呀

  • 累计撰写 72 篇文章
  • 累计创建 73 个标签
  • 累计收到 23 条评论

从零玩转系列之微信支付实战PC端支付微信取消接口搭建

杨不易呀
2023-08-03 / 0 评论 / 1 点赞 / 509 阅读 / 2,008 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2023-08-22,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

一、前言

作者: 杨不易呀

halo各位大佬很久没更新了最近在搞微信支付,因商户号审核了我半个月和小程序认证也找了资料并且将商户号和小程序进行关联,至此微信支付Native支付完成.此篇文章过长我将分几个阶段的文章发布(项目源码都有,小程序和PC端)

在此之前已经更新了微信支付开篇、微信支付安全、微信实战基础框架搭建、本次更新为微信支付实战PC端接口搭建,实战篇分为几个章节因为代码量确实有点多哈.

banner

本次项目使用技术栈

后端: SpringBoot3.1.x、Mysql8.0、MybatisPlus

前端: Vue3、Vite、ElementPlus

小程序: Uniapp、Uview

一、取消订单接口

场景

  1. 用户下单完毕后未支付 可进行取消订单

  2. 订单超时支付系统自动取消订单

修改 WechatNativeController

    /**
     * 用户取消订单
     */
    @PostMapping("/cancel/{orderNo}")
    public R<String> cancel(@PathVariable String orderNo) {
        log.info("取消订单");
        wxPayService.cancelOrder(orderNo);
        return R.ok("订单已取消");
    }

修改 wxPayService

    /**
     * 关闭订单
     */
    @SneakyThrows
    public void cancelOrder(String orderNo) {
        // ...../
      // 
        // 
        // 
        // 
      
      	
      
        // step 2 还未支付才能取消订单
    }

逻辑分析

在工作中我们逻辑可能是这样子的

step 1 查询该订单状态是否需要关闭订单,如果订单已经关闭则不需要再次关闭

思考: 我们应该去哪里查询订单的状态?

输入图片说明

假如我们去数据库查询记录的话,如果数据库因为什么原因导致状态可能不对呢?

所以我们直接去微信服务器查最新的直接更新关闭状态到数据库当中

输入图片说明

你看微信也要我们这样子玩那就万无一失直接干

================================================================

好既然我们要去调用微信查询接口我们是不是可以封装一个通用的 后续肯定有其他地方也会调用查询支付信息的情况

文档(商户): https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_2.shtml

有两种查询方式第二种方便就这么简单

代码很好理解传递商户订单号和直连商户号mchid

/**
     * 抽出公共获取微信订单信息
     */
    private WeChartOrderInfo selectOrderInfo(String orderNo) throws IOException {
        log.info("查询订单,直连商户号:{} , 微信支付订单号: {}", orderNo, wxPayConfig.getMchId());
        String url = wxPayConfig.getDomain().concat(String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo)).concat("?mchid=").concat(wxPayConfig.getMchId());
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");
        CloseableHttpResponse response = wxPayClient.execute(httpGet);
        WeChartOrderInfo weChartOrderInfo = buildBodyParams(response, WeChartOrderInfo.class);
        log.info("查询订单响应, {}", weChartOrderInfo);
        response.close();
        return weChartOrderInfo;
    }

响应结果

{
	"amount": {
		"currency": "CNY",
		"payer_currency": "CNY",
		"payer_total": 1,
		"total": 1
	},
	"appid": "wxdace645e0bc2cXXX",
	"attach": "",
	"bank_type": "OTHERS",
	"mchid": "1900006XXX",
	"out_trade_no": "44_2126281063_5504",
	"payer": {
		"openid": "o4GgauJP_mgWEWictzA15WT15XXX"
	},
	"promotion_detail": [],
	"success_time": "2021-03-22T10:29:05+08:00",
	"trade_state": "SUCCESS",
	"trade_state_desc": "支付成功",
	"trade_type": "JSAPI",
	"transaction_id": "4200000891202103228088184743"
}

完善逻辑

		/**
     * 关闭订单
     */
    @SneakyThrows
    public void cancelOrder(String orderNo) {
  			// step 1 查询该订单状态是否需要关闭订单
      	WeChartOrderInfo state = selectOrderInfo(orderNo);
				// 判断如果订单已经关闭则不需要再次关闭 更新数据库
        if (null == state || state.getTrade_state() == null) {
            // 更新本地订单状态超时关闭订单
            orderInfoService.lambdaUpdate().eq(OrderInfo::getOrderNo, orderNo).set(OrderInfo::getOrderStatus, OrderStatus.CLOSED.getType()).update();
            return;
        }
      
        // step 2 还未支付才能取消订单
        if (state.getTrade_state().equals(OrderStatus.NOTPAY.name())) {
            // step 2 进行调用微信关闭订单接口
            sendCloseRequest(orderNo);
            // step 2 更新商户端的订单状态用户取消订单
            this.orderInfoService.lambdaUpdate().eq(OrderInfo::getOrderNo, orderNo).set(OrderInfo::getOrderStatus, OrderStatus.CANCEL.getType()).update();
        }
    }

抽出通用订单关闭代码

文档: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_3.shtml

 /**
     * 发送关闭订单请求
     *
     * @param orderNo 订单编号
     */
    @SneakyThrows
    private void sendCloseRequest(String orderNo) {
        log.info("关闭订单, 订单号:{}", orderNo);
        String url = String.format(wxPayConfig.getDomain().concat(WxApiType.CLOSE_ORDER_BY_NO.getType()), orderNo);
        HttpPost httpPost = new HttpPost(url);
        Map<String, Object> paramsMap = new HashMap<>(1);
        paramsMap.put("mchid", wxPayConfig.getMchId());
        String jsonParams = JSONUtil.toJsonStr(paramsMap);
        log.info("请求参数 ===> {}", jsonParams);
        StringEntity entity = new StringEntity(jsonParams, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
            log.info("关单响应: {}", response.getEntity());
            log.info("解析body {}", buildBodyParams(response, Map.class));
        }
    }

到这里订单取消就完毕了

二、查询订单接口接口

根据上面编写的查询订单方法完善一下

修改 WechatNativeController

/**
 * 查询订单
 */
@PostMapping("/query/{orderNo}")
public R<WeChartOrderInfo> query(@PathVariable String orderNo) {
    log.info("查询订单");
    return R.ok(wxPayService.queryOrder(orderNo));
}

修改 WxPayService

/**
 * 查询订单信息
 *
 * @param orderNo 订单号
 * @return 订单信息
 */
@SneakyThrows
public WeChartOrderInfo queryOrder(String orderNo) {
    return this.selectOrderInfo(orderNo);
}

好了查询接口也写完了so easy to happy !

我们来测试看看是什么效果咯~

输入图片说明

三、测试

下单

我们还没编写到前端来所以还是和之前的文章操作一样使接口调试工具操作这里我使用之前推荐的IDEA FastRequest插件如下图

发送请求

发送

发送

生成二维码

复制codeUrl参数打开草料 https://cli.im/url 不要支付哦我们确保订单是否成功创建,确保二维码没有过期哦

下单

我们也可以先看看订单啥状态上面我们不是写了个查询订单详情的嘛

查询订单详情

调用取消订单接口

复制 orderNo 订单编号直接发送取消完成

取消订单

在查询一下订单看看状态是不是取消成功

输入图片说明


输入图片说明

最后

本期结束咱们下次再见👋~

,关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗

【选题思路】

“技术源于生活” 为什么写微信支付这种项目的文章呢? 因为我看到市面上的文章都不全面不细节不小白话更加没有配套Demo!!!

从而我的从零玩转微信支付诞生啦~ 搭配PC端、Uniapp端的不同实现.

【写作提纲】

一. 前言

通过前言表达我每次的文章内容是什么东西

二、取消订单接口实现

集结生活之中的场景来解析他的逻辑

三、查询订单接口实现

完善取消订单接口当中已经实现了的功能

四、测试

A. 通过测试用例一步步排查编写是否存在BUG

1
广告 广告

评论区