通常一些电商项目使用到微信支付操作,所以简单地介绍一下微信支付的具体流程。
微信支付是微信内置微信浏览器(其他浏览器不支持)或者微信小程序的支付接口,主要负责用户对商家执行支付操作的流程。
例如常见的电商在下单环节,就需要通过使用微信支付接口,唤醒支付金额以及输入支付密码界面。再通过支付是否成功,跳转到相应的支付成功,支付取消或者支付失败页面。
通常支付会分成两种形式:
一、在商品详情页跳转到下单页面去执行支付(此时订单未创建),对应以下的1.2.1 订单未创建的下单支付流程。
二、在订单页面处于待支付去支付(此时订单已经创建了),对应以下的1.2.2 订单已创建的下单支付流程。
具体大概流程如下所述:
① 用户点击关闭支付密码界面,JSAPI 支付接口就会返回res.err_msg=“get_brand_wcpay_request:cancel”,即用户取消支付,前端书写跳转路由跳到支付取消页面;
② 用户支付密码输错后,JSAPI 支付接口就会返回res.err_msg == “get_brand_wcpay_request:fail”,即用户支付失败,前端书写跳转路由跳到支付失败页面;
③ 用户支付密码正确后,JSAPI 支付接口就会返回res.err_msg == “get_brand_wcpay_request:ok”,即用户支付成功,前端书写跳转路由跳到支付成功页面;
具体大概流程如下所述:
现在一般微信的支付接口会分成两种:
一、JSAPI 支付接口
二、微信公众号的JSSDK中的wx.chooseWXPay
通常支付接口会封装好放在全局中,以便前端调用可以减少重复书写。
// 检测支付环境中的 WeixinJSBridge 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(); } function onBridgeReady() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId": "appId", //公众号名称,由商户传入 "timeStamp": "timeStamp", //时间戳,自1970年以来的秒数 "nonceStr": "nonceStr", //随机串 "package": "package", "signType": "MD5", //微信签名方式: "paySign": "paySign" //微信签名 }, function(res) { // 支付成功 if (res.err_msg == "get_brand_wcpay_request:ok") { // 使用以上方式判断前端返回,微信团队郑重提示: //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 } // 支付过程中用户取消 if (res.err_msg == "get_brand_wcpay_request:cancel") { } // 支付失败 if (res.err_msg == "get_brand_wcpay_request:fail") { } /** * 其它 * 1、请检查预支付会话标识prepay_id是否已失效 * 2、请求的appid与下单接口的appid是否一致 * */ if (res.err_msg == "调用支付JSAPI缺少参数:total_fee") { } }); }
从上述代码中我们可以看出,先会检测支付环境中的 WeixinJSBridge,个人认为是为了判断执行代码是否处于微信环境。在执行WeixinJSBridge.invoke()的接口请求时,会用到一组支付签名的数据,这正是通过后端请求支付签名所给的。
分别为以下五种数据:
(注意:在调用支付接口的参数,支付签名的数据中的字段名受大小写敏感)
wx.chooseWXPay使用前需要先准备jweixin-1.6.0.js文件,并在需要使用的页面引用此JS文件。具体使用说明可以查看微信官方JSSDK文档
let WeChatPay = function() { // 2、引入js后、获取公众号校验信息 let timestamp = '', nonceStr = '', signature = ''; let v = { // 用于换取微信校验信息的参数:要求不可以包含 “#” 号 url: location.split('#')[0] }; // 3、通过config接口注入权限验证配置(需要同步进行,在获取到校验信息后方可注入config,否则校验失败!) wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '', // 必填,签名 jsApiList: ["checkJsApi", "chooseWXPay", "updateAppMessageShareData", "updateTimelineShareData"] // 必填,需要使用的JS接口列表 }); axios.post('/wx/pay/orderPay_XXXX', data).then(res => { // 支付成功状态 if (res.code == 200) { // 获取支付必备的参数 let { nonceStr, package, signType, paySign } = res.data; // 4、通过ready接口处理成功验证 wx.ready(function() { /* 微信支付 */ wx.chooseWXPay({ timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 nonceStr: nonceStr, // 支付签名随机串,不长于 32 位 package: package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*) signType: signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' paySign: paySign, // 支付签名 success: function(res) { // 前端判断返回方式,微信团队郑重提示:不保证绝对可靠,切记! if (res.errMsg == 'chooseWXPay:ok') { // 【支付成功】 } else if (res.errMsg == 'chooseWXPay:cancel') { // 【支付取消】:用户取消支付不会进入这个判断,而是进入complate和cancel函数 } else { } }, complete: function(res) { // 接口调用完成时执行的回调函数,无论成功或失败都会执行 if (res.errMsg == 'chooseWXPay:ok') { // 【支付成功】:支付成功提示页面,点击完成按钮之后 wx.closeWindow(); /* 关闭微信窗口,调用时需要在config中进行校验 */ } else if (res.errMsg == 'chooseWXPay:cancel') { // 【支付取消】 } else { } /** * iOS和Android支付成功点击“完成”后都会进入success和complete函数,都返回'chooseWXPay:ok' * (也有人说Android支付成功不进入success函数,) * 原因是【iOS和Android返回数据不同。支付成功后Android返回 {"errMsg":"getBrandWCPayRequest:ok"},iOS返回{"err_Info":"success","errMsg":"chooseWXPay:ok"},故Android找不到success方法,导致失败】 * */ }, fail: function(err) { // 接口调用失败 }, cancel: function(err) { // 用户点击取消时的回调函数:用户取消支付后实际上进入cancel 和 complate函数 } }); }); } }).catch(err => { console.log('支付失败:', err); }); }
观察上述代码,对比之前的JS API支付接口,可以看多出了2,3两步,需要进行config接口的权限认证,下面支付场景就不多叙述了,重点看第2,3步。
在此中不但需要支付签名的数据,还是用到了jsApiList的字符串数组。那jsApiList的字符串数组是什么用呢?在下面1.3.2.3 jsApiList 会具体说明一下。
jsApiList里面一组字符串就是一种功能。
例如微信的H5需要同时使用到微信的获取地址getLocation与共享地址库openAddress。
就可以在 wx.config权限认证时,书写你想要是哦用的功能,即jsApiList: [“getLocation”,“openAddress”]。后面wx.功能名调用此功能接口,实现相应的功能。
具体jsApiList里面能书写的功能可以查看微信官方JSSDK文档
通常H5分享到好友或者分享到朋友圈可以使用此功能。分享出去是一个卡片,里面带图片加标题文字。若不执行wx.config权限认证的话,用户直接进行分享操作时,绘制分享出去是一段链接。
之前本人项目会遇到H5需要通过jssdk来分享的业务场景,但首次用户A分享到用户B的时候,往往是没有一卡片的形式分享出来。
在收藏卡片样式如下图所示:
在好友转发界面卡片样式如下图所示:
在那之后进行网上搜索,发现首次分享的用户可以通过以下三种规则使用其中一种进行分享:
这是微信官方jssdk的分享规定,H5的分享确实不像微信小程序一样简单,毕竟H5比微信小程序少了上线审核步骤,不太严谨。
网上查了一圈基本都是这些分享方案,所以首次分享的用户最好是通过开发人员分享出来给客户(按照上面三种的分享规则处理),后面用户B或者更后面用户看到就是卡片+标题+简介的样子