首页 > 其他分享 >从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期

从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期

时间:2023-08-08 13:55:23浏览次数:45  
标签:refund 微信 订单号 之微信 订单 支付 退款

一、前言

从零玩转系列之微信支付实战PC端支付微信退款接口搭建 | 技术创作特训营第一期

继前文章取消订单接口和查询订单接口此篇为申请退款流程,此篇文章过长我将分几个阶段的文章发布(项目源码都有,小程序和PC端)

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

输入图片说明

本次项目使用技术栈

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

前端: Vue3、Vite、ElementPlus

小程序: Uniapp、Uview

演示地址查看 WEB端 小程序端

一、订单退款

什么是订单退款?

订单退款是指在购买商品或服务后,由于某种原因,消费者选择取消订单或者商家无法提供所承诺的商品或服务,从而触发一项退款过程。退款通常是指商家将之前从消费者支付的金额返还给消费者的操作。这可以是因为商品瑕疵、服务不满意、订单错误或其他原因,消费者和商家之间达成的一种解决方案,旨在确保消费者的权益得到保护。

场景

申请退款的场景有很多,以下是一些常见的情况:

  1. 商品瑕疵: 消费者收到的商品存在损坏、缺陷或不符合描述,可以申请退款以获得补偿或返还款项。
  2. 不满意的服务: 消费者购买的服务未达到预期,例如餐厅用餐体验差、旅行服务不如预期等。
  3. 订单错误: 消费者可能因误操作或信息错误而下错订单,需要取消并申请退款。
  4. 发货延迟: 如果商家延迟了订单的发货,消费者可能会申请退款。
  5. 重复支付: 消费者可能因系统问题或网络故障而重复支付了一笔订单,需要申请退款。
  6. 无法提供服务: 商家无法按约定提供服务,例如演出取消、酒店无法入住等情况。
  7. 不适用: 购买的商品或服务并不适用于消费者,例如购买了不适合自己的尺寸、不适合的软件等。
  8. 退货: 消费者购买了实物商品后,决定退货并获得退款。

以上是GPT3.5专业的回答

思考

思考我们程序当中需要的步骤初步形成

  1. 我们支付完毕后拿到该订单的订单号
  2. 根据订单号查询我们数据库里的支付日志表状态必须是支付成功
  3. 因为我们目前是没有登录功能的是不知道哪些订单是谁的所以我们需要根据某个唯一的编号来判断这个订单是这个客户的
  4. ‼️ 微信申请退款成功后会发起一个退款回调的请求这个后面会讲!!!!!!

思考


我们都知道支付成功后微信会提示我们支付成功并且会生成一个交易记录我们点击进去可以看到交易订单号

好我们去查看一下文档会不会给我们这个编号

交易订单号

很明显我们是会拿到的~ 那么就到时候存一下呗在用户提供咱们判断一下呗 不就完事了呗~

微信说明

当交易发生之后一年内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付金额退还给买家,微信支付将在收到退款请求并且验证成功之后,将支付款按原路退还至买家账号上。

⚠️注意

1、交易时间超过一年的订单无法提交退款

2、微信支付退款支持单笔交易分多次退款(不超50次),多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号

3、错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次

4、每个支付订单的部分退款次数不能超过50次

5、如果同一个用户有多笔退款,建议分不同批次进行退款,避免并发退款导致退款失败

6、申请退款接口的返回仅代表业务的受理情况,具体退款是否成功,需要通过退款查询接口获取结果

7、一个月之前的订单申请退款频率限制为:5000/min

8、同一笔订单多次退款的请求需相隔1分钟

交互

退款状态转变如下:

流程

请求参数必填

