设为首页收藏本站

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 397|回复: 3

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

[复制链接]
发表于 2014-3-10 12:13:05 | 显示全部楼层 |阅读模式
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、用户分组。


  1. <P> </P>
  2. <DIV class=blockcode>
  3. <BLOCKQUOTE><?php
  4. /**
  5. * 微信公众平台API
  6. */
  7. class WeixinChat
  8. {

  9. private $token;

  10. private $appid;

  11. private $appsecret;

  12. private $access_token;

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

  15. private $_reply = '';

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

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

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

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

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

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

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

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

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

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

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

  38. // 获取 access_token
  39. const AUTH_URL = '/token?grant_type=client_credential&';

  40. // 获取用户基本信息
  41. const USER_INFO_URL = '/user/info?';

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

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

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

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

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

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

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



  56. /**
  57. * 初始化配置数据
  58. * @param array $options
  59. */
  60. public function __construct($options)
  61. {
  62. $this->token = isset($options['token']) ? $options['token'] : '';
  63. $this->appid = isset($options['appid']) ? $options['appid'] : '';
  64. $this->appsecret = isset($options['appsecret']) ? $options['appsecret'] : '';
  65. }


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


  80. /**
  81. * 获取微信服务器发来的消息
  82. */
  83. public function getRevData()
  84. {
  85. return $this->_receive;
  86. }


  87. /**
  88. * 获取接收者
  89. */
  90. public function getRevTo()
  91. {
  92. return isset($this->_receive['ToUserName']) ? $this->_receive['ToUserName'] : false;
  93. }


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


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


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


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


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


  132. /**
  133. * 获取接收图片消息
  134. */
  135. public function getRevImage()
  136. {
  137. if(isset($this->_receive['PicUrl'])){
  138. return array(
  139. 'picUrl' => $this->_receive['PicUrl'], //图片链接
  140. 'mediaId' => $this->_receive['MediaId'] //图片消息媒体id,可以调用多媒体文件下载接口拉取数据。
  141. );
  142. }
  143. return false;
  144. }


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


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


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


  196. /**
  197. * 获取接收链接消息
  198. */
  199. public function getRevLink()
  200. {
  201. if(isset($this->_receive['Title'])){
  202. return array(
  203. 'title' => $this->_receive['Title'], //消息标题
  204. 'description' => $this->_receive['Description'], //消息描述
  205. 'url' => $this->_receive['Url'] //消息链接
  206. );
  207. }
  208. return false;
  209. }


  210. /**
  211. * 获取接收事件类型
  212. * 事件类型如:subscribe(订阅)、unsubscribe(取消订阅)、click
  213. */
  214. public function getRevEvent()
  215. {
  216. if(isset($this->_receive['Event']))
  217. {
  218. return array(
  219. 'event' => strtolower($this->_receive['Event']),
  220. 'key'=> isset($this->_receive['EventKey']) ? $this->_receive['EventKey'] : ''
  221. );
  222. }
  223. return false;
  224. }
复制代码


 楼主| 发表于 2014-3-10 12:15:37 | 显示全部楼层

  1. <P><?php

  2. /**
  3. * 设置回复文本消息
  4. * @param string $content
  5. * @param string $openid
  6. */
  7. public function text($content='')
  8. {
  9. $textTpl = "<xml>
  10. <ToUserName><![CDATA[%s]]></ToUserName>
  11. <FromUserName><![CDATA[%s]]></FromUserName>
  12. <CreateTime>%s</CreateTime>
  13. <MsgType><![CDATA[%s]]></MsgType>
  14. <Content><![CDATA[%s]]></Content>
  15. </xml>";

  16. $this->_reply = sprintf($textTpl,
  17. $this->getRevFrom(),
  18. $this->getRevTo(),
  19. Date::getTimeStamp(),
  20. 'text',
  21. $content
  22. );
  23. return $this;
  24. }


  25. /**
  26. * 设置回复音乐信息
  27. * @param string $title
  28. * @param string $desc
  29. * @param string $musicurl
  30. * @param string $hgmusicurl
  31. */
  32. public function music($title, $desc, $musicurl, $hgmusicurl='')
  33. {
  34. $textTpl = '<xml>
  35. <ToUserName><![CDATA[%s]]></ToUserName>
  36. <FromUserName><![CDATA[%s]]></FromUserName>
  37. <CreateTime>%s</CreateTime>
  38. <MsgType><![CDATA[%s]]></MsgType>
  39. <Music>
  40. <Title><![CDATA[%s]]></Title>
  41. <Description><![CDATA[%s]]></Description>
  42. <MusicUrl><![CDATA[%s]]></MusicUrl>
  43. <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
  44. </Music>
  45. </xml>';
  46. //<ThumbMediaId><![CDATA[%s]]></ThumbMediaId>

  47. $this->_reply = sprintf($textTpl,
  48. $this->getRevFrom(),
  49. $this->getRevTo(),
  50. Date::getTimeStamp(),
  51. 'music',
  52. $title,
  53. $desc,
  54. $musicurl,
  55. $hgmusicurl
  56. );
  57. return $this;
  58. }


  59. /**
  60. * 回复图文消息
  61. * @param array
  62. */
  63. public function news($data)
  64. {
  65. $count = count($data);
  66. $subText = '';
  67. if($count > 0)
  68. {
  69. foreach($data as $v)
  70. {
  71. $tmpText = '<item>
  72. <Title><![CDATA[%s]]></Title>
  73. <Description><![CDATA[%s]]></Description>
  74. <PicUrl><![CDATA[%s]]></PicUrl>
  75. <Url><![CDATA[%s]]></Url>
  76. </item>';

  77. $subText .= sprintf(
  78. $tmpText, $v['title'],
  79. isset($v['description']) ? $v['description'] : '',
  80. isset($v['picUrl']) ? $v['picUrl'] : '',
  81. isset($v['url']) ? $v['url'] : ''
  82. );
  83. }
  84. }

  85. $textTpl = '<xml>
  86. <ToUserName><![CDATA[%s]]></ToUserName>
  87. <FromUserName><![CDATA[%s]]></FromUserName>
  88. <CreateTime><![CDATA[%s]]></CreateTime>
  89. <MsgType><![CDATA[news]]></MsgType>
  90. <ArticleCount><![CDATA[%d]]></ArticleCount>
  91. <Articles>%s</Articles>
  92. </xml>';

  93. $this->_reply = sprintf(
  94. $textTpl,
  95. $this->getRevFrom(),
  96. $this->getRevTo(),
  97. Date::getTimeStamp(),
  98. $count,
  99. $subText
  100. );
  101. return $this;
  102. }


  103. /**
  104. * 回复消息
  105. * @param array $msg
  106. * @param bool $return
  107. */
  108. public function reply()
  109. {
  110. header('Content-Type:text/xml');
  111. echo $this->_reply;
  112. exit;
  113. }


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

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

  128. return false;
  129. }


  130. /**
  131. * 自定义菜单查询
  132. */
  133. public function getMenu()
  134. {
  135. if(!$this->access_token && !$this->checkAuth()) return false;

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

  143. return false;
  144. }


  145. /**
  146. * 自定义菜单删除
  147. */
  148. public function deleteMenu()
  149. {
  150. if(!$this->access_token && !$this->checkAuth()) return false;

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

  158. return false;
  159. }


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

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

  174. return false;
  175. }


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

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

  190. return false;
  191. }
  192. </P>
  193. <P>?>
  194. </P>
