关于对接支付接口遇到的问题(微信和支付宝)

 

目录

 

前言

 问题

支付场景非法或请在微信外打开订单

微信公众号支付 错误chooseWXPay:fail, the permission value is offline verifying

其他支付对接方式

H5微信支付

支付宝支付

支付各环境测试情况

写在最后


前言

这次项目是基于react写的一个h5,但是后期改成了SDK的形式,打包工具用的webpack;总的来说遇到了不少问题,解决的时候一度挠秃头。毕竟挂钩是否能提前转正,碍于面子总想着加班提前完成,费了不少精力,好在是终于完成了,松了口气~

对于这次项目遇到的问题就分模块写几篇记录,这篇是支付遇到的问题~

首先说明,本人技术仅高于菜鸟一级~文章倾向于大白话风格,写的若是有什么不对的地方欢迎指正~(希望不要批评我哈哈哈~*✧⁺˚⁺ପ(๑・ω・)੭ु⁾⁾ )也欢迎补充(*^▽^*)~

 问题

支付场景非法或请在微信外打开订单

解决方法

区别环境使用不同的微信API。

首先遇到的一个坑就是不同环境下的支付需要调用不同的API类型。

例如我这次的项目有两种支付环境,可以区分为微信环境非微信环境。因此,对应就需要用到下图中的JSAPI支付H5支付。

关于对接支付接口遇到的问题(微信和支付宝)_第1张图片 微信支付开发文档的截图

原来我都是按H5写,调用支付的时候就自己想当然的使用H5支付。于是在微信环境内测试就出现了如下问题。

关于对接支付接口遇到的问题(微信和支付宝)_第2张图片 H5支付文档中的常见问题5

微信H5支付文档中的常见问题的确很实用,遇到的错误都可以再这里找到问题原因。

既然说是H5支付不能再微信客户端内调起,那么就只能换一个了,于是我仔细看了下文档才发现微信环境内调用是需要使用JSAPI的 。

JSAPI使用比较简单,前面基本的设置,JSAPI支付文档已经写的很清楚了,后面的调用也都是由后端调用。

后端注意交易类型的区分:trade_type=MWEB(H5支付)trade_type=JSAPI(JSAPI支付)否则会报支付场景非法。

前端判断代码:

// 示例代码来源于官方文档
function onBridgeReady(){
   WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
         "appId":"wx2421b1c4370ec43b",     //公众号名称,由商户传入     
         "timeStamp":"1395712654",         //时间戳,自1970年以来的秒数     
         "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串     
         "package":"prepay_id=u802345jgfjsdfgsdg888",     
         "signType":"MD5",         //微信签名方式:     
         "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
      },
      function(res){
      if(res.err_msg == "get_brand_wcpay_request:ok" ){
      // 使用以上方式判断前端返回,微信团队郑重提示:
            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
      } 
   }); 
}
if (typeof WeixinJSBridge == "undefined"){
   if( document.addEventListener ){
       document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
   }else if (document.attachEvent){
       document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
   }
}else{
   onBridgeReady();
}

getBrandWCPayRequest参数可以全部由后端返回。前端只需要调用WeixinJSBridge内置对象和判断返回结果即可。具体要仔细研读文档。

// 判断是否是微信环境的代码
var isWechart = function () {
   var rst = true
   if(window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)){
     var ua = navigator.userAgent.toLowerCase();
     if (!(ua.match(/MicroMessenger/i) == "micromessenger")) {
       rst = false;
     }
   }else {
     rst = false;
   }
   return rst;
 }

/* ------------------- 其他 js判断浏览器的环境代码 --------------------------*/
/* 参考链接:https://www.jb51.net/article/178066.htm */

// 判断微信浏览器是PC端还是手机端,以及手机端是微信浏览器还是非微信浏览器
//平台、设备和操作系统  
    var system = { 
      win: false, 
      mac: false, 
      xll: false, 
      ipad: false
    }; 
    //检测平台  
    var p = navigator.platform; 
    system.win = p.indexOf("Win") == 0; 
    system.mac = p.indexOf("Mac") == 0; 
    system.x11 = (p == "X11") || (p.indexOf("Linux") == 0); 
    system.ipad = (navigator.userAgent.match(/iPad/i) != null) ? true : false; 
    //跳转语句,如果是手机访问就自动跳转到wap.baidu.com页面  
    if (system.win || system.mac || system.xll || system.ipad) { 
      alert("在PC端上打开的");
    } else { 
      var ua = navigator.userAgent.toLowerCase();  
      if(ua.match(/MicroMessenger/i)=="micromessenger") {  
        alert("在手机端微信上打开的"); 
      } else {  
        alert("在手机上非微信上打开的"); 
      }  
    }

// 判断浏览器函数
// 方法一
 function isMobile(){
   if(window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
     return true; // 移动端
   }else{
     return false; // PC端
   }
 }

