微信網頁授權之地理位置獲取----微信js-sdk
阿新 • • 發佈:2019-02-05
我們通過微信瀏覽器開啟頁面時,有時會提示要獲取地理位置資訊.點選同意後,自己的地理位置資訊就會相應的顯示在頁面,同時通過資料庫的查詢,以實現以地理位置分類的邏輯業務.
本例通過thinkphp5來完成,下面介紹實現詳細步驟!
首先我們引入一個類:
需要注意的,類中獲取的api_ticket和jsapi_ticket有效期是7200秒.通過access_token來獲取。由於獲取jsapi_ticket和api_ticket的api呼叫次數非常有限,頻繁重新整理他們會導致api呼叫受限,影響自身業務,必須在自己的服務全域性快取他們.
所以以下利用了tp5的cache快取機制來儲存他們.
我這裡為了省事,直接將微信的appid和appsecret存在了配置檔案中,並在類中直接常量定義
下載好類Wxjssdk.php,我把它放在了extends的wxweb目錄下,並且名稱空間為wxweb
<?php namespace wxweb; /* 方倍工作室 http://www.fangbei.org/ CopyRight 2014 All Rights Reserved */ define('APPID', config('appid')); define('APPSECRET', config('appsecret')); class Wxjssdk { public $appid = APPID; public $appsecret = APPSECRET; //建構函式,獲取Access Token public function __construct($appid = NULL, $appsecret = NULL) { if($appid && $appsecret){ $this->appid = $appid; $this->appsecret = $appsecret; } // $res = file_get_contents(EXTEND_PATH.'/wxweb/access_token.json'); // $result = json_decode($res, true); // $this->expires_time = $result["expires_time"]; // $this->access_token = $result["access_token"]; $this->access_token = cache('access_token'); if(!cache('expires_time')){ $this->expires_time = 0; }else{ $this->expires_time = cache('expires_time'); } if (time() > ($this->expires_time + 3600)){ $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->appid."&secret=".$this->appsecret; $res = $this->http_request($url); $result = json_decode($res, true); $this->access_token = $result["access_token"]; $this->expires_time = time(); // file_put_contents(EXTEND_PATH.'/wxweb/access_token.json', '{"access_token": "'.$this->access_token.'", "expires_time": '.$this->expires_time.'}'); cache('access_token',$this->access_token); cache('expires_time',$this->expires_time); } } //生成長度16的隨機字串 public 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; } //獲得微信卡券api_ticket public function getCardApiTicket() { // $res = file_get_contents(EXTEND_PATH.'/wxweb/cardapi_ticket.json'); // $result = json_decode($res, true); // $this->cardapi_ticket = $result["cardapi_ticket"]; // $this->cardapi_expire = $result["cardapi_expire"]; $this->cardapi_ticket = cache('cardapi_ticket'); if(!cache('cardapi_expire')){ $this->cardapi_expire = 0; }else{ $this->cardapi_expire = cache('cardapi_expire'); } if (time() > ($this->cardapi_expire + 3600)){ $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card&access_token=".$this->access_token; $res = $this->http_request($url); $result = json_decode($res, true); $this->cardapi_ticket = $result["ticket"]; $this->cardapi_expire = time(); // file_put_contents(EXTEND_PATH.'/wxweb/cardapi_ticket.json', '{"cardapi_ticket": "'.$this->cardapi_ticket.'", "cardapi_expire": '.$this->cardapi_expire.'}'); cache('cardapi_ticket',$this->cardapi_ticket); cache('cardapi_expire',$this->cardapi_expire); } return $this->cardapi_ticket; } //cardSign卡券簽名 public function get_cardsign($bizObj) { //字典序排序 asort($bizObj); //URL鍵值對拼成字串 $buff = ""; foreach ($bizObj as $k => $v){ $buff .= $v; } //sha1簽名 return sha1($buff); } //獲得JS API的ticket private function getJsApiTicket() { // $res = file_get_contents(EXTEND_PATH.'/wxweb/jsapi_ticket.json'); // $result = json_decode($res, true); // $this->jsapi_ticket = $result["jsapi_ticket"]; // $this->jsapi_expire = $result["jsapi_expire"]; $this->jsapi_ticket = cache('jsapi_ticket'); if(!cache('jsapi_expire')){ $this->jsapi_expire = 0; }else{ $this->jsapi_expire = cache('jsapi_expire'); } if (time() > ($this->jsapi_expire + 3600)){ $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".$this->access_token; $res = $this->http_request($url); $result = json_decode($res, true); $this->jsapi_ticket = $result["ticket"]; $this->jsapi_expire = time(); // file_put_contents(EXTEND_PATH.'/wxweb/jsapi_ticket.json', '{"jsapi_ticket": "'.$this->jsapi_ticket.'", "jsapi_expire": '.$this->jsapi_expire.'}'); cache('jsapi_ticket',$this->jsapi_ticket); cache('jsapi_expire',$this->jsapi_expire); } return $this->jsapi_ticket; } //獲得簽名包 public function getSignPackage() { $jsapiTicket = $this->getJsApiTicket(); $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(); $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url"; $signature = sha1($string); $signPackage = array( "appId" => $this->appid, "nonceStr" => $nonceStr, "timestamp" => $timestamp, "url" => $url, "signature" => $signature, "rawString" => $string ); return $signPackage; } //HTTP請求(支援HTTP/HTTPS,支援GET/POST) protected function http_request($url, $data = null) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); $output = curl_exec($curl); curl_close($curl); return $output; } }
然後在控制器如下:
<?php
namespace app\index\controller;
use app\index\model\User;
use wxweb\Wxjssdk;
class Index
{
public function index()
{
$wxjssdk = new Wxjssdk();
$signPackage = $wxjssdk->GetSignPackage();
return view('',['res'=>$signPackage]);
}
}
$signPackage就是微信js-sdk的config介面注入許可權驗證配資訊
wx.config({
debug: true, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
appId: '', // 必填,公眾號的唯一標識
timestamp: , // 必填,生成簽名的時間戳
nonceStr: '', // 必填,生成簽名的隨機串
signature: '',// 必填,簽名,見附錄1
jsApiList: [] // 必填,需要使用的JS介面列表,所有JS介面列表見附錄2
});
然後在檢視頁面,首先引入微信js,必須項
<script src="https://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>
然後寫js檔案如下:
<script>
//微信config配置資訊注入
wx.config({
debug: false,
appId: '{$res.appId}',
timestamp: '{$res.timestamp}',
nonceStr: '{$res.nonceStr}',
signature: '{$res.signature}',
jsApiList: [
'checkJsApi',
'openLocation',
'getLocation',
]
});
wx.checkJsApi({
jsApiList: [
'getLocation'
],
success: function (res) {
// alert(JSON.stringify(res));
// alert(JSON.stringify(res.checkResult.getLocation));
if (res.checkResult.getLocation == false) {
alert('你的微信版本太低,不支援微信JS介面,請升級到最新的微信版本!');
return;
}
}
});
wx.ready(function () {
//自動執行的
wx.checkJsApi({
jsApiList: [
'getLocation',
],
success: function (res) {
}
});
//如果不支援則不會執行
wx.getLocation({
success: function (res) {
// 使用者同意後,將獲取的位置基礎資訊(經度和緯度資訊)請求到控制器
//控制器中利用百度的api請求返回地理位置資訊資料
$.get("/index/user/map",{ 'res':res },function(data){
if(data.status == 0){
$('#wx_location').html(data.result.addressComponent.city);
}else{
$('#wx_location').html('未知城市');
}
});
},
cancel: function (res) {
alert('使用者拒絕授權獲取地理位置');
}
});
});
wx.error(function (res) {
alert(res.errMsg);
});
</script>
ajax請求的控制中如下:
//獲取使用者地理位置資訊
public function map()
{
$ak = '8gcWsC7GGjpiGsAN7hfEyXNPHr7wDz27';
$data = input('get.res/a');
$lat = $data['latitude'];
$lng = $data['longitude'];
$url = "http://api.map.baidu.com/geocoder/v2/?ak={$ak}&location={$lat},{$lng}&output=json&coordtype=gcj02ll";
$res = file_get_contents($url);
//百度地圖返回的並不是json,而是字串,需要自己在做一個處理
$res = json_decode($res,true);
return json($res);
}