微信接口开发之高级篇系列【微信权限封装类WechatAuth】
ThinkPHP框架目录结构:
<?php
/**
* Created by PhpStorm.
* User: Tinywan
* Date: 2016/9/11
* Time: 9:55
*/ namespace Org\Util; class WechatAuth
{ /* 消息类型常量 */
const MSG_TYPE_TEXT = 'text';
const MSG_TYPE_IMAGE = 'image';
const MSG_TYPE_VOICE = 'voice';
const MSG_TYPE_VIDEO = 'video';
const MSG_TYPE_SHORTVIDEO = 'shortvideo';
const MSG_TYPE_LOCATION = 'location';
const MSG_TYPE_LINK = 'link';
const MSG_TYPE_MUSIC = 'music';
const MSG_TYPE_NEWS = 'news';
const MSG_TYPE_EVENT = 'event'; /* 二维码类型常量 */
const QR_SCENE = 'QR_SCENE';
const QR_LIMIT_SCENE = 'QR_LIMIT_SCENE'; /**
* 微信开发者申请的appID
* @var string
*/
private $appId = ''; /**
* 微信开发者申请的appSecret
* @var string
*/
private $appSecret = ''; /**
* 获取到的access_token
* @var string
*/
private $accessToken = ''; /**
* 微信api根路径
* @var string
*/
private $apiURL = 'https://api.weixin.qq.com/cgi-bin'; /**
* 微信二维码根路径
* @var string
*/
private $qrcodeURL = 'https://mp.weixin.qq.com/cgi-bin'; //授权地址
private $requestCodeURL = 'https://open.weixin.qq.com/connect/oauth2/authorize'; private $oauthApiURL = 'https://api.weixin.qq.com/sns'; /**
* 构造方法,调用微信高级接口时实例化SDK
* @param string $appid 微信appid
* @param string $secret 微信appsecret
* @param string $token 获取到的access_token
*/
public function __construct($appid, $secret, $token = null)
{
if ($appid && $secret) {
$this->appId = $appid;
$this->appSecret = $secret;
if (!empty($token)) $this->accessToken = $token;
} else {
throw new \Exception('缺少参数 APP_ID 和 APP_SECRET!');
}
} // 是为了拼接成一URL地址,什么地址,拼接一个
public function getRequestCodeURL($redirect_uri, $state = null, $scope = 'snsapi_userinfo')
{ $query = array(
'appid' => $this->appId,
'redirect_uri' => $redirect_uri,
'response_type' => 'code',
'scope' => $scope,
); if (!is_null($state) && preg_match('/[a-zA-Z0-9]+/', $state)) $query['state'] = $state; //生成 URL-encode 之后的请求字符串 :foo=bar&baz=boom&cow=milk&php=hypertext+pro
$query = http_build_query($query);
return "{$this->requestCodeURL}?{$query}#wechat_redirect";
} /**
* 获取access_token,用于后续接口访问
* @return array access_token信息,包含 token 和有效期
*/
public function getAccessToken($type = 'client', $code = null)
{
$param = array(
'appid' => $this->appId,
'secret' => $this->appSecret
); switch ($type) {
case 'client':
$param['grant_type'] = 'client_credential';
$url = "{$this->apiURL}/token";
break; case 'code':
$param['code'] = $code;
$param['grant_type'] = 'authorization_code';
$url = "{$this->oauthApiURL}/oauth2/access_token";
break; default:
throw new \Exception('不支持的grant_type类型!');
break;
} $token = self::http($url, $param);
$token = json_decode($token, true); if (is_array($token)) {
if (isset($token['errcode'])) {
throw new \Exception($token['errmsg']);
} else {
$this->accessToken = $token['access_token'];
return $token;
}
} else {
throw new \Exception('获取微信access_token失败!');
}
} /**
* 获取授权用户信息
* @param string $openid 用户的OpenID
* @param string $lang 指定的语言
* @return array 用户信息数据,具体参见微信文档
*/
public function getUserInfo($openid, $lang = 'zh_CN')
{
$query = array(
'access_token' => $this->accessToken,
'openid' => $openid,
'lang' => $lang,
); $info = self::http("{$this->oauthApiURL}/userinfo", $query);
return json_decode($info, true);
} /**
* 上传零时媒体资源
* @param string $filename 媒体资源本地路径
* @param string $type 媒体资源类型,具体请参考微信开发手册
*/
public function mediaUpload($filename, $type)
{
$filename = realpath($filename);
if (!$filename) throw new \Exception('资源路径错误!'); $data = array(
'type' => $type,
'media' => "@{$filename}"
); return $this->api('media/upload', $data, 'POST', '', false);
} /**
* 上传永久媒体资源
* @param string $filename 媒体资源本地路径
* @param string $type 媒体资源类型,具体请参考微信开发手册
* @param string $description 资源描述,仅资源类型为 video 时有效
*/
public function materialAddMaterial($filename, $type, $description = '')
{
$filename = realpath($filename);
if (!$filename) throw new \Exception('资源路径错误!'); $data = array(
'type' => $type,
'media' => "@{$filename}",
); if ($type == 'video') {
if (is_array($description)) {
//保护中文,微信api不支持中文转义的json结构
array_walk_recursive($description, function (&$value) {
$value = urlencode($value);
});
$description = urldecode(json_encode($description));
}
$data['description'] = $description;
}
return $this->api('material/add_material', $data, 'POST', '', false);
} /**
* 获取媒体资源下载地址
* 注意:视频资源不允许下载
* @param string $media_id 媒体资源id
* @return string 媒体资源下载地址
*/
public function mediaGet($media_id)
{
$param = array(
'access_token' => $this->accessToken,
'media_id' => $media_id
); $url = "{$this->apiURL}/media/get?";
return $url . http_build_query($param);
} /**
* 给指定用户推送信息
* 注意:微信规则只允许给在48小时内给公众平台发送过消息的用户推送信息
* @param string $openid 用户的openid
* @param array $content 发送的数据,不同类型的数据结构可能不同
* @param string $type 推送消息类型
*/
public function messageCustomSend($openid, $content, $type = self::MSG_TYPE_TEXT)
{ //基础数据
$data = array(
'touser' => $openid,
'msgtype' => $type,
); //根据类型附加额外数据
$data[$type] = call_user_func(array(self, $type), $content); return $this->api('message/custom/send', $data);
} /**
* 发送文本消息
* @param string $openid 用户的openid
* @param string $text 发送的文字
*/
public function sendText($openid, $text)
{
return $this->messageCustomSend($openid, $text, self::MSG_TYPE_TEXT);
} /**
* 发送图片消息
* @param string $openid 用户的openid
* @param string $media 图片ID
*/
public function sendImage($openid, $media)
{
return $this->messageCustomSend($openid, $media, self::MSG_TYPE_IMAGE);
} /**
* 发送语音消息
* @param string $openid 用户的openid
* @param string $media 音频ID
*/
public function sendVoice($openid, $media)
{
return $this->messageCustomSend($openid, $media, self::MSG_TYPE_VOICE);
} /**
* 发送视频消息
* @param string $openid 用户的openid
* @param string $media_id 视频ID
* @param string $title 视频标题
* @param string $discription 视频描述
*/
public function sendVideo()
{
$video = func_get_args();
$openid = array_shift($video);
return $this->messageCustomSend($openid, $video, self::MSG_TYPE_VIDEO);
} /**
* 发送音乐消息
* @param string $openid 用户的openid
* @param string $title 音乐标题
* @param string $discription 音乐描述
* @param string $musicurl 音乐链接
* @param string $hqmusicurl 高品质音乐链接
* @param string $thumb_media_id 缩略图ID
*/
public function sendMusic()
{
$music = func_get_args();
$openid = array_shift($music);
return $this->messageCustomSend($openid, $music, self::MSG_TYPE_MUSIC);
} /**
* 发送图文消息
* @param string $openid 用户的openid
* @param array $news 图文内容 [标题,描述,URL,缩略图]
* @param array $news1 图文内容 [标题,描述,URL,缩略图]
* @param array $news2 图文内容 [标题,描述,URL,缩略图]
* ... ...
* @param array $news9 图文内容 [标题,描述,URL,缩略图]
*/
public function sendNews()
{
$news = func_get_args();
$openid = array_shift($news);
return $this->messageCustomSend($openid, $news, self::MSG_TYPE_NEWS);
} /**
* 发送一条图文消息
* @param string $openid 用户的openid
* @param string $title 文章标题
* @param string $discription 文章简介
* @param string $url 文章连接
* @param string $picurl 文章缩略图
*/
public function sendNewsOnce()
{
$news = func_get_args();
$openid = array_shift($news);
$news = array($news);
return $this->messageCustomSend($openid, $news, self::MSG_TYPE_NEWS);
} /**
* 创建用户组
* @param string $name 组名称
*/
public function groupsCreate($name)
{
$data = array('group' => array('name' => $name));
return $this->api('groups/create', $data);
} /**
* 查询所有分组
* @return array 分组列表
*/
public function groupsGet()
{
return $this->api('groups/get', '', 'GET');
} /**
* 查询用户所在的分组
* @param string $openid 用户的OpenID
* @return number 分组ID
*/
public function groupsGetid($openid)
{
$data = array('openid' => $openid);
return $this->api('groups/getid', $data);
} /**
* 修改分组
* @param number $id 分组ID
* @param string $name 分组名称
* @return array 修改成功或失败信息
*/
public function groupsUpdate($id, $name)
{
$data = array('id' => $id, 'name' => $name);
return $this->api('groups/update', $data);
} /**
* 移动用户分组
* @param string $openid 用户的OpenID
* @param number $to_groupid 要移动到的分组ID
* @return array 移动成功或失败信息
*/
public function groupsMemberUpdate($openid, $to_groupid)
{
$data = array('openid' => $openid, 'to_groupid' => $to_groupid); return $this->api('groups/member/update', $data);
} /**
* 用户设备注名
* @param string $openid 用户的OpenID
* @param string $remark 设备注名
* @return array 执行成功失败信息
*/
public function userInfoUpdateremark($openid, $remark)
{
$data = array('openid' => $openid, 'remark' => $remark); return $this->api('user/info/updateremark', $data);
} /**
* 获取指定用户的详细信息
* @param string $openid 用户的openid
* @param string $lang 需要获取数据的语言
*/
public function userInfo($openid, $lang = 'zh_CN')
{
$param = array('openid' => $openid, 'lang' => $lang);
return $this->api('user/info', '', 'GET', $param);
} /**
* 获取关注者列表
* @param string $next_openid 下一个openid,在用户数大于10000时有效
* @return array 用户列表
*/
public function userGet($next_openid = '')
{
$param = array('next_openid' => $next_openid);
return $this->api('user/get', '', 'GET', $param);
} /**
* 创建自定义菜单
* @param array $button 符合规则的菜单数组,规则参见微信手册
*/
public function menuCreate($button)
{
$data = array('button' => $button);
return $this->api('menu/create', $data);
} /**
* 获取所有的自定义菜单
* @return array 自定义菜单数组
*/
public function menuGet()
{
return $this->api('menu/get', '', 'GET');
} /**
* 删除自定义菜单
*/
public function menuDelete()
{
return $this->api('menu/delete', '', 'GET');
} /**
* 创建二维码,可创建指定有效期的二维码和永久二维码
* @param integer $scene_id 二维码参数
* @param integer $expire_seconds 二维码有效期,0-永久有效
*/
public function qrcodeCreate($scene_id, $expire_seconds = 0)
{
$data = array(); if (is_numeric($expire_seconds) && $expire_seconds > 0) {
$data['expire_seconds'] = $expire_seconds;
$data['action_name'] = self::QR_SCENE;
} else {
$data['action_name'] = self::QR_LIMIT_SCENE;
} $data['action_info']['scene']['scene_id'] = $scene_id;
return $this->api('qrcode/create', $data);
} /**
* 根据ticket获取二维码URL
* @param string $ticket 通过 qrcodeCreate接口获取到的ticket
* @return string 二维码URL
*/
public function showqrcode($ticket)
{
return "{$this->qrcodeURL}/showqrcode?ticket={$ticket}";
} /**
* 长链接转短链接
* @param string $long_url 长链接
* @return string 短链接
*/
public function shorturl($long_url)
{
$data = array(
'action' => 'long2short',
'long_url' => $long_url
); return $this->api('shorturl', $data);
} /**
* 调用微信api获取响应数据
* @param string $name API名称
* @param string $data POST请求数据
* @param string $method 请求方式
* @param string $param GET请求参数
* @return array api返回结果
*/
protected function api($name, $data = '', $method = 'POST', $param = '', $json = true)
{
$params = array('access_token' => $this->accessToken); if (!empty($param) && is_array($param)) {
$params = array_merge($params, $param);
} $url = "{$this->apiURL}/{$name}";
if ($json && !empty($data)) {
//保护中文,微信api不支持中文转义的json结构
array_walk_recursive($data, function (&$value) {
$value = urlencode($value);
});
$data = urldecode(json_encode($data));
} $data = self::http($url, $params, $data, $method); return json_decode($data, true);
} /**
* 发送HTTP请求方法,目前只支持CURL发送请求
* @param string $url 请求URL
* @param array $param GET参数数组
* @param array $data POST的数据,GET请求时该参数无效
* @param string $method 请求方法GET/POST
* @return array 响应数据
*/
protected static function http($url, $param, $data = '', $method = 'GET')
{
$opts = array(
CURLOPT_TIMEOUT => 30,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
); /* 根据请求类型设置特定参数 */
$opts[CURLOPT_URL] = $url . '?' . http_build_query($param); if (strtoupper($method) == 'POST') {
$opts[CURLOPT_POST] = 1;
$opts[CURLOPT_POSTFIELDS] = $data; if (is_string($data)) { //发送JSON数据
$opts[CURLOPT_HTTPHEADER] = array(
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($data),
);
}
} /* 初始化并执行curl请求 */
$ch = curl_init();
curl_setopt_array($ch, $opts);
$data = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch); //发生错误,抛出异常
if ($error) throw new \Exception('请求发生错误:' . $error); return $data;
} /**
* 构造文本信息
* @param string $content 要回复的文本
*/
private static function text($content)
{
$data['content'] = $content;
return $data;
} /**
* 构造图片信息
* @param integer $media 图片ID
*/
private static function image($media)
{
$data['media_id'] = $media;
return $data;
} /**
* 构造音频信息
* @param integer $media 语音ID
*/
private static function voice($media)
{
$data['media_id'] = $media;
return $data;
} /**
* 构造视频信息
* @param array $video 要回复的视频 [视频ID,标题,说明]
*/
private static function video($video)
{
$data = array();
list(
$data['media_id'],
$data['title'],
$data['description'],
) = $video; return $data;
} /**
* 构造音乐信息
* @param array $music 要回复的音乐[标题,说明,链接,高品质链接,缩略图ID]
*/
private static function music($music)
{
$data = array();
list(
$data['title'],
$data['description'],
$data['musicurl'],
$data['hqmusicurl'],
$data['thumb_media_id'],
) = $music; return $data;
} /**
* 构造图文信息
* @param array $news 要回复的图文内容
* [
* 0 => 第一条图文信息[标题,说明,图片链接,全文连接],
* 1 => 第二条图文信息[标题,说明,图片链接,全文连接],
* 2 => 第三条图文信息[标题,说明,图片链接,全文连接],
* ]
*/
private static function news($news)
{
$articles = array();
foreach ($news as $key => $value) {
list(
$articles[$key]['title'],
$articles[$key]['description'],
$articles[$key]['url'],
$articles[$key]['picurl']
) = $value; if ($key >= 9) break; //最多只允许10条图文信息
} $data['articles'] = $articles;
return $data;
} }
微信接口开发之高级篇系列【微信权限封装类WechatAuth】的更多相关文章
- 微信接口开发之高级篇系列【微信JS-SDK】
PHP微信公众平台开发高级篇—微信JS-SDK 第一步.绑定域名: 第二步.引入JS文件: 第三部.通过Config接口注入权限验证配置 第四部.通过Read接口处理成功验证 第五部.通过Error接 ...
- C#.NET微信公众账号接口开发系列文章整理--微信接口开发目录,方便需要的博友查询
前言: 涉及微信接口开发比较早也做的挺多的,有时间的时候整理了开发过程中一些思路案例,供刚学习微信开发的朋友参考.其实微信接口开发还是比较简单的,但是由于调试比较麻烦,加上微信偶尔也会给开发者挖坑,并 ...
- C#微信公众号接口开发实例-高级接口-申请带参数的二维码
最近公司涉及到微信绑定用户,做了高级接口-申请带参数的二维码,总结了下微信开发接口.微信接口开发都是除了消息用的xml 回复基本上都是用json的形式传递信息(post/get),开发的方法基本都是一 ...
- PHP九大接口视频教程( 支付宝,QQ,短信接口,微信接口开发, 支付宝即时到账接口开发三级分销全套)
PHP九大接口视频教程( 支付宝,QQ,短信接口,微信接口开发, 支付宝即时到账接口开发三级分销全套) 需要的联系我:QQ: 1844912514 PHP九大接口视频教程( 支付宝,QQ,短信接口 ...
- java 微信自定义菜单 java微信接口开发 公众平台 SSM redis shiro 多数据源
A 调用摄像头拍照,自定义裁剪编辑头像,头像图片色度调节B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 ,0个代码不用写,生成 ...
- 微信接口开发1--向微信发送请求--获取access_token
//随便放置一个php文件在服务器上.执行该方法--调用模拟get提交---到微信-->获得微信返回的access_token 不建议自己编写模拟get提交方法. 建议直接导入微信框架LaneW ...
- 【微信Java开发 --番外篇】错误解析
虽然在微信开发过程中,会有微信公众平台开发者文档中的<全局返回码>作为错误的参考对比:但是依旧的,会觉得有时候的问题莫名其妙.[注:本人使用weixin-java-tools进行开发] 下 ...
- dom4j微信接口开发
新建一个web项目,我用的是eclipse和tomcat7.0 ,外网环境用的nat123 先建立一个实体bean:TextMessage /** * xml基本对象 * @author xiaohu ...
- Spring+SpringMVC+MyBatis深入学习及搭建(十六)——SpringMVC注解开发(高级篇)
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7085268.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十五)——S ...
随机推荐
- PHP 4种输出的方式
<?php //测试用的数组 $info = array('11'=>'aaa', '22'=>'bbb', '33'=>'ccc'); //第一种,将整个数组作为一个对象输出 ...
- TMainMenu - 隐藏与显示菜单
//隐藏与显示菜单 Self.Menu := nil; {隐藏菜单} Self.Menu := MainMenu1; {显示菜单}
- python之工作举例:通过复制NC文件来造数据
# 通过对NC文件复制来造数据 import os, shutil # 遍历的根目录 root_dir = "D:\\test_data\\DISASTER\\" # 获取NC文件 ...
- BZOJ1834[ZJOI2010]网络扩容——最小费用最大流+最大流
题目描述 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1.在不扩容的情况下,1到N的最大流: 2.将1到N的最大流增加K所需的最小扩容费用 ...
- Trailing Zeroes (III) LightOJ - 1138(二分)
You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in d ...
- Educational Codeforces Round 25 A,B,C,D
A:链接:http://codeforces.com/contest/825/problem/A 解题思路: 一开始以为是个进制转换后面发现是我想多了,就是统计有多少个1然后碰到0输出就行,没看清题意 ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
- 【BZOJ4161】Shlw loves matrixI (常系数齐次线性递推)
[BZOJ4161]Shlw loves matrixI (常系数齐次线性递推) 题面 BZOJ 题解 \(k\)很小,可以直接暴力多项式乘法和取模. 然后就是常系数齐次线性递推那套理论了,戳这里 # ...
- Java -- JDBC 学习--通过Statement进行数据库更新操作
通过 JDBC 向指定的数据表中插入一条记录. 1. Statement: 用于执行 SQL 语句的对象 1). 通过 Connection 的 createStatement() 方法来获取 2). ...
- Linux下将使用rm删除的文件显示在回收站中
人难免会失误,出现一些问题,在删除文件的时候使用rm,删除之后就后悔了.因为rm命令删除的文件是不进入回收站的,这使得恢复起来很困难.解决这一难题,可以使用python编写的trash-cli( ht ...