博客
电影
宝箱
友链
关于
<
JavaScript排序算法及性能比较
sass之scss心得
>
PHP实现微信JS-SDK权限验证
作者:
Cifer
类别: 技术
时间:2017-02-07 00:24:24
字数:7908
版权所有,未经允许,请勿转载,谢谢合作~
#### 前言 之前在公众号中使用一些微信JS-SDK提供的功能,如录音、个性分享、上传、下载等功能,而这些都需要公众号的权限验证,根据以前[西法](http://www.boatsky.com "太空船博客" rel="nofollow")在网上搜索PHP相关实例后,发现相关资料不太多,觉得把以前写的东西提出一个demo是有意义的 #### 步骤 1.设置安全域名。在公众号平台里,公众号设置->功能设置->JS接口安全域名 里设置你的安全域名,如我在本站获取,则填写www.boatsky.com。 (最多设置3个,同时每月仅可修改3次) 2. 获取access_token。access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。可使用AppID(应用ID)与AppSecret(应用密钥)获取微信access_token。 接口:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET (官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183) (在线测试工具:https://mp.weixin.qq.com/debug/cgi-bin/apiinfo) access_token有效期2小时,调用频次最大2000次(测试号200次) 3.获取jsapi_ticket。jsapi_ticket是公众号用于调用微信JS接口的临时票据。使用access_token获取jsapi_ticket。 接口:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi (在线测试工具:) jsapi_ticket有效期2小时。官方未说明调用次数,只说“调用次数非常有限”,应该也是2000次。 4.生成签名算法。 签名算法由以下4个元素生成,按照字段名的ASCII 码从小到大排序,依次: noncestr=随机字符串 jsapi_ticket=上述jsapi_ticket timestamp=时间戳 url=调用JS-SDK页面的URL,URL参数也需带,如有中文之类特殊字符,需encodeURIComponent 4个元素得到一个类似这样的string jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value 再使用sha1加密,得到签名signature。 (在线验证:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign) 5.引入微信JS文件。 http: http://res.wx.qq.com/open/js/jweixin-1.0.0.js https: https://res.wx.qq.com/open/js/jweixin-1.0.0.js 摇一摇周边功能: jweixin-1.1.0.js 6.通过config接口注入权限验证配置。 ```javascript wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); ``` #### 实例 ```php <?php namespace App\Http\Controllers\common; use App\Http\Controllers\Controller; class Wx extends Controller { function __construct() { parent::__construct(); $this->cacheDir = dirname(__FILE__).'/cache'; $this->fileDir = $this->cacheDir.'/wx.txt'; //第三方用户唯一凭证 $this->appId = '你的appId'; //access_token,2小时有效期 $this->accessToken = null; //ticket,JS调用认证,2小时有效期 $this->ticket = null; //随机字符串 $this->noncestr = null; //时间戳 $this->timestamp = null; //签名 $this->signature = null; //希望调用的url $this->url = null; //保存这个长str $this->ticketStr = null; } //得到微信JS-SDK签名 public function getWxJsapiKey(){ $this->url = $_GET['url']; $callback = $_GET['callback']; if($this->url){ $this->cache_init(); if(!$this->cache_file_timeout($this->fileDir)){ $wxkey = $this->cache_read($this->fileDir); if($wxkey){ $resp = array( 'code' => 0, 'msg' => '获取微信JS-SDK签名成功', 'wxkey' => json_decode($wxkey) ); } else { $resp = $this->getWxKey(); } } else { $resp = $this->getWxKey(); } } else { $resp = array( 'code' => 405, 'msg' => '获取微信JS-SDK签名失败:当前页面URL未传入', ); } return response($callback . '(' . json_encode($resp) . ')'); } //重新获取微信签名 private function getWxKey(){ $this->timestamp = time(); $this->noncestr = $this->getNoncestr(); $this->accessToken = $this->getAccessToken(); $ticketResp = $this->getTicket($this->accessToken); if($ticketResp->errcode == 0){ $this->ticket = $ticketResp->ticket; $this->signature = $this->getSignature(); $saveData = array( 'appId' => $this->appId, 'timestamp' => $this->timestamp, 'nonceStr' => $this->noncestr, 'signature' => $this->signature, 'accessToken' => $this->accessToken, 'ticket' => $this->ticket, 'url' => $this->url, 'ticketStr' => $this->ticketStr ); $writeData = $this->cache_write($this->fileDir, json_encode($saveData)); if($writeData){ $resp = array( 'code' => 0, 'msg' => '获取微信JS-SDK签名成功', 'wxkey' => json_decode($writeData) ); } else { $resp = array( 'code' => 404, 'msg' => '获取微信JS-SDK获取失败:缓存写入或读取失败', 'wxkey' => json_decode($writeData) ); } } else { $resp = array( 'code' => 403, 'msg' => '微信ticket获取失败:'.$ticketResp->errmsg, ); } return response()->json($resp); } //生成签名的返回值 private function getSignature(){ $strs = 'jsapi_ticket='.$this->ticket.'&noncestr='.$this->noncestr.'×tamp='.$this->timestamp.'&url='.$this->url; $this->ticketStr = $strs; $signature = sha1($strs); return $signature; } //获得access_token private function getAccessToken(){ //获取access_token填写client_credential $grant_type = 'client_credential'; //第三方用户唯一凭证密钥,即appsecret $secret = '你的appsecret'; //微信获取access_token $accessTokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type='.$grant_type.'&appid='.$this->appId.'&secret='.$secret; $accessTokenResponse = json_decode(file_get_contents($accessTokenUrl)); $accessToken = $accessTokenResponse->access_token; return $accessToken; } //获取ticket返回结果 private function getTicket($accessToken){ $jsapiTicketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$accessToken.'&type=jsapi'; $res = json_decode(file_get_contents($jsapiTicketUrl)); return $res; } //得到一个随机字符串 private function getNoncestr($len = 16){ $chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; $charsLen = strlen($chars); $str = ''; for($i = 0;$i < $len;$i++){ $str.= substr($chars,mt_rand(0,$charsLen),1); } return $str; } //文件初始化 public function cache_init(){ //没有该目录,则在controller层创建一个cache目录 if(!is_dir($this->cacheDir)){ mkdir($this->cacheDir,0777,true); //受Linux系统的 umask限制了,Linux的umask默认值是0022,所以php 的 mkdir 函数只能建立出755权限的文件夹出来,此处重新更改 chmod($this->cacheDir,0777); } $this->cache_create_file($this->fileDir); } //创建文件 private function cache_create_file($fileDir){ if(!file_exists($fileDir)){ //w打开文件为写。删除文件内容或创建新文件,如果它不存在。文件指针在文件开头开始。 $file = fopen($fileDir,'w'); chmod($fileDir,0777); fclose($file); } } //文件是否过时 private function cache_file_timeout($fileDir){ $flag = false; //如果文件过期,默认7200 if(time() - filemtime($fileDir) > 6200){ $flag = true; } return $flag; } //读取文件 private function cache_read($fileDir){ //r表示只读 $file = fopen($fileDir,'r'); $fileContent = fread($file,1000);//filesize($fileDir) return $fileContent; } //文件内容写入,前者是文件名,后者是需要保存的字段 private function cache_write($fileDir, $saveStr){ //w打开文件为写。删除文件内容或创建新文件,如果它不存在。文件指针在文件开头开始。 $file = fopen($fileDir,'w'); fwrite($file, $saveStr); fclose($file); $file = fopen($fileDir,'r'); $fileContent = fread($file,1000); return $fileContent; } } ``` 注:因access_token与jsapi_ticket都是2小时有效期,接口调用次数有限,所以需要把它们保存在缓存服务器(如redis),在每次到期前更新该缓存。此处demo在CI框架的Controller里开辟了一个cache文件夹,里面的wx.txt作为该缓存文件,该法不推荐使用。同时getWxJsapiKey因一些原因使用了JSONP,推荐用CORS。
如果觉得有帮忙,您可以在本页底部留言。
相关推荐:
从youtube观看记录分析时长
Webpack深入浅出plugin
Webpack自动更新php静态资源文件名hash
Webpack构建流程之源码分析
Webpack基于scss生成css独立文件
Webpack深入浅出loader
移动端浏览器真机调试的几种方法
接入台湾超商门店地址选择
ember入门教程
Ember之Handlebars模板引擎
Mac高频快捷键之前端篇
简述浏览器缓存之cookie
浏览器打开页面的过程中发生了什么
Git命令简化笔记
SQL快速运用指南
如何用正确的姿势写HTML
正则表达式实例解析
……
更多
<
JavaScript排序算法及性能比较
sass之scss心得
>
全部留言
我要留言
内容:
网名:
邮箱:
个人网站:
发表
全部留言