鍍金池/ 問(wèn)答/HTML5  HTML/ 前兩天剛剛做了微信分享自定義logo和文字,做個(gè)標(biāo)記,從零開(kāi)始記錄

前兩天剛剛做了微信分享自定義logo和文字,做個(gè)標(biāo)記,從零開(kāi)始記錄

首先要有一個(gè)認(rèn)證過(guò)的公眾號(hào),才會(huì)有權(quán)限

clipboard.png

打開(kāi)微信的jsskd 使用說(shuō)明

在頁(yè)面中引入微信的js文件

clipboard.png

http://res.wx.qq.com/open/js/...

引入后
配置config

   wx.config({
    debug: true, // 開(kāi)啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái),若要查看傳入的參數(shù),可以在pc端打開(kāi),參數(shù)信息會(huì)通過(guò)log打出,僅在pc端時(shí)才會(huì)打印。
    appId: '', // 必填,公眾號(hào)的唯一標(biāo)識(shí)
    timestamp: , // 必填,生成簽名的時(shí)間戳
   nonceStr: '', // 必填,生成簽名的隨機(jī)串
   signature: '',// 必填,簽名
   jsApiList: [] // 必填,需要使用的JS接口列表

});
詳細(xì)說(shuō)一下怎么獲取每一個(gè)屬性
debug 為true的時(shí)候方便找錯(cuò),提示你的錯(cuò)誤信息
appId 就是你公眾號(hào)的id
timestamp 就是一個(gè)隨機(jī)的時(shí)間戳,溫馨提示時(shí)間戳最多為10位,當(dāng)時(shí)因?yàn)檫@個(gè)問(wèn)題找了半天
nonceStr 就是一個(gè)隨機(jī)字符串
signature 簽名,最麻煩的
要獲取簽名 先要獲取 access_token (有效期7200秒,開(kāi)發(fā)者必須在自己的服務(wù)全局緩存access_token ):
access_token通過(guò)接口獲取
https請(qǐng)求方式: GET

https://api.weixin.qq.com/cgi...
appid 是你自己的id,secret是你自己的秘鑰

clipboard.png

正常情況下,微信會(huì)返回下述JSON數(shù)據(jù)包給公眾號(hào):

{"access_token":"ACCESS_TOKEN","expires_in":7200}

clipboard.png

錯(cuò)誤時(shí)微信會(huì)返回錯(cuò)誤碼等信息,JSON數(shù)據(jù)包示例如下(該示例為AppID無(wú)效錯(cuò)誤):

{"errcode":40013,"errmsg":"invalid appid"}

clipboard.png

記得獲取完 access_token 要配置白名單 不然會(huì)報(bào)錯(cuò) 40094,白名單可以配置多個(gè),用回車 隔開(kāi)

clipboard.png

第一步拿到的access_token 采用http GET方式請(qǐng)求獲得jsapi_ticket(有效期7200秒,開(kāi)發(fā)者必須在自己的服務(wù)全局緩存jsapi_ticket)

https://api.weixin.qq.com/cgi...

access_token 是你剛剛獲取到的 access_token,type是固定的
成功返回如下JSON:

 {
  "errcode":0,
  "errmsg":"ok",
  "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8- 
  41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
  "expires_in":7200
 }

獲得jsapi_ticket之后,就可以生成JS-SDK權(quán)限驗(yàn)證的簽名了。簽名算法建議放在后臺(tái)來(lái)實(shí)現(xiàn)

簽名生成規(guī)則如下:參與簽名的字段包括noncestr(隨機(jī)字符串), 有效的jsapi_ticket, timestamp(時(shí)間戳), url(當(dāng)前網(wǎng)頁(yè)的URL,不包含#及其后面部分) 。對(duì)所有待簽名參數(shù)按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串string1。這里需要注意的是所有參數(shù)名均為小寫字符。對(duì)string1作sha1加密,字段名和字段值都采用原始值,不進(jìn)行URL 轉(zhuǎn)義。
即signature=sha1(string1)。 示例:

 noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
 timestamp=1414587457
 url=http://mp.weixin.qq.com?params=value

步驟1. 對(duì)所有待簽名參數(shù)按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串string1:

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value

步驟2. 對(duì)string1進(jìn)行sha1簽名,得到signature:

   0f9de62fce790f9a083d5c99e95740ceb90c27ed

注意事項(xiàng)
1.簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。

2.簽名用的url必須是調(diào)用JS接口頁(yè)面的完整URL。

3.出于安全考慮,開(kāi)發(fā)者必須在服務(wù)器端實(shí)現(xiàn)簽名的邏輯。

如出現(xiàn)invalid signature 等錯(cuò)誤詳見(jiàn)附錄5常見(jiàn)錯(cuò)誤及解決辦法。

常見(jiàn)的報(bào)錯(cuò)
調(diào)用config 接口的時(shí)候傳入?yún)?shù) debug: true 可以開(kāi)啟debug模式,頁(yè)面會(huì)alert出錯(cuò)誤信息。以下為常見(jiàn)錯(cuò)誤及解決方法:

