微信js-sdk開發獲取簽名和獲取地理位置接口示例

###微信js-sdk開發獲取簽名和獲取地理位置接口示例

前言:在作微信公衆號開發時須要獲取用戶的地理位置信息,以前經過高德或者百度、騰訊等地圖的api時發現常常獲取不到,畢竟第三方的東西,後來改成採用微信內置的js-sdk中的獲取地理位置接口,在這主要記錄下簽名的獲取(麻煩點)和一個獲取地理位置的例子。javascript

準備工做:

  1. 微信測試號appid和appsecret
    獲取地址:微信測試帳號獲取
  2. 在測試帳號裏先填寫接口配置信息和js接口安全域名(這個是必須的)
  3. 示例:頁面中須要點擊圖標獲取地理位置信息
    流程以下:
    點擊按鈕->觸發事件去獲取->ajax異步獲取簽名->拿簽名去獲取地理位置->獲得經緯度->高德api再去逆地理編碼獲取真實地址信息
前端代碼以下:(主要是使用js-sdk,直接拿來用就行,換下ajax請求地址)
<!--引入js-sdk-->
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>

<!--點擊圖標觸發事件-->
<img onclick="getCurrentLocation()" src="__PUBLIC__/img/gap.png">

//根據微信js-sdk內置接口 getCurrentLocation
function getCurrentLocation(){
    //這個是獲取簽名時的url,動態變化,因此在前段獲取,後端傳入直接使用
    var url = location.href.split('#')[0];
    var ajaxUrl = '/*****/getWxsdkSign';   //ajax異步獲取微信簽名sign
    $.get(ajaxUrl, {url : url}, function(json){
        if(json.code == 0){
            let sdkSign = json.data; // 後臺返回的值
            wx.config({
                debug: false, // ture會alert所有信息,上線時改成false
                appId: sdkSign.appId, // 必填,公衆號惟一標識
                timestamp: sdkSign.timestamp, // 必填,生成簽名的時間戳
                nonceStr: sdkSign.nonceStr, // 必填,生成簽名的隨機串
                signature: sdkSign.signature,// 必填,簽名
                jsApiList: ['getLocation',] // 必填,須要調用的接口列表,本需求裏只是獲取位置信息,具體的接口名稱查閱js-sdk文檔
            });
            //獲取地理位置(經緯度)
            wx.getLocation({
                type: 'gcj02', // 默認爲wgs84的gps座標,若是要返回直接給openLocation用的火星座標,可傳入'gcj02'
                success: function (res) {
                    var latitude = res.latitude;   //緯度,浮點數
                    var longitude = res.longitude; //經度,浮點數
                    //如下這部份內容就是再經過異步操做逆地理編碼獲取真實的地址信息
                    getLocationBylatlng(latitude, longitude);
                }
            });
        }else{
            //TODO 獲取簽名失敗的處理,未獲取到地理位置
            *****************
            *****************
        }
    },'json');
}
後端代碼以下:(主要是用來獲取js-sdk的簽名,很是重要)
/*---------------------------------獲取js-sdk簽名   start--------------------------------*/
    /**
     * 獲取js-sdk調用權限,獲取簽名
     */
    public function getWxsdkSign(){
        $appId = $this->appid; //這裏填appid
        $appsecret = $this->appsecret; //這裏填appsecret
        //通常$url是固定的,能夠寫死,可是個人項目中地址是動態的,因此由前段傳入
        $url = I('get.url');   //獲取簽名的頁面的url地址,因爲是動態地址,因此由前段傳入
        // 獲取accesstoken
        $accessToken = $this->getAccessToken();
        if(empty($accessToken)){
            $this->ajaxReturn(['code'=>-1, 'msg'=>'accessToken未獲取到']);
        }
        // 獲取jsapi_ticket
        $jsapi_ticket = $this->_getJsapiTicket($accessToken);
        if(empty($jsapi_ticket)){
            $this->ajaxReturn(['code'=>-1, 'msg'=>'jsapi_ticket未獲取到']);
        }
        $nonceStr = $this->make_nonceStr();        //獲取隨機字符串
        $timestamp = time();
        $signature = $this->make_signature($nonceStr,$timestamp,$jsapi_ticket,$url);
        $sdkSign = array(
            'appId'     => $this->appid,      //appid
            'signature' => $signature,        //簽名
            'timestamp' => $timestamp,        //時間戳
            'nonceStr'  => $nonceStr,         //隨機字符串
        );
        $this->ajaxReturn(['code'=>0, 'data'=>$sdkSign]);
    }
    
    /**
     * 此AccessToken   與 getUserAccessToken不同,注意一下定要全局緩存,不然每日次數限制很快就GG了
     * 得到AccessToken
     */
    private function getAccessToken()
    {
        //獲取緩存(我用的是本身封裝的Memcached類,Vender引入的直接使用)
        Vendor('Memcacheds.Memcacheds');
        $memcached = new \Memcacheds();
        $access = $memcached->get_cache('access_token');
        // 緩存不存在-從新建立
        if (empty($access)) {
            // 獲取 access token
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this -> appid}&secret={$this->appsecret}";
            $accessToken = file_get_contents($url);
            $accessToken = json_decode($accessToken);
            // 保存至緩存
            $access = $accessToken->access_token;
            $memcached->set_cache('access_token', $access, 7000);
        }
        return $access;
    }
    
    /**
     * 獲取JS證實 注意一下定要全局緩存,不然每日次數限制很快就GG了
     * @param $accessToken
     */
    private function _getJsapiTicket($accessToken)
    {
        Vendor('Memcacheds.Memcacheds');
        $memcached = new \Memcacheds();
        //獲取緩存
        $ticket = $memcached->get_cache('jsapi_ticket');
        //緩存不存在-從新建立
        if (empty($ticket)) {
            // 獲取js_ticket
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" . $accessToken . "&type=jsapi";
            $jsTicket = file_get_contents($url);
            $jsTicket = json_decode($jsTicket);
            //保存至緩存
            $ticket = $jsTicket->ticket;
            $memcached->set_cache('jsapi_ticket', $ticket, 7000);
        }
        return $ticket;
    }

    //獲取隨機字符串
    public function make_nonceStr(){
        $codeSet = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        for ($i = 0; $i<16; $i++) {
            $codes[$i] = $codeSet[mt_rand(0, strlen($codeSet)-1)];
        }
        $nonceStr = implode($codes);
        return $nonceStr;
    }

    /**
     * 獲取簽名
     * @param string $nonceStr  隨機字符串
     * @param int    $timestamp 時間戳
     * @param string $jsapi_ticket 獲取的ticket憑據
     * @param string $url       獲取簽名的頁面的url 'http://*****' eg:'http://wx.alisleept.top/index.php'
     */
    function make_signature($nonceStr,$timestamp,$jsapi_ticket,$url){
        $tmpArr = array(
            'noncestr' => $nonceStr,
            'timestamp' => $timestamp,
            'jsapi_ticket' => $jsapi_ticket,
            'url' => $url
        );
        ksort($tmpArr, SORT_STRING);
        $string1 = http_build_query( $tmpArr );
        $string1 = urldecode( $string1 );
        $signature = sha1( $string1 );
        return $signature;
    }
    /*---------------------------------獲取js-sdk簽名   end--------------------------------*/

以上php部分就是徹底的異步獲取簽名的代碼,裏邊只須要注意php

  1. appidappsecret 修改成本身的
  2. 注意access_tokenjsapi_ticket的緩存
  3. 注意$url換成本身的,我這個是動態的,因此前段傳回的
相關文章
相關標籤/搜索