前言:花了好幾天的時間搞了下微信公衆號支付,期間歷程無比心酸,總的來講仍是理解能力不夠和經驗不足,如今概括下支付中遇到的坑。php
先看業務流程
前端
首先,公衆號支付採用的是,利用微信的js-sdk調起支付的方式進行的,其中分爲兩種狀況:微信jssdk調起和微信支付開放平臺調起。可是,不管是採用什麼方法首先都要先配置wx.config。git
wx.config({ debug: true, // 開啓調試模式,調用的全部api的返回值會在客戶端alert出來,若要查看傳入的參數,能夠在pc端打開,參數信息會經過log打出,僅在pc端時纔會打印。 appId: '', // 必填,公衆號的惟一標識 timestamp: , // 必填,生成簽名的時間戳 nonceStr: '', // 必填,生成簽名的隨機串 signature: '',// 必填,簽名 jsApiList: [] // 必填,須要使用的[JS接口列表][4],chooseWXPay 微信支付接口 });
參數分析:appId,timestamp,nonceStr 這裏須要注意一下變量的大小寫,這裏採用的是駝峯命名法,timestamp由於自己就是一個單詞,因此不要寫錯。signature這個須要注意一下,畢竟涉及到的 sign(簽名)、token 實在太多了,極其容易混淆。同時,生成簽名以前必須先了解一下jsapi_ticket,jsapi_ticket是公衆號用於調用微信JS接口的臨時票據。正常狀況下,jsapi_ticket的有效期爲7200秒,經過access_token來獲取,獲取jsapi_ticket的api調用次數很是有限,頻繁刷新jsapi_ticket會致使api調用受限,影響自身業務,開發者必須在本身的服務全局緩存jsapi_ticket ,然而access_token的有效期也只有7200秒,因此把jsapi_ticket和access_token同時緩存(固然你能夠只存jsapi_ticket) 。這裏推薦參數從後臺獲取,代碼以下:github
{ const moment = require('moment'), //時間處理類 cnpm i moment request = require("request"); //cnpm i request https://github.com/request/request wxConfig = { appid:'', //appid appsecret:'', //appsecret mcnsecret:'', //商戶key mcnid:'', //商戶號 notify_url:'' //支付成功想要回調的後臺地址,用於修改訂單狀態等等操做 } // 獲取 公衆號的access_token和ticket ,須要存入緩存或者數據庫,有效期7200s,請注意和獲取用戶access_token api進行區分 app.get('/accpetSubscriptionNow',async function (req,res,next) { let task = await XXXXModel.findOne({where:where});//獲取存在數據庫裏面的公衆號的accesstoken,XXXXModel是本身的表 let cc = {}; let WXInitConfig = {};//建立一個空對象用以存儲微信公衆號配置信息 // 判斷數據庫裏面是否存在accesstoken等信息,且存放的時間是否超過7200秒 if(JSON.stringify(task.updateBy)==='{}' || parseInt(moment(task.updateBy.updateTime).format('X')) + 7200 < parseInt(moment().format('X'))){ console.log('#1.判斷accesstoken的更新時間大於7200s,從新拉取accesstoken') request.get( { // 獲取access_token的接口 url: `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${wxConfig.appid}&secret=${wxConfig.appsecret}` }, async function (error, response, body) { console.log('body', body) //成功獲取到access_token,這裏應該有個判斷 const ACCESS_TOKEN = JSON.parse(response.body).access_token; let json = JSON.parse(response.body); request.get({ // 獲取jsapi_ticket的接口 url: `https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${ACCESS_TOKEN}&type=jsapi` }, async function (error, response, body) { //成功獲取到jsapi_ticket,這裏應該有個判斷 console.log('body2', body) let updateBy = { updateTime : new Date() } json.ticket = JSON.parse(body).ticket; // 把獲取到的access_token和jsapi_ticket存放到數據庫,並標明更新時間 cc = await XXXXModel.findOneAndUpdate({ where:where }, {data: data}) WXInitConfig = cc.content; //console.log('WXInitConfig',WXInitConfig) let data = await acceptsignature(WXInitConfig); //console.log('data',data) res.send(data);//傳遞微信號配置信息到前端 }) } ) }else { console.log('#2.判斷accesstoken的更新時間小於7200s,從數據庫獲取access_token和ticket') WXInitConfig = task.content; let data = await acceptsignature(WXInitConfig); res.send(data); } }) // 獲取signature簽名的方法 function acceptsignature(WXInitConfig) { console.log('WXInitConfig2',WXInitConfig) let appid = wxConfig.appid; let nonceStr = Math.random().toString(36).substr(2, 15); let access_token = WXInitConfig.access_token; let jsapi_ticket = WXInitConfig.ticket; let timestamp = moment().format('X'); let url = 'http://mmobile.hwason.cn/'; // 把所需的參數ASCII序列化 let ASC = `jsapi_ticket=${jsapi_ticket}&noncestr=${nonceStr}×tamp=${timestamp}&url=${url}`; console.log('ASCII',ASC) // 把序列化的數據使用 SHA1 方法加密,記住獲得的是小寫的加密串 let signature = SHA1(ASC).toLowerCase(); console.log('signature',signature) let data = { appid:appid, nonceStr:nonceStr, // access_token:access_token, // jsapi_ticket:jsapi_ticket, timestamp:timestamp, // url:url, signature:signature, result:'00' } return data; } }
到此,前端調用上述的接口就能夠獲取到微信的配置參數了。
參數配置好了,就開始正式啓動微信公衆號支付了。數據庫
步驟①:設置支付目錄
步驟②:設置受權域名
步驟③:前臺進入微信受權頁面
微信受權又分爲5步:
1)進入微信受權頁,用戶贊成受權,獲取codenpm
//進入受權頁有兩張方式 // 1、前端直接跳轉 let return_url = ''; //受權後回調的頁面,這裏是前端的地址url window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx1a1cf7c547b07420&redirect_uri=" + encodeURIComponent(return_url) + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect" // 2、後端重定向 //尤爲注意:因爲受權操做安全等級較高,因此在發起受權請求時,微信會對受權連接作正則強匹配校驗,若是連接的參數順序不對,受權頁面將沒法正常訪問