// 方法二摘自:im.qq.com
var os = function() { 
   var ua = navigator.userAgent, 
   isWindowsPhone = /(?:Windows Phone)/.test(ua), 
   isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone,  
   isAndroid = /(?:Android)/.test(ua),  
   isFireFox = /(?:Firefox)/.test(ua),  
   isChrome = /(?:Chrome|CriOS)/.test(ua), 
   isTablet = /(?:iPad|PlayBook)/.test(ua) || (isAndroid && !/(?:Mobile)/.test(ua)) || (isFireFox && /(?:Tablet)/.test(ua)), 
   isPhone = /(?:iPhone)/.test(ua) && !isTablet, 
   isPc = !isPhone && !isAndroid && !isSymbian; 
   return { 
     isTablet: isTablet, 
     isPhone: isPhone, 
     isAndroid : isAndroid, 
     isPc : isPc 
   }; 
}(); 
  
// 使用方法 
if(os.isAndroid || os.isPhone){
alert("-----");
}

微信公众号支付 错误chooseWXPay:fail, the permission value is offline verifying

为了方便测试我开了微信开发者工具的公众号网页来测试,普通功能是没问题的,调支付接口的话就会报错。

有两种可能,一种是非真机调用引起的,一种是url地址错误。

解决方法

一是在模拟器中实行发起支付,要在真机是发起

二是微信公众号支付授权目录要填写实际发起支付的url地址,比如你的页面是http://www.newfms.com/order/pay/id-115,那么此处应该填http://www.newfms.com/order/pay/

参考链接:https://blog.csdn.net/haibo0668/article/details/85209238

其他支付对接方式

H5微信支付

h5微信支付调用比较简单,由后端调统一下单接口,返回一个url地址,前端只需要跳转这个url就行。

支付宝支付

支付宝的也很简单,由后端发起订单请求,根据返回的订单数据来拉起支付宝支付。

我采用的是form提交。

let temp = document.createElement("form");
temp.action = res.action;
temp.method = res.method;
temp.style.display = "none";
let params = res.para;
for (const k in params) {
    let opt = document.createElement("input");
    opt.name = k;
    opt.value = params[k];
    temp.appendChild(opt);
}
document.body.appendChild(temp);
temp.submit();

// 参考链接: https://www.cnblogs.com/jun-qi/p/12313495.html

最后走通流程测试后,发现支付宝支付有个问题, form表单调用支付宝会跳转到H5收银台页面然后再调起跳转到支付宝APP,在取消支付后回来,H5收银页无法关闭。

至此开始走了不少弯路。。。

首先是写了iframe,让H5收银页显示在iframe中,再额外手动写个关闭按钮放上去。

关于对接支付接口遇到的问题(微信和支付宝)_第3张图片

解决了H5收银页关闭的问题,出现了另一个问题,在IOS中,iframe无法调起支付宝APP,并且在安卓中也需要用户手动点击蓝色的【使用支付宝APP付款】的按钮才可以跳转,并不是自动跳转。

除此之外前前后后还试了不少方法,看了几遍文档,无奈后端小哥哥太忙,没有时间配合我做其他方法的测试。最后好歹是发现了控件跳转这个方法(其实也在文档中)。

但是这个方法前端并不用做什么事情,我查过收银页的代码,发现跳转的代码是写在这里的,并且也有打印出来,只是我无法获取到,于是改由后端去访问,再返回已经拼接好的(以alipay:// 或 alipays:// 开头的)跳转链接,前端只需要重定向到这个链接就能不跳转收银页调起支付宝APP了。

支付各环境测试情况

关于对接支付接口遇到的问题(微信和支付宝)_第4张图片

大致测试结果如图,由于是我项目完成后总结回忆的,并且安卓的测试情况由后端小哥哥提供,所以可能有偏差,欢迎指正~

项目要求是微信环境下不设支付宝支付,所以“ - ” 都是不需要测试的情况,仅使用微信JSAPI即可。

最终出了微信环境下微信支付,其他项目全部采用控件调起APP支付,微信控件支付同支付宝调起类似,也是后端返回拼接好的以weixin://  开头的跳转链接,重定向即可。但是如上图所示,可以看出在IOS中会出现支付完成或取消后跳转QQ浏览器的页面。不大清楚有没有自身错误操作的原因,但是最终没找到问题,卸载QQ浏览器后也不是跳到IOS默认浏览器Safari中,而是直接关闭支付弹窗,需要像支付宝一样手动返回自己的网站或者网页。

写在最后

支付功能一度被我放在项目进度后面的后面,但是其实了解了后就觉得也没有很棘手,官方文档还是要好好看~看多几个人家写的demo就差不多啦~

你可能感兴趣的:(前端,#,JavaScript)