微信分享常見問題--避坑指北

孤舟蓑翁發表於2021-07-28

再講微信分享需要躲避的一些坑之前,先說說微信分享的一些背景知識

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&timestamp=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的獲取分兩種情況:

如果是第三方應用開發,需要以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配置出錯的情況下,文章雖能分享。可是分享出去的文章,是有問題的。從下圖可以看出,描述變成了文章的網址。這個錯誤比較迷惑人。

 

相關文章