再講微信分享需要躲避的一些坑之前,先說說微信分享的一些背景知識
1.JS-SDK的用途
微信JS-SDK是 微信公眾平台 面向網頁開發者提供的基於微信內的網頁開發工具包。通過使用微信JS-SDK,網頁開發者可借助微信高效地使用拍照、選圖、語音、位置等手機系統的能力,同時可以直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,為微信用戶提供更優質的網頁體驗。微信開放這些能力給開發者,要對開發者進行鑒權。防止開發者對某些接口濫用,比如說傳播類的接口。鑒權的時候需要簽名,簽名需要票據,隨機字符串,時間戳,網址。比較麻煩的參數票據,票據的生成,需要調用另外一個接口,參數是appId和serect。這個接口每天只能調用2000次,每次調用的有效期是2小時。
2.簽名的獲取方法
2.1 准備工作
1.登錄微信公眾平台,在開發設置中查看AppID和AppSecret
2 設置JS接口安全域名。這里填寫的是一級域名,不帶www和http。最多可以設置三個域名。相比以前的分享沒有任何域名限制,現在設置安全域名,目的是為了當微信發現此公眾平台發現誘導分享行為時,可以根據此域名追溯到所有分享出去的鏈接,以及通過這些鏈接增加的粉絲。這樣,微信就可以牢牢控制了你的微信平台,一旦發現違規,讓分享鏈接失效,刪除掉誘導行為增加的粉絲,是瞬間就可以完成的。因此,一定要合理來使用分享功能,不要因小失大。等到你的微信平台被封,估計哭都來不及。
2.2 獲得Access Token
access_token是公眾號的全局唯一票據,公眾號調用各接口時都需使用access_token。正常情況下 access_token有效期為7200秒,重復獲取將導致上次獲取的access_token失效。公眾號可以使用AppID和AppSecret調用本接口來獲取access_token。AppID和AppSecret可在微信公眾平台中獲得(見上圖)。 注意調用所有微信接口時均需使用https協議。
// https請求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
參數說明
返回說明
正常情況下,微信會返回下述JSON數據包:
{"access_token":"ACCESS_TOKEN","expires_in":7200}
錯誤時微信會返回錯誤碼等信息,JSON數據包示例如下(該示例為AppID無效錯誤):
{"errcode":40013,"errmsg":"invalid appid"}
2.3 獲取jsapi_ticket
生成簽名之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號用於調用微信JS接口的臨時票據。正常情況下,jsapi_ticket的有效期為7200秒,通過access_token來獲取。由於獲取jsapi_ticket的api調用次數非常有限,頻繁刷新jsapi_ticket會導致api調用受限,影響自身業務,開發者必須在自己的服務全局緩存jsapi_ticket 。
用第一步拿到的access_token , 采用https GET方式請求獲得jsapi_ticket(有效期7200秒,開發者必須在自己的服務全局緩存jsapi_ticket),接口地址如下
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
成功返回如下JSON:
{ "errcode":0, "errmsg":"ok", "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA", "expires_in":7200 }
獲得jsapi_ticket之后,就可以生成JS-SDK權限驗證的簽名了。
2.4 簽名算法實現
簽名生成規則如下:
對所有待簽名參數按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串string。這里需要注意的是所有參數名均為小寫字符。對string作sha1加密,字段名和字段值都采用原始值,不進行URL 轉義。即** signature=sha1(string)**。 示例:
2.4.1 對所有待簽名參數按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串string:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value
2.4.2 對string進行sha1簽名,得到signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
2.5 企業微信獲取JS-SDK使用權限簽名步驟
參見 企業微信JS-SDK使用授權簽名算法,其中jsapi_ticket的獲取比較麻煩一些,需要向如下地址發起get請求
https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN
入參access_token的獲取分兩種情況:
- 企業內部開發,獲取方式參考 獲取access_token
- 第三方應用開發,獲取方式參考“獲取企業憑證”
如果是第三方應用開發,需要以post方式向如下地址發起請求
https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=SUITE_ACCESS_TOKEN
入參為:
{ "auth_corpid": "auth_corpid_value", // 授權方corpid "permanent_code": "code_value" // 永久授權碼,通過get_permanent_code獲取 }
permanent_code的獲取方式是,向如下地址發起post請求
https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=SUITE_ACCESS_TOKEN
入參:
{ "auth_code": "auth_code_value" // 臨時授權碼,會在授權成功時附加在redirect_uri中跳轉回第三方服務商網站,或通過授權成功通知回調推送給服務商。長度為64至512個字節 }
第三方服務商在得到公眾號或小程序運營者(簡稱運營者)授權 后,第三方平台開發者可以通過調用微信開放平台的接口能力,為公眾號或小程序的運營者提供賬號申請、小程序創建、技術開發、行業方案、活動營銷、插件能力等全方位服務。
3 項目中的問題
3.1 IOS下微信環境 -- 分享的文章內容描述與圖標不對
微信應用右上角自帶的分享功能,在分享內容之前需要調用wx.config對微信分享JS-SDK鑒權,需要的傳參如下:
wx.config({
debug: true, // 開啟調試模式
appId: "xxx", // 必填,公眾號的唯一標識
timestamp: "timestamp", // 必填,生成簽名的時間戳
nonceStr: "nonceStr", // 必填,生成簽名的隨機串
signature: "signature",// 必填,簽名
jsApiList: ['onMenuShareAppMessage','onMenuShareTimeline'] // 必填
});
其中不好獲取的參數是signature。signature是怎么獲取的呢?在我們的項目中,是通過請求getTicket接口,獲取signature,而請求getTicket接口的參數中,最容易出問題的就是jsUrl。
const params = { appId: newAppId || appId, corpId: env === "wx" ? authCorpId : currentCorpId, wechatType: env, jsUrl: url, agentId, }; const res = await ajax('getTicket', params, isShowError); const { retdata = {} } = res; const { appId, noncestr, signature, timestamp, nextUpdateTime } = retdata; const obj = { debug: false, // 是否開啟調試模式 appId, // appid timestamp, // 時間戳 nonceStr: noncestr, // 隨機字符串 signature, // 簽名 jsApiList, openTagList: [], }; if (env === 'qywx') { obj.beta = true; obj.appId = currentCorpId; } wx.config(obj);
這個jsUrl參數,按理說要取當前分享頁面的url,在Android上確實是這樣,可是在IOS手機上,企業微信環境下沒有問題,可是微信環境如果取當前分享頁面的url,
url = encodeURIComponent(window.location.href);
分享出去的內容,圖標和描述的展示會有問題
應該取進入單頁應用首頁的url,而不是當前頁面的url
url = encodeURIComponent(localStorage.getItem(keyDict.entryUrl));
所以獲取jsUrl的時候,要添加判斷條件:
// 如果是 iOS 設備,個人微信環境,則使用應用首頁的 URL 去請求 wxConfig,不然的話會導致 iOS 中分享的鏈接描述信息或者圖標不對 if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent) && env === "wx") { // console.log('簽名地址=======================', localStorage.getItem(keyDict.entryUrl)) url = encodeURIComponent(localStorage.getItem(keyDict.entryUrl)); } else { // console.log('簽名地址=======================', window.location.href) url = encodeURIComponent(window.location.href); }
鑒權失敗會報如下錯誤,此時重點要檢查一下url有沒有多次調用encodeURIComponent編碼
wx.config {"errMsg": "config:invalid signature"}
3.2 有些JS-SDK接口,比如說h5跳轉微信小程序, 除了調用wx.config之后,還要調用 wx.agentConfig,否則會報no_permission錯誤
3.2.1 wx.config和wx.agentConfig的區別
wx.config注入的是企業的身份與權限,而wx.agentConfig注入的是應用的身份與權限。尤其是當調用者為第三方服務商時,通過config無法准確區分出調用者是哪個第三方應用,而在部分場景下,又必須嚴謹區分出第三方應用的身份,此時即需要通過agentConfig來注入應用的身份信息。wx.agentConfig配置步驟:
3.2.2 先要引入 jwxwork sdk
<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
3.2.3 wx.agentConfig配置參數
wx.agentConfig({
corpid: '', // 必填,企業微信的corpid,必須與當前登錄的企業一致
agentid: '', // 必填,企業微信的應用id (e.g. 1000247)
timestamp: , // 必填,生成簽名的時間戳
nonceStr: '', // 必填,生成簽名的隨機串
signature: '',// 必填,簽名,見附錄-JS-SDK使用權限簽名算法
jsApiList: ['selectExternalContact'], //必填,傳入需要使用的接口名稱
success: function(res) {
// 回調
},
fail: function(res) {
if(res.errMsg.indexOf('function not exist') > -1){
alert('版本過低請升級')
}
}
});
3.2.4 調用agentConfig的注意事項(摘錄於企微官方文檔)
1. agentConfig與config的簽名算法完全一樣,但是jsapi_ticket的獲取方法不一樣,請特別注意,查看獲取應用身份的ticket
2. agentConfig僅在企業微信2.5.0及以后版本支持,微信客戶端不支持(微信開發者工具也不支持)
3. 調用wx.agentConfig之前,必須確保先成功調用wx.config. 注意:從企業微信3.0.24及以后版本,無須先調用wx.config,可直接wx.agentConfig. 可通過 企業微信UA 判斷版本號
4. 當前頁面url中的域名必須是在該應用中設置的可信域名。
5. 僅部分接口才需要調用agentConfig,需注意每個接口的說明
3.3 跨企業微信分享內容,在另一企業打開,再次分享,分享出去的文章的描述不對,有時圖標也不顯示, wx.config報如下錯誤
errMsg: "config:invalid corpid more info at https://open.work.weixin.qq.com/devtool/query?e=40013"
原因是: 當前登錄的企業微信與獲取簽名使用的企業微信不一致。 在B企業下,無法用A企業的JS-SDK授權功能。即使A, B企業下,配置了相同的可信域名。也無法共享授權。只能在各自的企業下,調用微信提供的JS-SDK。
因為在B企業下打開分享內容時,hideMenuItems是第一個被調用的JS-SDK,所以第一個報的JS-SDK調用錯誤是hideMenuItems接口:
wx.config配置出錯的情況下,文章雖能分享。可是分享出去的文章,是有問題的。從下圖可以看出,描述變成了文章的網址。這個錯誤比較迷惑人。
3.4 wx.agentConfig 授權配置客戶聊天JSSDK ['sendChatMessage', 'getCurExternalChat', 'getContext']時,報錯
解決方法: 在企業微信管理后台,給對應的應用授予 可調用外部聯系人接口的權限。