微信扫码支付

微信扫码支付

什么是二维码

二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。

二维码容错级别

L级(低) 7%的码字可以被恢复。
M级(中) 的码字的15%可以被恢复。
Q级(四分)的码字的25%可以被恢复。
H级(高) 的码字的30%可以被恢复。

二维码生成插件qrious

<html>
<head>
<title>二维码入门小demo</title>
</head>
<body>
<img id="qrious">
<script src="qrious.min.js"></script>
<script>
     var qr = new QRious({
           element:document.getElementById('qrious'),
           size:250,       
           value:'XXX'
        });
</script>
</body>
</html>

用此方法可以再页面生成一个简单的二维码

微信支付开发文档

我们可以通过调用微信提供的接口来实现微信支付
首先导入微信支付的依赖

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

通过httpClient的方式来访问微信提供的两个接口,
https://api.mch.weixin.qq.com/pay/unifiedorder 用于生成订单
https://api.mch.weixin.qq.com/pay/orderquery 用于查询订单支付状态

生成订单

微信要求我们一个xml参数传递到他们所提供的接口
这里我们可以通过构建一个由属性名=属性值组成的一个map集合,通过微信提供的WXPayUtil.generateSignedXml(paramMap, partnerkey)方法,传递map集合与签名,生成一个xml
再通过WXPayUtil.xmlToMap(content) 把响应回来的数据返回一个map集合来处理数据

这里的redisTemplate.boundHashOps(“paylog”).get(userId)是为了获取支付信息中的商户订单号 out_trade_no
而改属性是在订单模块中点击立即支付后所生成的paylog对象存入redis中时存入的

    @Override
    public Map createNative(String userId) throws Exception {
//      获取该userId对应的payLog信息,从redis中
        TbPayLog payLog = (TbPayLog) redisTemplate.boundHashOps("paylog").get(userId);
//      调用微信给我们提供的接口
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
//      提供接口所需参数,用map存储
        Map<String, String> paramMap = new HashMap<>();
//      公众账号ID  appid   是   String(32)  wxd678efh567hg6787  微信支付分配的公众账号ID(企业号corpid即为此appId)
        paramMap.put("appid", appid);
//      商户号 mch_id  是   String(32)  1230000109  微信支付分配的商户号
        paramMap.put("mch_id", partner);
//      随机字符串   nonce_str   是   String(32)  5K8264ILTKCH16CQ2502SI8ZNMTM67VS    随机字符串,长度要求在32位以内。推荐随机数生成算法
        String str = WXPayUtil.generateNonceStr();
        paramMap.put("nonce_str", str);
//      商品描述    body    是   String(128) 腾讯充值中心-QQ会员充值   商品简单描述,该字段请按照规范传递,具体请见参数规定(微信支付时显示的字)
        paramMap.put("body", "品优购支付");
//      商户订单号   out_trade_no    是   String(32)  20150806125346  商户系统内部订单号
        String out_trade_no = payLog.getOutTradeNo();
        paramMap.put("out_trade_no", out_trade_no);
//      标价金额    total_fee   是   Int 88  订单总金额,单位为分,详见支付金额
        paramMap.put("total_fee", "1");
//      终端IP    spbill_create_ip    是   String(16)  123.12.12.123   APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。
        paramMap.put("spbill_create_ip", "127.0.0.1");
//      通知地址    notify_url  是   String(256) http://www.weixin.qq.com/wxpay/pay.php  异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
        paramMap.put("notify_url", notifyurl);
//      交易类型    trade_type  是   String(16)  JSAPI   JSAPI公众号支付      NATIVE扫码支付      APP APP支付说明详见参数规定
        paramMap.put("trade_type", "NATIVE");
//      签名  sign    是   String(32)  C380BEC2BFD727A4B6845133519F3AD6    通过签名算法计算得出的签名值,详见签名生成算法
        String xml = WXPayUtil.generateSignedXml(paramMap, partnerkey);
//      使用httpClient把xml设置提交
        httpClient.setXmlParam(xml);
        httpClient.post();
//      接收微信相应的数据
        String content = httpClient.getContent();
//      把响应到的数据转化成map集合返回
        Map<String, String> map = WXPayUtil.xmlToMap(content);
        System.out.println(map);
        map.put("out_trade_no", out_trade_no+"");
        map.put("total_fee", "1");
        System.out.println(map.get("out_trade_no"));
        return map;
    }

其中返会的map中有一个属性为交易链接,我们把这个交易连接生成二维码展示到页面即可让用户完成支付

