thinkphp3.2,微信JS-SDK開發過程中遇到的各種問題與細節分享

王震Leo發表於2019-02-16

首先完成官方文件前兩步(很好理解就不具體說了):
步驟一:繫結域名
先登入微信公眾平臺進入“公眾號設定”的“功能設定”裡填寫“JS介面安全域名”。
備註:登入後可在“開發者中心”檢視對應的介面許可權。
步驟二:引入JS檔案
在需要呼叫JS介面的頁面引入如下JS檔案,(支援https):jweixin-1.2.0.js
備註:支援使用 AMD/CMD 標準模組載入方法載入
然後是從步驟3開始進行實現
步驟三:通過config介面注入許可權驗證配置
這個地方採用ajax的方式來注入許可權;

    var link = "";                //用來接收返回的url

    $(document).ready(function(){
        ajaxconfig();
    });
    
    function ajaxconfig(){
        /*    獲取當前頁面url,傳遞給伺服器端完成簽名,此處是最大的坑一定要對url進行encodeURIComponent(),
         *    因為頁面一旦分享,微信客戶端會在你的連結末尾加入其它引數,如果不是動態獲取當前連結,將導致分享後的頁面簽名失敗。
         */
        
        var url = encodeURIComponent(window.location.href.split(`#`)[0]);
        
        var eventinfo = {
            url:url,
        };
    
        $.ajax({

            type: "post",
            url: "{:U(`Event/get_config`)}",     //    伺服器端url
            data : eventinfo,
            dataType: `json`,
            success: function(obj){
                // 注入許可權驗證配置
                wx.config({
                    debug : true,                 //實現階段開啟debug
                    appId : obj.appId,             //必填,公眾號的唯一標識
                    timestamp : obj.timestamp,   //必填,生成簽名的時間戳
                    nonceStr : obj.nonceStr,     //必填,生成簽名的隨機串
                    signature : obj.signature,     //必填,簽名
                    jsApiList : [                 //必填,需要使用的JS介面列表,所有JS介面列表見官方文件
                        `checkJsApi`,
                        `onMenuShareTimeline`,
                        `onMenuShareAppMessage`,
                        `onMenuShareQQ`,
                        `onMenuShareWeibo`
                    ]
                }); 
                link = obj.url;                    //    獲取成功簽名返回的url
            }
        })
    }

    wx.ready(function () {
        // 注入許可權驗證成功後會執行這裡,以"分享給朋友"為例
        wx.onMenuShareAppMessage({
    
            title: ``,                 // 分享標題
            desc: ``,                 // 分享描述
            link: link,             // 分享連結,該連結域名或路徑必須與當前頁面對應的公眾號JS安全域名一致(ajax返回的url)
            imgUrl: ``,             // 分享圖示
            type: ``,                 // 分享型別,music、video或link,不填預設為link
            dataUrl: ``,             // 如果type是music或video,則要提供資料連結,預設為空
            success: function () { 
            
                // 使用者確認分享後執行的回撥函式
            },
            cancel: function () { 
                // 使用者取消分享後執行的回撥函式
            }
        });
         };

下一步,在伺服器端完成簽名,返回許可權驗證配置資訊。下載官網提供的示例程式碼,參照jssdk.php中的程式碼一步一步來實現。
先建立一個”活動(Event)”控制器:EventController.class.php;模版檔案event.html;

// 控制器程式碼
// 獲取隨機串,直接複製jssdk.php
private function createNonceStr($length = 16) {
  $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  $str = "";
  for ($i = 0; $i < $length; $i++) {
    $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  }
  return $str;
}
//獲取票據,複製jssdk.php進行修改
private function getJsApiTicket() {
//用於快取jsapiTicket的檔案地址,複製官方例子中的jsapi_ticket.php到你要存放的位置
//拼接檔案地址
$jsapi_ticket_url = $_SERVER[`DOCUMENT_ROOT`]."/Public/js/home/event/jsapi_ticket.php";
    
// jsapi_ticket 應該全域性儲存與更新,以下程式碼以寫入到檔案中做示例
$data = json_decode( $this -> get_php_file($jsapi_ticket_url) );    //修改get_php_file( )中的變數
if ($data->expire_time < time()) {
    $accessToken = $this->getAccessToken();    
    $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
    $res = json_decode($this->httpGet($url));    
    $ticket = $res->ticket;
    if ($ticket) {
        $data -> expire_time = time() + 7000;
        $data -> jsapi_ticket = $ticket;
        $this -> set_php_file($jsapi_ticket_url, json_encode($data));    //修改set_php_file( )中的變數
    }
} else {
    $ticket = $data->jsapi_ticket;
}
  return $ticket;
}
//獲取AccessToken,複製jssdk.php進行修改
private function getAccessToken() {
    
$appId = "你的AppID";
$appSecret = "開發者密碼AppSecret";
//用於快取AccessToken的檔案地址,複製官方例子中的access_token.php到你要存放的位置    
$access_token_url = $_SERVER[`DOCUMENT_ROOT`]."/Public/js/home/event/access_token.php";
    
// access_token 應該全域性儲存與更新,以下程式碼以寫入到檔案中做示例
$data = json_decode($this->get_php_file($access_token_url));    //修改get_php_file( )中的變數    
if ( $data -> expire_time < time()) {  
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appId&secret=$appSecret";
    $res = json_decode($this->httpGet($url));
    $access_token = $res->access_token;    
    if ($access_token) {
        $data -> expire_time = time() + 7000;
        $data -> access_token = $access_token;    
        $this -> set_php_file($access_token_url, json_encode($data));    //修改set_php_file( )中的變數
    }
} else {    
    $access_token = $data->access_token;
}
return $access_token;
}

//直接複製jssdk.php
private function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
//直接複製jssdk.php
private function get_php_file($filename) {
return trim(substr(file_get_contents($filename), 15));
}
//直接複製jssdk.php
private function set_php_file($filename, $content) {
$fp = fopen($filename, "w");
fwrite($fp, "<?php exit();?>" . $content);
fclose($fp);
}

public function get_config(){
    
    $url = urldecode(I(`post.url`)); //    把ajax傳送過來的url進行解碼!!!此處是坑
    $timestamp =  time();//    時間戳
    $nonceStr = $this -> createNonceStr(16);//    隨機串
    $jsapiTicket = $this-> getJsApiTicket();//    票據
    
    $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

    $signature = sha1($string);//    簽名
    
    //在這也可以將 分享標題,分享描述,縮圖地址等一起返回    
    $config[`appId`] = "AppID";
    $config[`timestamp`] = $timestamp;
    $config[`nonceStr`] = $nonceStr;
    $config[`signature`] = $signature;
    $config[`url`] = $url;
    
    $this -> ajaxReturn($config);    
}    

在手機測試,開啟debug後,如果簽名成功直接提示OK,如果簽名沒有成功,逐步列印,查詢錯誤位置。
1、AccessToken是否獲取成功
2、AccessToken和jsapiTicket 是否能寫入和讀取
3、url是否轉碼和解碼,這個地方非常重要。否則分享後的頁面會簽名失敗
4、ajax返回的url與分享的link是否一致

相關文章