1.invalid url domain當(dāng)前頁(yè)面所在域名與使用的appid沒(méi)有綁定,請(qǐng)確認(rèn)正確填寫綁定的域名,僅支持80(http)和443(https)兩個(gè)端口,因此不需要填寫端口號(hào)(一個(gè)appid可以綁定三個(gè)有效域名,見(jiàn) ]目錄1.1.1)。

2.invalid signature簽名錯(cuò)誤。建議按如下順序檢查:

1.確認(rèn)簽名算法正確,可用http://mp.weixin.qq.com/debug... 頁(yè)面工具進(jìn)行校驗(yàn)。

2.確認(rèn)config中nonceStr(js中駝峰標(biāo)準(zhǔn)大寫S), timestamp與用以簽名中的對(duì)應(yīng)noncestr, timestamp一致。

3.確認(rèn)url是頁(yè)面完整的url(請(qǐng)?jiān)诋?dāng)前頁(yè)面alert(location.href.split('#')[0])確認(rèn)),包括'http(s)://'部分,以及'?'后面的GET參數(shù)部分,但不包括'#'hash后面的部分。

4.確認(rèn) config 中的 appid 與用來(lái)獲取 jsapi_ticket 的 appid 一致。

5.確保一定緩存access_token和jsapi_ticket。

6.確保你獲取用來(lái)簽名的url是動(dòng)態(tài)獲取的,動(dòng)態(tài)頁(yè)面可參見(jiàn)實(shí)例代碼中php的實(shí)現(xiàn)方式。如果是html的靜態(tài)頁(yè)面在前端通過(guò)ajax將url傳到后臺(tái)簽名,前端需要用js獲取當(dāng)前頁(yè)面除去'#'hash部分的鏈接(可用location.href.split('#')[0]獲取,而且需要encodeURIComponent),因?yàn)轫?yè)面一旦分享,微信客戶端會(huì)在你的鏈接末尾加入其它參數(shù),如果不是動(dòng)態(tài)獲取當(dāng)前鏈接,將導(dǎo)致分享后的頁(yè)面簽名失敗。

3.the permission value is offline verifying這個(gè)錯(cuò)誤是因?yàn)閏onfig沒(méi)有正確執(zhí)行,或者是調(diào)用的JSAPI沒(méi)有傳入config的jsApiList參數(shù)中。建議按如下順序檢查:

1.確認(rèn)config正確通過(guò)。

2.如果是在頁(yè)面加載好時(shí)就調(diào)用了JSAPI,則必須寫在wx.ready的回調(diào)中。

3.確認(rèn)config的jsApiList參數(shù)包含了這個(gè)JSAPI。

4.permission denied該公眾號(hào)沒(méi)有權(quán)限使用這個(gè)JSAPI,或者是調(diào)用的JSAPI沒(méi)有傳入config的jsApiList參數(shù)中(部分接口需要認(rèn)證之后才能使用)。

5.function not exist當(dāng)前客戶端版本不支持該接口,請(qǐng)升級(jí)到新版體驗(yàn)。

6.為什么6.0.1版本config:ok,但是6.0.2版本之后不ok(因?yàn)?.0.2版本之前沒(méi)有做權(quán)限驗(yàn)證,所以config都是ok,但這并不意味著你config中的簽名是OK的,請(qǐng)?jiān)?.0.2檢驗(yàn)是否生成正確的簽名以保證config在高版本中也ok。)

7.在iOS和Android都無(wú)法分享(請(qǐng)確認(rèn)公眾號(hào)已經(jīng)認(rèn)證,只有認(rèn)證的公眾號(hào)才具有分享相關(guān)接口權(quán)限,如果確實(shí)已經(jīng)認(rèn)證,則要檢查監(jiān)聽(tīng)接口是否在wx.ready回調(diào)函數(shù)中觸發(fā))

