eaglephp使用微信api接口开发微信框架

2014-05-17  来源:本站原创  分类:php实例  人气:10 

EaglePHP框架开发微信5.0的API接口,包含微信5.0 API基础接口、自定义菜单、高级接口,包括如下接收用户消息、向用户回复消息、会话界面自定义菜单、语音识别、客服接口等功能

适用平台:window/Linux
依赖项目:EaglePHP框架

包含微信5.0 API基础接口、自定义菜单、高级接口,具体如下:
1、接收用户消息。
2、向用户回复消息。
3、接受事件推送。
4、会话界面自定义菜单。
5、语音识别。
6、客服接口。
7、OAuth2.0网页授权。
8、生成带参数二维码。
9、获取用户地理位置。
10、获取用户基本信息。
11、获取关注者列表。
12、用户分组。

<?php
/**
 * 微信公众平台API
 */
class WeixinChat
{

 private $token;

 private $appid;

 private $appsecret;

 private $access_token;

 // 接收的数据
 private $_receive = array();

 private $_reply = '';

 // 接口错误码
 private $errCode = '';

 // 接口错误信息
 private $errMsg = '';

 // 微信oauth登陆获取code
 const CONNECT_OAUTH_AUTHORIZE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize?';

 // 微信oauth登陆通过code换取网页授权access_token
 const SNS_OAUTH_ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token?';

 // 微信oauth登陆刷新access_token(如果需要)
 const SNS_OAUTH_REFRESH_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/refresh_token?';

 // 通过ticket换取二维码
 const SHOW_QRCODE_URL = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?';

 // 微信oauth登陆拉取用户信息(需scope为 snsapi_userinfo)
 const SNS_USERINFO_URL = 'https://api.weixin.qq.com/sns/userinfo?';

 // 请求api前缀
 const API_URL_PREFIX = 'https://api.weixin.qq.com/cgi-bin';

 // 自定义菜单创建
 const MENU_CREATE_URL = '/menu/create?';

 // 自定义菜单查询
 const MENU_GET_URL = '/menu/get?';

 // 自定义菜单删除
 const MENU_DELETE_URL = '/menu/delete?';

 // 获取 access_token
 const AUTH_URL = '/token?grant_type=client_credential&';
 // 获取用户基本信息
 const USER_INFO_URL = '/user/info?';

 // 获取关注者列表
 const USER_GET_URL = '/user/get?';

 // 查询分组
 const GROUPS_GET_URL = '/groups/get?'; 

 // 创建分组
 const GROUPS_CREATE_URL = '/groups/create?';

 // 修改分组名
 const GROUPS_UPDATE_URL = '/groups/update?';

 // 移动用户分组
 const GROUPS_MEMBERS_UPDATE_URL = '/groups/members/update?';

 // 发送客服消息
 const MESSAGE_CUSTOM_SEND_URL = '/message/custom/send?';

 // 创建二维码ticket
 const QRCODE_CREATE_URL = '/qrcode/create?';

 /**
  * 初始化配置数据
  * @param array $options
  */
 public function __construct($options)
 {
  $this->token = isset($options['token']) ? $options['token'] : '';
  $this->appid = isset($options['appid']) ? $options['appid'] : '';
  $this->appsecret = isset($options['appsecret']) ? $options['appsecret'] : '';
 }

 /**
  * 获取发来的消息
  * 当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
  */
 public function getRev()
 {
  $postStr = file_get_contents('php://input');
  if($postStr)
  {
   $this->_receive = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
   //Log::info(var_export($this->_receive, true));
  }
  return $this;
 }

 /**
  * 获取微信服务器发来的消息
  */
 public function getRevData()
 {
  return $this->_receive;
 }

 /**
  * 获取接收者
  */
 public function getRevTo()
 {
  return isset($this->_receive['ToUserName']) ? $this->_receive['ToUserName'] : false;
 }

 /**
  * 获取消息发送者(一个OpenID)
  */
 public function getRevFrom()
 {
  return isset($this->_receive['FromUserName']) ? $this->_receive['FromUserName'] : false;
 }

 /**
  * 获取接收消息创建时间 (整型)
  */
 public function getRevCTime()
 {
  return isset($this->_receive['CreateTime']) ? $this->_receive['CreateTime'] : false;
 }

 /**
  * 获取接收消息类型(text、image、voice、video、location、link、event)
  */
 public function getRevType()
 {
  return isset($this->_receive['MsgType']) ? $this->_receive['MsgType'] : false;
 }

