本文基於工作使用學習,做的整理筆記
當我們進行微信分享時,分享出去的效果,我們最容易發現的是沒有圖,那我們就埋一個301 * 301的圖。但是,我們又發現沒有描述,只有鏈接。這個該怎么解決呢。最終方法就是需要使用微信公眾平台的JS-SDK來實現,調用分享接口。實現這個功能時遇到不少坑,走了不少彎路,這里就整理記錄一下以便后面查閱。那么,來一起看看吧。
前提條件:
本文后台基於nodeJS,需要有一點這一方面基礎。
(還需域名,服務器,微信公眾號或測試號)
編碼環境:
系統:OS X EI Capitan
版本:10.12.5

目錄
| - 0.題外話
| - 1.JS-SDK使用說明
| - 2.實例開發
| - 1)獲取access_token
| - 2)獲取jsapi_ticket
| - 3)計算signature
| - 4)前端調用
| - 5)配置測試
| - 6)優化請求
| - 3.常見問題
| - 1)config錯誤
| - 2)signature錯誤
| - 3)url domain錯誤
| - 4)其他錯誤
| - 4.附QQ分享
| - 5.結束
0.題外話
當不使用JS-SDK,我們該怎么實現“分享”帶縮略圖呢?之前有一個取巧的方法,如下:
- 標題:取meta標簽title的內容。
- 縮略圖:取body內第1張符合條件的圖片。
圖片規格要求:尺寸必須大於300 * 300,放在<img src="" alt="">
標簽內。
所以,我們會埋一張301 * 301的圖片,比如:
// 
在分享的時候會自動獲取到這張圖片,但實際並沒有顯示。(但有一定的概率失效,原因未仔細查找,因為准備使用JS-SDK)
1.JS-SDK使用說明
微信JS-SDK說明文檔傳送門:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
閱讀文檔,發現其實真對我們想要的分享功能,閱讀前3大點內容就夠了,如下:
- 綁定域名,配置“JS接口安全域名”
- 引入JS文件
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
- 通過config接口注入權限驗證配置
wx.config({ debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。 appId: '', // 必填,公眾號的唯一標識 timestamp: , // 必填,生成簽名的時間戳 nonceStr: '', // 必填,生成簽名的隨機串 signature: '',// 必填,簽名,見附錄1 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2 });
其中,最重要的就是signature簽名的生成。附錄1告訴我們: 1)生成`signature`需要`jsapi_ticket`, 2)生成`jsapi_ticket`需要`access_token` 3)還有7200秒過期等規則,組裝規則(稍后再看)
- 通過ready接口處理成功驗證
wx.ready(function(){ // config信息驗證后會執行ready方法,所有接口調用都必須在config接口獲得結果之后,config是一個客戶端的異步操作,所以如果需要在頁面加載時就調用相關接口,則須把相關接口放在ready函數中調用來確保正確執行。對於用戶觸發時才調用的接口,則可以直接調用,不需要放在ready函數中。 });
- 通過error接口處理失敗驗證
wx.error(function(res){ // config信息驗證失敗會執行error函數,如簽名過期導致驗證失敗,具體錯誤信息可以打開config的debug模式查看,也可以在返回的res參數中查看,對於SPA可以在這里更新簽名。 });
【用自己的話】解釋整個流程就是:
- 先有個公眾號,這樣就有appID和appSecret(在開發/基本配置分類下)
- 引入JS文件
http://res.wx.qq.com/open/js/jweixin-1.2.0.js
,去使用微信JS-SDK - 拿access_token,配置IP白名單才能調此接口,根據appID和appSecret進行請求 (有效期7200秒,每次使用前檢查,過期重新獲取)
- 拿jsapi_ticket,根據上一步的access_token進行請求 (有效期7200秒,每次使用前檢查,過期重新獲取)
- 計算signature,根據上一步的jsapi_ticket
1)排序,參與簽名的字段:noncestr(隨機字符串),有效的jsapi_ticket,timestamp(時間戳),url(不帶#后面部分部分),字典序從小到大排序,
2)拼接,使用URL鍵值對的格式拼接字符串string1,參數名必須均為小寫字符
3)加密,對string1作sha1加密,字段名和字段值都采用原始值,不進行URL 轉義
注意:計算簽名必須在服務端完成簽名,返回前端。 - 添加JS接口安全域名(
在公眾號后台的設置/公眾號設置/功能設置中添加
),這里需要實現MP_verify_AwmmQFM5B0vHg035.txt
文件檢查功能 - 部署測試,注意事項:80端口,域名已備案
2.實例開發
官方DEMO頁面和例子傳送門:附錄6。
如果你有可以使用的公眾號,那么直接用就好了。如果沒有,就需要使用測試公眾號。在在公眾號后台的開發/開發者工具/公眾平台測試帳號
,登陸進入就可以使用測試公眾號了。
我這里的信息如下:
appID:wx5ee658102855e872
appSecret:af7207aaa4bec3b9b1ed941564a4580f
1)獲取access_token
// 這里應該判斷是否存在簽名,是否已過期 //(稍后添加) // ... // 公眾號字段 var appID = "wxa2c416de84300ee5"; var appSecret = "bba57000821ac67cbcee3a573db85498"; // 獲取access_token var tokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='+appID+'&secret='+appSecret; request(tokenUrl, function (error, response, body) { if (response.statusCode === 200) { body = JSON.parse(body); // 這里我緩存到了global global.wxshare.access_token = body.access_token; // 獲取jsapi_ticket // ... }
2)獲取jsapi_ticket
// 獲取jsapi_ticket var ticketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + body.access_token + '&type=jsapi'; request(ticket, function (err, response, content) { content = JSON.parse(content); if (content.errcode == 0) { // 這里我緩存到了global global.wxshare.jsapi_ticket = content.ticket; // 計算signature // ... } })
3)計算signature
// 計算signature // 先拿一個當前時間戳,這里我緩存到了global global.wxshare.deadline = new Date().getTime(); // 通過調用計算簽名方法 var signatureStr = sign(content.ticket, req.body.url); // 當前時間戳 signatureStr.deadline = new Date().getTime(); // 緩存簽名 if (signindex && signindex !== 0) { global.wxshare.signs(signindex, 1, signatureStr); } else { global.wxshare.signs.push(signatureStr); } // 返回給頁面 res.status(200).json(signatureStr);
// 隨機字符串 var createNonceStr = function () { return Math.random().toString(36).substr(2, 15); }; // 時間戳 var createTimestamp = function () { return parseInt(new Date().getTime() / 1000) + ''; }; // 排序拼接 var raw = function (args) { var keys = Object.keys(args); keys = keys.sort() var newArgs = {}; keys.forEach(function (key) { newArgs[key.toLowerCase()] = args[key]; }); var string = ''; for (var k in newArgs) { string += '&' + k + '=' + newArgs[k]; } string = string.substr(1); return string; }; /** * @synopsis 簽名算法 * * @param jsapi_ticket 用於簽名的 jsapi_ticket * @param url 用於簽名的 url ,注意必須動態獲取,不能 hardcode * * @returns */ var sign = function (jsapi_ticket, url) { var ret = { jsapi_ticket: jsapi_ticket, nonceStr: createNonceStr(), timestamp: createTimestamp(), url: url }; var string = raw(ret); jsSHA = require('jssha'); shaObj = new jsSHA(string, 'TEXT'); ret.signature = shaObj.getHash('SHA-1', 'HEX'); return ret; }; module.exports = sign;
//檢查頁面鏈接對應的簽名是否可用 var signtag = false; var signindex; // 檢查簽名 global.wxshare.signs.forEach(function (item, index) { if (item.url === req.body.url) { signindex = index; if (item.deadline && new Date().getTime() - item.deadline < 6000000) { signtag = true; } } }); //當簽名不可用時,檢測jsapi_ticket是否可用,來決定是直接請求簽名還是先請求jsapi_ticket再請求簽名 if (!signtag) { // 請求操作 // 計算簽名操作 // ... }
// 相應路由 app.post('/signture', Base.wxconfig); // 對應方法 exports.wxconfig = function(req,res,next) { // ... }
4)前端調用
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script> // 請求簽名 $.ajax({ url: "/signture", type: 'post', data: { url: location.href.split('#')[0] }, success:function(res){ wx.config({ debug: false, appId: 'wxa2c416de84300ee5', timestamp: res.timestamp, nonceStr: res.nonceStr, signature: res.signature, jsApiList: [ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ' ] }); wx.ready(function () { var shareData = { title: document.title, desc: getDesc(), link: res.url, imgUrl: getImage() }; wx.onMenuShareAppMessage(shareData); wx.onMenuShareTimeline(shareData); wx.onMenuShareQQ(shareData); }); wx.error(function (res) { alert(res.errMsg); // 正式環境記得關閉啊!!!! }); } }); // 獲取描述字段方法 function getDesc() { var meta = document.getElementsByTagName("meta"); for (var i=0;i<meta.length;i++){ if(typeof meta[i].name!="undefined"&&meta[i].name.toLowerCase()=="description"){ return meta[i].content; } } }; // 獲取圖片 function getImage() { return 'http://'+location.host+'/images/logo.png'; }; </script>
5)配置測試
添加JS接口安全域名(在公眾號后台的設置/公眾號設置/功能設置中添加
),這里需要實現MP_verify_AwmmQFM5B0vHg035.txt
文件檢查功能。
因為這個MP_verify_AwmmQFM5B0vHg035.txt文件里,只有一行字符串,直接返回即可
// 相應路由 app.get('/MP_verify_CwPkZ2phenWhKlmR.txt', Base.checkWx); // 對應方法 exports.checkWx = function(req, res) { res.send('CwPkZ2phenWhKlmR'); }
6)優化請求(檢查微信環境,減少不必要的微信接口調用次數)
<script> // 檢查微信環境 function isWeiXin() { var ua = window.navigator.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) == 'micromessenger') { return true; } else { return false; } }; // 如果為真,則請求 if(isWeiXin()){ // 去獲取signature簽名 .... }); </script>
3.常見問題
官方常見錯誤查閱傳送門:附錄5。
因為在實際開發的時候,真的是不端的遇到問題,不斷的去找答案。錯誤出現的話,是有一定順序的,這對我們找原因有一定的幫助。首先是config fail
,若沒錯的話,才有可能出現invalid signature
,若沒錯的話,才有可能出現``` invalid url domain``。最后就完全沒錯了,說明已成功。
1)config 錯誤
如果config fail
,一般說明存在配置字段遺漏,或者配置字段的值為空(null,undefined,"")。
2)signature錯誤
如果報invalid signature
錯誤,一般說明簽名沒有生成正確,再核對一遍規則。可以使用微信 JS 接口簽名校驗工具:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign,對比代碼生成出來的是否和檢驗工具生成的一樣。比如時間戳長度,順序,拼接遺漏。
3)url domain錯誤
如果報invalid url domain
錯誤,說明配置工作已經OK啦。出現這個的原因是域名沒有添加到JS接口安全域名
下,或者沒有使用80、443端口。
4)其他錯誤
如permission denied
,接口無權限
等等,查閱文檔吧。
4.附QQ分享
手機QQ對外分享組件接口文檔傳送門:http://open.mobile.qq.com/api/component/share
閱讀文檔后發現比較簡單,引用一個JS文件,然后幾行配置代碼。但注意一下:文檔頁面舉例代碼含有“微信配置”,請勿重復配置WXconfig
。
// 引入JS腳本
<script type="text/javascript" src="http://qzonestyle.gtimg.cn/qzone/qzact/common/share/share.js"></script> <script type="text/javascript"> // 配置 setShareInfo({ title: document.title, // 獲取頁面的標題 summary: getDesc, //獲取頁面的desc pic: 'http://xxx/xx/pic.png', // 獲取圖片(這里自己寫吧,整站固定圖片or頁面第一張或指定圖片) url: location.href // 獲取地址 }); // 獲取描述字段方法 function getDesc() { var meta = document.getElementsByTagName("meta"); for (var i=0;i<meta.length;i++){ if(typeof meta[i].name!="undefined"&&meta[i].name.toLowerCase()=="description"){ return meta[i].content; } } }; </script>
5.結束
本文的主要內容就是關於“微信JS-SDK的接口調用”,那這里舉例就是分享接口,其他接口類推吧,用到什么去看文檔。覺得難就不去看的話,就相當於棄坑了;可是仔細去看一下文檔,先理清思路步驟,在每個步驟去完成,串聯起來也就實現了。回頭一看,發現並不難。文章的最后附了一個QQ的分享配置方法,需要可以嘗試。
最后針對不同瀏覽器,這個就說不准了。有的瀏覽器自己就可以幫你完成圖片和描述的完美呈現,有的就只能是URL地址(沒有描述)。真要去看這個,可能要進行反復測試找規律,想想都心累了。我們比較常見的也就是“微信”,“QQ”,也許還有“企業微信”。補充一句,“企業微信”不會使用JS-SDK的,但是它可以自動幫你獲取到標題、描述,但圖片地址就和頁面圖有關了。需要可以自己留意下。
到這里,就先結束了。
學習是一條漫漫長路,每天不求一大步,進步一點點就是好的。
作者:SeasonDe
鏈接:https://www.jianshu.com/p/1a35e1dbe1ad
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。