進(jìn)軍微信第一步:接入微信JS-SDK

【前言】 某天,接到這么一個(gè)需求:自定義微信網(wǎng)頁(yè)分享出來(lái)的標(biāo)題贺拣,描述和圖標(biāo)蓖谢。以前沒(méi)玩過(guò)這個(gè),感覺(jué)應(yīng)該很簡(jiǎn)單譬涡,動(dòng)手了之后闪幽,躺過(guò)各種坑才知道并沒(méi)那么容易。完全獨(dú)立研究排錯(cuò)涡匀,感受頗多盯腌,分享出來(lái)給大家鋪一鋪路

一: 需求來(lái)源

?開(kāi)發(fā)了一個(gè)移動(dòng)端H5活動(dòng)頁(yè)面,該頁(yè)面要實(shí)現(xiàn)微信中的“分享給好友”陨瘩,“分享到朋友圈”腕够,“分享到QQ”级乍,“分享到騰訊微博”等功能。如果沒(méi)有接入jssdk燕少,分享出來(lái)的就是如下樣子:


微信分享默認(rèn)卡片

?除了標(biāo)題比較容易自定義以外卡者,描述內(nèi)容和圖標(biāo)都是默認(rèn)樣式,好丑客们。如果就這么分享出去崇决,活動(dòng)本身的吸引力就會(huì)被大打折扣,所以底挫,這個(gè)功能必須完成恒傻!
?

二: 需要工具

?我自己在開(kāi)發(fā)的時(shí)候,不知道需要這些東西建邓,都是遇到一個(gè)坑盈厘,才去找的一個(gè)蘿卜;這里提前提到官边,帶你走捷徑:

  1. 微信公眾平臺(tái)技術(shù)文檔 - 必備沸手,接入微信的功能,一切都是從這里開(kāi)始
  2. 微信JS接口簽名校驗(yàn)工具 - 該工具能幫你核查生成的簽名的正確性
  3. 微信web開(kāi)發(fā)者工具 - 模擬web網(wǎng)頁(yè)調(diào)試微信接口注簿,能查看JS-SDK的狀態(tài)契吉,查看權(quán)限列表,還能接入移動(dòng)設(shè)備調(diào)試诡渴;完美解決微信接口調(diào)試難的問(wèn)題捐晶。獲取方法: 登錄微信公眾平臺(tái) -> 進(jìn)入開(kāi)發(fā)者工具 -> 下載微信web開(kāi)發(fā)者工具 下載后,使用方法和chrome類似妄辩,不多說(shuō)惑灵。
  4. Xshell - 用來(lái)部署服務(wù)端代碼(linux環(huán)境),因?yàn)榻尤胛⑿拍K必須是線上聯(lián)調(diào)的眼耀,所以你的服務(wù)端都是需要部署到線上英支,即使是聯(lián)調(diào)服務(wù)器,也要滿足外網(wǎng)能訪問(wèn)哮伟。當(dāng)然潭辈,如果服務(wù)端人員能幫你解決這個(gè)問(wèn)題,請(qǐng)無(wú)視澈吨。
    ?

三: 開(kāi)發(fā)前需要

1. 綁定域名

?登錄微信公眾平臺(tái)(真實(shí)運(yùn)營(yíng)的服務(wù)號(hào)),進(jìn)入“公眾號(hào)設(shè)置”寄摆,選擇導(dǎo)航標(biāo)簽中的“功能設(shè)置”谅辣,填寫(xiě)“JS接口安全域名”。注意婶恼,該頁(yè)上也有描述桑阶,需要下載一個(gè) .txt 文件放到你網(wǎng)頁(yè)(你所填寫(xiě)的安全域名)要部署的服務(wù)器的根目錄(或目錄路徑)下柏副,這個(gè)文件是微信用來(lái)檢測(cè)你的服務(wù)器是否可達(dá)使用,不同公眾號(hào)的txt文件不同蚣录,我就不小心用放在桌面上的自己的公眾號(hào)的測(cè)試文件放到服務(wù)器中割择,然后以公司的服務(wù)號(hào)去跑,一直通不過(guò)萎河。
?服務(wù)號(hào)才有對(duì)應(yīng)的接口權(quán)限荔泳,如果你綁定了一個(gè)私人的公眾號(hào),一樣沒(méi)法使用虐杯。你可以“開(kāi)發(fā)者中心”查看一下你是否擁有對(duì)應(yīng)接口的開(kāi)發(fā)權(quán)限玛歌,免得白忙活。

2. 引入 JS 文件

