開發(七)分享接入,接入
文章作者:松陽
本文出自 阿修羅道,禁止用於商業用途,轉載請註明出處。
原文連結:http://blog.csdn.net/fansongy/article/details/44680987
分享
上做推廣活動一般都是著眼於分享,這篇文章介紹如何在頁面中加入分享的處理。本文使用語言為Java+js。
原理
分享功能的痛點,在於使用者是否真正的分享了推廣頁面,所以我們要知道使用者分享成功的操作。經過查詢文檔,提供了對應的JS介面。對應文檔在這裡 .
大體流程是這樣的:
- 綁定網域名稱
- 引入JS檔案
- 通過config介面注入許可權驗證配置
- 通過ready介面處理成功驗證
- 通過error介面處理失敗驗證
- 編寫對應回調
如果你自信滿滿的完成了上面這些步驟,就可以開始著手測試了。 當點擊對應功能時,會回調對應的介面。我的需求是當使用者分享到自己的朋友圈時,做一些猥瑣的操作 ,因此下面以分享朋友圈為例,當然其他功能也很類似,此處按下不表。
實現
上面概括了原理了原理,接下來一步一步看。本文可以結合 官方文檔 一起看,畢竟它更新維護的比較勤。
綁定網域名稱
先登入公眾平台進入“公眾號設定”的“功能設定”裡填寫“JS介面安全網域名稱”。 備忘:登入後可在“開發人員中心”查看對應的介面許可權。
此處要注意了,服務號還沒驗證的程式狗,趕緊催促貴公司的商務人員,申請服務號驗證,目前沒有認證的服務號是沒法使用大多數JS介面的
引入JS檔案
在需要調用JS介面的頁面引入如下JS檔案,(支援https):
http://res.wx.qq.com/open/js/jweixin-1.0.0.js
備忘:支援使用 AMD/CMD 標準模組載入方法載入
這個沒啥說的,就是注意要把引入放到其他步驟的上面,JS指令碼按順序載入,大家都懂的。
通過config介面注入許可權驗證配置
這個最麻煩了,首先說指令碼的格式:
wx.config({ debug: true, // 開啟偵錯模式,調用的所有api的傳回值會在用戶端alert出來,若要查看傳入的參數,可以在pc端開啟,參數資訊會通過log打出,僅在pc端時才會列印。 appId: '', // 必填,公眾號的唯一標識 timestamp: , // 必填,產生簽名的時間戳記 nonceStr: '', // 必填,產生簽名的隨機串 signature: '',// 必填,簽名,見附錄1 jsApiList: [] // 必填,需要使用的JS介面列表,所有JS介面列表見附錄2});
這部分資訊的擷取,推薦使用ajax請求一下自己的伺服器,畢竟加密這東西沒法在用戶端搞。所以大體流程是使用者開啟網頁,運行ajax指令碼請求伺服器一堆資訊,成功發下來後,在寫到js裡面。下面上代碼:
var url = location.href.split('#').toString();$.ajax({ type : "POST", url : "yourInterfaceURL", dataType : "html", async : false, data:"url="+url, success : function(dataStr) { var data = $.parseJSON(dataStr); wx.config({ debug: true, appId: data.appid, timestamp: data.timestamp, nonceStr: data.nonceStr, signature: data.signature, jsApiList: [ 'checkJsApi', 'onMenuShareTimeline' ] }); }, error: function(xhr, status, error) { alert(status); alert(xhr.responseText); },});
這裡有一點要注意,我們需要將請求頁面的URL傳上去,因為會在頁面後面加入一些尾碼比如&isInstall=0之類的。所以它要求你動態算一個URL地址,而不能寫入程式碼。
然後伺服器收到這請求就加密去。要加密要一個jsapi_ticket,而要jsapi_ticket又需要token.
由於原理一樣,這裡僅以jsapi_ticket為例:
public String jsapi_ticket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";public String getJsapiTicket() { long now = System.currentTimeMillis(); if(now - curJSTokenTime > expiresJSToken*1000) { String requestUrl = jsapi_ticket.replace("ACCESS_TOKEN", getToken()); JSONObject jsonObject = httpsRequest(requestUrl, "GET", null); System.out.println("Getting weixin js_token...URL:"+requestUrl); if (null != jsonObject) { try { curJSToken = jsonObject.getString("ticket"); expiresJSToken = jsonObject.getInt("expires_in"); curJSTokenTime = System.currentTimeMillis(); System.out.println("update weixin token:"+curJSToken+"expires_in is:"+expiresJSToken+" curTime:"+curJSTokenTime); } catch (JSONException e) { System.out.println("Get JS_Token Error! errcode:{} errmsg:{}"+jsonObject.getInt("errcode")+jsonObject.getString("errmsg")+e); } } else { System.out.println("http for weixin return null"); curJSToken=""; } } return curJSToken;}
拿到了這個東西就可以算加密串了。當然用這個函數需要先去取Access_Token,這就又要用到appid和appSercet,你必然知道在哪找到這貨,啥?不知道?去的開發人員中心的配置項那邊碰碰運氣吧。
public Map<String, String> makeWXTicket(String jsapi_ticket, String url) { Map<String, String> ret = new HashMap<String, String>(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String string1; String signature = ""; //注意這裡參數名必須全部小寫,且必須有序 string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(string1.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", jsapi_ticket); ret.put("nonceStr", nonce_str); ret.put("timestamp", timestamp); ret.put("signature", signature); ret.put("appid", 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);}
makeWXTicket這個函數有倆參數,第一個是上面的jsapi_ticket,第二個是頁面傳上來的url,傳回值是一個Map。後面就看各路大神八仙過海了,大死不靈啥的,總之你肯定有辦法把這貨傳回去的。傳回去後,就到wx.config中把內容填充進去了。
ready & error & 功能調用
最噁心的部分搞過去,其他就一馬平川了。
wx.ready(function () { wx.onMenuShareTimeline({ title: '互連網之子?', link: 'http://movie.douban.com/subject/25785114/', imgUrl: 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg', trigger: function (res) { // 不要嘗試在trigger中使用ajax非同步請求修改本次分享的內容,因為用戶端分享操作是一個同步操作,這時候使用ajax的回包會還沒有返回. alert('click shared'); }, success: function (res) { alert('shared success'); //some thing you should do }, cancel: function (res) { alert('shared cancle'); }, fail: function (res) { alert(JSON.stringify(res)); } }); wx.error(function (res) { alert(res.errMsg); });});
在網頁中添加以上內容,使用者點擊對應的操作就會彈出提示對話方塊啦 如果沒有回調,簽名又沒有問題,去開發人員中心檢查一下介面是否開通了吧。
總結
接入過程很糾結,測試比較麻煩,伺服器的回調只認有備案的網域名稱。驗簽可以使用這個網址 做測試。總之,祝你好運~
如果你覺得這篇文章對你有協助,可以順手點個頂,不但不會喜當爹,還能讓更多人能看到它...