 /**
  * 获取接收消息编号
  */
 public function getRevId()
 {
  return isset($this->_receive['MsgId']) ? $this->_receive['MsgId'] : false;
 }

 /**
  * 获取接收消息文本
  * 通过语音识别接口,用户发送的语音,将会同时给出语音识别出的文本内容。(需申请服务号的高级接口权限)
  */
 public function getRevText()
 {
  if(isset($this->_receive['Content'])) return trim($this->_receive['Content']);
  elseif(isset($this->_receive['Recognition'])) return trim($this->_receive['Recognition']);
  else return false;
 }

 /**
  * 获取接收图片消息
  */
 public function getRevImage()
 {
  if(isset($this->_receive['PicUrl'])){
   return array(
        'picUrl' => $this->_receive['PicUrl'],  //图片链接
     'mediaId' => $this->_receive['MediaId'] //图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
       );
  }
  return false;
 }

 /**
  * 获取接收语音消息
  */
 public function getRevVoice()
 {
  if(isset($this->_receive['MediaId'])){
   return array(
        'mediaId' => $this->_receive['MediaId'],  //语音消息媒体id,可以调用多媒体文件下载接口拉取数据。
     'format' => $this->_receive['Format'] //语音格式,如amr,speex等
       );
  }
  return false;
 }

 /**
  * 获取接收视频消息
  */
 public function getRevVideo()
 {
  if(isset($this->_receive['MediaId'])){
   return array(
        'mediaId' => $this->_receive['MediaId'],       //视频消息媒体id,可以调用多媒体文件下载接口拉取数据。
     'thumbMediaId' => $this->_receive['ThumbMediaId']  //视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。
       );
  }
  return false;
 } 

 /**
  * 获取用户地理位置
  */
 public function getRevLocation()
 {
  if(isset($this->_receive['Location_X'])){
   return array(
        'locationX' => $this->_receive['Location_X'],  //地理位置维度
     'locationY' => $this->_receive['Location_Y'],  //地理位置经度
     'scale' => $this->_receive['Scale'], //地图缩放大小
     'label' => $this->_receive['Label'] //地理位置信息
       );
  }
  //开通了上报地理位置接口的公众号,用户在关注后进入公众号会话时,会弹框让用户确认是否允许公众号使用其地理位置。
  //弹框只在关注后出现一次,用户以后可以在公众号详情页面进行操作。
  elseif(isset($this->_receive['Latitude']))
  {
   return array(
        'latitude' => $this->_receive['Latitude'],  //地理位置纬度
     'longitude' => $this->_receive['Longitude'], //地理位置经度
      'precision' => $this->_receive['Precision'] // 地理位置精度
       );
  }
  return false;
 }

 /**
  * 获取接收链接消息
  */
 public function getRevLink()
 {
  if(isset($this->_receive['Title'])){
   return array(
        'title' => $this->_receive['Title'],  //消息标题
     'description' => $this->_receive['Description'],  //消息描述
     'url' => $this->_receive['Url'] //消息链接
       );
  }
  return false;
 }

 /**
  * 获取接收事件类型
  * 事件类型如:subscribe(订阅)、unsubscribe(取消订阅)、click
  */
 public function getRevEvent()
 {
  if(isset($this->_receive['Event']))
  {
   return array(
     'event' => strtolower($this->_receive['Event']),
     'key'=> isset($this->_receive['EventKey']) ? $this->_receive['EventKey'] : ''
       );
  }
  return false;
 }

 /**
  * 设置回复文本消息
  * @param string $content
  * @param string $openid
  */
 public function text($content='')
 {
  $textTpl = "<xml>
      <ToUserName><![CDATA[%s]]></ToUserName>
      <FromUserName><![CDATA[%s]]></FromUserName>
      <CreateTime>%s</CreateTime>
      <MsgType><![CDATA[%s]]></MsgType>
      <Content><![CDATA[%s]]></Content>
     </xml>";

  $this->_reply = sprintf($textTpl,
         $this->getRevFrom(),
         $this->getRevTo(),
         Date::getTimeStamp(),
         'text',
         $content
        );
  return $this;
 }

 /**
  * 设置回复音乐信息
  * @param string $title
  * @param string $desc
  * @param string $musicurl
  * @param string $hgmusicurl
  */
 public function music($title, $desc, $musicurl, $hgmusicurl='')
 {
  $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>';
  //<ThumbMediaId><![CDATA[%s]]></ThumbMediaId>

  $this->_reply = sprintf($textTpl,
         $this->getRevFrom(),
         $this->getRevTo(),
         Date::getTimeStamp(),
         'music',
         $title,
         $desc,
         $musicurl,
         $hgmusicurl
        );
  return $this;
 }

