微信JS-SDK分享功能開發實例

JSSDK使用步驟

 

步驟一:綁定域名

一、在此以前先確認一下你是否有已得到相應接口的權限,查看方法:登陸微信公衆平臺,開發者中心-》接口權限表-》功能服務-》分享接口。查看本身是否已經獲取分享自定義的接口權限。php

如圖:html

二、而後進入「公衆號設置」-》「功能設置」裏填寫「JS接口安全域名」。jquery

如圖:web

 

步驟二:引入JS文件

在須要調用JS接口的頁面引入以下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js算法

備註:支持使用 AMD/CMD 標準模塊加載方法加載sql


步驟三:經過config接口注入權限驗證配置

全部須要使用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

 

JS-SDK使用權限簽名算法

jsapi_ticket數組

生成簽名以前必須先了解一下jsapi_ticket,jsapi_ticket是公衆號用於調用微信JS接口的臨時票據。正常狀況下,jsapi_ticket的有效期爲7200秒,經過access_token來獲取。因爲獲取jsapi_ticket的api調用次數很是有限,頻繁刷新jsapi_ticket會致使api調用受限,影響自身業務,開發者必須在本身的服務全局緩存jsapi_ticket 。

  1. 參考如下文檔獲取access_token(有效期7200秒,開發者必須在本身的服務全局緩存access_token)。

  2. 用第一步拿到的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

  • url=http://mp.weixin.qq.com?params=value


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

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


步驟2. 對string1進行sha1簽名,獲得signature:

0f9de62fce790f9a083d5c99e95740ceb90c27ed

注意事項

  1. 簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。

  2. 簽名用的url必須是調用JS接口頁面的完整URL。

  3. 出於安全考慮,開發者必須在服務器端實現簽名的邏輯

個人思路:

由於個人服務器沒有裝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&timestamp=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常見錯誤及解決辦法。

 

好了,你們試試吧。。。

相關文章
相關標籤/搜索