//生成二维码的方法
    $scope.createNative=function(){
        payService.createNative().success(function(response){
            $scope.resultMap=response;
            new QRious({
                  element: document.getElementById('payImg'),
                  size: 300,
                  value: response.code_url,
                  level:'L'
                });
            $scope.flag=false;
            $scope.payMessage="";
            //查询支付的方法
            $scope.queryOrder(response.out_trade_no);
        })

查询支付状态

由上面的代码我们可以发现,在生成二维码之后需要立即调用查询支付的方法,因为我们不确定用户何时回支付,因此我们需要写一个循环,在此循环中每3秒查询一次支付状态,一旦支付完成立马跳转到支付成功页面.如果超过一定的时间则提示支付超时,ran用户可以选择重新生成二维码

angularjs代码

$scope.queryOrder=function(out_trade_no){
        payService.queryOrder(out_trade_no).success(function(response){
            if(response.success){
                location.href="paysuccess.html#?totalFee=" + $scope.resultMap.total_fee;
            }else{
                if(response.message=="支付超时"){
                    $scope.flag=true;
                    $scope.payMessage="二维码过期,请刷新重新获取二维码"
                }else{
                    location.href="payfail.html";
                }
            }
        })
    }

controller层代码

分别调用两个方法,查询支付状态,如果支付成功,则立即修改订单表与支付信息表

//创建支付二维码
    @RequestMapping("/queryOrder/{out_trade_no}")
    public Result queryOrder(@PathVariable String out_trade_no) {
        try {
            int times=0;
            //创建一个循环,循环访问10次如果10次均未支付,则验证码过期
            while(times<10) {
                Thread.sleep(3000);
                System.out.println(out_trade_no);
                Map map = payService.queryOrder(out_trade_no);
                System.out.println(map);
                times++;
                //如果支付状态为success则表示支付成功
                if(map.get("trade_state").equals("SUCCESS")) {
                    //在这里表示支付成功,应该修改payLog支付信息与order订单状态
                    String userId = SecurityContextHolder.getContext().getAuthentication().getName();
                    String transaction_id = (String) map.get("transaction_id");
                    //调用service修改payLog支付信息与order订单状态
                    payService.updatePayLogAndOrder(transaction_id, userId);
                    return new Result(true, "支付成功");
                }
            }
            return new Result(false, "支付超时");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false, "支付失败,请重试");
        }

    }

serviceImpl层方法:查询支付状态

调用微信给我们提供的接口,具体思路与生成订单时的思路基本相同

    @Override
    public Map queryOrder(String out_trade_no) throws Exception  {
        //调用微信给我们提供的接口
                HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
                //提供接口所需参数,用map存储
                Map<String, String> paramMap = new HashMap<>();
//              公众账号ID  appid   是   String(32)  wxd678efh567hg6787  微信支付分配的公众账号ID(企业号corpid即为此appId)
                paramMap.put("appid", appid);
//              商户号 mch_id  是   String(32)  1230000109  微信支付分配的商户号
                paramMap.put("mch_id", partner);
//              随机字符串   nonce_str   是   String(32)  5K8264ILTKCH16CQ2502SI8ZNMTM67VS    随机字符串,长度要求在32位以内。推荐随机数生成算法
                String str = WXPayUtil.generateNonceStr();
                paramMap.put("nonce_str", str);
//              商品描述    body    是   String(128) 腾讯充值中心-QQ会员充值   商品简单描述,该字段请按照规范传递,具体请见参数规定(微信支付时显示的字)
                paramMap.put("out_trade_no", out_trade_no+"");      
//              签名  sign    是   String(32)  C380BEC2BFD727A4B6845133519F3AD6    通过签名算法计算得出的签名值,详见签名生成算法
                String xml = WXPayUtil.generateSignedXml(paramMap, partnerkey);
//              使用httpClient把xml设置提交
                httpClient.setXmlParam(xml);
                httpClient.post();
//              接收微信相应的数据
                String content = httpClient.getContent();
//              把响应到的数据转化成map集合返回
                Map<String, String> map = WXPayUtil.xmlToMap(content);
                return map;
    }

serviceImpl层方法:修改订单表与支付信息表

从redis数据库中获取paylog对支付信息进行修改并保存

    @Override
    public void updatePayLogAndOrder(String transaction_id, String userId) {
        //根据userId获取支付信息
        TbPayLog payLog = (TbPayLog) redisTemplate.boundHashOps("paylog").get(userId);
        payLog.setPayTime(new Date());
        payLog.setTradeState("1");
        payLog.setTransactionId(transaction_id);
        //保存支付信息
        payLogMapper.updateByPrimaryKey(payLog);
        //获取订单Id
        String orderList = payLog.getOrderList();
        String[] orderIds = orderList.split(",");
        for (String orderId : orderIds) {
            TbOrder order = orderMapper.selectByPrimaryKey(Long.parseLong(orderId));
            order.setPaymentTime(new Date());
            order.setStatus("2");
            order.setUpdateTime(new Date());
            orderMapper.updateByPrimaryKey(order);
        }
    }

至此所有的信息存入mysql数据库中,支付模块也就做完了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值