 /**
  * 回复图文消息
  * @param array
  */
 public function news($data)
 {
  $count = count($data);
  $subText = '';
  if($count > 0)
  {
   foreach($data as $v)
   {
    $tmpText = '<item>
      <Title><![CDATA[%s]]></Title>
      <Description><![CDATA[%s]]></Description>
      <PicUrl><![CDATA[%s]]></PicUrl>
      <Url><![CDATA[%s]]></Url>
      </item>';

    $subText .= sprintf(
        $tmpText, $v['title'],
        isset($v['description']) ? $v['description'] : '',
        isset($v['picUrl']) ? $v['picUrl'] : '',
        isset($v['url']) ? $v['url'] : ''
       );
   }
  }

  $textTpl = '<xml>
      <ToUserName><![CDATA[%s]]></ToUserName>
      <FromUserName><![CDATA[%s]]></FromUserName>
      <CreateTime><![CDATA[%s]]></CreateTime>
      <MsgType><![CDATA[news]]></MsgType>
      <ArticleCount><![CDATA[%d]]></ArticleCount>
      <Articles>%s</Articles>
     </xml>';

  $this->_reply = sprintf(
       $textTpl,
       $this->getRevFrom(),
       $this->getRevTo(),
       Date::getTimeStamp(),
       $count,
       $subText
      );
  return $this;
 }

 /**
  * 回复消息
  * @param array $msg
  * @param bool $return
  */
 public function reply()
 {
  header('Content-Type:text/xml');
  echo $this->_reply;
  exit;
 }

 /**
  * 自定义菜单创建
  * @param array 菜单数据
  */
 public function createMenu($data)
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $result = curlRequest(self::API_URL_PREFIX.self::MENU_CREATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return true;
  }

