摘要:最近開發(fā)微信公眾號(hào)內(nèi)嵌頁(yè)面,使用搭建的項(xiàng)目,由于業(yè)務(wù)需求,需要實(shí)現(xiàn)微信自定義分享功能,所以項(xiàng)目中集成微信。
最近開發(fā)微信公眾號(hào)內(nèi)嵌H5頁(yè)面,使用vue搭建的項(xiàng)目,由于業(yè)務(wù)需求,需要實(shí)現(xiàn)微信自定義分享功能,所以項(xiàng)目中集成微信JS-SDK。微信JS-SDK是微信公眾平臺(tái)面向網(wǎng)頁(yè)開發(fā)者提供的基于微信內(nèi)的網(wǎng)頁(yè)開發(fā)工具包。通過(guò)使用微信JS-SDK,網(wǎng)頁(yè)開發(fā)者可借助微信高效地使用拍照、選圖、語(yǔ)音、位置等手機(jī)系統(tǒng)的能力,同時(shí)可以直接使用微信分享、掃一掃、卡券、支付等微信特有的能力,為微信用戶提供更優(yōu)質(zhì)的網(wǎng)頁(yè)體驗(yàn)。
1.綁定域名微信公眾號(hào)開發(fā)測(cè)試帳號(hào):http://mp.weixin.qq.com/debug...,需要填寫接口配置,一個(gè)公網(wǎng)能訪問(wèn)的域名,推薦用natapp/路由俠。填寫JS接口安全域名 ,設(shè)置JS接口安全域后,通過(guò)關(guān)注該測(cè)試號(hào),開發(fā)者即可在該域名下調(diào)用微信開放的JS接口,請(qǐng)閱讀微信JSSDK開發(fā)文檔
1)這里使用路由俠,實(shí)現(xiàn)內(nèi)網(wǎng)穿透http://www.luyouxia.com/,下載安裝后,配置相應(yīng)的內(nèi)網(wǎng)映射地址
2)設(shè)置JS接口安全域
通過(guò)npm安裝微信的js-sdk,或者在index.html頁(yè)面中直接加script標(biāo)簽來(lái)引用,這里采用npm安裝,
npm install weixin-js-sdk
在需要分享的頁(yè)面中引入
import wx from "weixin-js-sdk"
1)jsapi_ticket
生成簽名之前必須先了解一下jsapi_ticket,jsapi_ticket是公眾號(hào)用于調(diào)用微信JS接口的臨時(shí)票據(jù)。正常情況下,jsapi_ticket的有效期為7200秒,通過(guò)access_token來(lái)獲取。由于獲取jsapi_ticket的api調(diào)用次數(shù)非常有限,頻繁刷新jsapi_ticket會(huì)導(dǎo)致api調(diào)用受限,影響自身業(yè)務(wù),開發(fā)者必須在自己的服務(wù)全局緩存jsapi_ticket。
2)獲取access_token(有效期7200秒,開發(fā)者必須在自己的服務(wù)全局緩存access_token)
access_token是公眾號(hào)的全局唯一接口調(diào)用憑據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用access_token,官方文檔:https://mp.weixin.qq.com/wiki...
@RequestMapping(value = "/get_access_token", method = RequestMethod.GET) public String getAssessToken() { String url = "https://api.weixin.qq.com/cgi-bin/token"; String str = HttpClientUtil.sendGet(url, "grant_type=" + Constants.GRANTTYPE + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID); JSONObject jsonObject = JSONObject.fromObject(str); return jsonObject.toString(); }
3)獲取access_token后,采用http GET方式請(qǐng)求獲得jsapi_ticket
@RequestMapping(value = "/get_ticket", method = RequestMethod.GET) public String getTicket() { String urlToken = "https://api.weixin.qq.com/cgi-bin/token"; String tokenObj = HttpClientUtil.sendGet(urlToken, "grant_type=" + Constants.GRANTTYPE + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID); JSONObject jsonToken = JSONObject.fromObject(tokenObj); String access_token = jsonToken.getString("access_token"); String urlTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; String strTicket = HttpClientUtil.sendGet(urlTicket, "type=jsapi" + "&access_token=" + access_token); JSONObject jsonTicket = JSONObject.fromObject(strTicket); return jsonTicket.toString(); }
4)簽名算法
簽名生成規(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)義。
@RequestMapping(value = "/get_signature", method = RequestMethod.GET) public MapgetSignature(String url) { Map ret = new HashMap (); String wxTicket = getWxApiTicket(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String str; String signature = ""; //注意這里參數(shù)名必須全部小寫,且必須有序 str = "jsapi_ticket=" + wxTicket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url; logger.info(str); try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(str.getBytes("UTF-8")); signature = byteToHex(crypt.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret.put("url", url); ret.put("jsapi_ticket", wxTicket); ret.put("nonceStr", nonce_str); ret.put("timestamp", timestamp); ret.put("signature", signature); ret.put("appId", Constants.APPID); return ret; } private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } private static String create_nonce_str() { return UUID.randomUUID().toString(); } private static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); }
簽名接口返回信息
{ "signature":"4021b3f502e6bd15798a0433af33c4ef1be4ff83", "appId":"wx618f45e4948c3889", "jsapi_ticket":"sM4AOVdWfPE4DxkXGEs8VOxnOWlkG3Q1qP1pwA8mBLNgkCewNOfFiU8EmlnAx8_Fe0Zh-rGS03Nu8BQZB0a4-g", "url":null, "nonceStr":"ab5d0e96-429b-4a86-bd88-dc1276dcf76f", "timestamp":"1566527616" }
注意事項(xiàng)
1.簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。
2.簽名用的url必須是調(diào)用JS接口頁(yè)面的完整URL。
3.出于安全考慮,開發(fā)者必須在服務(wù)器端實(shí)現(xiàn)簽名的邏輯。
所有需要使用JS-SDK的頁(yè)面必須先注入配置信息,否則將無(wú)法調(diào)用(同一個(gè)url僅需調(diào)用一次,對(duì)于變化url的SPA的web app可在每次url變化時(shí)進(jìn)行調(diào)用,目前Android微信客戶端不支持pushState的H5新特性,所以使用pushState來(lái)實(shí)現(xiàn)web app的頁(yè)面會(huì)導(dǎo)致簽名失敗,此問(wèn)題會(huì)在Android6.2中修復(fù))。
wx.config({ debug: true, // 開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái),若要查看傳入的參數(shù),可以在pc端打開,參數(shù)信息會(huì)通過(guò)log打出,僅在pc端時(shí)才會(huì)打印。 appId: "", // 必填,公眾號(hào)的唯一標(biāo)識(shí) timestamp: , // 必填,生成簽名的時(shí)間戳 nonceStr: "", // 必填,生成簽名的隨機(jī)串 signature: "",// 必填,簽名 jsApiList: [] // 必填,需要使用的JS接口列表 });
config配置里面的參數(shù)appid, timestamp, nonceStr, signature都是要后臺(tái)接口返回的,前端可以通過(guò)axios發(fā)送接口請(qǐng)求獲取
this.axios.get("/wx/get_signature?url=" + encodeURIComponent(location.href.split("#")[0])).then((res) => { wx.config({ debug: true, // 開啟調(diào)試模式 appId: res.data.appId, // 必填,公眾號(hào)的唯一標(biāo)識(shí) timestamp: res.data.timestamp, // 必填,生成簽名的時(shí)間戳 nonceStr: res.data.nonceStr, // 必填,生成簽名的隨機(jī)串 signature: res.data.signature,// 必填,簽名 jsApiList: [ "updateAppMessageShareData",//自定義“分享給朋友”及“分享到QQ”按鈕的分享內(nèi)容 "updateTimelineShareData",//自定義“分享到朋友圈”及“分享到QQ空間”按鈕的分享內(nèi)容 "onMenuShareWeibo",//獲取“分享到騰訊微博”按鈕點(diǎn)擊狀態(tài)及自定義分享內(nèi)容接口 ] // 必填,需要使用的JS接口列表 }) }).catch((error) => { console.log(error) }); //通過(guò)ready接口處理成功驗(yàn)證 wx.ready(function(){ this.wxShareTimeline(); this.wxShareAppMessage(); // config信息驗(yàn)證后會(huì)執(zhí)行ready方法,所有接口調(diào)用都必須在config接口獲得結(jié)果之后,config是一個(gè)客戶端的異步操作,所以如果需要在頁(yè)面加載時(shí)就調(diào)用相關(guān)接口,則須把相關(guān)接口放在ready函數(shù)中調(diào)用來(lái)確保正確執(zhí)行。對(duì)于用戶觸發(fā)時(shí)才調(diào)用的接口,則可以直接調(diào)用,不需要放在ready函數(shù)中。 }); wx.error(function(res){ //config信息驗(yàn)證失敗會(huì)執(zhí)行error函數(shù),如簽名過(guò)期導(dǎo)致驗(yàn)證失敗,具體錯(cuò)誤信息可以打開config的debug模式查看,也可以在返回的res參數(shù)中查看,對(duì)于SPA可以在這里更新簽名。 });5.實(shí)現(xiàn)自定義分享朋友/朋友圈
wxShareTimeline() {// 自定義“分享給朋友”及“分享到QQ”按鈕的分享內(nèi)容 wx.updateAppMessageShareData({ title: "世界那么大,我想去看看-微信test", // 分享標(biāo)題 desc: "世界那么大,我想去看看-微信test", // 分享描述 link: location.href.split("#")[0], // 分享鏈接,該鏈接域名或路徑必須與當(dāng)前頁(yè)面對(duì)應(yīng)的公眾號(hào)JS安全域名一致 imgUrl: "http://www.baidu.com/FpEhdOqBzM8EzgFz3ULByxatSacH", // 分享圖標(biāo) success: () => { } }) }, wxShareAppMessage() {//自定義“分享到朋友圈”及“分享到QQ空間”按鈕的分享內(nèi)容 wx.updateTimelineShareData({ title: "世界那么大,我想去看看-微信test2", // 分享標(biāo)題 desc: "世界那么大,我想去看看-微信test2", // 分享描述 link: location.href.split("#")[0], // 分享鏈接,該鏈接域名或路徑必須與當(dāng)前頁(yè)面對(duì)應(yīng)的公眾號(hào)JS安全域名一致 imgUrl: require("./logo.jpg"), // 分享圖標(biāo)(不能賦相對(duì)路徑,一定要是絕對(duì)路徑) success: () => { } }) }6.遇到問(wèn)題
1)invalid signature
獲取的簽名錯(cuò)誤,原因可能是公眾號(hào)平臺(tái)配置有問(wèn)題或者是后臺(tái)返回簽名接口的算法有問(wèn)題
2)invalid url domain
當(dāng)前頁(yè)面所在域名與使用的appid沒有綁定,請(qǐng)確認(rèn)正確填寫綁定的域名,僅支持80(http)和443(https)兩個(gè)端口,因此不需要填寫端口號(hào)。
3)自定義的縮略圖不顯示
路徑錯(cuò)誤導(dǎo)致的,不能使用相對(duì)路徑,一定要是絕對(duì)路徑,另外一個(gè)原因就是圖片尺寸和類型問(wèn)題,推薦使用jpg格式
4)二次分享導(dǎo)致不能調(diào)用自定義的接口
url進(jìn)行編碼之后傳給后臺(tái)獲取的簽名才不會(huì)計(jì)算錯(cuò),因?yàn)槲⑿艜?huì)在分享后的鏈接后面加from=singlemessage&isappinstalled=0這串字符串。
1)通過(guò)數(shù)據(jù)庫(kù)保存
做法是獲取access_token的時(shí)候把當(dāng)前系統(tǒng)時(shí)間和access_token保存到數(shù)據(jù)表中,當(dāng)再次獲取時(shí),查詢上次獲取的時(shí)間與當(dāng)前系統(tǒng)時(shí)間比較,看看時(shí)間是否大于2個(gè)小時(shí)(7200s)。如果超過(guò)這個(gè)時(shí)間限制,再獲取一個(gè)access_token,然后更新數(shù)據(jù)表的accessToken和getTime。
2)通過(guò)物理磁盤創(chuàng)建txt文件保存
3)通過(guò)servlet啟動(dòng)線程,讓線程定時(shí)執(zhí)行獲取
可以參考https://blog.csdn.net/guobinh...
以上便是這次調(diào)用微信js-sdk總結(jié),想要了解更多可以閱讀微信JS-SDK說(shuō)明文檔https://mp.weixin.qq.com/wiki...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/106910.html
摘要:你要是問(wèn)我為什么會(huì)出現(xiàn)這種情況,等我什么時(shí)候進(jìn)微信團(tuán)隊(duì)了,我再給大家解答。。。 很久沒有寫文章了,最近項(xiàng)目是基于微信公眾號(hào)的Vue項(xiàng)目,有一個(gè)非常重要的分享功能,不搞不知道一搞不得了,發(fā)現(xiàn)vue-router和微信SDK配置有很大的兼容性問(wèn)題,翻遍文檔,社區(qū),博客,都沒有找到可以適合解決我這個(gè)問(wèn)題的方法,最后是我們一起一個(gè)一個(gè)方法、一個(gè)一個(gè)api嘗試才找到解決辦法,現(xiàn)在和大家分享一下我...
摘要:微信說(shuō)明文檔分享的坑根據(jù)的文檔,很多人都是在初始化的配置的時(shí)候,傳入的當(dāng)前的地址不正確。同樣的,給微信初始化的加入對(duì)應(yīng)的參數(shù)。 date: 2018-12-13 15:23:09 用于記錄接入微信JS-SDK的坑,以后方便查詢第一次接入公眾號(hào)微信支付、分享、定位等等的坑的時(shí)候,心里是迷茫而又恐懼。因?yàn)?,聽說(shuō)坑特別多,后來(lái)發(fā)現(xiàn)自己的親身體驗(yàn)到了這一點(diǎn)。 支付的坑 1、當(dāng)前URL未注冊(cè) ...
摘要:微信說(shuō)明文檔分享的坑根據(jù)的文檔,很多人都是在初始化的配置的時(shí)候,傳入的當(dāng)前的地址不正確。同樣的,給微信初始化的加入對(duì)應(yīng)的參數(shù)。 date: 2018-12-13 15:23:09 用于記錄接入微信JS-SDK的坑,以后方便查詢第一次接入公眾號(hào)微信支付、分享、定位等等的坑的時(shí)候,心里是迷茫而又恐懼。因?yàn)?,聽說(shuō)坑特別多,后來(lái)發(fā)現(xiàn)自己的親身體驗(yàn)到了這一點(diǎn)。 支付的坑 1、當(dāng)前URL未注冊(cè) ...
摘要:微信說(shuō)明文檔分享的坑根據(jù)的文檔,很多人都是在初始化的配置的時(shí)候,傳入的當(dāng)前的地址不正確。同樣的,給微信初始化的加入對(duì)應(yīng)的參數(shù)。 date: 2018-12-13 15:23:09 用于記錄接入微信JS-SDK的坑,以后方便查詢第一次接入公眾號(hào)微信支付、分享、定位等等的坑的時(shí)候,心里是迷茫而又恐懼。因?yàn)椋犝f(shuō)坑特別多,后來(lái)發(fā)現(xiàn)自己的親身體驗(yàn)到了這一點(diǎn)。 支付的坑 1、當(dāng)前URL未注冊(cè) ...
摘要:安裝并引入依賴包這里是說(shuō)明文檔下載依賴包在需要用到的模塊引入檢查是否引入成功可以在引入的模塊中執(zhí)行控制臺(tái)顯示以上代碼表示引入成功配置微信所有需要使用的頁(yè)面必須先注入配置信息,否則將無(wú)法調(diào)用開啟調(diào)試模式調(diào)用的所有的返回值會(huì) 1.安裝并引入JS-SDK依賴包 這里是JS-SDK說(shuō)明文檔 1.1 npm 下載依賴包 npm install weixin-js-sdk --save 1.2.在...
閱讀 4351·2021-09-26 10:17
閱讀 941·2021-09-22 15:02
閱讀 3560·2021-09-06 15:00
閱讀 1124·2021-07-25 16:52
閱讀 2818·2019-08-29 16:16
閱讀 2588·2019-08-29 13:25
閱讀 1645·2019-08-26 13:51
閱讀 2243·2019-08-26 10:58