18、QR二维码的生成、微信支付第三方平台、统一下单思路说明、微信支付二维码实现思路、支付查询流程、对接订单生成逻辑&生成支付单完成支付、付款成功后修改订单状态&支付单状态

使用微信支付,需要新建两个模块,一个是interface,另一个是service。
在service中引入微信支付的依赖。

  		<dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>

QR二维码的生成

使用生成二维码的qrious二维码插件来生成二维码。
在这里插入图片描述
经过删减之后的index中生成二维码的代码如下:(单单只生成一个二维码)

<!DOCTYPE html>
<html lang="zh">
<head>

</head>
<body>	
		    <img id="qrious">
	
	<script src="./dist/umd/qrious.js"></script>
	<script>
	  (function() {
	    var qr = window.qr = new QRious({
	      element: document.getElementById('qrious'),
	      size: 200,			//这里是二维码的大小
	      value: 'http://www.baidu.com',	   		//这里输入二维码
		  level:'H'				//容错度,最低是L,最高是H(一共四级别)
	    })
	  })()
	</script>
</body>
</html>

微信支付第三方平台

参考的是微信支付的第三方api。

统一下单思路说明

微信支付二维码实现思路

在cart-web模块中的controller中实现生成二维码的方法,传递需要的参数
在这里插入图片描述
在这里使用了定义的searchPayLogFromRedis方法来查找支付订单,获取订单中的金额
实现类如下:(在生成商品订单的同时生成了支付订单,同时存入了redis)
在这里插入图片描述

1、在interface中创建生成二维码的方法在这里插入图片描述
2、在impl中实现方法
需要将配置文件中的信息引入到当前类中
在这里插入图片描述
通过httpclient请求来发送获取支付链接的请求,请求中包括微信支付的api所有需要的参数数据,将所有参数封装到requestMap中通过httpclient发送。

注意:微信支付api需要的数据是xml格式。需要使用微信提供的工具类来将map转成xml。

然后再通过工具类获取微信支付的返回值,返回的数据是xml格式,需要手动转成map,使用的还是微信提供的工具类。

