• 微信支付之微信H5支付(坑,ajax不支持重定向跳转)


    这里讲的是  微信h5支付,    是微信以外的手机浏览器调用微信h5支付

     h5支付:

    H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。
    主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付。

    一、基本信息和配置

    在基本配置的之初请参考【公众号支付】 的前面部分,
    不同的是H5支付需要申请通过才能使用,申请的地方是商户平台 产品中心>我的产品,申请通过如下:

     在开发配置里配上H5支付的域名:

    基本信息配置到此,下面开始敲代码

    二、开发支付

    建议参考微信H5开发文档
    https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_1

    微信H5支付开发也是两步走:
    1. 通过统一下单接口发起请求,获得mweb_url(支付跳转url),这个是你接下来进入微信提供的支付页面的地址;
    2. 完成支付流程后,实现后续逻辑。

    一)发起统一下单接口

    此处请参考【微信支付之公众号支付】博客里的流程,这里有两个地方需要注意:
    1)本次请求中的参数:交易类型(trade_type)的值是“MWEB”
    2)本次返回结果需要得到的是“mweb_url”的值

    参考方法(由于上一篇公众号支付写的比较详细,只列出上文没有细说的方法,值得注意的是这个UnifiedOrder对象里是没有openid这个字段,api说明里也提到过公众号支付必填openid,H5支付是不用填写的,主要是没有,O(∩_∩)O哈哈~)

     /**
         * 
         * @Description: 微信支付 -统一订单类型获得mweb_url
         * @author tianpengw 
         * @param uo
         * @return
         */
        public static String getUnifiedOrderMWebUrl(UnifiedOrder uo){
            String sign = createUnifiedOrderSign(uo);
            uo.setSign(sign);
            String xml = XMLBeanUtils.objectToXMLStr(uo);
            log.info("H5支付统一订单请求参数:"+xml);
            String res = HttpHelper.httpsRequest(unifiedUrl,"POST",xml);
            log.info("H5支付统一订单返回结果:"+res);
            Map<String, String> responseMap = XMLBeanUtils.readStringXmlOut(res);
            return responseMap.get("mweb_url");
        }

    相关的工具类不在赘述,参考上文公众号支付博客

    通过此方法得到MWebUrl结果后,送到前端,通过window.location.href跳转即可完成H5支付流程,值得注意的是,H5支付扫尾比公众号支付要麻烦:

    【官方文档】
    一、回调页面
    
    正常流程用户支付完成后会返回至发起支付的页面,如需返回至指定页面,则可以在MWEB_URL后拼接上redirect_url参数,来指定回调页面。
    
    如,您希望用户支付完成后跳转至https://www.wechatpay.com.cn,则可以做如下处理:
    
    假设您通过统一下单接口获到的MWEB_URL= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096 
    
    则拼接后的地址为MWEB_URL= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096&redirect_url=https%3A%2F%2Fwww.wechatpay.com.cn
    
        注意:
        1.需对redirect_url进行urlencode处理
        2.由于设置redirect_url后,回跳指定页面的操作可能发生在:1,微信支付中间页调起微信收银台后超过5秒 2,用户点击“取消支付“或支付完成后点“完成”按钮。因此无法保证页面回跳时,支付流程已结束,所以商户设置的redirect_url地址不能自动执行查单操作,应让用户去点击按钮触发查单操作。回跳页面展示效果可参考下图

    官方文档提到两个关键地方,第一点是用户可通过拼接redirect_url来指引微信处理后的跳转动向,这个地址需要urlencode处理,第二点是不管什么结果最终结束后微信都会调用这个redirect_url地址,这些交给后端完成,让后端跳转 微信h5支付的链接,  前端  就一个下单接口, 其他事交给后端,

    这边特别注意这块代码(红色的)  必须写,  不然会报错,  后端代码也需要改,参考下面链接

    ajax不支持  重定向 跳转!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  参考链接 ajax不支持重定向!!https://www.cnblogs.com/ynxrsoft/p/9408253.html

    前端部分代码如下:

    var jqxhr
                    $.ajaxSetup({
                        complete: function () {
                            if ("REDIRECT" == jqxhr.getResponseHeader("REDIRECT")) { //若HEADER中含有REDIRECT说明后端想重定向,
                                var win = window;
                                while (win != win.top) {
                                    win = win.top;
                                }
                                win.location.href = jqxhr.getResponseHeader("CONTENTPATH");//将后端重定向的地址取出来,使用win.location.href去实现重定向的要求
                            }
                        }
                    });
                        
                    jqxhr = $.ajax({
                        url: config.api_buy,
                        type:"post",
                        async:true,
                        headers: {
                            'Content-Type':'application/json;charset=UTF-8'
                        },
                        data: JSON.stringify(obj),
                        success:res=>{
                            console.log('0元下单',res)
                            if(res.error == "00"){
                                that.$toast.success('领取成功')
                                that.flag = 1
                                // window.location.href = res.mweb_url+'&redirect_url='+'http://127.0.0.1:5500/Page-YongAnXing/localLife.html?aa='+res.mweb_url
                            }else{
                                that.$toast.fail(res.msg)
                            }
                        }
                    })

    重定向 页面自己写了,  到时候调用  订单查询看看是否支付成功   或者支付失败  取消支付   在对其 进行跳转

    最后贴出服务端方法:

    /**
         * H5支付
         * @param req
         * @param ids
         * @param addrId
         * @param orderRemark
         * @return 
         * @throws UnsupportedEncodingException 
         */
        @RequestMapping(value = "gotoJSPayH5.json")
        @ResponseBody
        public Response gotoJSPayH5(HttpServletRequest req, @RequestBody PhoneBean pb) throws UnsupportedEncodingException{
            log.info("进入H5支付:" + pb.getOrderId());
            Response resp = new Response();
            if(!MyStringUtils.isEmpty(pb.getOrderId())){
                Order order = orderService.findOrderForPayH5(pb.getOrderId());
                if(null != order){
                    Date endDate = MyDateUtil.parseDate(MyDateUtil.get30Minute(order.getOrderCreateTime()),MyDateUtil.DATETIME);
                    if(MyConstants.order_need_pay == order.getOrderStatus() && new Date().before(endDate)){
                        UnifiedOrder uo = new UnifiedOrder();
                        uo.setSpbill_create_ip(HttpHelper.getClientIP(req));
                        uo.setTrade_type(WechatPayUtil.tradeTypeH5);
                        uo.setBody(MyConstants.project_title+"-商品支付");
                        uo.setOut_trade_no(order.getOrderId());
                        //测试环境
                        if("test".equals(getDicValueByAlias("environment"))){
                            uo.setTotal_fee(1);//测试使用单位分
                        }else{
                            uo.setTotal_fee(order.getOrderTotalPrice().multiply(new BigDecimal(100)).intValue());//单位分
                        }
                        String mwebUrl = WechatPayUtil.getUnifiedOrderMWebUrl(uo);
                        if(!MyStringUtils.isEmpty(mwebUrl)){
                            //增加支付记录
                            WechatPay wp = new WechatPay();
                            wp.setPayId(RandomUtils.g());
                            wp.setPayOrderId(order.getOrderId());
                            //测试环境
                            if("test".equals(getDicValueByAlias("environment"))){
                                wp.setPayAmount(new BigDecimal(0.01));//测试使用
                            }else{
                                wp.setPayAmount(order.getOrderTotalPrice());
                            }
                            wp.setPayReturnUrl(mwebUrl);
                            wp.setPayType(WechatPayUtil.tradeTypeH5);
                            wp.setPayStatus(MyConstants.pay_status_ing);
                            wp.setPayNonceStr(uo.getNonce_str());
                            wpService.insertWechatPay(wp);
                            //拼接实现地址:跳转支付完成页面
                            resp.setData(mwebUrl+ "&redirect_url=" +URLEncoder.encode(MyConstants.product_address 
                                    + "/phone/payComplete.do?orderId=" + order.getOrderId() + "&tradeType=" + WechatPayUtil.tradeTypeH5,"utf-8"));
                            resp.setErrCode(ErrorCode.err_code_success);
                        }
    
                    }else if(MyConstants.order_has_pay == order.getOrderStatus()){
                        resp.setErrCode(ErrorCode.err_code_fail);
                        resp.setErrMsg("订单已完成支付,请勿重复支付!");
                    }else{
                        resp.setErrCode(ErrorCode.err_code_fail);
                        resp.setErrMsg("订单已失效,请重新选购商品!");
                    }
                }
            }else{
                resp.setErrCode(ErrorCode.err_code_fail);
                resp.setErrMsg("订单无效,支付异常!");
            }
            return resp;
        }

    这里有一些常用的方法就不再贴出了,简单描述下:
    MyStringUtils:字符串处理工具类isEmpty() 非空判断方法;
    MyDateUtil:日期解析工具类 parseDate()字符串转日期方法;

    至此H5支付的主要流程就结束了,我的代码是两种支付的结合,有单独需求的可以分开,请继续关注【微信开发之自定义分享】,下文中我将把我自己总结jar包和源码都分享出来,供大家参考学习

    参考地址:  https://blog.csdn.net/niaoer2010/article/details/78229247?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.edu_weight

  • 相关阅读:
    POJ2184 01背包变形 xingxing在努力
    HDU2955 01背包变体 xingxing在努力
    Uva624 01背包输出方案 xingxing在努力
    HDU2602 01背包 xingxing在努力
    Jersey初谈
    Jersey初谈
    Oracle基本语句
    Oracle基本语句
    2013下半年工作总结
    2013下半年工作总结
  • 原文地址:https://www.cnblogs.com/520BigBear/p/13825089.html
Copyright © 2020-2023  润新知