微信H5支付

作者: TsingXu | 来源:发表于2018-05-28 16:15 被阅读0次

    这几天做WAP网站,涉及到微信支付和支付宝支付,在开通应用前只是针对技术文档做了预研,了解下程序的逻辑实现。结果导致后期开发中支付宝很顺利,毕竟API很强大。微信有些坑要填补,真是悲催。

    第一个坑:浏览器兼容问题

    回调页面

    逻辑是这样的:一开始弹框是没有的,用户点击右下角的“确认支付”,显示弹框,跳转到微信。
    重点是后面的操作,在微信中点击“取消”,有些浏览器回退后刷新了这个页面,导致弹框又没有了。

    当时我想了个简单的办法:前端存储一个标记值在localStorage中,点击弹框中的按钮后,清除该值。

    这是个幼稚的想法~假如用户没有点击弹框中的按钮,直接关掉页面或者其他操作,岂不是这个localStorage一直在,下次进入这个页面弹框立马就出来了。

    所以我最终解决的办法是将该页面地址作为回调地址redirect_url传递过去,并且携带标记参数,是否需要弹出提示框。

    第二个坑:回调地址提早请求了

    官方文档这样说明:


    微信API文档

    回调指定页面的操作可能发生在:
    1、支付中间页调起客户端超过5秒
    2、点击“取消支付”或“完成”

    然而通过打日志实践证明,当我成功调起微信收银台没几秒,还没点击"取消”或者支付,就已经请求了我的回调地址。

    第三个坑:chrome、猎豹浏览器 回调到了 safari

    第一次发现这个坑有点搞笑,明明在谷歌浏览器访问WAP网站进行支付,成功跳转到微信收银台,点击左上角的取消,莫名其妙的到了safari浏览器中,真是一趟跨界的旅行呵~

    发现这个问题后,就去研究饿了么,美团的H5支付。
    发现和我们平台有不同点:饿了么是直接schema调起的,而我们平台是从支付中间页再通过schema调起的微信。然后在网上有看到一篇文章,正解我疑惑,是接口新版和旧版的区别 => 原文地址通道请戳这里

    那最终的解决办法是只能随它跳转到safari了,回调页中去除了登录校验,保证之后的流程能正常走完,管它在哪个浏览器里。

    第四个坑:授权域名

    当我在开发环境完成了开发,提测后,发现测试环境支付提示如下:


    微信API

    这才发现后台有授权域名的设置,这个问题也是自己想当然了,之前做过微信的PC扫码支付和APP支付,不需要填写类似的东西,所以就没注意,真是缺乏经验啊~吃了个教训

    最多只能配置5个授权域名,允许顶级域名配置。

    但是考虑到我们自身平台的特殊性,一份代码部署在一台服务器上,然而有几十个域名,大部分是符合XXX.ABC.cn的规则,有些是自定义的域名。怎么着都已经超过5个了。

    这还怎么玩,回家睡觉吧~

    不行不行,工作重要,工资重要,钱重要,还是改代码吧~

    因为微信自己说了他是根据referer来判断的。那么就伪造referer头
    只能想到curl了。把主域名作为referer头请求mweb_url,获取到中间页的html,再新写一个方法,用来从主域名中重定向回请求时的域名回调页。

            $orderno   =  "123456";
            $money     = 1;  //单位分  TEST
            $client_ip = get_client_ip(0,true);
    
            require_once "./Wxpay/lib/WxPay.Data.php";
            require_once "./Wxpay/lib/WxPay.Api.php";
    
            $scene_info ='{"h5_info":{"type":"Wap","wap_url":"","wap_name":""}}';//场景信息 必要参数
    
            //步骤二,调用统一下单接口 unifiedOrder
            $body  = '支付订单';
            $input = new \WxPayUnifiedOrder();
            $input -> SetBody($body);
            $input -> SetAttach($body);
            $input -> SetOut_trade_no($orderno);
            $input -> SetTotal_fee($money);
            $input -> SetTime_start(date("YmdHis"));
            $input -> SetTime_expire(date("YmdHis", time() + C("ORDER_EXPIRE_TIME")+600));  //冗余10分钟
            $input -> SetNotify_url("XXXXX"); //异步回调地址
            $input -> SetTrade_type("MWEB");
            $input -> SetSpbill_create_ip($client_ip);
            $input -> SetSceneInfo($scene_info);
            $result = \WxPayApi::wapUnifiedOrder($input);
    
            /*curl请求*/
            //TO DO 异常处理
            $returnUrl = "主域名/distribute.php?orderno=x&tocheck=1&type=wechat&from=当前域名);
            $headers = array(
                'REFERER: '.$returnUrl,
                'USER-AGENT:'.$_SERVER["HTTP_USER_AGENT"]
            );
            $url = $result['mweb_url']."&redirect_url=".urlencode($returnUrl);
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLINFO_HEADER_OUT, true);
            curl_setopt($ch, CURLOPT_POST, 1);
            $output = curl_exec($ch);
            curl_close($ch);
            echo $output;exit;
    

    distribute 分配的方法,重定向回之前域名下的支付订单页,也就是上面提到的有遮罩弹框的页面。

        public function distribute(){
    
            $orderno = I("get.orderno");
            $tocheck = I("get.tocheck");
            $type    = I("get.type");
            $from    = I("get.from");
    
            redirect('http://'.$from.U("Wap/Pay/payOrderTmp",array("orderno"=>$orderno,"tocheck"=>$tocheck,"type"=>$type)));exit;
        }
    

    尼玛~为什么写下来就这么点,搞代码搞这么久

    以上若有不对或者不完善的地方,请多多指教!

    不积跬步无以至千里

    相关文章

      网友评论

        本文标题:微信H5支付

        本文链接:https://www.haomeiwen.com/subject/xmlgjftx.html