微信js-sdk開發獲取簽名和獲取地理位置接口示例
前言:在做微信公眾號開發時需要獲取用戶的地理位置信息,之前通過高德或者百度、騰訊等地圖的api時發現經常獲取不到,畢竟第三方的東西,后來改為采用微信內置的js-sdk中的獲取地理位置接口,在這主要記錄下簽名的獲取(麻煩點)和一個獲取地理位置的例子。
准備工作:
- 微信測試號appid和appsecret
獲取地址:微信測試賬號獲取 - 在測試賬號里先填寫接口配置信息和js接口安全域名(這個是必須的)
- 示例:頁面中需要點擊圖標獲取地理位置信息
流程如下:
點擊按鈕->觸發事件去獲取->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部分就是完全的異步獲取簽名的代碼,里邊只需要注意
- appid 和 appsecret 修改為自己的
- 注意access_token和jsapi_ticket的緩存
- 注意$url換成自己的,我這個是動態的,所以前段傳回的