年初产品引入了微信支付到现在不到半年的时间,一直没有过太大的坑爹经历,自认为微信支付也能hold住了,没想到上周还是被微信支付团队的同学狠狠的摆了一道。在这里留个记录,希望同入此坑的同学能尽快爬上来。

背景:

上半年上线了商城的微信支付,此项目前端为angularjs 的SPA(single page application,单页面应用)。地址类似于:http://mall.zjkyz8.com/public/page/index.html。微信支付需要配置一个神奇的支付授权目录,你需要将项目中的支付地址置于该配置之下,支付方能成功。所以将该配置设为:http://mall.zjkyz8.com/public/page/。 而实际上由于我们的项目前端使用了angularjs。所以实际的支付地址为http://mall.zjkyz8.com/public/page/index.html#/pay-method/0df8398837。

微信对其支付授权目录的配置规则描述如下:

  • 1、所有使用公众号支付方式发起支付请求的链接地址,都必须在支付授权目录之下;
  • 2、最多设置3个支付授权目录,且域名必须通过ICP备案;
  • 3、头部要包含http或https,须细化到二级或三级目录,以左斜杠“/”结尾。

其中并为对是否允许特殊字符做特别描述(此处特殊字符指#),但实际据客服讲是不允许的,也就是说对SPA,支付目录是无法配置到细化的目录的。不过没关系,这样的配置微信支付是可以正常工作的。目前为止,一切正常。

问题:

下面我们来说说问题是什么。这两天做了个列表页,将一些推广活动放在一起,需求要求用户通过这个列表页点击某个商品也可以完成购买。平衡功能分离与复用后,实现浏览购买流程如下:http://mall.zjkyz8.com/public/page/list.html(列表页) ->http://mall.zjkyz8.com/public/page/list.html#/detail/83984775(商品详情页)->http://mall.zjkyz8.com/public/page/index.html#/create-order/83984775(下单页)->http://mall.zjkyz8.com/public/page/index.html#/pay-method/0df8398837(支付页)。然后神奇的事情发生了:微信支付报错!错误信息为:“当前页面的URL未注册:http://mall.zjkyz8.com/public/page/index.html#/create-order/83984775”.。

分析:

很奇怪,微信错误信息中提及的URL并不是发起支付的页面,而是下单页。更奇怪的是整个下单支付逻辑完全是复用商城中已有逻辑,并未做任何修改,但测试后发现商城中的功能正常。于是通过邮件联系微信支付技术支持(邮件啊,亲,效率那是要多低有多低),客服一口咬定是SPA的中的哈希路由的问题,移除以后就没有问题。虽然我反复强调之前的功能同样带着这部分,但是却可以支付成功,但客服同学完全忽略这个观点,只是不停强调是这个问题。最后事实证明客服的这个说法是正确的,但是原因却让人哭笑不得。

原因:

客服沟通失败,只能靠自己了。折腾了一星期,反复google。最后终于找到原因。文末会添加给了我巨大帮助的一篇文章,感兴趣的小伙伴可以看一下。这个问题的产生实际是两个原因共同作用的结果:

1. 当微信支付被调起时,微信自己会验证当前调起微信支付的页面URL是否与微信支付授权目录匹配。那么何为调起微信支付页面的URL呢,嘿嘿,并不是window.location.href这么简单。这个URL实际是最后一次引起页面刷新的URL。回归到我们的项目,商城端的这个URL实际是http://mall.zjkyz8.com/public/page/index.html,因为只有第一次打开商城时也就是点击了链接后会引起全页面刷新,而之后的所有操作均是SPA内部的路由变换,只会引起哈希变化,页面部分刷新。而新的这个列表页比较复杂,因为有了复用,用户在点击下单后会跳转下单页,即http://mall.zjkyz8.com/public/page/list.html#/detail/83984775(商品详情页)->http://mall.zjkyz8.com/public/page/index.html#/create-order/83984775(下单页),SPA发生了切换,从list.html切换到了index.html,这时候微信会重新获取调起微信支付的页面URL,正好这次变换是带着哈希部分的,所以微信会连着哈希部分一起取过来比较。这正好解释了为什么微信报错的URL不是当前URL。

2. 比较过程就比较有意思了,这部分内容由于无法接触到微信的检查逻辑,所以基本上是自己根据现象猜的,各位小伙伴可以自行选择与理解。大概的逻辑可能是取到URL后用最后一个'/'做分隔符,将URL分为两部分,用第一部分和配置的支付授权目录做比对,匹配则验证成功,否则验证失败。很显然,这种验证方式下,URL分隔后的第一部分会包含哈希,于是验证失败。

解决方案:

既然知道了微信获取支付页面URL不能支持哈希部分,那么想办法把哈希部分干掉。方法很简单粗暴,在#前加个?。哈哈,既然你微信不想支持SPA的哈希,那你总得支持查询参数吧。而且既然不支持哈希,估计也没想着URL中会出现哈希,那么他们的逻辑就会写成在分隔URL前先来步预处理,将查询参数干掉,估计也是简单的用?分隔,取第一部分。

写在最后:

经过验证,这个解决方案是可行的。这也从一个侧面反映出很多人对于URL的理解以及对代码兼容性的理解。URL中的哈希部分并不是一个新的技术。我想如果我换为锚点大家就一定有印象了。这个东西最早被应用于页面内定位到某个DOM节点。后来在SPA中被用来做路由。很显然,微信在做支付功能时完全没有考虑这个技术,虽然我们可以说已经很少使用锚点了。但是单页面应用的普及却在逐步提高。换个角度,我觉得既然查询参数已经能够支持了,那么再支持一个哈希并不是什么困难的事情吧。10分钟的开发时间加半小时的测试时间换来的是对整个SPA的友好支持,应该不吃亏啊。

最后的最后,提出一个我的疑问。我始终无法理解微信支付中授权支付目录的业务价值在哪里。听名字像是尝试解决安全问题。但是整个JSSDK是基于网站域名的,这还不够吗?真诚地希望了解的同学来普及一下。

附上对我帮助巨大的文章地址:http://www.kejik.com/article/152868.html。 不知道为什么chrome访问这个地址,会报有安全隐患,请小伙伴们自行斟酌吧 :) 。

微信支付趟坑之旅之单页面应用相关推荐

  1. android微信支付坑,微信支付踏坑之旅

    其实微信支付的集成步骤也就那么几步,奈何第一次接触无论是微信官方文档还是5+SDK文档都看的晕头转向,于是我换个思路 (以下只针对android app支付功能,服务端为java) 1.首选确定app ...

  2. 加入域时出现以下错误 登陆失败 该目标账户名称不正确_微信支付踩坑合集:微信小程序支付失败是什么原因?持续更新...

    微信小程序开发的过程一定会遇到各种问题,最让人棘手的就是支付问题,因为没有支付做商城类似的小程序就没有办法完成最关键的一步.那么支付失败到底什么原因呢?一下子收集了几个错误类似,希望对你有帮助: No ...

  3. 微信开发踩坑之旅 之 开发准备及服务器配置

    在工作和兴趣的机缘巧合之下,我开始接触微信开发.在这里简单记述自己的微信开发踩坑之旅. 首先,由于本人标准的理工科生,记述的语言有所不足,我尽量说明准确和详细点. 本文记述主线 ·申请公众号 ·公众号 ...

  4. 微信小程序 通过wx.redirectTo,实现单页面刷新效果 & 下拉刷新页面数据效果

    微信小程序 通过wx.redirectTo,实现单页面刷新效果 & 下拉刷新页面数据效果 一: 使用 wx.redirectTo(),实现页面刷新数据效果 API说明: 关闭当前页面,跳转到应 ...

  5. 微信支付软件架构重构之旅

    方秋枋 读完需要 10 分钟 速读仅需 1 分钟 原文链接:https://www.cnblogs.com/imstudy/p/12567241.html 本文原文由微信客户端高级工程师方秋枋原创发表 ...

  6. 微信支付踩坑血泪史(JAVA -V3版本)

    背景介绍 最近第一次接触到微信支付,踩了很多坑,赶紧写下来,全是心酸和眼泪.话不多说.开始展示. 项目中使用的接入方式是JSAPI(参考 产品中心 - 微信支付商户平台),当然也可以使用其他接入方式, ...

  7. 微信支付的坑 返回值 -1

    2019独角兽企业重金招聘Python工程师标准>>> 最近在用android接入微信支付.. 之前的包没问题,发现这段时间突然不行了... 于是调试之. 1.开始用的支付配置参数估 ...

  8. 微信支付的坑(思路)

    获取openid页面刷新:https://bbs.csdn.net/topics/391115929 异步通知验证签名:微信返回xml数据中的sign使用的是HMAC-SHA256加密方法,所以不能使 ...

  9. app端微信支付(二) - 生成预付单

    ​前一篇文章的时序图中说了,app端调用微信支付必须先由后台调用微信后台生成预付单,再构建参数给手机端,而数据的构建要以xml形式,那么看看代码具体实现吧,代码已经精简过了,自己的业务已经除去,精简的 ...

最新文章

  1. js调用python脚本_javascript – 如何从NodeJs调用python脚本
  2. $cfg_dbtype = mysql_多库操作2:终于实现多个数据库操作
  3. Windows学习总结(6)——MindManager新手入门教程
  4. python创_Python创建Windows 服务
  5. C/C++——cmd下丢失mspdb100.DLL解决方法
  6. kaggle:PUBG Finish Placement Prediction
  7. asp adodb连接mysql数据库语句_ASP连接MySQL数据库的方法
  8. 2021年安徽全椒中学高考成绩查询,全椒中学2020届高考记录是这样的!
  9. 安卓修改大师功能简介
  10. 苹果电脑怎样禁用首字母自动大写?
  11. AD(altium designer)15原理图与PCB设计教程(五)——工程编译与报表生成
  12. 计算机网络基础之互联网总结
  13. iCCP: cHRM chunk does not match sRGB
  14. flutter安装及过程中遇到的问题解决
  15. 使用BIOS进行键盘输入和磁盘读写
  16. 工具分享--IDM下载工具利器,让下载速度提升一百倍
  17. Google SEO优化排名常见的三种问题
  18. 电脑垃圾,怎么清理电脑垃圾 让电脑全面瘦身
  19. 我们利用计算机解决问题时第一步应该,算法与程序设计综合评价练习题
  20. 不可多得的WinXP技巧十则(转)

热门文章

  1. ApplicationContext和Bean的初始化和销毁
  2. 详述ArrayList类中的contains()方法及原理
  3. 调用百度搜索接口查询
  4. Udacity CS101 笔记
  5. excel表格xlsx解开权限密码,excel表格xlsx不能复制打印怎么办?
  6. 无监督对比学习之MOCO 《Momentum Contrast for Unsupervised Visual Representation Learning》
  7. latex学习笔记1
  8. 神探Python程序员,带你千里捉小三!
  9. 全屏或者退出全屏检测
  10. VisionPro 常用控件的说明 C# 开发