? 和其他的模塊一致擎椰,想要調(diào)用微信的功能支子,同樣也需要引入微信js文件,目前最新版本為1.2.0达舒;該文件有 http形式https形式值朋,下載之后在需要調(diào)用js接口的頁(yè)面引入。也可以全局引入巩搏,已經(jīng)壓縮過(guò)昨登,大小為11.5k,還算小塔猾。
?模塊化推薦使用 AMD/CMD 標(biāo)準(zhǔn)加載
?

四: 開(kāi)始開(kāi)發(fā)

1. 權(quán)限驗(yàn)證配置

?有了上述的準(zhǔn)備篙骡,我們可以通過(guò)config在要使用JS-SDK的頁(yè)面注入配置信息,這是你調(diào)用微信接口微信驗(yàn)證的入口丈甸。config接收一個(gè)對(duì)象糯俗,具體如下:

接口權(quán)限配置

即:

wx.config({
  debug: false,    // 是否打開(kāi)調(diào)試模式,調(diào)用的api會(huì)被alert出來(lái)睦擂,在pc端也能看到log信息
  appid:''得湘,   // 必填,微信公眾號(hào)的唯一標(biāo)識(shí)
  timestamp: ,  // 必填顿仇,生成簽名的時(shí)間戳
  nonceStr: '',  // 必填淘正,生成簽名的隨機(jī)串
  signature: '',  //必填,用于驗(yàn)證的簽名
  jsApiList: []    //必填臼闻,需要使用到的JS接口列表
})

?大部分文檔都這么一說(shuō)而過(guò)鸿吆,然而還是容易踩坑。
?糞坑: 為什么叫糞坑述呐,因?yàn)樽銐虻椭巧坛痛尽R婚_(kāi)始沒(méi)對(duì)微信公眾號(hào)的這些機(jī)制了解多少,直接用appid, appSecret生成靜態(tài)的accesstoken乓搬,然后用accesstoken生成了靜態(tài)的jsapi_ticket思犁,最后生成靜態(tài)的signature代虾,然后就把這幾個(gè)參數(shù)填進(jìn)去了,肯定錯(cuò)啊激蹲。這些信息除了idsecret其他都是動(dòng)態(tài)的棉磨。
?坑1: 可以從上圖中看出來(lái),我直接設(shè)置debug參數(shù)為false学辱,并不是我覺(jué)得多余乘瓤,而是根本看不明白,本地調(diào)試基本沒(méi)法看出問(wèn)題项郊。怎么辦馅扣? 在 “需要工具” 中提供的微信web開(kāi)發(fā)者工具,他由微信團(tuán)隊(duì)提供着降,用了才知道差油,要啥debug調(diào)試,這個(gè)工具簡(jiǎn)直完美任洞,所有信息展示 清清楚楚蓄喇,一目了然。
?坑2: timestamp配置項(xiàng)處沒(méi)有引號(hào)交掏,也就是說(shuō)妆偏,這里的類型是 INT。另外盅弛,還有一個(gè)很重要的就是钱骂,這里 單位是秒,相信絕大多數(shù)一開(kāi)始和我一樣挪鹏,以為是毫秒见秽,直接new Date().getTime()完事。踩了踩了讨盒。
?坑3:nonceStr必須遵循駝峰式命名規(guī)則解取。這里比較容易混淆是因?yàn)樵谏珊灻且徊剑枰冉M成字符串string1返顺,那里要求所有key包括noncestr也都是小寫(xiě)的禀苦,所以誤以為這里也是小寫(xiě)的。
?坑4:或許你有看到jsApiList中有的文檔有checkJsApi項(xiàng)遂鹊,有的又沒(méi)有振乏。是這樣的:在真正調(diào)用微信接口功能如“分享到朋友圈”之前,我們可以對(duì)微信接口先進(jìn)行驗(yàn)證接口是否可用秉扑,即昆码,checkJsApi是一個(gè)基礎(chǔ)接口,所以也要加入該數(shù)組中,如下

ready中的checkJsApi接口

?為了不打亂思路赋咽,這里將如何獲取簽名過(guò)程放在最后面因涉及太多重要信息吨娜,這個(gè)步驟要求必須在服務(wù)端實(shí)現(xiàn)脓匿。

2. ready驗(yàn)證成功回調(diào)

?config信息驗(yàn)證成功后,下一步就是使用微信的各種接口宦赠。微信提供config的回調(diào)函數(shù)ready()陪毡,供我們執(zhí)行這些接口。注意:config是一個(gè)客戶端的異步操作勾扭,所以如果需要在頁(yè)面加載時(shí)就調(diào)用相關(guān)接口毡琉,則須把相關(guān)接口放在ready函數(shù)中調(diào)用來(lái)確保正確執(zhí)行。但是如果是一些交互操作妙色,這不必寫(xiě)在ready中桅滋,可以直接調(diào)用。比如說(shuō)“發(fā)送給好友”就是與用戶交互后的操作身辨。

