网站如何接入微信支付功能?微信支付详细教程它来了(建议收藏)

2021/9/3/23:23

一、微信支付流程分析

下图来源于微信支付官方文档

在这里插入图片描述
根据官方的这张时序图可以分析出微信支付流程

1.创建订单接口

这个具体怎么做呢?以下图天猫手机为例
请添加图片描述
当用户点击立即购买时会进入一个待支付页面,这个点击立即购买就会调用创建订单这个接口;所以数据库中必须要有一张订单表,该表中包含了一些用户信息和商品信息,当然最核心的是要包含订单号(order_no)字段和是否支付(is_pay)字段

1.1、创建订单业务逻辑分析

首先订单表(order_no)最少的情况也要包含一些用户信息字段和商品信息字段,所以这就涉及另外两张表用户表(t_user)和商品(t_goods)表;(我以微服务为例进行阐述),远程调用商品模块和用户模块,将需要的字段封装到订单实体类中,进而保存数据库即可;其中有个需要注意的点,那就是订单号怎么生成呢?其实我们可以利用日期来编写一个工具类生成即可,这样也就不会造成重复的情况(时间一直向前嘛)。

1.2、创建订单业务逻辑核心代码

代码中的工具类和商品模块已经用户模块的代码等等已经省略,因为比如JwtUtils工具类以及OpenFeign远程调用、还有商品和用户的CRUD应该是很简单的,最重要的是思路。

 	@Override
    public String createOrder(String goodsId, HttpServletRequest request) {
        //1.远程调用用户服务,获取用户信息
        String userId = JwtUtils.getUserIdByToken(request);
        UserInfoVO userInfo = userClient.getUserInfo(userId);
        //2.根据courseId查询出课程相关信息
        GoodsInfo goodsInfo = goodsClient.getGoodsInfo(goodsId);
        //3.创建订单
        Order order = new Order();
        order.setOrderNo(OrderNoUtil.getOrderNo())
                .setGoodsId(goodsId)
                .setGoodsName(goodsInfo.getName())
                .setGoodsCover(goodsInfo.getCover())
                .setUserId(userId)
                .setNickname(userInfo.getNickname())
                .setMobile(userInfo.getMobile())
                .setTotalFee(courseInfo.getPrice())
                .setPayType(1)
                .setStatus(0);
        baseMapper.insert(order);
        return order.getOrderNo();


2.待支付页面数据回显接口

2.1、待支付页面数据逻辑分析

请添加图片描述
以上方天猫商品为例,这个待支付页面包含了用户信息和商品信息,所以如果要做到这样的待支付页面,就需要根据订单号去数据库查询相关的订单信息,订单号?看下方示例代码

			<section class="vn-qwe" v-else>
              <a href="javascript:void(0)" title="立即购买" @click="createOrder()" class="attr-btn c-btn-3">立即购买</a>
            </section>
createOrder() {
        if (cookie.get('user_token') == null) {
          window.location.href = 'http://localhost:8555/login'
        }
        order.createOrder(this.usereId)
          .then(response => {
            if (response.data.success) {
              console.log("===============" + response.data.data.orderNo)
              this.$router.push({path: '/order/' + response.data.data.orderNo})

            }
          })
      },

如上图中的前端代码为例,当点击立即购买时,就会跳转到待支付页面;从跳转的路径来看,路径中包含订单号,这个订单号就是调用创建订单接口后端返回的
在这里插入图片描述

请添加图片描述
所以这个待支付页面就可以通过订单号将相关的信息查询出来

2.2、回显数据代码实现

	@ApiOperation("根据订单号查询订单")
    @GetMapping("/getOrder/{orderNo}")
    public ResponseEntity getOrder(@PathVariable String orderNo) {
        Order order = orderService.getOne(new QueryWrapper<Order>().eq("order_no", orderNo));
        return ResponseEntity.ok().data("order", order);
    }


3、生成微信支付二维码接口

想来也都明白,肯定是扫码支付

3.1、微信支付二维码逻辑分析

请添加图片描述
假设当前只能使用微信支付,当点击提交订单时,就会出现一个支付二维码;所以这个点击提交按钮就会调用后端生成二维码接口

官方文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_1.shtml

其中需要一些核心的参数,当然你得认证通过之后(这些参数的意思不再过多阐述,官网可以了解)

1.appid 唯一标识
2.mch_id 商户号
3.notify_url 回调地址
4.partnerkey 商户密钥

接口思路是什么?
封装这些参数到map集合中,然后远程调用微信接口即可;微信响应回来的包含result_code,code_url等等,这个url就是支付二维码地址

3.2、微信支付二维码核心逻辑代码实现

需要微信的依赖包wxpay-sdk

	@Override
    public Map createNative(String orderNo) {

        try {
            Order order = orderService.getOne(new QueryWrapper<Order>().eq("order_no", orderNo));
            //设置发送参数(例如appid等等都是必须的)
            Map map = new HashMap<>();
            map.put("appid", WxConstantProperties.APP_ID);
            map.put("mch_id", WxConstantProperties.MCH_ID);
            map.put("nonce_str", WXPayUtil.generateNonceStr());
            map.put("body", order.getGoodsName());
            map.put("out_trade_no", orderNo);
            map.put("total_fee",  order.getTotalFee());
            map.put("spbill_create_ip", "127.0.0.1");
            map.put("notify_url", WxConstantProperties.NOTIFY_URL);
            map.put("trade_type", "NATIVE");
            System.out.println("map------------>"+map);
            //2.发送
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            //密钥加密,将map类型转换成xml格式,这是微信规定的
            client.setXmlParam(WXPayUtil.generateSignedXml(map, WxConstantProperties.PARTNER_KEY));
            //支持https请求,上面的链接就是https
            client.setHttps(true);
           //发送post请求
            client.post();
            //3.得到相应响应参数
            String xmlResponse = client.getContent();
            Map<String, String> response = WXPayUtil.xmlToMap(xmlResponse);

            //4.封装响应结果
            Map responseMap = new HashMap();
            responseMap.put("out_trade_no", orderNo);
            responseMap.put("goods_id", order.getGoodsId());
            responseMap.put("total_fee", order.getTotalFee());
            responseMap.put("result_code", response.get("result_code"));
            responseMap.put("code_url", response.get("code_url"));
            return responseMap;
        } catch (Exception e) {
            throw new CommonException(40026, "二维码调用失败!");
        }
    }

请添加图片描述
前端代码不再展示,这是点击购买之后跳转的路径,
到这里会有一个问题,当我们扫码之后,系统怎么知道我们已经付过款了呢?由此请接着往下看



4.定时查询支付状态

4.1、后端逻辑分析

这里后端实现比较简单,封装appid等参数到map集合,向微信的支付接口查询即可;需要注意的是这里的参数要包括订单号,也就是第三步我们远程调用二维码接口时传给微信的订单号(key:out_trade_no # value:orderNo),否者微信支付服务器怎么识别查询哪个订单的状态

4.2、核心逻辑代码

    @Override
    public Map<String, String> queryPayStatus(String orderNo) {
        try {
            Map m = new HashMap();
            m.put("appid", WxConstantProperties.APP_ID);
            m.put("mch_id", WxConstantProperties.MCH_ID);
            m.put("out_trade_no", orderNo);
            m.put("nonce_str", WXPayUtil.generateNonceStr());  //随机字符串->生成签名用到
            //这里发送的地址是微信提供的,是固定不变的
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            //加密,并将其转换为xml格式,官方规定的
            client.setXmlParam(WXPayUtil.generateSignedXml(m, WxConstantProperties.PARTNER_KEY));
            client.setHttps(true);
            client.post();
            String xmlResponse = client.getContent();
            //转换为map集合,以便get到其中的值
            return WXPayUtil.xmlToMap(xmlResponse);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

在返回响应的结果中,可以通过trade_state获取到其中的value,判断是否是SUCCESS,如果是代表该订单已经支付

if (map.get("trade_state").equals("SUCCESS")){...}

另外如果是SUCCESS代表以及支付,那么就要将订单表中的is_pay修改为true(代表已经支付),另外还可以创建一个支付日志表,用来存储已经支付的订单信息

4.3、前端逻辑分析

怎么做到用户扫码付款之后,就显示支付成功呢?可以通过计时器来实现
setInterval(test,3000)这个代表每隔3s调用一次test方法。所以我们可以在mounted中编写这个计时函数(mounted是VUE生命周期中的重要组成部分,它代表当页面渲染之后调用该mounted中的函数)

4.4、前端js核心代码实现

    mounted() {
      this.timer = setInterval(()=>{
        this.queryStatus()
      }, 3000)
    },
    methods: {
      queryStatus() {
        order.queryPayStatus(this.orderId)
        .then(response => {
          if (response.data.success) {
            clearInterval(this.timer)
            this.$message({
              type: 'success',
              message: '支付成功!'
            })
            this.$router.push({path: '/goods/' + this.payQc.goods_id})
          }
        })
      }
    }

这里也需要注意一个点,就是这个计时器在支付之后要清空,否者它会一直执行下去!

结束!

2021/9/4/15:37

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thecoastlines

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值