<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
namespace Extend;
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_MUSIC = 'music';
const MSG_TYPE_NEWS = 'news';
const MSG_TYPE_LOCATION = 'location';
const MSG_TYPE_LINK = 'link';
const MSG_TYPE_EVENT = 'event';
/* 二维码类型常量 */
const QR_SCENE = 'QR_SCENE';
const QR_STR_SCENE = 'QR_STR_SCENE';
const QR_LIMIT_SCENE = 'QR_LIMIT_SCENE';
const QR_LIMIT_STR_SCENE = 'QR_LIMIT_STR_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 $mediaURL = 'http://file.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('参数错误!');
}
}
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;
}
$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 $token acess_token
* @param string $lang 指定的语言
* @return array 用户信息数据,具体参见微信文档
*/
public function getUserInfo($token, $lang = 'zh_CN'){
$query = array(
'access_token' => $token['access_token'],
'openid' => $token['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){
$param = array(
'access_token' => $this->accessToken,
'type' => $type
);
$filename = realpath($filename);
if(!$filename) throw new \Exception('资源路径错误!');
$file = array('media' => "@{$filename}");
$url = "{$this->mediaURL}/media/upload";
$data = self::http($url, $param, $file, 'POST');
return json_decode($data, true);
}
/**
* 获取媒体资源下载地址
* 注意:视频资源不允许下载
* @param string $media_id 媒体资源id
* @return string 媒体资源下载地址
*/
public function mediaGet($media_id){
$param = array(
'access_token' => $this->accessToken,
'media_id' => $media_id
);
$url = "{$this->mediaURL}/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){
error_reporting(0);
//基础数据
$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(