本类包含了微信官方公布的所有可使用的接口,包括了普通接口及高级接口,具体哪些接口可用还是要看您的账号级别。
具体接口如下:
基础支持
接收消息
发送消息
用户管理
自定义菜单
推广支持
Weixin JS接口
代码如下:
<?php
class WeiXin {
const MSG_TYPE_TEXT = 'text';
const MSG_TYPE_IMAGE = 'image';
const MSG_TYPE_VOICE = 'voice';
const MSG_TYPE_VIDEO = 'video';
const MSG_TYPE_LOCATION = 'location';
const MSG_TYPE_LINK = 'link';
const MSG_TYPE_EVENT = 'event';
const MSG_EVENT_SUBSCRIBE = 'subscribe';
const MSG_EVENT_UNSUBSCRIBE = 'unsubscribe';
const MSG_EVENT_SCAN = 'scan';
const MSG_EVENT_LOCATION = 'LOCATION';
const MSG_EVENT_CLICK = 'CLICK';
const REPLY_TYPE_TEXT = 'text';
const REPLY_TYPE_IMAGE = 'image';
const REPLY_TYPE_VOICE = 'voice';
const REPLY_TYPE_VIDEO = 'video';
const REPLY_TYPE_MUSIC = 'music';
const REPLY_TYPE_NEWS = 'news';
const MEDIA_TYPE_IMAGE = "image";
const MEDIA_TYPE_VOICE = 'voice';
const MEDIA_TYPE_VIDEO = 'video';
const MEDIA_TYPE_THUMB = 'thumb';
const SCOPE_REDIRECT = "snsapi_base";
const SCOPE_POP = "snsapi_userinfo";
private static $links = array(
'message' => "https://api.weixin.qq.com/cgi-bin/message/custom/send",
'group_create' => "https://api.weixin.qq.com/cgi-bin/groups/create",
'group_get' => "https://api.weixin.qq.com/cgi-bin/groups/get",
'group_getid' => "https://api.weixin.qq.com/cgi-bin/groups/getid",
'group_rename' => "https://api.weixin.qq.com/cgi-bin/groups/update",
'group_move' => "https://api.weixin.qq.com/cgi-bin/groups/members/update",
'user_info' => "https://api.weixin.qq.com/cgi-bin/user/info",
'user_get' => 'https://api.weixin.qq.com/cgi-bin/user/get',
'menu_create' => 'https://api.weixin.qq.com/cgi-bin/menu/create',
'menu_get' => 'https://api.weixin.qq.com/cgi-bin/menu/get',
'menu_delete' => 'https://api.weixin.qq.com/cgi-bin/menu/delete',
'qrcode' => 'https://api.weixin.qq.com/cgi-bin/qrcode/create',
'showqrcode' => 'https://mp.weixin.qq.com/cgi-bin/showqrcode',
'media_download' => 'http://file.api.weixin.qq.com/cgi-bin/media/get',
'media_upload' => 'http://file.api.weixin.qq.com/cgi-bin/media/upload',
'oauth_code' => 'https://open.weixin.qq.com/connect/oauth2/authorize',
'oauth_access_token' => 'https://api.weixin.qq.com/sns/oauth2/access_token',
'oauth_refresh' => 'https://api.weixin.qq.com/sns/oauth2/refresh_token',
'oauth_userinfo' => 'https://api.weixin.qq.com/sns/userinfo'
);
private static $errors = array(
'-1' => '系统繁忙',
'0' => '请求成功',
'40001' => '获取access_token时AppSecret错误,或者access_token无效',
'40002' => '不合法的凭证类型',
'40003' => '不合法的OpenID',
'40004' => '不合法的媒体文件类型',
'40005' => '不合法的文件类型',
'40006' => '不合法的文件大小',
'40007' => '不合法的媒体文件id',
'40008' => '不合法的消息类型',
'40009' => '不合法的图片文件大小',
'40010' => '不合法的语音文件大小',
'40011' => '不合法的视频文件大小',
'40012' => '不合法的缩略图文件大小',
'40013' => '不合法的APPID',
'40014' => '不合法的access_token',
'40015' => '不合法的菜单类型',
'40016' => '不合法的按钮个数',
'40017' => '不合法的按钮个数',
'40018' => '不合法的按钮名字长度',
'40019' => '不合法的按钮KEY长度',
'40020' => '不合法的按钮URL长度',
'40021' => '不合法的菜单版本号',
'40022' => '不合法的子菜单级数',
'40023' => '不合法的子菜单按钮个数',
'40024' => '不合法的子菜单按钮类型',
'40025' => '不合法的子菜单按钮名字长度',
'40026' => '不合法的子菜单按钮KEY长度',
'40027' => '不合法的子菜单按钮URL长度',
'40028' => '不合法的自定义菜单使用用户',
'40029' => '不合法的oauth_code',
'40030' => '不合法的refresh_token',
'40031' => '不合法的openid列表',
'40032' => '不合法的openid列表长度',
'40033' => '不合法的请求字符,不能包含uxxxx格式的字符',
'40035' => '不合法的参数',
'40038' => '不合法的请求格式',
'40039' => '不合法的URL长度',
'40050' => '不合法的分组id',
'40051' => '分组名字不合法',
'41001' => '缺少access_token参数',
'41002' => '缺少appid参数',
'41003' => '缺少refresh_token参数',
'41004' => '缺少secret参数',
'41005' => '缺少多媒体文件数据',
'41006' => '缺少media_id参数',
'41007' => '缺少子菜单数据',
'41008' => '缺少oauth code',
'41009' => '缺少openid',
'42001' => 'access_token超时',
'42002' => 'refresh_token超时',
'42003' => 'oauth_code超时',
'43001' => '需要GET请求',
'43002' => '需要POST请求',
'43003' => '需要HTTPS请求',
'43004' => '需要接收者关注',
'43005' => '需要好友关系',
'44001' => '多媒体文件为空',
'44002' => 'POST的数据包为空',
'44003' => '图文消息内容为空',
'44004' => '文本消息内容为空',
'45001' => '多媒体文件大小超过限制',
'45002' => '消息内容超过限制',
'45003' => '标题字段超过限制',
'45004' => '描述字段超过限制',
'45005' => '链接字段超过限制',
'45006' => '图片链接字段超过限制',
'45007' => '语音播放时间超过限制',
'45008' => '图文消息超过限制',
'45009' => '接口调用超过限制',
'45010' => '创建菜单个数超过限制',
'45015' => '回复时间超过限制',
'45016' => '系统分组,不允许修改',
'45017' => '分组名字过长',
'45018' => '分组数量超过上限',
'46001' => '不存在媒体数据',
'46002' => '不存在的菜单版本',
'46003' => '不存在的菜单数据',
'46004' => '不存在的用户',
'47001' => '解析JSON/XML内容错误',
'48001' => 'api功能未授权',
'50001' => '用户未授权该api'
);
private static $debug = false;
private $token;
private $postStr;
private $postObj;
private $appid;
private $appsecret;
private $access_token;
private $valid = 0;
/**
* @param $token
* @param null $appid
* @param null $appsecret
* @param bool $debug
*/
public function __construct($token, $appid = null, $appsecret = null, $debug = false) {
$this->token = $token;
if (!empty($_GET) && $this->checkSignature())
$this->handleRequest();
$this->appid = $appid;
$this->appsecret = $appsecret;
self::$debug = $debug;
}
/**
* 检查签名
*
* @return bool
*/
private function checkSignature() {
if (!isset($_GET['signature']) || !isset($_GET['timestamp']) || !isset($_GET['nonce']))
return false;
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$tmpArr = array($this->token, $timestamp, $nonce);
sort($tmpArr);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr == $signature)
return true;
else
return false;
}
/**
* 处理请求
*/
private function handleRequest() {
if (isset($_GET['echostr']))
{
echo $_GET['echostr'];
exit;
}
else
{
$this->postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($this->postStr))
{
$this->postObj = simplexml_load_string($this->postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
}
else
{
Log::simpleappend('fail', $this->postStr);
exit;
}
}
}
/**
* 获取高级接口的access_token
*
* @return bool
*/
private function getAccessToken() {
if ($this->appid && $this->appsecret)
{
if ($this->valid <= time())
{
$access = json_decode(Tools::curl("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appid}&secret={$this->appsecret}"));
if (isset($access->access_token) && isset($access->expires_in))
{
$this->access_token = $access->access_token;
$this->valid = time() + $access->expires_in;
}
else
return false;
}
return true;
}
return false;
}
/**
* 获取请求中的收信人OpenId,一般为公众账号自身
*
* @return mixed
*/
public function getToUserName() {
return $this->postObj->ToUserName;
}
/**
* 请求中的发信人OpenId
*
* @return mixed
*/
public function getFromUserName() {
return $this->postObj->FromUserName;
}
/**
* 获取Object格式的消息内容
*
* @return mixed
*/
public function getPostObj() {
return $this->postObj;
}
/**
* 获取字符串格式的消息内容
*
* @return mixed
*/
public function getPostStr() {
return $this->postStr;
}
/**
* 获取消息ID
*
* @return mixed
*/
public function getMsgId() {
return $this->postObj->MsgId;
}
/**
* 消息创建时间
*
* @return string
*/
public function getCreateTime() {
return strval($this->postObj->CreateTime);
}
//获取消息类型
public function getMsgType() {
return $this->postObj->MsgType;
}
/**
* 获取事件推送的时间类型,非事件的消息返回false
*
* @return mixed
*/
public function getEvent() {
if ($this->postObj->MsgType == self::MSG_TYPE_EVENT)
{
return $this->postObj->Event;
}
return false;
}
/**
* 是否为文本消息
*
* @return bool
*/
public function isTextMessage() {
return $this->postObj->MsgType == self::MSG_TYPE_TEXT;
}
/**
* 是否为图片消息
*
* @return bool
*/
public function isImageMessage() {
return $this->postObj->MsgType == self::MSG_TYPE_IMAGE;
}
/**
* 是否为语音消息
*
* @return bool
*/
public function isVoiceMessage() {
return $this->postObj->MsgType == self::MSG_TYPE_VOICE;
}
/**
* 是否为视频消息
*
* @return bool
*/
public function isVideoMessage() {
return $this->postObj->MsgType == self::MSG_TYPE_VIDEO;
}
/**
* 是否为地理位置消息
*
* @return bool
*/
public function isLocationMessage() {
return $this->postObj->MsgType == self::MSG_TYPE_LOCATION;
}
/**
* 是否为链接消息
*
* @return bool
*/
public function isLinkMessage() {
return $this->postObj->MsgType == self::MSG_TYPE_LINK;
}
/**
* 是否为普通关注事件
*
* @return bool
*/
public function isEventSubscribe() {
return $this->postObj->MsgType == self::MSG_TYPE_EVENT && $this->postObj->Event == self::MSG_EVENT_SUBSCRIBE && !isset($this->postObj->EventKey);
}
/**
* 是否为取消关注事件
*
* @return bool
*/
public function isEventUnSubscribe() {
return $this->postObj->MsgType == self::MSG_TYPE_EVENT && $this->postObj->Event == self::MSG_EVENT_UNSUBSCRIBE;
}
/**
* 是否为扫描二维码关注事件
*
* @return bool
*/
public function isEventScanSubscript() {
return $this->postObj->MsgType == self::MSG_TYPE_EVENT && $this->postObj->Event == self::MSG_EVENT_SUBSCRIBE && isset($this->postObj->EventKey);
}
/**
* 是否为已关注扫描二维码事件
*
* @return bool
*/
public function isEventScan() {
return $this->postObj->MsgType == self::MSG_TYPE_EVENT && $this->postObj->Event == self::MSG_EVENT_SCAN;
}
/**
* 是否为上报地理位置事件
*
* @return bool
*/
public function isEventLocation() {
return $this->postObj->MsgType == self::MSG_TYPE_EVENT && $this->postObj->Event == self::MSG_EVENT_LOCATION;
}
/**
* 是否为菜单点击事件
*
* @return bool
*/
public function isEventClick() {
return $this->postObj->MsgType == self::MSG_TYPE_EVENT && $this->postObj->Event == self::MSG_EVENT_CLICK;
}
/**
* 获取文本消息内容
*
* @return string
*/
public function requestText() {
return strval($this->postObj->Content);
}
/**
* 获取图片消息内容
*
* @return array
*/
public function requestImage() {
$image = array();
$image['PicUrl'] = strval($this->postObj->PicUrl);
$image['MediaId'] = strval($this->postObj->MediaId);
return $image;
}
/**
* 获取语音消息内容,可能包含语音识别结果
*
* @return array
*/
public function requestVoice() {
$voice = array();
$voice['MediaId'] = $this->postObj->MediaId;
$voice['Format'] = $this->postObj->Format;
if (isset($this->postObj->Recognition))
$voice['Recognition'] = $this->postObj->Recognition;
return $voice;
}
/**
* 获取视频消息内容
*
* @return array
*/
public function requestVideo() {
$video = array();
$video['MediaId'] = $this->postObj->MediaId;
$video['ThumbMediaId'] = $this->postObj->ThumbMediaId;
return $video;
}
/**
* 获取地理位置消息内容
*
* @return array
*/
public function requestLocation() {
$location = array();
$location['Location_X'] = strval($this->postObj->Location_X);
$location['Location_Y'] = strval($this->postObj->Location_Y);
$location['Scale'] = strval($this->postObj->Scale);
$location['Label'] = strval($this->postObj->Label);
return $location;
}
/**
* 获取链接消息内容
*
* @return array
*/
public function requestLink() {
$link = array();
$link['Title'] = strval($this->postObj->Title);
$link['Description'] = strval($this->postObj->Description);
$link['Url'] = strval($this->postObj->Url);
return $link;
}
/**
* 获取扫描二维码事件内容
*
* @return array
*/
public function requestEventScan() {
$info = array();
$info['EventKey'] = $this->postObj->EventKey;
$info['Ticket'] = $this->postObj->Ticket;
$info['Scene_Id'] = str_replace('qrscene_', '', $this->postObj->EventKey);
return $info;
}
/**
* 获取上报地理位置事件内容
*
* @return array
*/
public function requestEventLocation() {
$location = array();
$location['Latitude'] = $this->postObj->Latitude;
$location['Longitude'] = $this->postObj->Longitude;
$location['Precision'] = $this->postObj->Precision;
return $location;
}
/**
* 获取菜单点击事件内容
*
* @return string
*/
public function requestEventClick() {
return strval($this->postObj->EventKey);
}
/**
* GET方法
*
* @param $link
*
* @return mixed
*/
private static function get($link) {
if (self::$debug)
Log::out("weixin_debug", 'I', "get:" . $link);
return json_decode(Tools::curl($link));
}
/**
* POST方法
*
* @param $link
* @param $data
*
* @return mixed
*/
private static function post($link, $data) {
if (self::$debug)
Log::out("weixin_debug", 'I', "post:", $link . ":" . serialize($data));
return json_decode(Tools::curl($link, 'POST', $data));
}
/**
* 向微信服务器ECHO内容
*
* @param $content
*/
private static function response($content) {
if (self::$debug)
Log::out("weixin_debug", 'I', 'echo:' . $content);
echo $content;
}
/**
* 获取错误代码中文描述
*
* @param $errorcode
*
* @return mixed
*/
public static function error($errorcode) {
return self::$errors[$errorcode];
}
/**
* 回复文本消息
*
* @param $content
*/
public function responseTextMessage($content) {
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$resultStr = sprintf($textTpl, $this->postObj->FromUserName, $this->postObj->ToUserName, time(), self::REPLY_TYPE_TEXT, $content);
if (!headers_sent())
header('Content-Type: application/xml; charset=utf-8');
self::response($resultStr);
}
/**
* 回复图片消息
*
* @param $mediaid
*/
public function responseImageMessage($mediaid) {
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Image>
<MediaId><![CDATA[%s]]></MediaId>
</Image>
</xml>";
$resultStr = sprintf($textTpl, $this->postObj->FromUserName, $this->postObj->ToUserName, time(), self::REPLY_TYPE_IMAGE, $mediaid);
if (!headers_sent())
header('Content-Type: application/xml; charset=utf-8');
self::response($resultStr);
}
/**
* 回复语音消息
*
* @param $mediaid
*/
public function responseVoiceMessage($mediaid) {
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Voice>
<MediaId><![CDATA[%s]]></MediaId>
</Voice>
</xml>";
$resultStr = sprintf($textTpl, $this->postObj->FromUserName, $this->postObj->ToUserName, time(), self::REPLY_TYPE_VOICE, $mediaid);
if (!headers_sent())
header('Content-Type: application/xml; charset=utf-8');
self::response($resultStr);
}
/**
* 回复视频消息
*
* @param $mediaid
* @param string $title
* @param string $description
*/
public function responseVideoMessage($mediaid, $title = "", $description = "") {
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Video>
<MediaId><![CDATA[%s]]></MediaId>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
</Video>
</xml>";
$resultStr = sprintf($textTpl, $this->postObj->FromUserName, $this->postObj->ToUserName, time(), self::REPLY_TYPE_VIDEO, $mediaid, $title, $description);
if (!headers_sent())
header('Content-Type: application/xml; charset=utf-8');
self::response($resultStr);
}
/**
* 回复音乐消息
*
* @param string $title
* @param string $description
* @param string $url
* @param string $hq_url
*/
public function responseMusicMessage($title = '', $description = '', $url = '', $hq_url = '') {
$textTpl = '<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Music>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<MusicUrl><![CDATA[%s]]></MusicUrl>
<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
</Music>
</xml>';
$resultStr = sprintf($textTpl, $this->postObj->FromUserName, $this->postObj->ToUserName, time(), self::REPLY_TYPE_MUSIC, $title, $description, $url, $hq_url);
if (!headers_sent())
header('Content-Type: application/xml; charset=utf-8');
self::response($resultStr);
}
/**
* 回复图文消息
*
* @param $items
*
* @throws Exception
*/
public function responseNewsMessage($items) {
$textTpl = '<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<ArticleCount>%d</ArticleCount>
<Articles>%s</Articles>
</xml>';
$itemTpl = '<item>
<Title><![CDATA[%s]]></Title>
<Discription><![CDATA[%s]]></Discription>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>';
$articles = '';
if ($items && is_array($items))
{
foreach ($items as $item)
{
if (is_array($item) && (isset($item['Title']) || isset($item['Description']) || isset($item['PicUrl']) || isset($item['Url'])))
$articles .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
else
throw new Exception("item => array('Title'=>'','Description'=>'','PicUrl'=>'','Url'=>'')");
}
}
$resultStr = sprintf($textTpl, $this->postObj->FromUserName, $this->postObj->ToUserName, time(), self::REPLY_TYPE_NEWS, count($items), $articles);
if (!headers_sent())
header('Content-Type: application/xml; charset=utf-8');
self::response($resultStr);
}
/**发送文本客服消息,需要access_token
*
* @param $openid
* @param $content
*
* @return bool|mixed
*/
public function sendTextMessage($openid, $content) {
if ($this->getAccessToken())
{
$message = array();
$message['touser'] = $openid;
$message['msgtype'] = "text";
$message['text']['content'] = $content;
return self::post(self::$links['message'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 发送图片客服消息,需要access_token
*
* @param $openid
* @param $mediaid
*
* @return bool|mixed
*/
public function sendImageMessage($openid, $mediaid) {
if ($this->getAccessToken())
{
$message = array();
$message['touser'] = $openid;
$message['msgtype'] = "image";
$message['image']['media_id'] = $mediaid;
return self::post(self::$links['message'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 发送语音客服消息,需要access_token
*
* @param $openid
* @param $media_id
*
* @return bool|mixed
*/
public function sendVoiceMessage($openid, $media_id) {
if ($this->getAccessToken())
{
$message = array();
$message['touser'] = $openid;
$message['msgtype'] = "voice";
$message['voice']['media_id'] = $media_id;
return self::post(self::$links['message'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 发送视频客服消息,需要access_token
*
* @param $openid
* @param $media_id
* @param string $title
* @param string $description
*
* @return bool|mixed
*/
public function sendVideoMessage($openid, $media_id, $title = "", $description = "") {
if ($this->getAccessToken())
{
$message = array();
$message['touser'] = $openid;
$message['msgtype'] = "video";
$message['video']['media_id'] = $media_id;
$message['video']['title'] = $title;
$message['video']['description'] = $description;
return self::post(self::$links['message'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 发送音乐客服消息,需要access_token
*
* @param $openid
* @param $url
* @param $hq_url
* @param $media_id
* @param string $title
* @param string $description
*
* @return bool|mixed
*/
public function sendMusicMessage($openid, $url, $hq_url, $media_id, $title = "", $description = "") {
if ($this->getAccessToken())
{
$message = array();
$message['touser'] = $openid;
$message['msgtype'] = "music";
$message['music']['title'] = $title;
$message['music']['description'] = $description;
$message['music']['musicurl'] = $url;
$message['music']['hqmusicurl'] = $hq_url;
$message['music']['thumb_media_id'] = $media_id;
return self::post(self::$links['message'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 发送图文客服消息,需要access_token
*
* @param $openid
* @param $items
*
* @return bool|mixed
* @throws Exception
*/
public function sendNewsMessage($openid, $items) {
if ($this->getAccessToken())
{
$message = array();
$message['touser'] = $openid;
$message['msgtype'] = "news";
if ($items && is_array($items))
{
foreach ($items as $item)
{
if (is_array($item) && (isset($item['Title']) || isset($item['Description']) || isset($item['PicUrl']) || isset($item['Url'])))
{
$it['title'] = isset($item['Title']) ? $item['Title'] : "";
$it['description'] = isset($item['Description']) ? $item['Description'] : "";
$it['url'] = isset($item['Url']) ? $item['Url'] : "";
$it['picurl'] = isset($item['PicUrl']) ? $item['PicUrl'] : "";
if ($it['title'] && $it['description'] && $it['url'] && $it['picurl'])
$message['news']['articles'][] = $it;
}
else
throw new Exception("item => array('Title'=>'','Description'=>'','PicUrl'=>'','Url'=>'')");
}
}
return self::post(self::$links['message'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 创建分组
*
* @param $name
*
* @return bool|mixed
*/
public function groupCreate($name) {
if ($this->getAccessToken())
{
$message = array();
$message['name'] = $name;
return self::post(self::$links['group_create'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 查询所有分组
*
* @return bool|mixed
*/
public function groupGetAll() {
if ($this->getAccessToken())
{
return self::get(self::$links['group_get'] . "?access_token={$this->access_token}");
}
return false;
}
/**
* 查询用户所在分组
*
* @param $openid
*
* @return bool|mixed
*/
public function groupGet($openid) {
if ($this->getAccessToken())
{
$message = array();
$message['openid'] = $openid;
return self::post(self::$links['group_getid'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 修改分组名
*
* @param $groupid
* @param $name
*
* @return bool|mixed
*/
public function groupRename($groupid, $name) {
if ($this->getAccessToken())
{
$message = array();
$message['id'] = $groupid;
$message['name'] = $name;
return self::post(self::$links['group_rename'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 移动用户分组
*
* @param $openid
* @param $to_groupid
*
* @return bool|mixed
*/
public function groupMove($openid, $to_groupid) {
if ($this->getAccessToken())
{
$message = array();
$message['openid'] = $openid;
$message['to_groupid'] = $to_groupid;
return self::post(self::$links['group_move'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 获取用户基本信息
*
* @param $openid
*
* @return bool|mixed
*/
public function userInfo($openid) {
if ($this->getAccessToken())
{
return self::get(self::$links['user_info'] . "?access_token={$this->access_token}&openid={$openid}");
}
return false;
}
/**
* 获取关注者列表
*
* @param null $next_openid
*
* @return bool|mixed
*/
public function userGet($next_openid = null) {
if ($this->getAccessToken())
{
if ($next_openid)
return self::get(self::$links['user_get'] . "?access_token={$this->access_token}&openid=");
else
return self::get(self::$links['user_get'] . "?access_token={$this->access_token}&next_openid={$next_openid}");
}
return false;
}
/**
* 创建自定义菜单
*
* @param $menus
*
* @return bool|mixed
*/
public function menuCreate($menus) {
if ($this->getAccessToken())
{
$message = array();
$message['button'] = $menus;
return self::post(self::$links['menu_create'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 获取自定义菜单
*
* @return bool|mixed
*/
public function menuGet() {
if ($this->getAccessToken())
{
return self::get(self::$links['menu_get'] . "?access_token={$this->access_token}");
}
return false;
}
/**
* 删除自定义菜单
*
* @return bool|mixed
*/
public function menuDelete() {
if ($this->getAccessToken())
{
return self::get(self::$links['menu_delete'] . "?access_token={$this->access_token}");
}
return false;
}
/**
* 生成带参数的二维码,通过expire_seconds可以设置临时二维码或永久二维码
*
* @param $sceneid
* @param int $expire_seconds
*
* @return bool|mixed
*/
public function qrcodeCreate($sceneid, $expire_seconds = 0) {
if ($this->getAccessToken())
{
$message = array();
if ($expire_seconds > 0)
{
if ($expire_seconds > 1800)
return false;
$message['expire_seconds'] = $expire_seconds;
$message['action_name'] = 'QR_SCENE';
}
else
$message['action_name'] = 'QR_LIMIT_SCENE';
$message['action_info']['scene']['scene_id'] = $sceneid;
return self::post(self::$links['qrcode'] . "?access_token={$this->access_token}", json_encode($message, JSON_UNESCAPED_UNICODE));
}
return false;
}
/**
* 用ticket换取二维码图片,返回结果未图片,可以直接展示或者下载
*
* @param $ticket
*
* @return mixed
*/
public static function qrcodeGet($ticket) {
return self::get(self::$links['showqrcode'] . "?tocket=" . urlencode($ticket));
}
/**
* 下载多媒体文件
*
* @param $mediaid
*
* @return mixed
*/
public function mediaDownload($mediaid) {
return self::get(self::$links['media_download'] . "?access_token={$this->access_token}&media_id=" . $mediaid);
}
/**
* 上传多媒体文件
* 图片(image): 128K,支持JPG格式
* 语音(voice):256K,播放长度不超过60s,支持AMRMP3格式
* 视频(video):1MB,支持MP4格式
* 缩略图(thumb):64KB,支持JPG格式
*
* @param $filetype
* @param $filepath
*
* @return bool|mixed
*/
public function mediaUpload($filetype, $filepath) {
if ($this->getAccessToken() && file_exists($filepath))
{
$fileext = strtolower(Tools::getFileExtension($filepath));
$filesize = filesize($filepath);
switch ($filetype)
{
case self::MEDIA_TYPE_IMAGE:
if ($fileext != 'jpg' || $filesize > 128 * 1024)
return false;
break;
case self::MEDIA_TYPE_VOICE:
if (!in_array($fileext, array('amr', 'mp3')) || $filesize > 256 * 1024)
return false;
break;
case self::MEDIA_TYPE_VIDEO:
if ($fileext != 'mp4' || $filesize > 1024 * 1024)
return false;
break;
case self::MEDIA_TYPE_THUMB:
if ($fileext != 'jpg' || $filesize > 64 * 1024)
return false;
break;
default:
return false;
break;
}
$media = array();
$media['access_token'] = $this->access_token;
$media['type'] = $filetype;
$media['media'] = '@' . $filepath;
return self::post(self::$links['media_upload'], $media);
}
return false;
}
/**
* 第三方网页通过Oauth2.0获取用户授权
* 获取code
*/
public function oauthGetCode($redirect, $scope, $state) {
return self::$links['oauth_code'] . "?appid={$this->appid}&redirect_uri={$redirect}&response_type=code&scope={$scope}&state={$state}#wechat_redirect";
}
/**
* 第三方网页通过Oauth2.0获取用户授权
* 通过code获取access_token
*/
public function oauthGetAccessToken($code) {
return self::get(self::$links['oauth_access_token'] . "?appid={$this->appid}&secret={$this->appsecret}&code={$code}&grant_type=authorization_code");
}
/**
* 第三方网页通过Oauth2.0获取用户授权
* 刷新access_token
*/
public function oauthRefreshAccessToken($refresh_token) {
return self::get(self::$links['oauth_refresh'] . "?appid={$this->appid}&grant_type=refresh_token&refresh_token={$refresh_token}");
}
/**
* 第三方网页通过Oauth2.0获取用户权限
* 获取用户信息,仅限scope为SCOPE_POP
*/
public function oauthUserInfo($access_token, $openid) {
return self::get(self::$links['oauth_userinfo'] . "?access_token={$access_token}&openid={$openid}");
}
/**
* 返回js代码,隐藏微信中网页右上角按钮
*
* @return string
*/
public static function hideOptionMenu() {
return <<<EOF
<script type="text/javascript">
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
WeixinJSBridge.call('hideOptionMenu');
});
</script>
EOF;
}
/**
* 返回js代码,隐藏微信中网页底部导航栏
*
* @return string
*/
public static function hideToolbar() {
return <<<EOF
<script type="text/javascript">
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
WeixinJSBridge.call('hideToolbar');
});
</script>
EOF;
}
/**
* 返回js代码,网页获取用户网络状态
*
* @return string
*/
public static function getNetworkType() {
return <<<EOF
<script type="text/javascript">
WeixinJSBridge.invoke('getNetworkType',{},
function(e){
WeixinJSBridge.log(e.err_msg);
}
);
</script>
EOF;
}
/**
* 返回微信支付的JS代码
*/
public static function getPayment($params,$account){
global $_W;
$wOpt['appId'] = $_W['account']['key'];
$wOpt['timeStamp'] = TIMESTAMP;
$wOpt['nonceStr'] = random(8);
$package = array();
$package['bank_type'] = 'WX';
$package['body'] = $params['title'];
$package['attach'] = $_W['weid'];
$package['partner'] = $wechat['partner'];
$package['out_trade_no'] = $params['tid'];
$package['total_fee'] = $params['fee'] * 100;
$package['fee_type'] = '1';
$package['notify_url'] = $_W['siteroot'] . 'payment/wechat/notify.php';
$package['spbill_create_ip'] = CLIENT_IP;
$package['time_start'] = date('YmdHis', TIMESTAMP);
$package['time_expire'] = date('YmdHis', TIMESTAMP + 600);
$package['input_charset'] = 'UTF-8';
ksort($package);
$string1 = '';
foreach ($package as $key => $v)
{
$string1 .= "{$key}={$v}&";
}
$string1 .= "key={$wechat['key']}";
$sign = strtoupper(md5($string));
$string2 = '';
foreach ($package as $key => $v)
{
$v = urlencode($v);
$string2 .= "{$key}={$v}&";
}
$string2 .= "sign={$sign}";
$string = '';
$keys = array('appId', 'timeStamp', 'nonceStr', 'package', 'appKey');
sort($keys);
foreach ($keys as $key)
{
$v = $wOpt[$key];
if ($key == 'appKey')
{
$v = $wechat['signkey'];
}
$key = strtolower($key);
$string .= "{$key}={$v}&";
}
$string = rtrim($string, '&');
$wOpt['package'] = $string2;
$wOpt['signType'] = 'SHA1';
$wOpt['paySign'] = sha1($string);
return $wOpt;
}
}
log.php
<?php
class Log {
private static $logpath = LOG_DIR;
/**
* 写入日志
*
* @param string $strFileName
* @param string $strType
* @param string $strMSG
* @param string $strExtra
* @param string $line
*/
public static function out($strFileName = "", $strType = "I", $strMSG = "", $strExtra = "", $line = "") {
if ($strType == "")
$strType = "I";
if (!file_exists(self::$logpath))
{
if (!mkdir(self::$logpath, '0777'))
{
if (DEBUG_MODE)
{
die(Tools::displayError("Make " . self::$logpath . " error"));
}
else
{
die("error");
}
}
}
elseif (!is_dir(self::$logpath))
{
if (DEBUG_MODE)
{
die(Tools::displayError(self::$logpath . " is already token by a file"));
}
else
{
die("error");
}
}
else
{
if (!is_writable(self::$logpath))
{
@chmod(self::$logpath, 0777);
}
$logfile = rtrim(self::$logpath, '/') . '/' . $strFileName . '_' . date("ymd") . '.log';
if (file_exists($logfile) && !is_writable($logfile))
{
@chmod($logfile, 0644);
}
$handle = @fopen($logfile, "a+");
if ($handle)
{
if (Tools::isCli())
{
$arg = "";
if ($_SERVER['argc'] > 0)
{
$arg = " ARGV:" . json_encode($_SERVER['argv']);
}
$strContent = "[" . date("Y-m-d H:i:s") . "] [" . strtoupper($strType) . "] [CLI] MSG:[" . $strMSG . "]" . $strExtra . " Location:" . $_SERVER["SCRIPT_FILENAME"] . $arg . ($line ? " Line:" . $line : "") . "
";
}
else
$strContent = "[" . date("Y-m-d H:i:s") . "] [" . strtoupper($strType) . "] [" . Tools::getRemoteAddr() . "] MSG:[" . $strMSG . "]" . $strExtra . " Location:" . $_SERVER["SCRIPT_FILENAME"] . ($line ? " Line:" . $line : "") . " QUERY_STRING:" . $_SERVER["QUERY_STRING"] . " HTTP_REFERER:" . (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "") . " User-Agent:" . $_SERVER["HTTP_USER_AGENT"] . "
";
if (!fwrite($handle, $strContent))
{
@fclose($handle);
die("Write permission deny");
}
@fclose($handle);
}
}
}
/**
* 将$strMSG写入$strFileName文件,覆盖原来内容
*
* @param $strFileName
* @param $strMSG
*/
public static function simplewrite($strFileName, $strMSG) {
if (!file_exists(self::$logpath))
{
if (!mkdir(self::$logpath, '0777'))
{
if (DEBUG_MODE)
{
die(Tools::displayError("Make " . self::$logpath . " error"));
}
else
{
die("error");
}
}
}
elseif (!is_dir(self::$logpath))
{
if (DEBUG_MODE)
{
die(Tools::displayError(self::$logpath . " is already token by a file"));
}
else
{
die("error");
}
}
else
{
if (!is_writable(self::$logpath))
{
@chmod(self::$logpath, 0777);
}
$logfile = rtrim(self::$logpath, '/') . '/' . $strFileName . '.log';
if (file_exists($logfile) && !is_writable($logfile))
{
@chmod($logfile, 0644);
}
$handle = @fopen($logfile, "w");
if ($handle)
{
$strContent = $strMSG . "
";
if (!fwrite($handle, $strContent))
{
@fclose($handle);
die("Write permission deny");
}
@fclose($handle);
}
}
}
/**
* 写入文件,追加方式
*
* @param $strFileName
* @param $strMSG
*/
public static function simpleappend($strFileName, $strMSG) {
if (!file_exists(self::$logpath))
{
if (!mkdir(self::$logpath, '0777'))
{
if (DEBUG_MODE)
{
die(Tools::displayError("Make " . self::$logpath . " error"));
}
else
{
die("error");
}
}
}
elseif (!is_dir(self::$logpath))
{
if (DEBUG_MODE)
{
die(Tools::displayError(self::$logpath . " is already token by a file"));
}
else
{
die("error");
}
}
else
{
if (!is_writable(self::$logpath))
{
@chmod(self::$logpath, 0777);
}
$logfile = rtrim(self::$logpath, '/') . '/' . $strFileName . '.log';
if (file_exists($logfile) && !is_writable($logfile))
{
@chmod($logfile, 0644);
}
$handle = @fopen($logfile, "a");
if ($handle)
{
$strContent = $strMSG . "
";
if (!fwrite($handle, $strContent))
{
@fclose($handle);
die("Write permission deny");
}
@fclose($handle);
}
}
}
/**
* 读文件内容
*
* @param $strFileName
*
* @return bool|string
*/
public static function simpleread($strFileName) {
$logfile = trim(self::$logpath, '/') . '/' . $strFileName . '.log';
if (file_exists($logfile) && is_readable($logfile))
{
$strContent = '';
$handler = @fopen($logfile, 'r');
if ($handler)
{
while (!feof($handler))
{
$strContent .= fgets($handler);
}
@fclose($handler);
}
return $strContent;
}
return false;
}
}
?>