提示签名错误,经排查,发现是组织签名时,url错误.
因为是用php后端获取jsapi Ticket,直接访问的url为
http://我的域名/index.php/index/jssdk/getSignPackage
而我的前端并不是用上面的网址直接访问的, 而是在下面地址中,
http://我的域名/ddz/
通过ajax访问http://我的域名/index.php/index/jssdk/getSignPackage
所以,对于微信来说,他自动签名时,用的真实url是当前url,即http://我的域名/ddz/这个
所以,后端处理时
public function getSignPackage()
{
$jsapiTicket = $this->getJsApiTicket();
//$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
//上面这个url不对.需要统一换成下面的url,才会签名正确.
$url = request()->param('url');//从前端get时,传具体的网址给后端才行
$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);
print_r(json_encode($signPackage));exit;
}
附thinkphp5完整代码,控制器目录位置为application\index\controller\jssdk
<?php
namespace app\index\controller;
class Jssdk extends Base
{
protected $appId='wx52c4165a19e681ac';
protected $appSecret='b6ce92390db4d20d93a13cd925e1ba0a';
//ajax专用
public function getSignPackage()
{
$jsapiTicket = $this->getJsApiTicket();
$url = request()->param('url');//从前端get时,传具体的网址给后端才行
$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);
print_r(json_encode($signPackage));exit;
}
//前端直接访问.专用比如这样 game.cn/index.php/index/jssdk/index
public function index()
{
$jsapiTicket = $this->getJsApiTicket();
$url = "http://$_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);
//print_r(json_encode($signPackage));exit;
$this->assign('signPackage', $signPackage);
return $this->fetch();
}
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;
}
function getJsApiTicket(){
// jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
$path = __DIR__ .'/../../../runtime/jsapi_ticket.json';
// print_r(APP_PATH);exit;
//print_r(__DIR__);exit;
///home/wwwroot/game_alixinyuxaun_cn/public_html/application/index/controller
$data = json_decode(file_get_contents($path));
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;
//F('jsapi_ticket',json_encode($data));
$fp = fopen($path, "w");
fwrite($fp, json_encode($data));
fclose($fp);
}
}else{
$ticket=$data->jsapi_ticket;
}
return $ticket;
}
// 获取token
function getAccessToken(){
// access_token 应该全局存储与更新,以下代码以写入到文件中做示例
$path = __DIR__ .'/../../../runtime/access_token.json';
$data = json_decode(file_get_contents($path));
if ($data->expire_time < time()) {
$url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
$json=$this->httpGet($url);
$res = json_decode($json,true);
//print_r($res);exit;
$access_token = $res['access_token'];
if ($access_token) {
$data->expire_time = time() + 6780;//7200->6780 服务器慢7分钟没问题,注意缓存同步的时间。
$data->access_token = $access_token;
$fp = fopen($path, "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;
}
}
?>
thinkphp 模板位置为application\index\view\jssdk\index.html
这个模板不是ajax用的.是直接访问时测试用的
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>游戏中心</title>
</head>
<body>
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script>
wx.config({
debug: true,
appId:"{$signPackage.appId}",
timestamp: "{$signPackage.timestamp}",
nonceStr: "{$signPackage.nonceStr}",
signature: "{$signPackage.signature}",
jsApiList: [
// 所有要调用的 API 都要加到这个列表中
'checkJsApi',
'openLocation',
'getLocation'
]
});
wx.ready(function () {
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.getLocation({
success: function (res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以米/每秒计
var accuracy = res.accuracy; // 位置精度
alert("纬度 "+latitude +"经度,"+longitude+" 精度 "+accuracy);
console.log("纬度 "+latitude +"经度,"+longitude+" 精度 "+accuracy);
},
cancel: function (res) {
alert('用户拒绝授权获取地理位置');
}
});
});
</script>
</body>
</html>
下面是ajax版测试用的.
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script>
function loginonclick(){
var url2=window.location.href;//当前网址, 传给后端,签名专用
url2=encodeURIComponent(url2);//转码
var actionUrl = "http://game.alixinyuxaun.cn/index.php/index/jssdk/getSignPackage/?url="+url2;
var xhr = new XMLHttpRequest();
xhr.open("get",actionUrl,true);
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4) {
if (xhr.status>=200 && xhr.status<300) {
alert(xhr.responseText);
var data = JSON.parse(xhr.responseText);
wx.config({
debug: true,
appId:data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: [
// 所有要调用的 API 都要加到这个列表中
'checkJsApi',
'openLocation',
'getLocation'
]
});
//所有代码放在ready中,表示网页加载时,自动调用位置信息,而不需要客户点击触发.微信端专用
wx.ready(function () {
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.getLocation({
success: function (res) {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以米/每秒计
var accuracy = res.accuracy; // 位置精度
alert("纬度 "+latitude +"经度,"+longitude+" 精度 "+accuracy);
console.log("纬度 "+latitude +"经度,"+longitude+" 精度 "+accuracy);
},
cancel: function (res) {
alert('用户拒绝授权获取地理位置');
}
});
});
};
};
}
}
loginonclick();
</script>