复制代码

 楼主| 发表于 2014-3-10 12:18:31 | 显示全部楼层
  1. /**
  2. * 查询分组
  3. */
  4. public function getGroup()
  5. {
  6. if(!$this->access_token && !$this->checkAuth()) return false;

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

  14. return false;
  15. }


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

  31. return false;
  32. }


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

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

  49. return false;
  50. }


  51. /**
  52. * 移动用户分组
  53. *
  54. * @param string $openid 用户唯一标识符
  55. * @param int $to_groupid 分组id
  56. */
  57. public function updateGroupMembers($openid, $to_groupid)
  58. {
  59. if(!$this->access_token && !$this->checkAuth()) return false;

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

  68. return false;
  69. }


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

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

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

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

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

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

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

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

  117. return false;
  118. }



  119. /**
  120. * 获取access_token
  121. */
  122. public function checkAuth()
  123. {

  124. // 从缓存中获取access_token
  125. $cache_flag = 'weixin_access_token';
  126. $access_token = cache($cache_flag);
  127. if($access_token)
  128. {
  129. $this->access_token = $access_token;
  130. return true;
  131. }

  132. // 请求微信服务器获取access_token
  133. $result = curlRequest(self::API_URL_PREFIX.self::AUTH_URL.'appid='.$this->appid.'&secret='.$this->appsecret);
  134. if($result)
  135. {
  136. $jsonArr = json_decode($result, true);
  137. if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0))
  138. {
  139. $this->error($jsonArr);
  140. }
  141. else
  142. {
  143. $this->access_token = $jsonArr['access_token'];
  144. $expire = isset($jsonArr['expires_in']) ? intval($jsonArr['expires_in'])-100 : 3600;
  145. // 将access_token保存到缓存中
  146. cache($cache_flag, $this->access_token, $expire, Cache::FILE);
  147. return true;
  148. }
  149. }
  150. return false;
  151. }