  return false;
 }

 /**
  * 自定义菜单查询
  */
 public function getMenu()
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $result = curlRequest(self::API_URL_PREFIX.self::MENU_GET_URL.'access_token='.$this->access_token);
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return $jsonArr;
  }

  return false;
 }

 /**
  * 自定义菜单删除
  */
 public function deleteMenu()
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $result = curlRequest(self::API_URL_PREFIX.self::MENU_DELETE_URL.'access_token='.$this->access_token);
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return true;
  }

  return false;
 }

 /**
  * 获取用户基本信息
  * @param string $openid 普通用户的标识,对当前公众号唯一
  */
 public function getUserInfo($openid)
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $result = curlRequest(self::API_URL_PREFIX.self::USER_INFO_URL.'access_token='.$this->access_token.'&openid='.$openid);
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return $jsonArr;
  }

  return false;
 }

 /**
  * 获取关注者列表
  * @param string $next_openid 第一个拉取的OPENID,不填默认从头开始拉取
  */
 public function getUserList($next_openid='')
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $result = curlRequest(self::API_URL_PREFIX.self::USER_GET_URL.'access_token='.$this->access_token.'&next_openid='.$next_openid);
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return $jsonArr;
  }

  return false;
 }

 /**
  * 查询分组
  */
 public function getGroup()
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $result = curlRequest(self::API_URL_PREFIX.self::GROUPS_GET_URL.'access_token='.$this->access_token);
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return $jsonArr;
  }

  return false;
 }

 /**
  * 创建分组
  * @param string $name 分组名字(30个字符以内)
  */
 public function createGroup($name)
 {
  if(!$this->access_token && !$this->checkAuth()) return false;
  $data = array('group' => array('name' => $name));
  $result = curlRequest(self::API_URL_PREFIX.self::GROUPS_CREATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return true;
  }

  return false;
 }

 /**
  * 修改分组名
  * @param int $id 分组id,由微信分配
  * @param string $name 分组名字(30个字符以内)
  */
 public function updateGroup($id, $name)
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $data = array('group' => array('id' => $id, 'name' => $name));
  $result = curlRequest(self::API_URL_PREFIX.self::GROUPS_UPDATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return true;
  }

  return false;
 }

 /**
  * 移动用户分组
  *
  * @param string $openid 用户唯一标识符
  * @param int $to_groupid 分组id
  */
 public function updateGroupMembers($openid, $to_groupid)
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $data = array('openid' => $openid, 'to_groupid' => $to_groupid);
  $result = curlRequest(self::API_URL_PREFIX.self::GROUPS_MEMBERS_UPDATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return true;
  }

  return false;
 }

 /**
  * 发送客服消息
  * 当用户主动发消息给公众号的时候(包括发送信息、点击自定义菜单clike事件、订阅事件、扫描二维码事件、支付成功事件、用户维权),
  * 微信将会把消息数据推送给开发者,开发者在一段时间内(目前为24小时)可以调用客服消息接口,通过POST一个JSON数据包来发送消息给普通用户,在24小时内不限制发送次数。
  * 此接口主要用于客服等有人工消息处理环节的功能,方便开发者为用户提供更加优质的服务。
  *
  * @param string $touser 普通用户openid
  */
 public function sendCustomMessage($touser, $data, $msgType = 'text')
 {
  $arr = array();
  $arr['touser'] = $touser;
  $arr['msgtype'] = $msgType;
  switch ($msgType)
  {
   case 'text': // 发送文本消息
    $arr['text']['content'] = $data;
    break;

   case 'image': // 发送图片消息
    $arr['image']['media_id'] = $data;
    break;

   case 'voice': // 发送语音消息
    $arr['voice']['media_id'] = $data;
    break;

   case 'video': // 发送视频消息
    $arr['video']['media_id'] = $data['media_id']; // 发送的视频的媒体ID
    $arr['video']['thumb_media_id'] = $data['thumb_media_id']; // 视频缩略图的媒体ID
    break;

   case 'music': // 发送音乐消息
    $arr['music']['title'] = $data['title'];// 音乐标题
    $arr['music']['description'] = $data['description'];// 音乐描述
    $arr['music']['musicurl'] = $data['musicurl'];// 音乐链接
    $arr['music']['hqmusicurl'] = $data['hqmusicurl'];// 高品质音乐链接,wifi环境优先使用该链接播放音乐
    $arr['music']['thumb_media_id'] = $data['title'];// 缩略图的媒体ID
    break;

   case 'news': // 发送图文消息
    $arr['news']['articles'] = $data; // title、description、url、picurl
    break;
  } 

  if(!$this->access_token && !$this->checkAuth()) return false;

  $result = curlRequest(self::API_URL_PREFIX.self::MESSAGE_CUSTOM_SEND_URL.'access_token='.$this->access_token, $this->jsonEncode($arr), 'post');
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return true;
  }

  return false;
 }

 /**
  * 获取access_token
  */
 public function checkAuth()
 {

  // 从缓存中获取access_token
  $cache_flag = 'weixin_access_token';
  $access_token = cache($cache_flag);
  if($access_token)
  {
   $this->access_token = $access_token;
   return true;
  }

  // 请求微信服务器获取access_token
  $result = curlRequest(self::API_URL_PREFIX.self::AUTH_URL.'appid='.$this->appid.'&secret='.$this->appsecret);
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0))
   {
    $this->error($jsonArr);
   }
   else
   {
    $this->access_token = $jsonArr['access_token'];
    $expire = isset($jsonArr['expires_in']) ? intval($jsonArr['expires_in'])-100 : 3600;
    // 将access_token保存到缓存中
    cache($cache_flag, $this->access_token, $expire, Cache::FILE);
    return true;
   }
  }
  return false;
 }

 /**
  * 微信oauth登陆->第一步:用户同意授权,获取code
  * 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),
  * snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
  * 直接在微信打开链接,可以不填此参数。做页面302重定向时候,必须带此参数
  *
  * @param string $redirect_uri 授权后重定向的回调链接地址
  * @param string $scope 应用授权作用域 0为snsapi_base,1为snsapi_userinfo
  * @param string $state 重定向后会带上state参数,开发者可以填写任意参数值
  */
 public function redirectGetOauthCode($redirect_uri, $scope=0, $state='')
 {
  $scope = ($scope == 0) ? 'snsapi_base' : 'snsapi_userinfo';
  $url = self::CONNECT_OAUTH_AUTHORIZE_URL.'appid='.$this->appid.'&redirect_uri='.urlencode($redirect_uri).'&response_type=code&scope='.$scope.'&state='.$state.'#wechat_redirect';
  redirect($url);
 }

 /**
  * 微信oauth登陆->第二步:通过code换取网页授权access_token
  *
  * @param string $code
  */
 public function getSnsAccessToken($code)
 {
  $result = curlRequest(self::SNS_OAUTH_ACCESS_TOKEN_URL.'appid='.$this->appid.'&secret='.$this->appsecret.'&code='.$code.'&grant_type=authorization_code');
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return $jsonArr;
  }

  return false;
 }

 /**
  * 微信oauth登陆->第三步:刷新access_token(如果需要)
  * 由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,
  * refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效的后,需要用户重新授权。
  *
  * @param string $refresh_token 填写通过access_token获取到的refresh_token参数
  */
 public function refershToken($refresh_token)
 {
  $result = curlRequest(self::SNS_OAUTH_REFRESH_TOKEN_URL.'appid='.$this->appid.'&grant_type=refresh_token&refresh_token='.$refresh_token);
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return $jsonArr;
  }

  return false;
 }

 /**
  * 微信oauth登陆->第四步:拉取用户信息(需scope为 snsapi_userinfo)
  * 如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。
  *
  * @param string $access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
  * @param string $openid 用户的唯一标识
  */
 public function getSnsUserInfo($access_token, $openid)
 {
  $result = curlRequest(self::SNS_USERINFO_URL.'access_token='.$access_token.'&openid='.$openid);
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return $jsonArr;
  }

  return false;
 }

 /**
  * 创建二维码ticket
  * 每次创建二维码ticket需要提供一个开发者自行设定的参数(scene_id),分别介绍临时二维码和永久二维码的创建二维码ticket过程。
  *
  * @param int $scene_id 场景值ID,临时二维码时为32位整型,永久二维码时最大值为1000
  * @param int $type 二维码类型,0为临时,1为永久
  * @param int $expire 该二维码有效时间,以秒为单位。 最大不超过1800。
  */
 public function createQrcode($scene_id, $type=0, $expire=1800)
 {
  if(!$this->access_token && !$this->checkAuth()) return false;

  $data = array();
  $data['action_info'] = array('scene' => array('scene_id' => $scene_id));
  $data['action_name'] = ($type == 0 ? 'QR_SCENE' : 'QR_LIMIT_SCENE');
  if($type == 0) $data['expire_seconds'] = $expire;

  $result = curlRequest(self::API_URL_PREFIX.self::QRCODE_CREATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');
  if($result)
  {
   $jsonArr = json_decode($result, true);
   if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);
   else return $jsonArr;
  }

  return false;
 }

 /**
  * 通过ticket换取二维码
  * 获取二维码ticket后,开发者可用ticket换取二维码图片。请注意,本接口无须登录态即可调用。
  * 提醒:TICKET记得进行UrlEncode
  * ticket正确情况下,http 返回码是200,是一张图片,可以直接展示或者下载。
  * 错误情况下(如ticket非法)返回HTTP错误码404。
  *
  * @param string $ticket
  */
 public function getQrcodeUrl($ticket)
 {
  return self::SHOW_QRCODE_URL.'ticket='.urlencode($ticket);
 }

 /**
  * 记录接口产生的错误日志
  */
 public function error($data)
 {
  $this->errCode = $data['errcode'];
  $this->errMsg = $data['errmsg'];
  Log::info('WEIXIN API errcode:['.$this->errCode.'] errmsg:['.$this->errMsg.']');
 }

 /**
  * 将数组中的中文转换成json数据
  * @param array $arr
  */
 public function jsonEncode($arr) {
     $parts = array ();
        $is_list = false;
        //Find out if the given array is a numerical array
        $keys = array_keys ( $arr );
        $max_length = count ( $arr ) - 1;
        if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) { //See if the first key is 0 and last key is length - 1
            $is_list = true;
            for($i = 0; $i < count ( $keys ); $i ++) { //See if each key correspondes to its position
               if ($i != $keys [$i]) { //A key fails at position check.
                  $is_list = false; //It is an associative array.
                  break;
               }
            }
        }
                foreach ( $arr as $key => $value ) {
                        if (is_array ( $value )) { //Custom handling for arrays
                                if ($is_list)
                                        $parts [] = $this->jsonEncode ( $value ); /* :RECURSION: */
                                else
                                        $parts [] = '"' . $key . '":' . $this->jsonEncode ( $value ); /* :RECURSION: */
                        } else {
                                $str = '';
                                if (! $is_list)
                                        $str = '"' . $key . '":';
                                //Custom handling for multiple data types
                                if (is_numeric ( $value ) && $value<2000000000)
                                        $str .= $value; //Numbers
                                elseif ($value === false)
                                $str .= 'false'; //The booleans
                                elseif ($value === true)
                                $str .= 'true';
                                else
                                        $str .= '"' . addslashes ( $value ) . '"'; //All other things
                                // :TODO: Is there any more datatype we should be in the lookout for? (Object?)
                                $parts [] = $str;
                        }
                }
                $json = implode ( ',', $parts );
                if ($is_list)
                        return '[' . $json . ']'; //Return numerical JSON
                return '{' . $json . '}'; //Return associative JSON
        }
 
 /**
  * 检验签名
  */
 public function checkSignature()
 {
        $signature = HttpRequest::getGet('signature');
        $timestamp = HttpRequest::getGet('timestamp');
        $nonce = HttpRequest::getGet('nonce');

  $token = $this->token;
  $tmpArr = array($token, $timestamp, $nonce);
  sort($tmpArr);
  $tmpStr = implode($tmpArr);
  $tmpStr = sha1($tmpStr);

  return ($tmpStr == $signature ? true : false);
 }

 /**
  * 验证token是否有效
  */
 public function valid()
 {
  if($this->checkSignature()) exit(HttpRequest::getGet('echostr'));
 }

}
相关文章
  • eaglephp使用微信api接口开发微信框架 2014-05-17

    EaglePHP框架开发微信5.0的API接口,包含微信5.0 API基础接口.自定义菜单.高级接口,包括如下接收用户消息.向用户回复消息.会话界面自定义菜单.语音识别.客服接口等功能 适用平台:window/Linux 依赖项目:EaglePHP框架 包含微信5.0 API基础接口.自定义菜单.高级接口,具体如下: 1.接收用户消息. 2.向用户回复消息. 3.接受事件推送. 4.会话界面自定义菜单. 5.语音识别. 6.客服接口. 7.OAuth2.0网页授权. 8.生成带参数二维码. 9.

  • PHP使用Face++接口开发微信公众平台人脸识别系统的方法 2013-10-10

    这篇文章主要介绍了PHP使用Face++接口开发微信公众平台人脸识别系统的方法,涉及微信公众平台相关接口的使用技巧,非常具有实用价值,需要的朋友可以参考下 本文实例讲述了PHP使用Face++接口开发微信公众平台人脸识别系统的方法.分享给大家供大家参考.具体如下: 效果图如下: 具体步骤如下: 首先,先登录Face++的官网注册账号:官网链接 注册之后会获取到api_secret和api_key,这些在调用接口的时候需要用到. 然后接下来的就是使用PHP脚本调用API了. 在使用PHP开发微信公

  • c#使用微信接口开发微信门户应用中微信消息的处理和应答 2014-03-20

    这篇文章主要介绍了c#使用微信接口开发微信门户中的微信消息的处理和应答的过程,需要的朋友可以参考下 微信应用如火如荼,很多公司都希望搭上信息快车,这个是一个商机,也是一个技术的方向,因此,有空研究下.学习下微信的相关开发,也就成为计划的安排事情之一了.本系列文章希望从一个循序渐进的角度上,全面介绍微信的相关开发过程和相关经验总结,希望给大家了解一下相关的开发历程.本篇随笔主要基于上一篇<c#使用微信接口开发微信门户应用>的基础上进行深入的介绍,介绍微信消息的处理和应答的过程. 1.微信的消息应

  • 浅谈使用 PHP 进行手机 APP 开发(API 接口开发) 2015-01-20

    做过 API 的人应该了解,其实开发 API 比开发 WEB 更简洁,但可能逻辑更复杂,因为 API 其实就是数据输出,不用呈现页面,所以也就不存在 MVC(API 只有 M 和 C),那么我们来探讨下,如何使用php进行手机API接口开发 一.先简单回答两个问题: 1.PHP 可以开发客户端? 答:可以,因为PHP是脚本语言,是负责完成 B/S架构 或 C/S架构 的S部分,即:主要用于服务端的开发.但是,PHP可不仅仅只能在互联网站上发展,一个PHP for Android(PFA)站点表示

  • c#使用微信接口开发微信门户应用 2014-02-28

    本系列文章希望从一个循序渐进的角度上,全面介绍微信的相关开发过程和相关经验总结,希望给大家了解一下相关的开发历程. 微信应用如火如荼,很多公司都希望搭上信息快车,这个是一个商机,也是一个技术的方向,因此,有空研究下.学习下微信的相关开发,也就成为日常计划的重要事情之一了.本系列文章希望从一个循序渐进的角度上,全面介绍微信的相关开发过程和相关经验总结,希望给大家了解一下相关的开发历程.本随笔主要针对微信开发过程的前期准备和一些初始的工作的介绍. 在写下本文的之前一周时间里,我主要就是参考一些介绍文

  • 网站直达上线运营,API接口开发中 2014-04-14

    今天(2014-4-14)开通的企业三剑客 的药店直达(http://store.yi18.net) 于是组成了 医药企业的三剑客 医院通 http://hospital.yi18.net 药企源 http://factory.yi18.net 药店直达 http://store.yi18.net 虽然网站还处于测试简单,并没有完成,网站的发布也在计划之内. 下一步就逐步完成功能和陆续开发这三块的API接口 ,请求期待-- 医药吧网 开发了药品.疾病.病状.手术.资讯.知识等相应的API接口 A

  • php如何设计微信支付接口 2015-03-18

    现在是微信时代,它的支付接口现在也慢慢的像支付宝一个可以利用api接口来实现第三方网站或应用进行支付了,下文整理了一个php微信支付接口开发程序并且己测试,有兴趣的朋友可进入reference,如何与国外有业务,也可以把国外支付接口palpal,visa等支付接口置入第三方应用程序 必要条件: appid //公众号后台开发者中心获得(和邮件内的一样) mchid//邮件内获得 key//商户后台自己设置 appsecret //公众号开发者中心获得 两个证书文件,邮件内获得 apiclient

  • JAVA微信公众账号开发平台 JeeWx 捷微 2014-07-06

    JeeWx 捷微 网站 : http://www.jeecg.org/ JeeWx,敏捷微信开发,简称"捷微",捷微是一款免费开源的JAVA微信公众账号开发平台. 平台介绍: 一.简介 jeewx是一个开源,高效,敏捷的微信开发平台采用JAVA语言,它是基于jeecg这个企业级快速开发框架实现的. jeewx的目的是最大化的简化微信开发的流程,使用开发者能把最好的精力放到微信具体业务开发,并能以最快的时间完成.把一些常规而频繁的工作交由jeewx来处理即可,平台兼备的代码生成器,在线开

  • 微信与第三方开发公司关系与再推风口浪尖 2015-05-06

    自从有了与腾讯有关的微信类开发应用:拍拍微店.京东微店.微信商城.微商城.微购物.微生活.微商户.微支付.微团购:一时间微信相关行业的人都鸡飞狗跳,业界的营销大湿.评论砖家.尤其是微信第三方开发者,大惊失色.奔走相告,大有狼来了的局势,那么"微信开小店,会不会把微信与第三方关系再推风口浪尖?""微信力推电商入歧途,或将逼死第三方"到目前为止,除了有一篇匿名的文章遮遮掩掩的提到了微盟的态度,其余也在微博上有发过一篇表态外,没有看到任何第三方正式的回应和声明,微码汇作为

  • [PhalApi]轻量级PHP后台接口开发框架 - 让接口开发更简单 - dogstar 2015-01-03

    一句话描述 PhalApi是一个轻量级PHP后台接口开发框架,目的是让接口开发更简单. 在这个框架中,我们不只是提供一个可以快速进行后台接口开发的框架,更多是分享那些有趣和值得学习.实践的内容,一如:领域驱动设计.设计模式.原则和最佳实践.敏捷开发.单元测试, 以及如何在此开发框架的基础上扩展衍生自定义的应用框架. 代码下载:http://git.codeweblog.com/dogstar/PhalApi WIKI文档:http://www.phalapi.net/wikis/ (全部设置了隐

  • 在Python的Bottle框架中使用微信API的示例 2014-02-25

    这篇文章主要介绍了在Python的Bottle框架中使用微信API的示例,作者还在文中给出了一个生成的微信可扫描的二维码图,需要的朋友可以参考下 微信这个东西估计宅男没几个不熟悉的吧,微信经过这么两年多的发展终于向开放平台跨出了友好的一步.蛋疼的以为微信会出一个详细的api等接口,兴奋不已的去申请了微信公共平台,然后开始找各种api的位置-- 花费了近一个小时,依然没找到-- 最后动用Google大杀器,终于找到了这么个链接.我了个去的,没比这还简单的api文档了吧. 最让人无法理解的是:居然没

  • 3款值得推荐的微信开发开源框架 2014-10-15

    下面向大家介绍的是微信开发项目里使用的3款基于PHP的开发框架,相信一定对你的开发工作有所帮助. 微信(英文名:wechat)是腾讯公司于2011年1月21日推出的一个为智能终端提供即时通讯服务的免费应用程序,微信支持跨通信运营商.跨操作系统平台通过网络快速发送免费(需消耗少量网络流量)语音短信.视频.图片和文字,同时,也可以使用通过共享流媒体内容的资料和基于位置的社交插件"摇一摇"."漂流瓶"."朋友圈"."公众平台".&q

  • 微信公众平台接口开发入门示例 2014-04-18

    这篇文章主要介绍了微信公众平台接口开发入门示例,较为简单透彻的分析了微信公众平台接口开发的技巧与具体方法,具有一定的参考借鉴价值,需要的朋友可以参考下 本文实例讲述了微信公众平台接口开发入门示例.分享给大家供大家参考.具体如下: 微信公众平台的接口开发是一个现在比较常用的功能了,很多的人都会去了解一下微信公众平台一些简单开发应用,这里就来给大家介绍一个入门示例. 这段时间都在忙于微信公众号平台来发,现在已经接近尾声了,所以对于微信开发平台的接口如何使用,在这里也唠刀一两句. 微信平台的开发并不像

  • .net实现微信公众账号接口开发实例代码 2014-10-27

    这篇文章主要介绍了.net实现微信公众账号接口开发实例代码,有需要的朋友可以参考一下 说起微信公众帐号,大家都不会陌生,使用这个平台能给网站或系统增加一个新亮点,直接进入正题吧,在使用之前一定要仔细阅读官方API文档. API文档地址:http://mp.weixin.qq.com/wiki/index.php 使用.net实现的方法: //微信接口地址 页面代码: weixin _wx = new weixin(); string postStr = ""; if (Request.

  • 微信公众平台开发 无高级接口账号获取用户基本信息 2014-05-20

    本文介绍如何获得微信公众平台关注用户的基本信息,包括昵称.头像.性别.国家.省份.城市.语言. 本文的方法将囊括订阅号和服务号以及自定义菜单各种场景,无论是否有高级接口权限,都有办法来获得用户基本信息,而无需模拟登录. 在本文中,特别要注意的是有两个不同的Access Token,他们产生的方式不一样,一种是使用AppID和AppSecret获取的access_token,一种是OAuth2.0授权中产生的access_token,方倍工作室分别称为全局Access Token和授权Access

  • PHP对接微信公众平台消息接口开发流程教程 2014-07-05

    这篇文章主要介绍了PHP对接微信公众平台消息接口开发流程,如何使用PHP版接口操作公众平台消息,需要的朋友可以参考下 一.写好接口程序 在你的服务器上上传好一个接口程序文件,如http://www.yourdomain.com/weixin.php 内容如下: <?php define("TOKEN", "weixin");//自己定义的token 就是个通信的私钥 $wechatObj = new wechatCallbackapiTest(); $wech

  • 一周的微信公众平台接口开发总结 2014-08-30

    在公司弄了一个星期的微信公众平台的接口开发,由于之前没弄过,开发的过程遇到了很多的小问题.下面我就总结一下我在开发过程中遇到了的问题和解决方法: 0x01首先是接口的配置问题 其实接口的配置一开始是没有问题的,但是后来我把它改成其他的之后再想改回来的时候发现改不回来了,总是报下面的错 后来才知道,修该接口配置的时候不能用之前用过的URL和TOKEN的组合. 0x02自定义菜单问题 在自定义菜单的设置过程中开始的时候发现怎么都设置不好,服务器总是返回 {"errcode":40016,&

  • 网站应用微信登录功能接口开发指南 2015-01-12

    准备工作 网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统. 在进行微信OAuth2.在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程. 授权流程说明 微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证

  • 微信公众账号接口开发 2013-06-20

    1. 注册微信公众账号 2. 微信公众账号开发者验证 3. 利用微信接口返回文本消息给用户 4. 利用微信接口返回图片消息给用户

  • 如何基于微信开放接口开发企业的微信 CRM? 2013-11-05

    [核心提示] 企业要开发微信 CRM,首先要从业务架构上进行设计清楚.微信 CRM 的本质,是在微信渠道上利用微信的特点和接口而扩展的 CRM 系统. 业内一直都在传说微信是天生的 CRM,可是没有人看到过微信 CRM 的真容.随着微信最新公众平台的改版和开放接口的微信认证开放,微信 CRM 离企业越来越近.汉拓科技第一时间申请认证并对接了微信开放接口,在此就详细展开一下,与大家分享如何基于微信开放接口来开发企业的微信 CRM? 企业要开发微信CRM,首先要从业务架构上进行设计清楚.微信 CRM