一、在此以前先確認一下你是否有已得到相應接口的權限,查看方法:登陸微信公衆平臺,開發者中心-》接口權限表-》功能服務-》分享接口。查看本身是否已經獲取分享自定義的接口權限。php
如圖:html
二、而後進入「公衆號設置」-》「功能設置」裏填寫「JS接口安全域名」。jquery
如圖:web
在須要調用JS接口的頁面引入以下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js算法
備註:支持使用 AMD/CMD 標準模塊加載方法加載sql
全部須要使用JS-SDK的頁面必須先注入配置信息,不然將沒法調用(同一個url僅需調用一次,對於變化url的SPA的web app可在每次url變化時進行調用,目前Android微信客戶端不支持pushState的H5新特性,因此使用pushState來實現web app的頁面會致使簽名失敗,此問題會在Android6.2中修復)。數據庫
wx.config({ debug: true, // 開啓調試模式,調用的全部api的返回值會在客戶端alert出來,若要查看傳入的參數,能夠在pc端打開,參數信息會經過log打出,僅在pc端時纔會打印。 appId: '', // 必填,公衆號的惟一標識 timestamp: , // 必填,生成簽名的時間戳 nonceStr: '', // 必填,生成簽名的隨機串 signature: '',// 必填,簽名,見附錄1 jsApiList: [] // 必填,須要使用的JS接口列表,全部JS接口列表見附錄2 });
此處我爲了方便測試,timestamp和nonceStr定爲死的,實際應用中你們也能夠寫爲動態的。json
下面我重點說一下signature是怎麼獲得的。api
jsapi_ticket數組
生成簽名以前必須先了解一下jsapi_ticket,jsapi_ticket是公衆號用於調用微信JS接口的臨時票據。正常狀況下,jsapi_ticket的有效期爲7200秒,經過access_token來獲取。因爲獲取jsapi_ticket的api調用次數很是有限,頻繁刷新jsapi_ticket會致使api調用受限,影響自身業務,開發者必須在本身的服務全局緩存jsapi_ticket 。
參考如下文檔獲取access_token(有效期7200秒,開發者必須在本身的服務全局緩存access_token)。
用第一步拿到的access_token 採用http 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權限驗證的簽名了。
簽名算法
簽名生成規則以下:參與簽名的字段包括noncestr(隨機字符串), 有效的jsapi_ticket, timestamp(時間戳), url(當前網頁的URL,不包含#及其後面部分) 。對全部待簽名參數按照字段名的ASCII 碼從小到大排序(字典序)後,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串string1。這裏須要注意的是全部參數名均爲小寫字符。對string1做sha1加密,字段名和字段值都採用原始值,不進行URL 轉義。
即signature=sha1(string1)。 示例:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
步驟1. 對全部待簽名參數按照字段名的ASCII 碼從小到大排序(字典序)後,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串string1:
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value
步驟2. 對string1進行sha1簽名,獲得signature:
0f9de62fce790f9a083d5c99e95740ceb90c27ed
注意事項
簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。
簽名用的url必須是調用JS接口頁面的完整URL。
出於安全考慮,開發者必須在服務器端實現簽名的邏輯。
個人思路:
由於個人服務器沒有裝memcached,因此我用數據庫來緩存access_token和jsapi_ticket,緩存你們能夠依據本身的實際狀況來定。緩存原理:在使用access_token和jsapi_ticket時,先判斷數據庫存的數據是否過時,若是過時就新生成新的數據並存入數據庫,若是沒有過時就從數據庫取。
先創建兩個表:
access_token緩存表:
jsapi_ticket緩存表:
代碼以下:先建一個微信類Wechat,用來獲取accessToken、getJSApi_ticket和signature
class Wechat { public $dsql; private function getAccessToken() //生成access_token,並存入數據庫 { global $dsql; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".AppId."&secret=".AppSecret; $data = getCurl($url);//經過自定義函數getCurl獲得https的內容 $resultArr = json_decode($data, true);//轉爲數組 //access_token插入數據庫作緩存 $time=time(); $sql="insert into wx_accesstoken(access_token,uptime) value('{$resultArr["access_token"]}',$time)"; $dsql->ExecuteNoneQuery($sql); return $resultArr["access_token"];//獲取access_token } private function getToken()//若是access_token有數據庫緩存,就從數據庫取,若是沒有就從新取 { global $dsql; $time=time()-7200; $sql="select * from wx_accesstoken where uptime>$time"; $row=$dsql->GetOne($sql); if($row) { return $row['access_token'];//從數據庫取 }else{ return $this->getAccessToken();//從新獲取 } } public function getJSApi_ticket(){//獲取JSApi_ticket global $dsql; $time=time()-7200; $sql="select * from wx_jsApiTicket where uptime>$time"; $row=$dsql->GetOne($sql); if($row) { return $row['access_token'];//從數據庫取 }else{ //若是數據庫沒有保存有效的jsApiTicket,就從新生成並存入數據庫 $accessToken = $this->getToken();//獲取access_token $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=".$accessToken."&type=jsapi"; $data = getCurl($url);//經過自定義函數getCurl獲得https的內容 $resultArr = json_decode($data, true);//轉爲數組 //插入數據庫作緩存 $nowtime=time(); $sql="insert into wx_jsApiTicket(jsApiTicket,uptime) value('{$resultArr["ticket"]}',$nowtime)"; $dsql->ExecuteNoneQuery($sql); return $resultArr['ticket'];//獲取jsApi_ticket } } public function getSignature(){ $jsApi_ticket = $this->getJSApi_ticket();//獲取access_token //file_put_contents("a.txt",$jsApi_ticket."\n",FILE_APPEND);此處是作斷點測試用的 //動態獲取url if($_SERVER['QUERY_STRING']){ $url= 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING']; }else{ $url= 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']; } //file_put_contents("a.txt",$url."\n",FILE_APPEND); $str = "jsapi_ticket=".$jsApi_ticket."&noncestr=2nDgiWM7gCxhL8v0×tamp=1420774989&url=".$url; $signature = ""; $signature=sha1($str); return $signature; } } function getCurl($url){//get https的內容 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);//不輸出內容 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $result = curl_exec($ch); curl_close ($ch); return $result; } function dataPost($post_string, $url) {//POST方式提交數據 $context = array ('http' => array ('method' => "POST", 'header' => "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) \r\n Accept: */*", 'content' => $post_string ) ); $stream_context = stream_context_create ( $context ); $data = file_get_contents ( $url, FALSE, $stream_context ); return $data; }
2.而後到須要調用JS接口的頁面得到signature
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>微信JS-SDK Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0"> <link rel="stylesheet" href=""> <script src="js/jquery-1.7.2.js"></script> </head> <?php
define(AppId, "本身的AppId");//定義AppId,須要在微信公衆平臺申請自定義菜單後會獲得 define(AppSecret, "本身的AppSecret");//定義AppSecret,須要在微信公衆平臺申請自定義菜單後會獲得
include("wechat.class.php");//引入微信類 $signatureObj = new Wechat();//實例化微信類 $signature = $signatureObj->getSignature();
?> <body ontouchstart=""> <div class="wxapi_container"> <input type="hidden" name="signature" value="<?php echo $signature;?>" id="signature"> <div class="lbox_close wxapi_form"> <h3 id="menu-basic">基礎接口</h3> <span class="desc">判斷當前客戶端是否支持指定JS接口</span> <button class="btn btn_primary" id="checkJsApi">checkJsApi</button>
<h3 id="menu-share">分享接口</h3> <span class="desc">獲取「分享到朋友圈」按鈕點擊狀態及自定義分享內容接口</span> <button class="btn btn_primary" id="onMenuShareTimeline">onMenuShareTimeline</button> <span class="desc">獲取「分享給朋友」按鈕點擊狀態及自定義分享內容接口</span> <button class="btn btn_primary" id="onMenuShareAppMessage">onMenuShareAppMessage</button> <span class="desc">獲取「分享到QQ」按鈕點擊狀態及自定義分享內容接口</span> <button class="btn btn_primary" id="onMenuShareQQ">onMenuShareQQ</button> <span class="desc">獲取「分享到騰訊微博」按鈕點擊狀態及自定義分享內容接口</span> <button class="btn btn_primary" id="onMenuShareWeibo">onMenuShareWeibo</button> </div> </div> </body> <script src=""> </script> <script> var signature = $("#signature").val(); var url = location.href.split('#')[0]; wx.config({ debug: true, appId: 'wx2fea4dec5cb77d24', timestamp: 1420774989,//此處同微信類裏用來生成signature的timestamp要相同 nonceStr: '2nDgiWM7gCxhL8v0',//此處同微信類裏用來生成signature的nonceStr要相同 signature: signature, jsApiList: [ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo' ] });
wx.ready(function () { wx.onMenuShareAppMessage({ title: '個人分享測試', // 分享標題 desc: '個人分享測試demo', // 分享描述 link: url, // 分享連接 imgUrl: 'http://img3.douban.com/view/movie_poster_cover/spst/public/p2166127561.jpg', // 分享圖標 type: '', // 分享類型,music、video或link,不填默認爲link dataUrl: '', // 若是type是music或video,則要提供數據連接,默認爲空 success: function () { // 用戶確認分享後執行的回調函數 alert("分享成功!"); }, cancel: function () { // 用戶取消分享後執行的回調函數 alert("取消分享!"); } }); })
</script> </html>
如出現invalid signature 等錯誤詳見微信附錄5常見錯誤及解決辦法。
好了,你們試試吧。。。