参数名 变量 类型长度限制 必填 描述
微信支付订单号 transaction_id string1, 32 二选一 body原支付交易对应的微信订单号 示例值:1217752501201407033233368018
商户订单号 out_trade_no string6, 32 二选一 body原支付交易对应的商户订单号 示例值:1217752501201407033233368018
商户退款单号 out_refund_no string1, 64 body商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。 示例值:1217752501201407033233368018
退款原因 reason string1, 64 不一定要填写
金额信息 amount object body订单金额信息
退款金额 refund int 退款金额,单位为分,只能为整数,不能超过原订单支付金额。示例值:888
原订单金额 total int 原支付交易的订单总金额,单位为分,只能为整数。示例值:888

二、步入正题

修改 WechatNativeController 编写申请退款接口

/**
     * 申请退款
     * @param orderNo 订单号
     * @param refundsNo 退款单号(交易订单号)
     * @param reason 退款原因
     */
    @PostMapping("/refunds/{orderNo}/{refundsNo}/{reason}")
    public R refunds(@PathVariable String orderNo, @PathVariable String refundsNo, @PathVariable String reason) {
        log.info("申请退款");
        wxPayService.refund(orderNo, reason, refundsNo);
        return R.ok();
    }

修改 wxPayService 创建 refund 方法

    /**
     * 申请退款
     *
     * @param orderNo   订单号
     * @param reason    退款原因
     * @param refundsNo 退款单号
     */
    @SneakyThrows
    public void refund(String orderNo, String reason, String refundsNo) {
        // ............
    }

前面思考提到的需要查询该订单是否存在和状态要支付成功的

    log.info("校验开始");
    PaymentInfo paymentInfo = paymentInfoService.lambdaQuery().eq(PaymentInfo::getOrderNo, orderNo)
            .eq(PaymentInfo::getTradeState, WxTradeState.SUCCESS.getType()).one();
    if (null == paymentInfo) {
        throw new RuntimeException("未查询到该订单,请稍后再试!");
    }

在校验客户输入的交易订单号是否正确我这里就判断后四位咯

// 判断是否是本人的订单
String transactionNo = paymentInfo.getTransactionId().substring(paymentInfo.getTransactionId().length() - 4);
        if (!transactionNo.equals(refundsNo)) {
        throw new RuntimeException("这笔可能不是你的订单哦.请核实支付成功后微信通知当中的交易订单号后四位!");
        }

搞定后我们还需要思考一下,支付这么重要的退款环节我们是不是得要记录一下? 退款啊我直接裂开没赚到钱~

思考

那么我们就查看一下之前文章提到的退款记录表,有同学可能直接懵逼直达车前往第三章从零玩转系列之微信支付实战基础框架搭建当中的创建三层结构所提到过

