Safari iframe方式无法呼起微信app之问题探索

摘要

微信h5支付测试时,发现使用Safari iframe的方式无法呼起微信app进行支付。本文首先讲述了微信支付的流程、随后进行了两个测试与网上的搜索等进行了一系列的探索,得到了可以证实的结论。

零、背景

微信h5支付流程如下图所示:
1、用户在商户侧完成下单,使用微信支付进行支付;
2、由商户后台向微信支付发起下单请求(调用统一下单接口);
3、统一下单接口返回支付相关参数给商户后台,包括:支付跳转url(参数名“mweb_url”);
4. 商户重定向到mweb_url,调起微信支付中间页,客户进行支付,点击支付完成回调到商户的买单页 or 商户指定的redirect_url,至此,客户端流程结束。
5. 其他流程,在此不解释。普通商户微信h5支付官方地址
【过程4解析】:当用户重定向到mweb_url后,微信会返回一个呼起微信app的scheme串,形如如下代码描述:

mweb_url串 : https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx06203454877852b3d995061c1369865961&package=2470898687
scheme串:weixin://wap/pay?prepayid%3Dwx06203454877852b3d995061c1369865961&package=2470898687&noncestr=1533558901&sign=06c9a12b39e341a2dfe9d68e470edbfa

交互的网络请求
微信h5支付(普通商户)流程

一、前序

在做微信的h5支付时,发现在Safari中使用iframe无法呼起微信客户端的问题。
现象A: h5支付,不使用iframe,直接redirect到预下单返回的mweb_url,火狐、chrome、Safari均可以呼起微信支付。
现象B: h5支付,使用iframe,将返回的mweb_url设置到iframe中的src,火狐、chrome均可以呼起微信支付,唯独Safari中无法呼起(ios的其他浏览器也做过尝试,是可以呼起的)。

现象A前端代码:


<html>
<head> 
<meta charset="utf-8"> 
<title>spy test h5 paytitle> 
head>
<body>

<h1>h5 pay testh1>
<p>测试商品 0.01元p>
<form id="payFrom" name="payform" action="https://您的后台处理地址" method="post">
    <input type="text" name="operFlag" value="h5pay">
    <input type="button" style="background-image:url(wechaticon.png);" value="微信支付">

form>
body>
html>

现象A后端代码:

//与微信交互获取到mweb_url,在此省略
response.sendRedirect(mweb_url );//重定向

现象B前端代码:


<html>
<head> 
<meta charset="utf-8"> 
<title>spy test h5 paytitle> 

<script src="/script/jquery-3.3.1.min.js">script>
<script src="/script/jQuery.form.js">script>
    <script type="text/javascript">
        function submitform(){  
            $('#payForm').ajaxSubmit(  //ajax方式提交表单
            {
                url: '您的地址',
                type: 'post',
                dataType: 'json',
                success: function (data) {
                    $('#payIframe').attr({"src":data.url});//src 是赋值成功的
                }
            })
        }
    script>
head>
<body>

<h1>h5 pay testh1>
<p>测试商品 0.01元p>
<iframe id="payIframe" name="payIframe" style="width:200px;height:200px" sandbox="allow-same-origin allow-top-navigation allow-forms allow-scripts">iframe>

<form id="payForm" name="payForm" action="#" method="post" target="payIframe">
    <input type="text" name="operFlag" value="h5pay1">
form>
<input type="button" style="background-image:url(wechaticon.png);" onclick="submitform()" value="微信支付">
body>
html>

现象B后端代码:

//与微信交互获取到mweb_url,在此省略
results = "{\"url\":\""+ mweb_url +"\"}";
response.setContentType("application/json;charset=UTF-8");
response.setHeader("catch-control", "no-catch");
PrintWriter out = response.getWriter();
out.write(results);
out.flush();
out.close();
return;  

可以看到现象B的form表单中,target是iframe,针对无法呼起来的原因,博主做了如下探索。

二、探索

在调试阶段,当我们使用mweb_url请求微信时,可以看到微信的返回中的一段代码:下图中url是呼起app的scheme串,赋值给了top.location.href,因为我们是从iframe发出去的,当response回来后,存在于iframe中,那么top.location 便指向了我们前端自己的jsp,即form所在的jsp中。随后,如图箭头所示,浏览器根据scheme协议,跳转到微信app,这个逻辑是没有任何问题的(至少其他浏览器总是可以呼起app的)。
Safari iframe方式无法呼起微信app之问题探索_第1张图片

测试1:

为了证明我的推理,由于微信的返回我们无法控制,于是拷贝了内容到h5wxjs.jsp,并alert top.location.href对象,如下是h5wxjs.jsp.

<script type="text/javascript">

window.onload=function()
{
    var url="weixin://wap/pay?prepayid%3Dwx06203454877852b3d995061c1369865961&package=2470898687&noncestr=1533558901&sign=06c9a12b39e341a2dfe9d68e470edbfa";
    var redirect_url="";
    alert(top.location.href);//弹出2
    top.location.href=url;
}
script>

在测试的jsp中,引入h5wxjs.jsp:

var tmp_url = "https://你的地址/h5wxjs.jsp";
alert(location.href); //弹出1
$("#payIframe").attr("src",tmp_url);//src 是赋值成功的

测试发现,依然是其他浏览器均可以呼起app,而Safari无法呼起,同本文前序中的测试现象B,并且两次弹出都是同一个对象(注释的弹出1和弹出2)。

测试2:

我们抛弃h5wxjs.jsp,直接在测试jsp中做如下测试:

function submitform(){
var tmp_url ="weixin://wap/pay?prepayid%3Dwx06203454877852b3d995061c1369865961&package=2470898687&noncestr=1533558901&sign=06c9a12b39e341a2dfe9d68e470edbfa";

location.href = tmp_url; //ok
//top.location.href=tmp_url; //ok
//window.location.href= tmp_url; //ok
// window.top.location.href = tmp_url;//ok
return;
}

实现证明,如上的4句赋值,包括Safari在内的所有浏览器均可以呼起微信app,同本文前序的测试现象A。

测试1和测试2证明了:

Safari做了安全控制,从iframe发出去的请求得到的response中,无法使用scheme协议呼起app。 此博文的博主也遇到了同样的问题,只不过是无法呼起支付宝app。参考:Safari iframe 无法呼起支付宝app
【备注:简书中 cls 的答复,其实并没有解决本质问题】
为了证明这点,我又使用苹果真机,Safari调试,可以看到请求微信后收到了response,但是并没有呼起微信app的过程。调试方法参考:苹果真机调试Safari

摘自网上的回复:

证明1
证明2
Safari iframe方式无法呼起微信app之问题探索_第2张图片

结论

  1. 使用scheme 协议呼起app,基本所有浏览器目前均是可以的。
  2. 使用iframe,scheme协议呼起app,Safari浏览器在ios9+系统后是行不通的,ios7\8还是可以的。
  3. 据说chrome 25以后也不会支持iframe内 scheme协议呼起app。
  4. 如果要在ios9+ 系统,Safari呼起app,可以使用universal link协议(博主没有亲自尝试)。
    univisal link唤起app
    univisal link解决呼起app可参考

感谢

在此特别感谢我师父陈立全、孙彦杰、白长昊同事,北京零度在线科技有限公司朋友的帮助。

你可能感兴趣的:(微信支付)