• 完整的微信接口类


    本类包含了微信官方公布的所有可使用的接口,包括了普通接口及高级接口,具体哪些接口可用还是要看您的账号级别。
    具体接口如下:
    
        基础支持
        接收消息
        发送消息
        用户管理
        自定义菜单
        推广支持
        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;
        }
    }
    ?>
    
    
    
     
  • 相关阅读:
    PuTTY 私钥'putty/sshdss.c' 多个信息泄露漏洞
    PuTTY DSA签名远程缓冲区溢出漏洞(CVE-2013-4207)
    Apache CloudStack多个跨站脚本漏洞(CVE-2013-2136)
    phpMyAdmin 完整路径泄露漏洞3
    程序员必知的 七 种软件架构模式!
    【扩展知识】数据结构之动态内存管理机制!
    新年新气象,拼多多退出春晚红包合作,由抖音补位!
    【新年第一个程序】三子棋小游戏(C语言数组实现)
    编程开发中你必须了解的内存知识!从分配到使用直至出现Bug!
    C语言小写转大写,小写字母转换成大写字母!
  • 原文地址:https://www.cnblogs.com/zuochuang/p/4685287.html
Copyright © 2020-2023  润新知