8.服務(wù)上線之后無(wú)法獲取jsapi_ticket,自己測(cè)試時(shí)沒(méi)問(wèn)題。(因?yàn)閍ccess_token和jsapi_ticket必須要在自己的服務(wù)器緩存,否則上線后會(huì)觸發(fā)頻率限制。請(qǐng)確保一定對(duì)token和ticket做緩存以減少2次服務(wù)器請(qǐng)求,不僅可以避免觸發(fā)頻率限制,還加快你們自己的服務(wù)速度。目前為了方便測(cè)試提供了1w的獲取量,超過(guò)閥值后,服務(wù)將不再可用,請(qǐng)確保在服務(wù)上線前一定全局緩存access_token和jsapi_ticket,兩者有效期均為7200秒,否則一旦上線觸發(fā)頻率限制,服務(wù)將不再可用)。

9.uploadImage怎么傳多圖(目前只支持一次上傳一張,多張圖片需等前一張圖片上傳之后再調(diào)用該接口)

10.沒(méi)法對(duì)本地選擇的圖片進(jìn)行預(yù)覽(chooseImage接口本身就支持預(yù)覽,不需要額外支持)

11.通過(guò)a鏈接(例如先通過(guò)微信授權(quán)登錄)跳轉(zhuǎn)到b鏈接,invalid signature簽名失敗(后臺(tái)生成簽名的鏈接為使用jssdk的當(dāng)前鏈接,也就是跳轉(zhuǎn)后的b鏈接,請(qǐng)不要用微信登錄的授權(quán)鏈接進(jìn)行簽名計(jì)算,后臺(tái)簽名的url一定是使用jssdk的當(dāng)前頁(yè)面的完整url除去'#'部分)

12.出現(xiàn)config:fail錯(cuò)誤(這是由于傳入的config參數(shù)不全導(dǎo)致,請(qǐng)確保傳入正確的appId、timestamp、nonceStr、signature和需要使用的jsApiList)

13.如何把jsapi上傳到微信的多媒體資源下載到自己的服務(wù)器(請(qǐng)參見(jiàn)文檔中uploadVoice和uploadImage接口的備注說(shuō)明)

14.Android通過(guò)jssdk上傳到微信服務(wù)器,第三方再?gòu)奈⑿畔螺d到自己的服務(wù)器,會(huì)出現(xiàn)雜音(微信團(tuán)隊(duì)已經(jīng)修復(fù)此問(wèn)題,目前后臺(tái)已優(yōu)化上線)

15.綁定父級(jí)域名,是否其子域名也是可用的(是的,合法的子域名在綁定父域名之后是完全支持的)

16.在iOS微信6.1版本中,分享的圖片外鏈不顯示,只能顯示公眾號(hào)頁(yè)面內(nèi)鏈的圖片或者微信服務(wù)器的圖片,已在6.2中修復(fù)

17.是否需要對(duì)低版本自己做兼容(jssdk都是兼容低版本的,不需要第三方自己額外做更多工作,但有的接口是6.0.2新引入的,只有新版才可調(diào)用)

18.該公眾號(hào)支付簽名無(wú)效,無(wú)法發(fā)起該筆交易(請(qǐng)確保你使用的jweixin.js是官方線上版本,不僅可以減少用戶流量,還有可能對(duì)某些bug進(jìn)行修復(fù),拷貝到第三方服務(wù)器中使用,官方將不對(duì)其出現(xiàn)的任何問(wèn)題提供保障,具體支付簽名算法可參考 JSSDK微信支付一欄)

19.目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來(lái)實(shí)現(xiàn)web app的頁(yè)面會(huì)導(dǎo)致簽名失敗,此問(wèn)題已在Android6.2中修復(fù)

20.uploadImage在chooseImage的回調(diào)中有時(shí)候Android會(huì)不執(zhí)行,Android6.2會(huì)解決此問(wèn)題,若需支持低版本可以把調(diào)用uploadImage放在setTimeout中延遲100ms解決

21.require subscribe錯(cuò)誤說(shuō)明你沒(méi)有訂閱該測(cè)試號(hào),該錯(cuò)誤僅測(cè)試號(hào)會(huì)出現(xiàn)

22.getLocation返回的坐標(biāo)在openLocation有偏差,因?yàn)間etLocation返回的是gps坐標(biāo),openLocation打開(kāi)的騰訊地圖為火星坐標(biāo),需要第三方自己做轉(zhuǎn)換,6.2版本開(kāi)始已經(jīng)支持直接獲取火星坐標(biāo)