3. error驗(yàn)證失敗處理
wx.error(function(res){
  console.log(res);      // res為微信返回的錯(cuò)誤結(jié)果
})
4. 自定義分享內(nèi)容

共用信息定義

?這里我定義了我們需要分享的一些內(nèi)容丐谋,如, 標(biāo)題煌珊,內(nèi)容描述号俐,和圖片地址。
坑:這里的圖片地址必須是絕對(duì)地址定庵。上圖中的data.url是發(fā)送給微信校驗(yàn)的那個(gè)url.

4. 定義分享接口

?這里只寫(xiě)了幾個(gè)最常用的接口吏饿,如需要分享西,

  • 分享到朋友圈 - onMenuShareTimeLine()

接受一個(gè)對(duì)象蔬浙,分享到朋友圈需要自定義三個(gè)內(nèi)容猪落,展示圖標(biāo)imgUrl,標(biāo)題title和鏈接地址link敛滋。

wx.onMenuShareTimeline({
    title: '', // 分享標(biāo)題
    link: '', // 分享鏈接许布,該鏈接域名或路徑必須與當(dāng)前頁(yè)面對(duì)應(yīng)的公眾號(hào)JS安全域名一致
    imgUrl: '', // 分享圖標(biāo)絕對(duì)路徑
    success: function () { 
        // 用戶確認(rèn)分享后執(zhí)行的回調(diào)函數(shù)
    },
    cancel: function () { 
        // 用戶取消分享后執(zhí)行的回調(diào)函數(shù)
    }
});
  • 發(fā)送給好友 - onMenuShareAppMessage()

?“發(fā)送給好友”需要自定義四個(gè)信息,標(biāo)題title绎晃,描述desc蜜唾,圖標(biāo)絕對(duì)地址imgUrl和跳轉(zhuǎn)的link

  • 分享到QQ - onMenuShareQQ()

?自定義四個(gè)信息:標(biāo)題title,描述desc庶艾,跳轉(zhuǎn)鏈接link袁余,和圖標(biāo)絕對(duì)地址Url

  • 分享到QQ空間 - onMenuShareQZone()
wx.onMenuShareQZone({
    title: title,
    desc: desc, 
    link: link, 
    imgUrl: imgUrl,
    success: function () { 
       // 用戶確認(rèn)分享后執(zhí)行的回調(diào)函數(shù)
    },
    cancel: function () { 
        // 用戶取消分享后執(zhí)行的回調(diào)函數(shù)
    }
});

?

JS-SDK使用權(quán)限簽名算法

?很高大上的名字,聽(tīng)著怪嚇人咱揍。其實(shí)只要幾個(gè)參數(shù)給對(duì)了颖榜,還是很容易處理的。需要注意的是,這個(gè)步驟需要在服務(wù)端實(shí)現(xiàn)
?上面“糞坑”提到的掩完,雖然校驗(yàn)是失敗的噪漾,但步驟就是如此了。這里再概括一下:

登錄微信公眾號(hào) →
拿到appId和appSecret →
用他們?nèi)ノ⑿奴@取access_token →
用access_token去獲取jsapi_ticket →
生成一個(gè)隨機(jī)字符串noncestr →
生成當(dāng)前時(shí)間戳且蓬,單位是秒 →
用隨機(jī)jsapi_ticket欣硼,當(dāng)前時(shí)間戳,隨機(jī)字符串以及分享的url用&拼接成string1 →
對(duì)string1進(jìn)行sha1加密 →
加密后的字符串就是signature →
數(shù)據(jù)返回客戶端

?先在腦海形成一個(gè)思路恶阴。我們?cè)趤?lái)細(xì)看每一步:

1. 獲取access_token

?微信提供access_token的有效期是兩個(gè)小時(shí)诈胜,即7200秒,超時(shí)失效冯事;且下一次獲取也會(huì)使上次獲取的結(jié)果失效焦匈。所以我們需要對(duì)它進(jìn)行動(dòng)態(tài)獲取。目前微信支持每個(gè)公眾號(hào)每天最多2000次的access_token獲取請(qǐng)求昵仅。我設(shè)定7000秒去更新一次缓熟,這里用的nodejs實(shí)現(xiàn),其實(shí)思路都是一樣的岩饼。具體實(shí)現(xiàn)如下:

獲取微信access_token的NodeJs實(shí)現(xiàn)

?這里先校驗(yàn)了本地文件accesss_token.json中的access_token字段是否為空荚虚,為空表示是第一次獲取。再利用下面語(yǔ)句判斷本地的是否已經(jīng)過(guò)了我們所設(shè)定的有效期:

accessTokenJson.expire_time < currentTime

