本来是使用easywechat的函数直接生成JS配置的,可是不知为何老是提示签名是非法的,无奈只有自己写一个操作类来获取签名了…..
但是不得不说easywechat是真的好用,特别是支付,简直不能更简单了,强行安利一波:https://www.easywechat.com/
正文内容
一些微信文档的细节:
1.字典排序的四个参数是按参数名排序,不是按值排序
2.加密的url是调用微信JS-SDK页面的url且包含参数部分
特别说明
实际的调用中强烈建议要缓存获取的access_token,因为获取access_token的接口微信是做了调用限制的,在下面的代码中给出提示的。
操作类
<?php
/**
* Created by PhpStorm.
* User: zheng
* Date: 2018/2/8
* Time: 11:03
*/
class WxJsConfig
{
static $count=5; //用于控制重复调用微信接口的次数,确保一定能调取成功
private $wxAppId = 'XXXXXXXXXXXXXXX'; //公众号的appid
private $wxAppSecret = 'XXXXXXXXXXXXXXXXXX'; //公众号的app_secret
/** 发送curl请求
* @param $url
* @param string $method
* @param array $requestData
* @return mixed
*/
public function curlRequest($url,$method='get',$requestData=[])
{
try {
$curlHandle = curl_init();
curl_setopt($curlHandle, CURLOPT_URL, $url);
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
if ($method == 'post') {
curl_setopt($curlHandle, CURLOPT_POST, true);
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $requestData);
}
$response = curl_exec($curlHandle);
curl_close($curlHandle);
return $response;
} catch (\Exception $e) {
exit('请求失败:' . $e->getMessage());
}
}
public function getJsConfig()
{
try{
//此URL是需要调用微信JS-SDK页面的url,由前端页面传过来的且包含请求参数部分
$url = $_GET['url'];
if(!$url){
exit('缺少必要参数');
}
$acc_url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='
.$this->wxAppId .'&secret='.$this->wxAppSecret;
//TODO 实际开发中获取access_token要进行缓存,执行curlRequest前判断是否存在缓存,不存在才进行调用,建议缓存7200秒
$accToken = json_decode($this->curlRequest($acc_url),true) ;
if(!isset($accToken['access_token'])){
exit($accToken['errmsg']);
}
$accToken = $accToken['access_token'];
$ticket_url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$accToken.'&type=jsapi';
$ticket = json_decode($this->curlRequest($ticket_url),true);
if(!isset($ticket['ticket'])){
return exit('微信服务器异常');
}
$ticket = $ticket['ticket'];
//生成随机字符串
$randStr = '';
$str = $ticket.$accToken;
$strLength = strlen($str);
for ($i=0;$i<15;$i++){
if($i%3==0){
$randStr.=rand();
}
$randStr.=$str[rand(0,$strLength)];
}
$randStr.=rand();
$time = time();
$tempSort = [
'noncestr'=>$randStr,
'jsapi_ticket'=>$ticket,
'timestamp'=>$time,
'url'=>$url
];
$keyStr = array_flip($tempSort);
//加密参数是按参数名排序,不是按值排序
ksort($tempSort,SORT_STRING);
$params = $tempSort;
$shaString = '';
foreach ($params as $key=>$val){
if($shaString==''){
$shaString = $keyStr[$val].'='.$val;
}else{
$shaString.='&'.$keyStr[$val].'='.$val;
}
}
$signature = sha1($shaString);
$jsConfig = [
'appId'=>$this->wxAppId,
'timestamp'=>$time,
'nonceStr'=>$randStr,
'signature'=>$signature,
//此处填写你需要调用的JS列表,比如这里是调用的微信获取地理位置
'jsApiList'=>['checkJsApi', 'openLocation','getLocation'],
'test'=>[
'ticket'=>$ticket,
'url'=>$url
]
];
return json_encode($jsConfig,true);
}catch (\Exception $e){
if(self::$count>0){ //重复调用,尽量请求成功
self::$count-=1;
$this->getJsConfig();
}else{
exit('微信服务器异常');
}
}
}
}
//测试代码
$obj = new WxJsConfig();
$config = $obj->getJsConfig();
var_dump(json_decode($config,true));
比如我这里是调用的请求地理位置的接口,获取到JS配置就可以去调用了。
最后的返回值还把,加密需要的参数返回了,字段名是test,根据这个test里面的参数就可以使用 微信的调试工具 检查签名是否正确
测试代码返回示例:
JS-SDK调取微信地理位置
注意:记得修改代码TODO部分,缓存access_token