CREATE TABLE `t_refund_info` (
                                 `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '款单id',
                                 `order_no` varchar(50) DEFAULT NULL COMMENT '商户订单编号',
                                 `refund_no` varchar(50) DEFAULT NULL COMMENT '商户退款单编号',
                                 `refund_id` varchar(50) DEFAULT NULL COMMENT '支付系统退款单号',
                                 `total_fee` int(11) DEFAULT NULL COMMENT '原订单金额(分)',
                                 `refund` int(11) DEFAULT NULL COMMENT '退款金额(分)',
                                 `reason` varchar(50) DEFAULT NULL COMMENT '退款原因',
                                 `refund_status` varchar(10) DEFAULT NULL COMMENT '退款状态',
                                 `content_return` text COMMENT '申请退款返回参数',
                                 `content_notify` text COMMENT '退款结果通知参数',
                                 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                                 `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
                                 PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

搞定后我们就处理创建退款单记录并且保存到数据库当中

修改 refundInfoService 创建 createRefundByOrderNo 方法

log.info("创建退款单记录");
//根据订单编号创建退款单
        RefundInfo refundsInfo = refundInfoService.createRefundByOrderNo(orderNo, reason);

        log.info("调用退款API");

输入图片说明

处理创建退款单逻辑

 // 根据订单号生成退款订单
 RefundInfo refundInfo = new RefundInfo();
         refundInfo.setOrderNo(orderNo);//订单编号
         refundInfo.setRefundNo(OrderNoUtils.getRefundNo());//退款单编号
         refundInfo.setTotalFee();//原订单金额(分)
         refundInfo.setRefund();//退款金额(分)
         refundInfo.setReason(reason);//退款原因

创建实体把参数注入进去剩下的我们还缺少订单金额 我们传递了个参数是订单编号 那么我们想想看这个在哪里搞?

调用订单服务获取金额信息

标签:refund,微信,订单号,之微信,订单,支付,退款
From: https://www.cnblogs.com/Yangbuyi/p/17613991.html

相关文章

  • 微信公众号HTML5如何预览EXCEL、word、ppt、pdf等文件
    1、pfile文件预览   很简单一句话window.open('http://www.pfile.com.cn/api/profile/onlinePreview?url='+encodeURIComponent(“文档地址”));使用了一段时间,简单完美,强烈推荐!!! 2、 officeonlineleturl="https://view.officeapps.live.com/op/view.aspx?src="+......
  • 微信小程序14 头部设置,通用,单独,动态。
    这里用一个例子来学习新的东西一个可以搜索,切换tab的页面,这个太常见了。新建一个newlist/newlist  在全局配置app.json中的pages里把newlist放到第一个去,这样方便。 通用头部设置这时候我们注意到,app.json中除了pages,还有这个"window":{"backgroundTextStyle":......
  • 搭建微信小程序的步骤
    1、租云服务器2、搭建后端服务3、申请购买域名4、域名解析5、服务器配置域名访问6、域名备案(备案后才能申请ssl证书)7、申请ssl证书(微信小程序必须使用https访问,必须申请ssl证书)8、在微信公众平台上申请创建小程序,填写项目信息,不是游戏不能选择游戏类型9、前端项目绑定小程......
  • 获取微信签名方法调用
    微信签名生成1、微信签名生成参照微信支付文档中心:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay4_0.shtmlimportjava.io.BufferedInputStream;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStream;import......
  • 微信小程序13 在请求url获取返回值后修改data变量的一个问题,es6箭头函数或外部定义变
    在之前解密电话时,我们有请求wx的apiwx.request({url:'https://api.weixin.qq.com/sns/jscode2session',data:{},success:(re)=>{//console.log('re:'+JSON.stringify(re));this.......
  • 微信小程序12 跳转,跳转时传参
    我们正常操作的话,肯定有很多页面之间的跳转,在微信小程序中navigator,跳转效果类似html中的a标签<navigatorurl="/pages/index/index">跳转到index</navigator>注意参数url指向要跳转的页面,本地跳转的话基本就是/pages/文件夹/文件名,没有后缀。这样点击标签后就会跳转......
  • 微信支付签名
    importcn.hutool.crypto.SecureUtil;importcom.dtyunxi.exchange.api.IFunctionAuthService;importorg.apache.commons.lang3.StringUtils;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.stereotype.Component;importjavax.......
  • 微信支付请求(带证书)
    importcn.hutool.core.lang.Pair;importcn.hutool.crypto.SecureUtil;importcom.dtyunxi.exchange.biz.model.ApiChannelType;importcom.dtyunxi.exchange.biz.utils.OkHttpUtil;importokhttp3.OkHttpClient;importorg.apache.http.HttpEntity;importorg.apache.......
  • 微信小程序11 弹窗showToast,showLoading,showModal
    弹窗是相当常用的功能,在微信里用弹窗还是挺方便的。不同于我们写网页时,对于alert,confirm这些比较简陋的原生弹窗通常要引入第三方插件来美化,微信自带的弹窗效果还不错。放一个按钮,绑定showToast方法。<buttonbind:tap="showToast">点击弹窗1</button>Js方法通用showToast......
  • 微信公众号授权回调 vue网址中带#号的处理
    1、改变vue模式为history,小编没有试2、通过配置nginx实现   A、替换跳转网址中的#为其他字符串,例如我的    consturl=this._getUrl("https://open.weixin.qq.com/connect/oauth2/authorize",{appid:this.appId,......