如果滿足條件籍茧,就重新發(fā)起requestGet請(qǐng)求重新獲取版述,否則從本地拿。
?為什么要這么做寞冯? 因?yàn)閷?duì)外的活動(dòng)渴析,如果用戶量比較大,每一個(gè)用戶都去獲取一次吮龄,微信限定的訪問(wèn)次數(shù)在2000個(gè)訪問(wèn)中就用完了俭茧,接下來(lái)當(dāng)天的訪問(wèn)將再也通不過(guò)簽名驗(yàn)證。

2. 生成 jsapi_ticket

?生成jsapi_ticket的步驟和獲取access_token的思路一致漓帚,具體如下所示:

利用access_token生成jsapi_ticket

?這里需要注意的是母债,不僅要判斷ticket是否為空,還要判斷token是否失效尝抖。因?yàn)楫?dāng)token提前失效后ticket將變得無(wú)意義.
?另外還要考慮這種情況毡们,某次請(qǐng)求獲取到一個(gè)token后,我們并不能保證其他人員不會(huì)去微信公眾號(hào)或者web url等方式去請(qǐng)求獲取token昧辽,這將導(dǎo)致因token被更新而上次的token失效衙熔,但我們的程序并不知道,繼續(xù)使用“上一次請(qǐng)求”的token搅荞,在下一個(gè)“重新請(qǐng)求”前將一直是失效的红氯,不要漏了這種情況框咙。

3. 生成隨機(jī)字符串

?傳給randomString一個(gè)長(zhǎng)度參數(shù),生成所需要的隨機(jī)長(zhǎng)度字符串痢甘。我這里設(shè)定的是長(zhǎng)度為16喇嘱,代碼如下,簡(jiǎn)單不解釋塞栅。

生成指定長(zhǎng)度的隨機(jī)字符串

4. 獲取JS-SDK簽名

?公式:signature=sha1(string1)婉称;即,需要生成string1构蹬,再對(duì)string1進(jìn)行sha1加密得到signature
?微信文檔中提到,

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

?其實(shí)簡(jiǎn)單了來(lái)說(shuō),string1就是jsapi_ticket=它的值&noncestr=隨機(jī)字符串&timestamp=當(dāng)前時(shí)間戳(單位秒)&url=當(dāng)前網(wǎng)頁(yè)url挚瘟。微信文檔說(shuō)要按字段名的字典序排序坤检,請(qǐng)注意兴猩,是按字段名的字典序,因?yàn)樽侄蚊蛔冊缧哉f(shuō)其實(shí)這個(gè)串中的各個(gè)參數(shù)順序是不變的倾芝。

獲取 js-sdk 簽名

【填坑】:

  1. 簽名用的noncestrtimestamp必須與wx.config中的nonceStrtimestamp相同。
  2. 簽名用的url必須是調(diào)用JS接口頁(yè)面的完整URL(請(qǐng)用location.href.split('#')[0])確認(rèn)箭跳,包括'http(s)://'部分晨另,以及'?'后面的GET參數(shù)部分,但不包括'#'hash后面的部分)

?能躺的坑基本已經(jīng)說(shuō)明谱姓,如有錯(cuò)誤或缺漏的地方借尿,歡迎交流。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末屉来,一起剝皮案震驚了整個(gè)濱河市路翻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奶躯,老刑警劉巖帚桩,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異嘹黔,居然都是意外死亡账嚎,警方通過(guò)查閱死者的電腦和手機(jī)莫瞬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)郭蕉,“玉大人疼邀,你說(shuō)我怎么就攤上這事≌傩猓” “怎么了旁振?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)涨岁。 經(jīng)常有香客問(wèn)我拐袜,道長(zhǎng),這世上最難降的妖魔是什么梢薪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任蹬铺,我火速辦了婚禮,結(jié)果婚禮上秉撇,老公的妹妹穿的比我還像新娘甜攀。我一直安慰自己,他們只是感情好琐馆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布规阀。 她就那樣靜靜地躺著,像睡著了一般瘦麸。 火紅的嫁衣襯著肌膚如雪谁撼。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天瞎暑,我揣著相機(jī)與錄音彤敛,去河邊找鬼。 笑死了赌,一個(gè)胖子當(dāng)著我的面吹牛墨榄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勿她,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼袄秩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了逢并?” 一聲冷哼從身側(cè)響起之剧,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎砍聊,沒(méi)想到半個(gè)月后背稼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡玻蝌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年蟹肘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了词疼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡帘腹,死狀恐怖贰盗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阳欲,我是刑警寧澤舵盈,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站球化,受9級(jí)特大地震影響秽晚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜筒愚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一爆惧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锨能,春花似錦、人聲如沸芍耘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)斋竞。三九已至倔约,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坝初,已是汗流浹背浸剩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鳄袍,地道東北人绢要。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拗小,于是被迫代替她去往敵國(guó)和親重罪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容