本类包含了微信官方公布的所有可使用的接口,包括了普通接口及高级接口,具体哪些接口可用还是要看您的账号级别。 具体接口如下: 基础支持 接收消息 发送消息 用户管理 自定义菜单 推广支持 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,支持AMR\MP3格式 * 视频(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 : "") . "\n"; } 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"] . "\n"; 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 . "\n"; 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 . "\n"; 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; } } ?>