返回的数据中包含很多信息。我们只需要三个:一个是商户订单号(我们传入的),一个是支付金额(我们传入的),还有一个是返回的支付链接。所以再次封装一个responseMap,存放这三个数据,返回。


    @Override                       //商户订单号,支付金额
    public Map createNative(String out_trade_no, String total_fee) {
        try {
            //通过我们的common模块发送http请求,请求地址是微信支付提供的支付链接请求的接口地址
            HttpClientUtil clientUtil = new HttpClientUtil("https://api.mch.weixin.qq.com/pay/unifiedorder");
            Map requestMap = new HashMap<>();
            requestMap.put("appid", appid);
            requestMap.put("mch_id", mch_id);
            requestMap.put("nonce_str", WXPayUtil.generateNonceStr());
            requestMap.put("body", "商城中的商品");
            requestMap.put("out_trade_no", out_trade_no);
            requestMap.put("total_fee", total_fee);
            requestMap.put("spbill_create_ip","127.0.0.1");
            requestMap.put("notify_url", notifyurl);
            requestMap.put("trade_type", "NATIVE");
            //微信工具类可以将map转xml的String,采用api:generateSignedXml
            String requestXml = WXPayUtil.generateSignedXml(requestMap, partnerkey);
            clientUtil.setXmlParam(requestXml);
            //需要设置请求的协议
            clientUtil.setHttps(true);

            //发送请求
            clientUtil.post();

            //接收参数
            String content = clientUtil.getContent();

            System.out.println("========================收到的xml"+content);

            Map<String, String> map = WXPayUtil.xmlToMap(content);

            //map中的数据太多,我们暂时不需要,并且我们需要返回订单号和支付金额,所以再封装一个新的map。
            Map responseMap = new HashMap<>();
            responseMap.put("out_trade_no", out_trade_no);
            responseMap.put("total_fee", total_fee);
            responseMap.put("code_url", map.get("code_url"));

            return responseMap;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

返回到前端页面上(cart-web),在js文件中完成二维码的生成,在页面绑定名字为“qrious”的id。

在这里插入图片描述

在这里插入图片描述

支付查询状态(查询是否支付了)

前端在生成二维码的方法下调用查询状态的方法。
在这里插入图片描述
前端js文件controller中的查询状态的方法中,通过返回值判断状态,并做处理。
在这里插入图片描述
在后端(pay_service)模块中创建对应方法

还是使用微信支付的查询状态的api。
使用的依然是httpclientutil工具类。
将需要的参数封装到map中,转成xml格式发送请求。
接收到的xml转成map直接返回即可。

 @Override
    public Map queryPayStatus(String out_trade_no) {
        try {
            HttpClientUtil clientUtil = new HttpClientUtil("https://api.mch.weixin.qq.com/pay/orderquery");
            Map requestMap = new HashMap<>();
            requestMap.put("appid", appid);
            requestMap.put("mch_id", mch_id);
            requestMap.put("nonce_str", WXPayUtil.generateNonceStr());
            requestMap.put("out_trade_no", out_trade_no);

            //微信工具类可以将map转xml的String,采用api:generateSignedXml
            String requestXml = WXPayUtil.generateSignedXml(requestMap, partnerkey);
            clientUtil.setXmlParam(requestXml);
            //需要设置请求的协议
            clientUtil.setHttps(true);
            //发送请求
            clientUtil.post();
            //接收参数
            String content = clientUtil.getContent();
            Map<String, String> responseMap = WXPayUtil.xmlToMap(content);
            //直接将微信返回的内容往前端返
            return responseMap;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

在调用这个方法的controller(cart-web)中,使用死循环的方式,间断查询订单状态。

    @RequestMapping("/queryPayStatus")
    public Result queryPayStatus(String out_trade_no){

        int timer = 1;  //定义一个记录次数

        while(true){
            Map map = weixinPayService.queryPayStatus(out_trade_no);
            if (map== null){
                return  new Result(false,"付款失败!");
            }
            //这里是微信支付的状态,参考微信支付api
            if("SUCCESS".equals(map.get("trade_state"))){
                weixinPayService.updateOrderStatus(out_trade_no, map.get("transaction_id").toString());
                return new Result(true,"付款成功!");
            }


            //设置支付超出时间
            if(timer > 6){  //判断30秒内需要完成支付动作,否则超时
                System.out.println("=支付超时=");//如果关闭了客户端页面,显示完支付超时后,就不再执行查询订单状态操作,不会一直死循环
                return  new Result(false,"timeout");
            }

            timer ++;

            try {
                Thread.sleep(5000);//5秒查询一个订单状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

测试支付结果的演示

对接订单生成逻辑&生成支付单完成支付

思路说明:在生成商品订单时,要同时生成支付订单。(在order_service模块中的OrderServiceImpl类中的add方法中)

  //生成支付单
        TbPayLog payLog = new TbPayLog();
        payLog.setTradeState("0");  //0未支付  1已支付
        payLog.setUserId(order.getUserId());
        payLog.setTotalFee((long) (payMoney * 100));  //支付总金额
        payLog.setPayType("1");   //1.微信支付,2.货到付款
        payLog.setCreateTime(new Date());
        //去掉左括号和右括号,最好也去掉中间的空格
        payLog.setOrderList(ordersIds.toString().replace("[", "").replace("]", "").replaceAll(" ", ""));
        payLog.setOutTradeNo(idWorker.nextId() + ""); //支付单号采用uuid
        //保存数据库
        payLogMapper.insert(payLog);

        //将payLog对象存到redis中
        redisTemplate.boundHashOps("payLog").put(payLog.getUserId(), payLog);

付款成功后修改订单状态&支付单状态

在这里插入图片描述
传入两个参数,一个是订单id,一个是微信流水号,修改支付单的状态,再修改订单的状态(注意修改每一个商品的状态)。最后清空redis中的缓存。

   @Override
    public void updateOrderStatus(String out_trade_no, String transaction_id) {
        //1.修改支付日志状态
        TbPayLog payLog = payLogMapper.selectByPrimaryKey(out_trade_no);
        payLog.setPayTime(new Date());
        payLog.setTradeState("1");//已支付
        payLog.setTransactionId(transaction_id);//微信内部交易号
        payLogMapper.updateByPrimaryKey(payLog);

        //2.修改本次支付所关联订单状态为"2"已付款
        String orderList = payLog.getOrderList();//获取订单号列表
        String[] orderIds = orderList.split(",");//获取订单号数组
        //状态:1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭,7、待评价
        for(String orderId:orderIds){
            TbOrder order = orderMapper.selectByPrimaryKey( Long.parseLong(orderId) );
            if(order!=null){
                order.setStatus("2");//已付款
                order.setPaymentTime(new Date());//订单更新付款时间
                orderMapper.updateByPrimaryKey(order);
            }
        }
        //3.清除redis中保存的支付缓存数据
        redisTemplate.boundHashOps("payLog").delete(payLog.getUserId());
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值