复制代码
 楼主| 发表于 2014-3-10 12:19:00 | 显示全部楼层
  1. /**
  2. * 微信oauth登陆->第一步:用户同意授权,获取code
  3. * 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),
  4. * snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
  5. * 直接在微信打开链接,可以不填此参数。做页面302重定向时候,必须带此参数
  6. *
  7. * @param string $redirect_uri 授权后重定向的回调链接地址
  8. * @param string $scope 应用授权作用域 0为snsapi_base,1为snsapi_userinfo
  9. * @param string $state 重定向后会带上state参数,开发者可以填写任意参数值
  10. */
  11. public function redirectGetOauthCode($redirect_uri, $scope=0, $state='')
  12. {
  13. $scope = ($scope == 0) ? 'snsapi_base' : 'snsapi_userinfo';
  14. $url = self::CONNECT_OAUTH_AUTHORIZE_URL.'appid='.$this->appid.'&redirect_uri='.urlencode($redirect_uri).'&response_type=code&scope='.$scope.'&state='.$state.'#wechat_redirect';
  15. redirect($url);
  16. }


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

  31. return false;
  32. }


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

  49. return false;
  50. }


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

  67. return false;
  68. }


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

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

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

  91. return false;
  92. }


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


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


  115. /**
  116. * 将数组中的中文转换成json数据
  117. * @param array $arr
  118. */
  119. public function jsonEncode($arr) {
  120. $parts = array ();
  121. $is_list = false;
  122. //Find out if the given array is a numerical array
  123. $keys = array_keys ( $arr );
  124. $max_length = count ( $arr ) - 1;
  125. if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) { //See if the first key is 0 and last key is length - 1
  126. $is_list = true;
  127. for($i = 0; $i < count ( $keys ); $i ++) { //See if each key correspondes to its position
  128. if ($i != $keys [$i]) { //A key fails at position check.
  129. $is_list = false; //It is an associative array.
  130. break;
  131. }
  132. }
  133. }
  134. foreach ( $arr as $key => $value ) {
  135. if (is_array ( $value )) { //Custom handling for arrays
  136. if ($is_list)
  137. $parts [] = $this->jsonEncode ( $value ); /* :RECURSION: */
  138. else
  139. $parts [] = '"' . $key . '":' . $this->jsonEncode ( $value ); /* :RECURSION: */
  140. } else {
  141. $str = '';
  142. if (! $is_list)
  143. $str = '"' . $key . '":';
  144. //Custom handling for multiple data types
  145. if (is_numeric ( $value ) && $value<2000000000)
  146. $str .= $value; //Numbers
  147. elseif ($value === false)
  148. $str .= 'false'; //The booleans
  149. elseif ($value === true)
  150. $str .= 'true';
  151. else
  152. $str .= '"' . addslashes ( $value ) . '"'; //All other things
  153. // :TODO: Is there any more datatype we should be in the lookout for? (Object?)
  154. $parts [] = $str;
  155. }
  156. }
  157. $json = implode ( ',', $parts );
  158. if ($is_list)
  159. return '[' . $json . ']'; //Return numerical JSON
  160. return '{' . $json . '}'; //Return associative JSON
  161. }


  162. /**
  163. * 检验签名
  164. */
  165. public function checkSignature()
  166. {
  167. $signature = HttpRequest::getGet('signature');
  168. $timestamp = HttpRequest::getGet('timestamp');
  169. $nonce = HttpRequest::getGet('nonce');

  170. $token = $this->token;
  171. $tmpArr = array($token, $timestamp, $nonce);
  172. sort($tmpArr);
  173. $tmpStr = implode($tmpArr);
  174. $tmpStr = sha1($tmpStr);

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


  177. /**
  178. * 验证token是否有效
  179. */
  180. public function valid()
  181. {
  182. if($this->checkSignature()) exit(HttpRequest::getGet('echostr'));
  183. }

  184. }
复制代码

您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|小黑屋|BC Morning Website ( Best Deal Inc. 001 )  

GMT-8, 2025-8-26 13:51 , Processed in 0.017581 second(s), 17 queries .

Supported by Best Deal Online X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表