1. 程式人生 > >TP5 微信網頁自定義分享類

TP5 微信網頁自定義分享類

荊軻刺秦王

上一篇部落格介紹了微信自定義分享內容的獲取微信簽名包的,但是有一個問題就是,微信截至本文發表,仍然對於獲取access_token 有上限,就像這樣:

 

為了解決這個問題,我們需要將上篇文章的獲取 access_token 的Jssdk 類稍微修改一下:

直接上程式碼:

<?php

namespace org\wechat;

class JSSDK {
    private $appId;
    private $appSecret;
    private $access_token_url;
    private $jsapi_ticket_url;

    public function __construct($appId, $appSecret) {
        $this->appId = $appId;
        $this->appSecret = $appSecret;
        $this->access_token_url = EXTEND_PATH."org\js-sdk\access_token_".$appId.".json";
        $this->jsapi_ticket_url = EXTEND_PATH."org\js-sdk\jsapi_ticket_".$appId.".json";
    }

    public function getSignPackage() {
        $jsapiTicket = $this->getJsApiTicket();

        // 注意 URL 一定要動態獲取,不能 hardcode.
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

        $timestamp = time();
        $nonceStr = $this->createNonceStr();

        // 這裡引數的順序要按照 key 值 ASCII 碼升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

        $signature = sha1($string);

        $signPackage = array(
            "appId"     => $this->appId,
            "nonceStr"  => $nonceStr,
            "timestamp" => $timestamp,
            "url"       => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        return $signPackage;
    }

    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;
    }

    private function getJsApiTicket() {
        // jsapi_ticket 應該全域性儲存與更新,以下程式碼以寫入到檔案中做示例
        $data = json_decode(file_get_contents($this->jsapi_ticket_url));
        if ($data->expire_time < time()) {
            $accessToken = $this->getAccessToken();
            // 如果是企業號用以下 URL 獲取 ticket
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
            $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;
                $fp = fopen($this->jsapi_ticket_url, "w");
                fwrite($fp, json_encode($data));
                fclose($fp);
            }
        } else {
            $ticket = $data->jsapi_ticket;
        }

        return $ticket;
    }

    public function getAccessToken() {
        // access_token 應該全域性儲存與更新,以下程式碼以寫入到檔案中做示例
        $data = json_decode(file_get_contents($this->access_token_url));
        if ($data->expire_time < time()) {
            // 如果是企業號用以下URL獲取access_token
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->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;
                $fp = fopen($this->access_token_url, "w");
                fwrite($fp, json_encode($data));
                fclose($fp);
            }
        } else {
            $access_token = $data->access_token;
        }
        return $access_token;
    }

    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;
    }
}

目錄結構:

注意:這兩個 json 檔案是不需要手動建立的(如果沒有的話,會自動生成)

解釋一下:

首先這個 Jssdk 類在需要呼叫分享介面,或者其他介面時,需要用到 access_token 的時候,會先去 org\js-sdk\jsapi_ticket_".$appId.".json 檔案裡面去找,這兩個檔案裡面的內容:

首先:access_token_wxb010c3cf978e2801.json

{"expire_time":1544671442,"access_token":"19_ZIsw9sNp6GmfG89e3lrl4gwZUJAyzEm9ittvz060mFTRMVsMNjpqYRyhkVwT5wefKWbyIOse25m9Wjqh4pTKRUDiuO_5meOhe-cXt67B7ve4Hp60uyOZO01GbCL9AG7F6oM04bsEAir8TZ_yEMBdADASAP"}

其次:jsapi_ticket_wxb010c3cf978e2801.json

{"expire_time":1544671442,"jsapi_ticket":"kgt8ON2yVITDhtdwci0qeb834GF2Vk7LoytTRYyoUkc_jmXn-B-Us_XzfIi8SUUwHUzZ9EjIgO0GtFZ4Ir88Mw"}

每次,呼叫微信介面的時候,程式都會先判斷這兩個 json 檔案裡面的 expire_time 是否小於當前時間,如果不小於當前時間,那麼會向微信發起請求,獲取 access_token ,獲取完 access_token 以後,會寫入 access_token_wxb010c3cf978e2801.json 檔案一個時間,這個時間是 當前時間的時間戳 + 7000秒,之所以是7000秒,是因為這個 access_token 的有效期是7200秒,所以保險起見,設定為7000秒。這個一般不會有什麼影響。

 

好了,這樣以來前臺控制器裡面就可以呼叫這個 Jssdk 類 來獲取微信簽名了,就可以實現微信自定義分享了!