Home Backend Development PHP Tutorial The latest and most comprehensive API interface of WeChat 5.0 developed based on EaglePHP framework v2.7

The latest and most comprehensive API interface of WeChat 5.0 developed based on EaglePHP framework v2.7

Jul 25, 2016 am 08:49 AM

Code source: http://www.eaglephp.com
Applicable platform: window/Linux
Dependent projects: EaglePHP framework

Includes WeChat 5.0 API basic interface, custom menu, and advanced interface, as follows:
1. Receive user messages .
2. Reply to the user.
3. Accept event push.
4. Conversation interface custom menu.
5. Voice recognition.
6. Customer service interface.
7. OAuth2.0 web authorization.
8. Generate QR code with parameters.
9. Obtain the user’s geographical location.
10. Obtain basic user information.
11. Get the followers list.
12. User grouping.
  1. /**
  2. * WeChat public platform API
  3. *
  4. * @author maojianlw@139.com
  5. * [url=home.php?mod=space&uid=17823]@LINK[/url] http://www.eaglephp.com
  6. */
  7. class WeixinChat
  8. {
  9. private $token;
  10. private $appid;
  11. private $appsecret;
  12. private $access_token;
  13. // Received data
  14. private $_receive = array();
  15. private $_reply = '';
  16. // Interface error code
  17. private $errCode = '';
  18. // Interface error message
  19. private $errMsg = '' ;
  20. // Log in with WeChat oauth to get the code
  21. const CONNECT_OAUTH_AUTHORIZE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize?';
  22. // Log in with WeChat oauth and exchange the code for webpage authorization access_token
  23. const SNS_OAUTH_ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token?';
  24. // WeChat oauth login refresh access_token (if necessary)
  25. const SNS_OAUTH_REFRESH_TOKEN_URL = 'https://api.weixin.qq .com/sns/oauth2/refresh_token?';
  26. // Exchange ticket for QR code
  27. const SHOW_QRCODE_URL = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?';
  28. // WeChat oauth login pulls user information (needs scope is snsapi_userinfo)
  29. const SNS_USERINFO_URL = 'https://api.weixin.qq.com/sns/userinfo?';
  30. // Request api prefix
  31. const API_URL_PREFIX = 'https: //api.weixin.qq.com/cgi-bin';
  32. // Custom menu creation
  33. const MENU_CREATE_URL = '/menu/create?';
  34. // Custom menu query
  35. const MENU_GET_URL = '/menu /get?';
  36. // Custom menu deletion
  37. const MENU_DELETE_URL = '/menu/delete?';
  38. // Get access_token
  39. const AUTH_URL = '/token?grant_type=client_credential&';
  40. // Get user Basic information
  41. const USER_INFO_URL = '/user/info?';
  42. // Get the follower list
  43. const USER_GET_URL = '/user/get?';
  44. // Query the group
  45. const GROUPS_GET_URL = '/groups/get? ';
  46. // Create a group
  47. const GROUPS_CREATE_URL = '/groups/create?';
  48. // Modify the group name
  49. const GROUPS_UPDATE_URL = '/groups/update?';
  50. // Move user groups
  51. const GROUPS_MEMBERS_UPDATE_URL = '/groups/members/update?';
  52. //Send customer service message
  53. const MESSAGE_CUSTOM_SEND_URL = '/message/custom/send?';
  54. //Create QR code ticket
  55. const QRCODE_CREATE_URL = '/qrcode/create? ';
  56. /**
  57. * Initialization configuration data
  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. * Get incoming messages
  68. * When an ordinary WeChat user sends a message to a public account, the WeChat server will POST the XML data packet of the message to the URL filled in by the developer.
  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. * Get messages sent from WeChat server
  82. */
  83. public function getRevData()
  84. {
  85. return $this->_receive;
  86. }
  87. /**
  88. * Get receiver
  89. */
  90. public function getRevTo()
  91. {
  92. return isset($this->_receive['ToUserName']) ? $this->_receive['ToUserName'] : false;
  93. }
  94. /**
  95. * Get the message sender (an OpenID)
  96. */
  97. public function getRevFrom()
  98. {
  99. return isset($this->_receive['FromUserName']) ? $this->_receive['FromUserName'] : false;
  100. }
  101. /* *
  102. * Get the creation time of the received message (integer type)
  103. */
  104. public function getRevCTime()
  105. {
  106. return isset($this->_receive['CreateTime']) ? $this->_receive['CreateTime'] : false;
  107. }
  108. /**
  109. * Get the received message type (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. * Get the received message number
  117. */
  118. public function getRevId()
  119. {
  120. return isset($this->_receive['MsgId']) ? $this->_receive['MsgId'] : false;
  121. }
  122. /**
  123. * Get the received message text
  124. * Through the speech recognition interface, the voice sent by the user will also give the text content recognized by the speech recognition.(You need to apply for the advanced interface permission of the service account)
  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. * Get and receive picture messages
  134. */
  135. public function getRevImage()
  136. {
  137. if(isset($this->_receive['PicUrl'])){
  138. return array(
  139. 'picUrl' => $this-> _receive['PicUrl'], //Picture link
  140. 'mediaId' => $this->_receive['MediaId'] //Picture message media id, you can call the multimedia file download interface to pull the data. }
  141. return false;
  142. }
  143. /**
  144. * Get and receive voice messages
  145. */
  146. public function getRevVoice()
  147. {
  148. if(isset($this->_receive['MediaId'])){
  149. return array(
  150. 'mediaId' => $this->_receive['MediaId'], //Voice message media id, you can call the multimedia file download interface to pull data.
  151. 'format' => $this->_receive[' Format'] //Voice format, such as amr, speex, etc.
  152. );
  153. }
  154. return false;
  155. }
  156. /**
  157. *Get to receive video messages
  158. */
  159. public function getRevVideo()
  160. {
  161. if(isset($this ->_receive['MediaId'])){
  162. return array(
  163. 'mediaId' => $this->_receive['MediaId'], //Video message media id, you can call the multimedia file download interface to pull it data.
  164. 'thumbMediaId' => $this->_receive['ThumbMediaId'] //The media ID of the video message thumbnail, you can call the multimedia file download interface to pull the data.
  165. );
  166. }
  167. return false;
  168. }
  169. /**
  170. * Get the user’s geographical location
  171. */
  172. public function getRevLocation()
  173. {
  174. if(isset($this->_receive['Location_X'])){
  175. return array(
  176. 'locationX' => $this->_receive['Location_X'], //Geographical location dimension
  177. 'locationY' => $this->_receive['Location_Y'], //Geographical location Longitude
  178. 'scale' => $this->_receive['Scale'], //Map zoom size
  179. 'label' => $this->_receive['Label'] //Geographical location information
  180. ) ;
  181. }
  182. //For a public account that has opened a geographical location reporting interface, when a user enters the public account session after following it, a box will pop up asking the user to confirm whether the public account is allowed to use its geographical location.
  183. //The pop-up box only appears once after following it. Users can operate on the official account details page in the future.
  184. elseif(isset($this->_receive['Latitude']))
  185. {
  186. return array(
  187. 'latitude' => $this->_receive['Latitude'], //Geographical location latitude
  188. ' longitude' => $this->_receive['Longitude'], //Geographical location longitude
  189. 'precision' => $this->_receive['Precision'] //Geographical location precision
  190. );
  191. }
  192. return false;
  193. }
  194. /**
  195. * Get receiving link message
  196. */
  197. public function getRevLink()
  198. {
  199. if(isset($this->_receive['Title'])){
  200. return array(
  201. ' title' => $this->_receive['Title'], //Message title
  202. 'description' => $this->_receive['Description'], //Message description
  203. 'url' => ; $this->_receive['Url'] //Message link
  204. );
  205. }
  206. return false;
  207. }
  208. /**
  209. * Get the receiving event type
  210. * Event types such as: subscribe, unsubscribe, click
  211. */
  212. public function getRevEvent()
  213. {
  214. if(isset ($this->_receive['Event']))
  215. {
  216. return array(
  217. 'event' => strtolower($this->_receive['Event']),
  218. 'key'=> isset ($this->_receive['EventKey']) ? $this->_receive['EventKey'] : ''
  219. );
  220. }
  221. return false;
  222. }
  223. /**
  224. * Set reply text message
  225. * @param string $content
  226. * @param string $openid
  227. */
  228. public function text($content='')
  229. {
  230. $textTpl = "
  231. < ;![CDATA[%s]]>
  232. %s
  233. ";
  234. $this->_reply = sprintf($textTpl,
  235. $this->getRevFrom (),
  236. $this->getRevTo(),
  237. Date::getTimeStamp(),
  238. 'text',
  239. $content
  240. );
  241. return $this;
  242. }
  243. /**
  244. * Set reply music information
  245. * @param string $title
  246. * @param string $desc
  247. * @param string $musicurl
  248. * @param string $hgmusicurl
  249. */
  250. public function music($title, $desc, $musicurl, $hgmusicurl='')
  251. {
  252. $textTpl = '
  253. < /ToUserName>
  254. %s
  255. <![CDATA[%s]]>
  256. ';
  257. //
  258. $this->_reply = sprintf( $textTpl,
  259. $this->getRevFrom(),
  260. $this->getRevTo(),
  261. Date::getTimeStamp(),
  262. 'music',
  263. $title,
  264. $desc,
  265. $musicurl,
  266. $ hgmusicurl
  267. );
  268. return $this;
  269. }
  270. /**
  271. * Reply to text message
  272. * @param array
  273. */
  274. public function news($data)
  275. {
  276. $count = count($data);
  277. $subText = '';
  278. if($count > 0)
  279. {
  280. foreach($data as $v)
  281. {
  282. $tmpText = '
  283. <![CDATA[%s]]></ Title> </li> <li> <Description><![CDATA[%s]]></Description></li> <li> <PicUrl><![CDATA[%s]]></PicUrl></li> <li> <Url> ;<![CDATA[%s]]></Url></li> <li> </item>';</li> <li> </li> <li> $subText .= sprintf(</li> <li> $tmpText, $v['title'], </li> <li> isset($ v['description']) ? $v['description'] : '', </li> <li> isset($v['picUrl']) ? $v['picUrl'] : '', </li> <li> isset($v['url ']) ? $v['url'] : ''</li> <li> );</li> <li> }</li> <li> }</li> <li> </li> <li> $textTpl = '<xml></li> <li> <ToUserName><![CDATA[%s]]></ToUserName></li> <li> <FromUserName><![CDATA[%s]]></FromUserName></li> <li> <CreateTime><![CDATA[%s]]></CreateTime></li> <li> <MsgType><![CDATA[news]]></MsgType></li> <li> <ArticleCount><![CDATA[%d]]></ArticleCount></li> <li> <Articles>%s</Articles></li> <li> </xml>';</li> <li> </li> <li> $this->_reply = sprintf(</li> <li> $textTpl, </li> <li> $this->getRevFrom(), </li> <li> $this->getRevTo(), </li> <li> Date::getTimeStamp(), </li> <li> $count, </li> <li> $subText</li> <li> );</li> <li> return $this;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Reply message </li> <li> * @param array $msg</li> <li> * @param bool $return</li> <li>*/</li> <li> public function reply()</li> <li> {</li> <li> header('Content-Type:text/xml');</li> <li> echo $this->_reply;</li> <li> exit;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Custom menu creation </li> <li> * @param array menu data </li> <li>*/</li> <li> public function createMenu($data)</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::MENU_CREATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return true;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> *Customized menu query</li> <li>*/</li> <li> public function getMenu()</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::MENU_GET_URL.'access_token='.$this->access_token);</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return $jsonArr;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> *Custom menu deleted</li> <li>*/</li> <li> public function deleteMenu()</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::MENU_DELETE_URL.'access_token='.$this->access_token);</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return true;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Get basic user information </li> <li> * @param string $openid Identification of ordinary users, unique to the current public account </li> <li>*/</li> <li> public function getUserInfo($openid)</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::USER_INFO_URL.'access_token='.$this->access_token.'&openid='.$openid);</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return $jsonArr;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Get the follower list </li> <li> * @param string $next_openid The first OPENID to pull, if not filled in, it will start pulling from the beginning by default </li> <li>*/</li> <li> public function getUserList($next_openid='')</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::USER_GET_URL.'access_token='.$this->access_token.'&next_openid='.$next_openid);</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return $jsonArr;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Query grouping </li> <li>*/</li> <li> public function getGroup()</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::GROUPS_GET_URL.'access_token='.$this->access_token);</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return $jsonArr;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Create a group </li> <li> * @param string $name Group name (within 30 characters) </li> <li>*/</li> <li> public function createGroup($name)</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> $data = array('group' => array('name' => $name));</li> <li> $result = curlRequest(self::API_URL_PREFIX.self::GROUPS_CREATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return true;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Modify the group name </li> <li> * @param int $id Group id, assigned by WeChat </li> <li> * @param string $name Group name (within 30 characters) </li> <li>*/</li> <li> public function updateGroup($id, $name)</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $data = array('group' => array('id' => $id, 'name' => $name));</li> <li> $result = curlRequest(self::API_URL_PREFIX.self::GROUPS_UPDATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return true;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Mobile user group</li> <li> * </li> <li> * @param string $openid User unique identifier</li> <li> * @param int $to_groupid Group id</li> <li>*/</li> <li> public function updateGroupMembers($openid, $to_groupid)</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $data = array('openid' => $openid, 'to_groupid' => $to_groupid);</li> <li> $result = curlRequest(self::API_URL_PREFIX.self::GROUPS_MEMBERS_UPDATE_URL.'access_token='.$this->access_token, $this->jsonEncode($data), 'post');</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return true;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * 发送客服消息</li> <li> * 当用户主动发消息给公众号的时候(包括发送信息、点击自定义菜单clike事件、订阅事件、扫描二维码事件、支付成功事件、用户维权),</li> <li> * 微信将会把消息数据推送给开发者,开发者在一段时间内(目前为24小时)可以调用客服消息接口,通过POST一个JSON数据包来发送消息给普通用户,在24小时内不限制发送次数。</li> <li> * 此接口主要用于客服等有人工消息处理环节的功能,方便开发者为用户提供更加优质的服务。</li> <li> * </li> <li> * @param string $touser ordinary user openid</li> <li> */</li> <li> public function sendCustomMessage($touser, $data, $msgType = 'text')</li> <li> {</li> <li> $arr = array();</li> <li> $arr['touser' ] = $touser;</li> <li> $arr['msgtype'] = $msgType;</li> <li> switch ($msgType)</li> <li> {</li> <li> case 'text': // Send text message</li> <li> $arr['text']['content'] = $data; </li> <li> break;</li> <li> </li> <li> case 'image': // Send a picture message </li> <li> $arr['image']['media_id'] = $data;</li> <li> break;</li> <li> </li> <li> case 'voice': // Send a voice message </li> <li> $arr['voice']['media_id'] = $data;</li> <li> break;</li> <li> </li> <li> case 'video': // Send video message </li> <li> $arr['video']['media_id'] = $data[' media_id']; // The media ID of the video sent</li> <li> $arr['video']['thumb_media_id'] = $data['thumb_media_id']; // The media ID of the video thumbnail</li> <li> break;</li> <li> </li> <li> case 'music ': //Send music message</li> <li> $arr['music']['title'] = $data['title'];//Music title</li> <li> $arr['music']['description'] = $data[ 'description'];//Music description</li> <li> $arr['music']['musicurl'] = $data['musicurl'];//Music link</li> <li> $arr['music']['hqmusicurl'] = $ data['hqmusicurl'];// High-quality music link, the wifi environment will give priority to using this link to play music</li> <li> $arr['music']['thumb_media_id'] = $data['title'];// Thumbnail media ID</li> <li> break;</li> <li> </li> <li> case 'news': //Send graphic message</li> <li> $arr['news']['articles'] = $data; // title, description, url, picurl</li> <li> break;</li> <li> } </li> <li> </li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::MESSAGE_CUSTOM_SEND_URL.'access_token='.$this-> access_token, $this->jsonEncode($arr), 'post');</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($ jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return true;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> </li> <li> / **</li> <li> * Get access_token</li> <li>*/</li> <li> public function checkAuth()</li> <li> {</li> <li> </li> <li> // Get access_token from cache</li> <li> $cache_flag = 'weixin_access_token';</li> <li> $access_token = cache($cache_flag);</li> <li> if($access_token) </li> <li> { </li> <li> $this->access_token = $access_token;</li> <li> return true;</li> <li> }</li> <li> </li> <li> // Request the WeChat server to obtain access_token </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::AUTH_URL.'appid='.$this- >appid.'&secret='.$this->appsecret);</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr ['errcode']) && $jsonArr['errcode'] > 0))</li> <li> {</li> <li> $this->error($jsonArr);</li> <li> }</li> <li> else</li> <li> {</li> <li> $this->access_token = $jsonArr[ 'access_token'];</li> <li> $expire = isset($jsonArr['expires_in']) ? intval($jsonArr['expires_in'])-100 : 3600;</li> <li> // Save access_token to cache</li> <li> cache($cache_flag, $this->access_token, $expire, Cache::FILE); </li> <li> return true;</li> <li> }</li> <li> }</li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * WeChat oauth login->Step 1: User consent Authorize, get code</li> <li> * Application authorization scope, snsapi_base (the authorization page will not pop up, jump directly, only the user's openid can be obtained), </li> <li> * snsapi_userinfo (the authorization page will pop up, you can get the nickname, gender, and location through openid). Moreover, even if you are not following the user, you can still obtain their information as long as the user authorizes it)</li> <li> * Open the link directly on WeChat, you do not need to fill in this parameter.When doing page 302 redirection, you must bring this parameter</li> <li> * </li> <li> * @param string $redirect_uri The callback link address for redirection after authorization</li> <li> * @param string $scope Application authorization scope 0 is snsapi_base, 1 is snsapi_userinfo</li> <li> * @param string $state will bring the state parameter after redirection. Developers can fill in any parameter value</li> <li> */</li> <li> public function redirectGetOauthCode($redirect_uri, $scope=0, $state='')</li> <li> {</li> <li> $scope = ($scope == 0) ? 'snsapi_base' : 'snsapi_userinfo';</li> <li> $url = self::CONNECT_OAUTH_AUTHORIZE_URL.'appid='.$this->appid.'&redirect_uri='.urlencode($redirect_uri).'&response_type=code&scope= '.$scope.'&state='.$state.'#wechat_redirect';</li> <li> redirect($url);</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * WeChat oauth login-> Step 2: Exchange the code for webpage authorization access_token</li> <li> * </li> <li> * @param string $code</li> <li>*/</li> <li> public function getSnsAccessToken($code)</li> <li> {</li> <li> $ result = curlRequest(self::SNS_OAUTH_ACCESS_TOKEN_URL.'appid='.$this->appid.'&secret='.$this->appsecret.'&code='.$code.'&grant_type=authorization_code');</li> <li> if ($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return $jsonArr;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * WeChat oauth login-> Step 3: Refresh access_token (if necessary) </li> <li> * Since access_token has a short validity period, when the access_token times out, you can use refresh_token to refresh, </li> <li> * refresh_token has a longer validity period (7 days , 30 days, 60 days, 90 days), when refresh_token expires, the user needs to re-authorize. </li> <li> * </li> <li> * @param string $refresh_token Fill in the refresh_token parameter obtained through access_token</li> <li>*/</li> <li> public function refershToken($refresh_token)</li> <li> {</li> <li> $result = curlRequest(self::SNS_OAUTH_REFRESH_TOKEN_URL.'appid='.$this->appid.'&grant_type=refresh_token&refresh_token='.$refresh_token);</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true) ;</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return $jsonArr; </li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * WeChat oauth login-> Step 4: Pull user information (need to have scope snsapi_userinfo)</li> <li> * If the web page authorization scope is snsapi_userinfo, the developer can now pull user information through access_token and openid. </li> <li> * </li> <li> * @param string $access_token Web page authorization interface call certificate, note: this access_token is different from the basic supported access_token</li> <li> * @param string $openid The unique identifier of the user</li> <li>*/</li> <li> public function getSnsUserInfo($access_token, $openid)</li> <li> {</li> <li> $result = curlRequest(self::SNS_USERINFO_URL.'access_token='.$ access_token.'&openid='.$openid);</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr || (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return $jsonArr;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Create a QR code ticket</li> <li> * Each time you create a QR code ticket, you need to provide a parameter (scene_id) set by the developer. The process of creating a QR code ticket for temporary QR codes and permanent QR codes is introduced respectively. </li> <li> * </li> <li> * @param int $scene_id Scene value ID, 32-bit integer for temporary QR code, maximum value is 1000 for permanent QR code</li> <li> * @param int $type QR code type, 0 is temporary, 1 It is permanent</li> <li> * @param int $expire The validity time of this QR code, in seconds. The maximum number does not exceed 1800. </li> <li>*/ </li> <li> public function createQrcode($scene_id, $type=0, $expire=1800)</li> <li> {</li> <li> if(!$this->access_token && !$this->checkAuth()) return false;</li> <li> </li> <li> $data = array ();</li> <li> $data['action_info'] = array('scene' => array('scene_id' => $scene_id));</li> <li> $data['action_name'] = ($type == 0 ? ' QR_SCENE' : 'QR_LIMIT_SCENE');</li> <li> if($type == 0) $data['expire_seconds'] = $expire;</li> <li> </li> <li> $result = curlRequest(self::API_URL_PREFIX.self::QRCODE_CREATE_URL.'access_token='. $this->access_token, $this->jsonEncode($data), 'post');</li> <li> if($result)</li> <li> {</li> <li> $jsonArr = json_decode($result, true);</li> <li> if(!$jsonArr | | (isset($jsonArr['errcode']) && $jsonArr['errcode'] > 0)) $this->error($jsonArr);</li> <li> else return $jsonArr;</li> <li> }</li> <li> </li> <li> return false;</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Exchange tickets for QR codes</li> <li> * After obtaining a QR code ticket, developers can exchange the ticket for a QR code image. Please note that this interface can be called without logging in. </li> <li> * Reminder: Remember to UrlEncode TICKET</li> <li> * When the ticket is correct, the http return code is 200, which is a picture and can be displayed or downloaded directly. </li> <li> * HTTP error code 404 will be returned in error situations (such as invalid ticket).</li> <li> * </li> <li> * @param string $ticket</li> <li> */</li> <li> public function getQrcodeUrl($ticket)</li> <li> {</li> <li> return self::SHOW_QRCODE_URL.'ticket='.urlencode($ticket);</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Record the error log generated by the interface</li> <li>*/</li> <li> public function error($data)</li> <li> {</li> <li> $this->errCode = $data['errcode'];</li> <li> $this->errMsg = $data['errmsg'];</li> <li> Log::info('WEIXIN API errcode:['.$this->errCode.'] errmsg:['.$this->errMsg.']');</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Convert Chinese in the array into json data</li> <li> * @param array $arr</li> <li>*/</li> <li> public function jsonEncode($arr) {</li> <li> $parts = array ();</li> <li> $is_list = false;</li> <li> //Find out if the given array is a numerical array</li> <li> $keys = array_keys ( $arr );</li> <li> $max_length = count ( $arr ) - 1;</li> <li> if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) { //See if the first key is 0 and last key is length - 1</li> <li> $is_list = true;</li> <li> for($i = 0; $i < count ( $keys ); $i ++) { //See if each key correspondes to its position<li> if ($i != $keys [$i]) { //A key fails at position check.<li> $is_list = false; //It is an associative array.<li> break;<li> }<li> }<li> }<li> foreach ( $arr as $key => $value ) {</li> <li> if (is_array ( $value )) { //Custom handling for arrays</li> <li> if ($is_list)</li> <li> $parts [] = $this->jsonEncode ( $value ); /* :RECURSION: */</li> <li> else</li> <li> $parts [] = '"' . $key . '":' . $this->jsonEncode ( $value ); /* :RECURSION: */</li> <li> } else {</li> <li> $str = '';</li> <li> if (! $is_list)</li> <li> $str = '"' . $key . '":';</li> <li> //Custom handling for multiple data types</li> <li> if (is_numeric ( $value ) && $value<2000000000)<li> $str .= $value; //Numbers<li> elseif ($value === false)<li> $str .= 'false'; //The booleans<li> elseif ($value === true)<li> $str .= 'true';<li> else<li> $str .= '"' . addslashes ( $value ) . '"'; //All other things<li> // :TODO: Is there any more datatype we should be in the lookout for? (Object?)<li> $parts [] = $str;<li> }<li> }<li> $json = implode ( ',', $parts );<li> if ($is_list)<li> return '[' . $json . ']'; //Return numerical JSON<li> return '{' . $json . '}'; //Return associative JSON<li> }<li><li> <li> /**<li> * Verify signature <li>*/<li> public function checkSignature()<li> {<li> $signature = HttpRequest::getGet('signature');<li> $timestamp = HttpRequest::getGet('timestamp');<li> $nonce = HttpRequest::getGet('nonce');<li> <li> $token = $this->token;</li> <li> $tmpArr = array($token, $timestamp, $nonce);</li> <li> sort($tmpArr);</li> <li> $tmpStr = implode($tmpArr);</li> <li> $tmpStr = sha1($tmpStr);</li> <li> </li> <li> return ($tmpStr == $signature ? true : false);</li> <li> }</li> <li> </li> <li> </li> <li> /**</li> <li> * Verify whether the token is valid</li> <li>*/</li> <li> public function valid()</li> <li> {</li> <li> if($this->checkSignature()) exit(HttpRequest::getGet('echostr'));</li> <li> }</li> <li> </li> <li>}</li> </ol></div> <em onclick="copycode($('code_ZWw'));">复制代码</em> </div> </td></tr></table> <div id="comment_51454" class="cm"> </div> <div id="post_rate_div_51454"></div> <br><br> </div> </div> <div class="wzconShengming_sp"> <div class="bzsmdiv_sp">Statement of this Website</div> <div>The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn</div> </div> </div> <ins class="adsbygoogle" style="display:block" data-ad-format="autorelaxed" data-ad-client="ca-pub-5902227090019525" data-ad-slot="2507867629"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> <div class="AI_ToolDetails_main4sR"> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-5902227090019525" data-ad-slot="3653428331" data-ad-format="auto" data-full-width-responsive="true"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> <!-- <div class="phpgenera_Details_mainR4"> <div class="phpmain1_4R_readrank"> <div class="phpmain1_4R_readrank_top"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/hotarticle2.png" alt="" /> <h2>Hot Article</h2> </div> <div class="phpgenera_Details_mainR4_bottom"> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796780570.html" title="R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)" class="phpgenera_Details_mainR4_bottom_title">R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>3 weeks ago</span> <span>By 尊渡假赌尊渡假赌尊渡假赌</span> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796780641.html" title="R.E.P.O. Best Graphic Settings" class="phpgenera_Details_mainR4_bottom_title">R.E.P.O. Best Graphic Settings</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>3 weeks ago</span> <span>By 尊渡假赌尊渡假赌尊渡假赌</span> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796785841.html" title="Assassin's Creed Shadows: Seashell Riddle Solution" class="phpgenera_Details_mainR4_bottom_title">Assassin's Creed Shadows: Seashell Riddle Solution</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>2 weeks ago</span> <span>By DDD</span> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796780520.html" title="R.E.P.O. How to Fix Audio if You Can't Hear Anyone" class="phpgenera_Details_mainR4_bottom_title">R.E.P.O. How to Fix Audio if You Can't Hear Anyone</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>3 weeks ago</span> <span>By 尊渡假赌尊渡假赌尊渡假赌</span> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796779766.html" title="WWE 2K25: How To Unlock Everything In MyRise" class="phpgenera_Details_mainR4_bottom_title">WWE 2K25: How To Unlock Everything In MyRise</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>3 weeks ago</span> <span>By 尊渡假赌尊渡假赌尊渡假赌</span> </div> </div> </div> <div class="phpgenera_Details_mainR3_more"> <a href="https://www.php.cn/article.html">Show More</a> </div> </div> </div> --> <div class="phpgenera_Details_mainR3"> <div class="phpmain1_4R_readrank"> <div class="phpmain1_4R_readrank_top"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/hottools2.png" alt="" /> <h2>Hot AI Tools</h2> </div> <div class="phpgenera_Details_mainR3_bottom"> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/ai/undresserai-undress" title="Undresser.AI Undress" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/ai_manual/001/246/273/173411540686492.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="Undresser.AI Undress" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/ai/undresserai-undress" title="Undresser.AI Undress" class="phpmain_tab2_mids_title"> <h3>Undresser.AI Undress</h3> </a> <p>AI-powered app for creating realistic nude photos</p> </div> </div> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/ai/ai-clothes-remover" title="AI Clothes Remover" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/ai_manual/001/246/273/173411552797167.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="AI Clothes Remover" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/ai/ai-clothes-remover" title="AI Clothes Remover" class="phpmain_tab2_mids_title"> <h3>AI Clothes Remover</h3> </a> <p>Online AI tool for removing clothes from photos.</p> </div> </div> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/ai/undress-ai-tool" title="Undress AI Tool" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/ai_manual/001/246/273/173410641626608.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="Undress AI Tool" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/ai/undress-ai-tool" title="Undress AI Tool" class="phpmain_tab2_mids_title"> <h3>Undress AI Tool</h3> </a> <p>Undress images for free</p> </div> </div> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/ai/clothoffio" title="Clothoff.io" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/ai_manual/001/246/273/173411529149311.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="Clothoff.io" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/ai/clothoffio" title="Clothoff.io" class="phpmain_tab2_mids_title"> <h3>Clothoff.io</h3> </a> <p>AI clothes remover</p> </div> </div> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/ai/ai-hentai-generator" title="AI Hentai Generator" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/ai_manual/001/246/273/173405034393877.jpg?x-oss-process=image/resize,m_fill,h_50,w_50" src="/static/imghw/default1.png" alt="AI Hentai Generator" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/ai/ai-hentai-generator" title="AI Hentai Generator" class="phpmain_tab2_mids_title"> <h3>AI Hentai Generator</h3> </a> <p>Generate AI Hentai for free.</p> </div> </div> </div> <div class="phpgenera_Details_mainR3_more"> <a href="https://www.php.cn/ai">Show More</a> </div> </div> </div> <script src="https://sw.php.cn/hezuo/cac1399ab368127f9b113b14eb3316d0.js" type="text/javascript"></script> <div class="phpgenera_Details_mainR4"> <div class="phpmain1_4R_readrank"> <div class="phpmain1_4R_readrank_top"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/hotarticle2.png" alt="" /> <h2>Hot Article</h2> </div> <div class="phpgenera_Details_mainR4_bottom"> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796780570.html" title="R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)" class="phpgenera_Details_mainR4_bottom_title">R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>3 weeks ago</span> <span>By 尊渡假赌尊渡假赌尊渡假赌</span> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796780641.html" title="R.E.P.O. Best Graphic Settings" class="phpgenera_Details_mainR4_bottom_title">R.E.P.O. Best Graphic Settings</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>3 weeks ago</span> <span>By 尊渡假赌尊渡假赌尊渡假赌</span> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796785841.html" title="Assassin's Creed Shadows: Seashell Riddle Solution" class="phpgenera_Details_mainR4_bottom_title">Assassin's Creed Shadows: Seashell Riddle Solution</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>2 weeks ago</span> <span>By DDD</span> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796780520.html" title="R.E.P.O. How to Fix Audio if You Can't Hear Anyone" class="phpgenera_Details_mainR4_bottom_title">R.E.P.O. How to Fix Audio if You Can't Hear Anyone</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>3 weeks ago</span> <span>By 尊渡假赌尊渡假赌尊渡假赌</span> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/1796779766.html" title="WWE 2K25: How To Unlock Everything In MyRise" class="phpgenera_Details_mainR4_bottom_title">WWE 2K25: How To Unlock Everything In MyRise</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <span>3 weeks ago</span> <span>By 尊渡假赌尊渡假赌尊渡假赌</span> </div> </div> </div> <div class="phpgenera_Details_mainR3_more"> <a href="https://www.php.cn/article.html">Show More</a> </div> </div> </div> <div class="phpgenera_Details_mainR3"> <div class="phpmain1_4R_readrank"> <div class="phpmain1_4R_readrank_top"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/hottools2.png" alt="" /> <h2>Hot Tools</h2> </div> <div class="phpgenera_Details_mainR3_bottom"> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/toolset/development-tools/92" title="Notepad++7.3.1" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/manual/000/000/001/58ab96f0f39f7357.jpg?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="Notepad++7.3.1" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/toolset/development-tools/92" title="Notepad++7.3.1" class="phpmain_tab2_mids_title"> <h3>Notepad++7.3.1</h3> </a> <p>Easy-to-use and free code editor</p> </div> </div> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/toolset/development-tools/93" title="SublimeText3 Chinese version" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/manual/000/000/001/58ab97a3baad9677.jpg?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="SublimeText3 Chinese version" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/toolset/development-tools/93" title="SublimeText3 Chinese version" class="phpmain_tab2_mids_title"> <h3>SublimeText3 Chinese version</h3> </a> <p>Chinese version, very easy to use</p> </div> </div> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/toolset/development-tools/121" title="Zend Studio 13.0.1" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/manual/000/000/001/58ab97ecd1ab2670.jpg?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="Zend Studio 13.0.1" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/toolset/development-tools/121" title="Zend Studio 13.0.1" class="phpmain_tab2_mids_title"> <h3>Zend Studio 13.0.1</h3> </a> <p>Powerful PHP integrated development environment</p> </div> </div> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/toolset/development-tools/469" title="Dreamweaver CS6" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/manual/000/000/001/58d0e0fc74683535.jpg?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="Dreamweaver CS6" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/toolset/development-tools/469" title="Dreamweaver CS6" class="phpmain_tab2_mids_title"> <h3>Dreamweaver CS6</h3> </a> <p>Visual web development tools</p> </div> </div> <div class="phpmain_tab2_mids_top"> <a href="https://www.php.cn/toolset/development-tools/500" title="SublimeText3 Mac version" class="phpmain_tab2_mids_top_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" class="lazy" data-src="https://img.php.cn/upload/manual/000/000/001/58d34035e2757995.png?x-oss-process=image/resize,m_fill,h_50,w_72" src="/static/imghw/default1.png" alt="SublimeText3 Mac version" /> </a> <div class="phpmain_tab2_mids_info"> <a href="https://www.php.cn/toolset/development-tools/500" title="SublimeText3 Mac version" class="phpmain_tab2_mids_title"> <h3>SublimeText3 Mac version</h3> </a> <p>God-level code editing software (SublimeText3)</p> </div> </div> </div> <div class="phpgenera_Details_mainR3_more"> <a href="https://www.php.cn/ai">Show More</a> </div> </div> </div> <div class="phpgenera_Details_mainR4"> <div class="phpmain1_4R_readrank"> <div class="phpmain1_4R_readrank_top"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/hotarticle2.png" alt="" /> <h2>Hot Topics</h2> </div> <div class="phpgenera_Details_mainR4_bottom"> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/gmailyxdlrkzn" title="Where is the login entrance for gmail email?" class="phpgenera_Details_mainR4_bottom_title">Where is the login entrance for gmail email?</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/eyess.png" alt="" /> <span>7467</span> </div> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/tiezi.png" alt="" /> <span>15</span> </div> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/cakephp-tutor" title="CakePHP Tutorial" class="phpgenera_Details_mainR4_bottom_title">CakePHP Tutorial</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/eyess.png" alt="" /> <span>1376</span> </div> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/tiezi.png" alt="" /> <span>52</span> </div> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/steamdzhmcssmgs" title="What is the format of the account name of steam" class="phpgenera_Details_mainR4_bottom_title">What is the format of the account name of steam</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/eyess.png" alt="" /> <span>77</span> </div> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/tiezi.png" alt="" /> <span>11</span> </div> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/winactivationkeyper" title="win11 activation key permanent" class="phpgenera_Details_mainR4_bottom_title">win11 activation key permanent</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/eyess.png" alt="" /> <span>45</span> </div> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/tiezi.png" alt="" /> <span>19</span> </div> </div> </div> <div class="phpgenera_Details_mainR4_bottoms"> <a href="https://www.php.cn/faq/newyorktimesdailybrief" title="nyt connections hints and answers" class="phpgenera_Details_mainR4_bottom_title">nyt connections hints and answers</a> <div class="phpgenera_Details_mainR4_bottoms_info"> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/eyess.png" alt="" /> <span>18</span> </div> <div class="phpgenera_Details_mainR4_bottoms_infos"> <img src="/static/imghw/tiezi.png" alt="" /> <span>19</span> </div> </div> </div> </div> <div class="phpgenera_Details_mainR3_more"> <a href="https://www.php.cn/faq/zt">Show More</a> </div> </div> </div> </div> </div> <div class="Article_Details_main2"> <div class="phpgenera_Details_mainL4"> <div class="phpmain1_2_top"> <a href="javascript:void(0);" class="phpmain1_2_top_title">Related knowledge<img src="/static/imghw/index2_title2.png" alt="" /></a> </div> <div class="phpgenera_Details_mainL4_info"> <div class="phphistorical_Version2_mids"> <a href="https://www.php.cn/faq/1796778251.html" title="Working with Flash Session Data in Laravel" class="phphistorical_Version2_mids_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/default1.png" class="lazy" data-src="https://img.php.cn/upload/article/001/253/068/174177050399455.png?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Working with Flash Session Data in Laravel" /> </a> <a href="https://www.php.cn/faq/1796778251.html" title="Working with Flash Session Data in Laravel" class="phphistorical_Version2_mids_title">Working with Flash Session Data in Laravel</a> <span class="Articlelist_txts_time">Mar 12, 2025 pm 05:08 PM</span> <p class="Articlelist_txts_p">Laravel simplifies handling temporary session data using its intuitive flash methods. This is perfect for displaying brief messages, alerts, or notifications within your application. Data persists only for the subsequent request by default: $request-</p> </div> <div class="phphistorical_Version2_mids"> <a href="https://www.php.cn/faq/1796779059.html" title="cURL in PHP: How to Use the PHP cURL Extension in REST APIs" class="phphistorical_Version2_mids_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/default1.png" class="lazy" data-src="https://img.php.cn/upload/article/000/000/080/67d3a4f0ef568156.png?x-oss-process=image/resize,m_fill,h_207,w_330" alt="cURL in PHP: How to Use the PHP cURL Extension in REST APIs" /> </a> <a href="https://www.php.cn/faq/1796779059.html" title="cURL in PHP: How to Use the PHP cURL Extension in REST APIs" class="phphistorical_Version2_mids_title">cURL in PHP: How to Use the PHP cURL Extension in REST APIs</a> <span class="Articlelist_txts_time">Mar 14, 2025 am 11:42 AM</span> <p class="Articlelist_txts_p">The PHP Client URL (cURL) extension is a powerful tool for developers, enabling seamless interaction with remote servers and REST APIs. By leveraging libcurl, a well-respected multi-protocol file transfer library, PHP cURL facilitates efficient execution of various network protocols, including HTTP, HTTPS, and FTP. This extension offers granular control over HTTP requests, supports multiple concurrent operations, and provides built-in security features. </p> </div> <div class="phphistorical_Version2_mids"> <a href="https://www.php.cn/faq/1796778255.html" title="Simplified HTTP Response Mocking in Laravel Tests" class="phphistorical_Version2_mids_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/default1.png" class="lazy" data-src="https://img.php.cn/upload/article/001/253/068/174177056555028.png?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Simplified HTTP Response Mocking in Laravel Tests" /> </a> <a href="https://www.php.cn/faq/1796778255.html" title="Simplified HTTP Response Mocking in Laravel Tests" class="phphistorical_Version2_mids_title">Simplified HTTP Response Mocking in Laravel Tests</a> <span class="Articlelist_txts_time">Mar 12, 2025 pm 05:09 PM</span> <p class="Articlelist_txts_p">Laravel provides concise HTTP response simulation syntax, simplifying HTTP interaction testing. This approach significantly reduces code redundancy while making your test simulation more intuitive. The basic implementation provides a variety of response type shortcuts: use Illuminate\Support\Facades\Http; Http::fake([ 'google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =></p> </div> <div class="phphistorical_Version2_mids"> <a href="https://www.php.cn/faq/1796787277.html" title="Alipay PHP SDK transfer error: How to solve the problem of 'Cannot declare class SignData'?" class="phphistorical_Version2_mids_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/default1.png" class="lazy" data-src="https://img.php.cn/upload/article/001/246/273/174303625625009.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Alipay PHP SDK transfer error: How to solve the problem of 'Cannot declare class SignData'?" /> </a> <a href="https://www.php.cn/faq/1796787277.html" title="Alipay PHP SDK transfer error: How to solve the problem of 'Cannot declare class SignData'?" class="phphistorical_Version2_mids_title">Alipay PHP SDK transfer error: How to solve the problem of 'Cannot declare class SignData'?</a> <span class="Articlelist_txts_time">Apr 01, 2025 am 07:21 AM</span> <p class="Articlelist_txts_p">Alipay PHP...</p> </div> <div class="phphistorical_Version2_mids"> <a href="https://www.php.cn/faq/1796778636.html" title="12 Best PHP Chat Scripts on CodeCanyon" class="phphistorical_Version2_mids_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/default1.png" class="lazy" data-src="https://img.php.cn/upload/article/001/242/473/174183889317163.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="12 Best PHP Chat Scripts on CodeCanyon" /> </a> <a href="https://www.php.cn/faq/1796778636.html" title="12 Best PHP Chat Scripts on CodeCanyon" class="phphistorical_Version2_mids_title">12 Best PHP Chat Scripts on CodeCanyon</a> <span class="Articlelist_txts_time">Mar 13, 2025 pm 12:08 PM</span> <p class="Articlelist_txts_p">Do you want to provide real-time, instant solutions to your customers' most pressing problems? Live chat lets you have real-time conversations with customers and resolve their problems instantly. It allows you to provide faster service to your custom</p> </div> <div class="phphistorical_Version2_mids"> <a href="https://www.php.cn/faq/1796782794.html" title="Explain the concept of late static binding in PHP." class="phphistorical_Version2_mids_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/default1.png" class="lazy" data-src="https://img.php.cn/upload/article/202503/21/2025032113332596253.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Explain the concept of late static binding in PHP." /> </a> <a href="https://www.php.cn/faq/1796782794.html" title="Explain the concept of late static binding in PHP." class="phphistorical_Version2_mids_title">Explain the concept of late static binding in PHP.</a> <span class="Articlelist_txts_time">Mar 21, 2025 pm 01:33 PM</span> <p class="Articlelist_txts_p">Article discusses late static binding (LSB) in PHP, introduced in PHP 5.3, allowing runtime resolution of static method calls for more flexible inheritance.Main issue: LSB vs. traditional polymorphism; LSB's practical applications and potential perfo</p> </div> <div class="phphistorical_Version2_mids"> <a href="https://www.php.cn/faq/1796786131.html" title="Customizing/Extending Frameworks: How to add custom functionality." class="phphistorical_Version2_mids_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/default1.png" class="lazy" data-src="https://img.php.cn/upload/article/202503/28/2025032817124947598.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Customizing/Extending Frameworks: How to add custom functionality." /> </a> <a href="https://www.php.cn/faq/1796786131.html" title="Customizing/Extending Frameworks: How to add custom functionality." class="phphistorical_Version2_mids_title">Customizing/Extending Frameworks: How to add custom functionality.</a> <span class="Articlelist_txts_time">Mar 28, 2025 pm 05:12 PM</span> <p class="Articlelist_txts_p">The article discusses adding custom functionality to frameworks, focusing on understanding architecture, identifying extension points, and best practices for integration and debugging.</p> </div> <div class="phphistorical_Version2_mids"> <a href="https://www.php.cn/faq/1796786130.html" title="Framework Security Features: Protecting against vulnerabilities." class="phphistorical_Version2_mids_img"> <img onerror="this.onerror=''; this.src='/static/imghw/default1.png'" src="/static/imghw/default1.png" class="lazy" data-src="https://img.php.cn/upload/article/202503/28/2025032817115475121.jpg?x-oss-process=image/resize,m_fill,h_207,w_330" alt="Framework Security Features: Protecting against vulnerabilities." /> </a> <a href="https://www.php.cn/faq/1796786130.html" title="Framework Security Features: Protecting against vulnerabilities." class="phphistorical_Version2_mids_title">Framework Security Features: Protecting against vulnerabilities.</a> <span class="Articlelist_txts_time">Mar 28, 2025 pm 05:11 PM</span> <p class="Articlelist_txts_p">Article discusses essential security features in frameworks to protect against vulnerabilities, including input validation, authentication, and regular updates.</p> </div> </div> <a href="https://www.php.cn/be/" class="phpgenera_Details_mainL4_botton"> <span>See all articles</span> <img src="/static/imghw/down_right.png" alt="" /> </a> </div> </div> </div> </main> <footer> <div class="footer"> <div class="footertop"> <img src="/static/imghw/logo.png" alt=""> <p>Public welfare online PHP training,Help PHP learners grow quickly!</p> </div> <div class="footermid"> <a href="https://www.php.cn/about/us.html">About us</a> <a href="https://www.php.cn/about/disclaimer.html">Disclaimer</a> <a href="https://www.php.cn/update/article_0_1.html">Sitemap</a> </div> <div class="footerbottom"> <p> © php.cn All rights reserved </p> </div> </div> </footer> <input type="hidden" id="verifycode" value="/captcha.html"> <script>layui.use(['element', 'carousel'], function () {var element = layui.element;$ = layui.jquery;var carousel = layui.carousel;carousel.render({elem: '#test1', width: '100%', height: '330px', arrow: 'always'});$.getScript('/static/js/jquery.lazyload.min.js', function () {$("img").lazyload({placeholder: "/static/images/load.jpg", effect: "fadeIn", threshold: 200, skip_invisible: false});});});</script> <script src="/static/js/common_new.js"></script> <script type="text/javascript" src="/static/js/jquery.cookie.js?1744392337"></script> <script src="https://vdse.bdstatic.com//search-video.v1.min.js"></script> <link rel='stylesheet' id='_main-css' href='/static/css/viewer.min.css?2' type='text/css' media='all' /> <script type='text/javascript' src='/static/js/viewer.min.js?1'></script> <script type='text/javascript' src='/static/js/jquery-viewer.min.js'></script> <script type="text/javascript" src="/static/js/global.min.js?5.5.53"></script> <script> var _paq = window._paq = window._paq || []; /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function () { var u = "https://tongji.php.cn/"; _paq.push(['setTrackerUrl', u + 'matomo.php']); _paq.push(['setSiteId', '9']); var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0]; g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s); })(); </script> <script> // top layui.use(function () { var util = layui.util; util.fixbar({ on: { mouseenter: function (type) { layer.tips(type, this, { tips: 4, fixed: true, }); }, mouseleave: function (type) { layer.closeAll("tips"); }, }, }); }); document.addEventListener("DOMContentLoaded", (event) => { // 定义一个函数来处理滚动链接的点击事件 function setupScrollLink(scrollLinkId, targetElementId) { const scrollLink = document.getElementById(scrollLinkId); const targetElement = document.getElementById(targetElementId); if (scrollLink && targetElement) { scrollLink.addEventListener("click", (e) => { e.preventDefault(); // 阻止默认链接行为 targetElement.scrollIntoView({ behavior: "smooth" }); // 平滑滚动到目标元素 }); } else { console.warn( `Either scroll link with ID '${scrollLinkId}' or target element with ID '${targetElementId}' not found.` ); } } // 使用该函数设置多个滚动链接 setupScrollLink("Article_Details_main1L2s_1", "article_main_title1"); setupScrollLink("Article_Details_main1L2s_2", "article_main_title2"); setupScrollLink("Article_Details_main1L2s_3", "article_main_title3"); setupScrollLink("Article_Details_main1L2s_4", "article_main_title4"); setupScrollLink("Article_Details_main1L2s_5", "article_main_title5"); setupScrollLink("Article_Details_main1L2s_6", "article_main_title6"); // 可以继续添加更多的滚动链接设置 }); window.addEventListener("scroll", function () { var fixedElement = document.getElementById("Article_Details_main1Lmain"); var scrollTop = window.scrollY || document.documentElement.scrollTop; // 兼容不同浏览器 var clientHeight = window.innerHeight || document.documentElement.clientHeight; // 视口高度 var scrollHeight = document.documentElement.scrollHeight; // 页面总高度 // 计算距离底部的距离 var distanceToBottom = scrollHeight - scrollTop - clientHeight; // 当距离底部小于或等于300px时,取消固定定位 if (distanceToBottom <= 980) { fixedElement.classList.remove("Article_Details_main1Lmain"); fixedElement.classList.add("Article_Details_main1Lmain_relative"); } else { // 否则,保持固定定位 fixedElement.classList.remove("Article_Details_main1Lmain_relative"); fixedElement.classList.add("Article_Details_main1Lmain"); } }); </script> </body> </html>