23.查看公眾號(hào)(未添加): "menuItem:addContact"不顯示,目前僅有從公眾號(hào)傳播出去的鏈接才能顯示,來(lái)源必須是公眾號(hào)

24.ICP備案數(shù)據(jù)同步有一天延遲,所以請(qǐng)?jiān)诘诙战壎?/p>

因?yàn)殡S機(jī)字符串和時(shí)間戳要和算法的保持一致,所以我是用了后臺(tái)返回給我的,
每次分享微信客戶端都會(huì)在你的鏈接后面加上參數(shù),表示這是第二次分享的,
一旦加入?yún)?shù)會(huì)導(dǎo)致我們的簽名失敗。當(dāng)時(shí)我也是很絕望啊,在網(wǎng)上找了很多的例子都沒(méi)有能實(shí)質(zhì)性的解決這個(gè)問(wèn)題,最后解決方案是
我每次會(huì)把當(dāng)前的url傳遞給后臺(tái),后臺(tái)每次都在生成簽名,但是7200秒生成的簽名是不會(huì)變的,感覺(jué)可行,立馬實(shí)施起來(lái)

附上源碼

      Weixin(){
                console.log(window.location.href.split('#')[0]);
                let encodeURIComponen=encodeURIComponent(window.location.href.split('#')[0]);
                   const data={jssdkUrl:encodeURIComponen};
                   console.log(data);
                                   axios.post("./api/getSignature",data,{
                                       headers: {
                                           "Content-Type": "application/json",
                                            "Accept":"application/json"
                                       }
                                   }).then((response) => {
                                       //success
                                       console.log(response);
                                       const jssdk=response.data.data;
                                        wx.config({
                                                debug: false, // 開(kāi)啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái),若要查看傳入的參數(shù),可以在pc端打開(kāi),參數(shù)信息會(huì)通過(guò)log打出,僅在pc端時(shí)才會(huì)打印。
                                                appId: jssdk.appId, // 必填,公眾號(hào)的唯一標(biāo)識(shí)
                                                timestamp: jssdk.timestamp, // 必填,生成簽名的時(shí)間戳
                                                nonceStr:jssdk.nonceStr, // 必填,生成簽名的隨機(jī)串
                                                signature: jssdk.signature,// 必填,簽名
                                                jsApiList: [
                                                    "onMenuShareTimeline",
                                                    "onMenuShareAppMessage"
                                                ] // 必填,需要使用的JS接口列表
                                            });
                                //分享
                            wx.ready(function(){
                                 // 微信分享的數(shù)據(jù)  
                                    //分享給朋友圈
                                        wx.onMenuShareTimeline({
                                        title: '', // 分享標(biāo)題
                                        link: window.location.href.split('#')[0], // 分享鏈接,該鏈接域名或路徑必須與當(dāng)前頁(yè)面對(duì)應(yīng)的公眾號(hào)JS安全域名一致
                                        imgUrl: '', // 分享圖標(biāo)
                                        success: function () {
                                        // 用戶確認(rèn)分享后執(zhí)行的回調(diào)函數(shù)
                                        console.log("分享成功");
                                    },cancel: function () {
                                            // 用戶取消分享后執(zhí)行的回調(diào)函數(shù)
                                             console.log("分享失敗");
                                            }
                                        });
                                    //分享給朋友
                                    wx.onMenuShareAppMessage({    
                                    title: '', // 分享標(biāo)題
                                    desc: '', // 分享描述
                                    link: window.location.href.split('#')[0], // 分享鏈接,該鏈接域名或路徑必須與當(dāng)前頁(yè)面對(duì)應(yīng)的公眾號(hào)JS安全域名一致
                                    imgUrl: '', // 分享圖標(biāo)
                                    type: 'link', // 分享類型,music、video或link,不填默認(rèn)為link
                                    success: function () {
                                    // 用戶確認(rèn)分享后執(zhí)行的回調(diào)函數(shù)
                                      console.log("分享成功");
                                    },
                                    cancel: function () {
                                    // 用戶取消分享后執(zhí)行的回調(diào)函數(shù)
                                     console.log("分享失敗");
                                    }
                                    });
                            })
                                   }, (error) => {
                                       console.log(error)
                                   });
        },

雖然這個(gè)這段代碼符合很多大部分的場(chǎng)景,但是畢竟不是萬(wàn)金油,還是要看你的場(chǎng)景
成長(zhǎng)的路上總是坎坎坷坷...

回答
編輯回答
魚(yú)梓

這個(gè)應(yīng)該發(fā)成文章而不是問(wèn)題吧

2017年9月23日 18:38