• Springboot----项目整合微信支付(用户取消订单)


    个人简介:

    📦个人主页:肇事司机赵四
    🏆学习方向:JAVA后端开发
    📣种一棵树最好的时间是十年前,其次是现在!
    🧡喜欢的话麻烦点点关注喔,你们的支持是我的最大动力。

    前言

    目前更新的是Springboot项目整合微信支付系列的文章,可以在我的主页中找到该系列其他文章,这一系列的文章将会系统介绍如何在项目中引入微信支付的下单、关单、处理回调通知等功能。由于前面创作经验不足,写的文章可能不是很好,后面我会多加努力学习怎么创作,也请各位大佬有什么建议的可以不吝赐教。因为我侧重的方面不是介绍项目开发,所以关于项目开发的具体代码可以查看文末的项目源代码(后面可能会出文章介绍该项目的开发)。喜欢的话希望大家多多点赞评论收藏,当然还可以加个关注喔,目前我的愿望是突破500粉,求各位大佬成全,我在线回。

    一:🚀问题引入

    1.1:🥃使用场景
    实际场景中会遇到用户下单之后不想要了或者其他原因而申请取消订单,取消订单并不是单单更新商户后台数据库订单状态这么简单,还需要向微信支付后台申请关闭订单服务。有两种情况需要调用微信支付的关单接口,其一就是上面提到的用户主动取消订单,其二就是订单过期自动取消。

    1.2:🥫接口说明

    • 适用对象:商户端
    • 请求URL:https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}/close
    • 请求方式:POST
    • 请求参数:String类型的直连商户号、String类型的商户订单号(长度为6-32)

    1.3:🚨注意事项
    关单没有时间限制,建议在订单生成后间隔几分钟(最短5分钟)再调用关单接口,避免出现订单状态同步不及时导致关单失败。

    二:🚀处理流程

    在这里插入图片描述
    关闭订单的处理流程比较简单,没有什么逻辑判断,只需要单纯创建远程请求对象然后完成签名并执行请求即可,最后还需要更新订单状态。

    三:🚀代码实现

    3.1:controller层

    /**
    * 用户取消订单
    * @param order
    * @return
    */
    @ApiOperation("取消订单")
    @PostMapping("/cancel")
    public R<String> cancelOrder(@RequestBody Orders order) throws Exception {
        log.info("取消订单");
        wxPayService.cancelOrder(order);
        return R.success("取消订单成功");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.2:service层

    /**
    * 取消订单
    * @param order
    */
    @Override
    public void cancelOrder(Orders order) throws Exception {
        //调用微信支付的关单接口
        this.closeOrder(order.getNumber());
    
        //更新订单状态
        Orders order_temp = ordersService.getById(order.getId());
        ordersService.updateStatusByOrderNo(order_temp.getNumber(),"5");
    }
    
    /**
    * 关单接口的调用
    * @param orderNo
    */
    @Override
    public void closeOrder(String orderNo) throws Exception {
        log.info("关单接口的调用,订单号 ===> {}", orderNo);
    
        //创建远程请求对象
        String url = String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(), orderNo);
        url = wxPayConfig.getDomain().concat(url);
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
    
        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("mchid",wxPayConfig.getMchId());
    
        objectMapper.writeValue(bos, rootNode);
        httpPost.setEntity(new StringEntity(bos.toString(StandardCharsets.UTF_8), "UTF-8"));
    
        //完成签名并执行请求
        try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
            String jsonString = JSON.toJSONString(response);
            JSONObject body = JSON.parseObject(jsonString);
            
            JSONObject statusLine = body.getJSONObject("statusLine");
            String code = statusLine.getString("statusCode");
            log.info("关闭订单成功订单号:===>{}", code);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在微信支付开发者文档中介绍说关闭订单是没有返回参数的,但是我们可以在response中获取到返回的状态码以判断是否处理成功,执行断点调试可以发现返回状态码为204。

    3.3:RabbitmqDelayConsumer

    /**
     * 监听订单延迟队列
     * @param orderNo
     * @throws Exception
    */
    @RabbitListener(queues = {"plugin.delay.order.queue"})
    public void orderDelayQueue(String orderNo, Message message, Channel channel) throws Exception {
        log.info("订单延迟队列开始消费...");
    
        try {
            //处理订单
            wxPayService.checkOrderStatus(orderNo);
            //告诉服务器收到这条消息 已经被我消费了 可以在队列删掉 这样以后就不会再发了 否则消息服务器以为这条消息没处理掉 后续还会在发
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            log.info("消息接收成功");
        } catch (Exception e) {
            e.printStackTrace();
            //消息重新入队
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,true);
            log.info("消息接收失败,重新入队");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    四:🚀友情链接

  • 相关阅读:
    Android—AMS启动
    git常见 操作仓库指令
    【生产力++】脚本自动化提取待复习内容 极大提高复习效率(下)
    【SQL刷题】Day3----SQL必会的常用函数专项练习
    #边学边考 必修5 高项:对人管理 第2章 项目沟通管理和干系人管理
    道路标识检测模型更新
    Windows11恢复组策略编辑器功能的方法
    JAVA面经整理(8)
    分词器与词表
    【Windows】搭建 FTP 服务器
  • 原文地址:https://blog.csdn.net/weixin_45750572/article/details/125564984