2.2 学习curl函数
使用开发模式创建微信自定义菜单,需要模拟HTTPS的POST协议,这里要使用到PHP的curl函数。另外,微信服务号的九大高级接口也要使用到curl函数,因此可以说curl函数是微信服务号开发的基础,必须熟练掌握。下面详细介绍curl函数的各种用法。
2.2.1 curl函数基础
curl函数的官方文档在http://www.php.net/manual/zh/book.curl.php。
PHP的curl函数是通过libcurl库与服务器使用各种类型的协议进行连接和通信的,curl目前支持HTTP、HTTPS、FTP、Gopher、Telnet、DICT、File和LDAP协议,同时也支持HTTPS认证、HTTP POST、HTTP PUT、FTP上传、HTTP基于表单的上传、代理、cookie和用户名+密码的认证,功能十分强大。curl函数在PHP 4.0.2中被引入,SAE(Sina App Engine)和BAE(Baidu App Engine)平台均可直接使用curl函数。
由于curl函数功能复杂,本书只介绍与微信服务号开发的几个重要函数,见表2-1。
表2-1 curl的几个重要函数
curl函数的关键在于curl_setopt的传输选项,见表2-2。
表2-2 curl_setopt的传输选项
2.2.2 curl函数模拟GET
根据HTTP规范,GET用于信息获取,可以理解为通过URL地址栏访问网址,是最基本的用法。下面以模拟访问百度首页为例,见代码2-1。
代码2-1 curl模拟get
<?php //GET方式抓取页面 $ch=curl_init(); //初始化 $url="http://www.baidu.com";//设置抓取URL地址 curl_setopt($ch,CURLOPT_URL,$url);//GET方式抓取URL curl_exec($ch);//执行 curl_close($ch);//关闭 ?>
将此文件保存为2-1.php,上传至服务器,然后在浏览器端运行×××/2-1.php,则会出现百度首页,如图2-6所示。
图2-6 curl模拟GET访问百度首页
2.2.3 curl函数处理GET数据
有时候通过GET方式获取的页面并不需要全部的数据,而需要截取部分数据,则可以通过CURLOPT_RETURNTRANSFER选项将页面以文件流的形式保存,然后进行输出。微信开发中典型的应用是获取access_token值。根据微信开发者文档,access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在开发模式中获得(需要已经成为开发者,且账号没有异常状态)。注意,调用所有微信接口时均需使用HTTPS协议。获取access_token接口调用方式为GET方式。
HTTP请求方式:GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
正常情况下会返回{"access_token":"ACCESS_TOKEN","expires_in":7200},这是JSON格式。而调用其他接口需要调用access_token,因此需要进一步处理数据,见代码2-2。
代码2-2 curl处理GET数据
<?php //处理GET数据 $appid="wx7ced2a8593275753";//填写AppID $secret="71f475563d00103a356943875e96d43a";//填写Secret $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//以文件流方式输出 $a=curl_exec($ch);//将文件保存到变量$a $strjson=json_decode($a);//JSON解析 $access_token = $strjson->access_token;//获取access_token echo $access_token; ?>
运行后将直接输出access_token值:
z1qkP4_0R8Mz07jfWRw2AI5NZiAcTp-DoUIeZmSZlNcKTMRcbqV7RZSwrLvKW6iyhnyFcDPS62oQYVCwoH1o8aEuNx63cGCqmzksYtbbbZ0SSUU9nyq9teuhQDRNSv9iMXG45wg_IrPjW690vyMRtg
2.2.4 curl函数模拟POST请求
根据HTTP规范,POST用于向服务器提交数据,典型的应用为表单提交,安全性较GET方式高。模拟POST请求需要使用CURLOPT_POST和CURLOPT_POSTFIELDS两个选项。下面以模拟查询南航CZ3109航班动态为例,POST内容和URL地址可以通过HttpWatch Studio或Chrome、搜狗浏览器等开发者工具得到,如南航官方查询地址为http://www.csair.com/cn/tourguide/flight_info/flight_dynamic.shtml#。
通过开发工具得到它的头部信息如下:
Request URL: http://eb.csair.com/flightQuery/fltQueryETicketResultN.jsp Request Method: POST Status Code: 200 OK Request Headersview source Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip,deflate,sdch Accept-Language: zh-CN,zh;q=0.8 Cache-Control: max-age=0 Connection: keep-alive Content-Length: 36 Content-Type: application/x-www-form-urlencoded Cookie: JSESSIONID=PXJzS2STS3GVTBn8Ycv6xhCF433h2s8RkCYzMjVh8chtQx22CG3g!683390317; language=zh_CN; WT-FPC=id=183.46.23.223-3445828208.30352577:lv=1391859010201:ss=1391858489078:fs=1391858489078:pv_Num=8:vt_Num=1 Host: eb.csair.com Origin: http://www.csair.com Referer: http://www.csair.com/cn/tourguide/flight_info/flight_dynamic.shtml User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 SE 2.X MetaSr 1.0 Form Dataview parsed queryType=flightNum&flightNum=CZ3109
经过分析和测试得到的POST请求URL地址为http://eb.csair.com/flightQuery/fltQueryETicketResultN.jsp。
POST数据格式为queryType=flightNum&flightNum=CZ3109。
由于南航网站限制请求来源,因此使用了CURLOPT_REFERER选项模拟请求来源,见代码2-3。
代码2-3 curl模拟POST请求
<?php //模拟POST请求 $flight="CZ3109";//查询航班号 $post="queryType=flightNum&flightNum={$flight}"; //POST提交内容 $url = "http://eb.csair.com/flightQuery/fltQueryETicketResultN.jsp"; //查询地址 $ch = curl_init(); curl_setopt ($ch, CURLOPT_REFERER, "http://www.csair.com/ "); //模拟来源 curl_setopt($ch, CURLOPT_URL, $url);//URL curl_setopt($ch, CURLOPT_POST, 1); //模拟POST curl_setopt($ch, CURLOPT_POSTFIELDS, $post);//POST内容 curl_exec($ch); curl_close($ch); ?>
浏览器运行后的结果如图2-7所示,读者也可以结合上一节内容,对数据进行截取处理,嫁接到微信中,做成一个小查询。
图2-7 curl模拟POST查询航班
2.2.5 curl函数模拟POST上传文件
POST除了用于表单提交外,另一个应用为上传文件,微信的高级接口也开放了多媒体文件上传功能。文件上传的加密方式为multipart/form-data,POST内容需为数组格式。服务器端处理上传文件(up.php)代码简单使用print_r($_FILES),不作其他处理。见代码2-4,将aa.jpg文件上传至服务器。
代码2-4 curl模拟POST上传文件
<?php //模拟POST上传文件 $post=array('filename' => '@aa.jpg'); //POST提交内容 $url = "http://1.fswange.sinaapp.com/up.php"; //上传地址 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url);//URL curl_setopt($ch, CURLOPT_POST, 1); //模拟POST curl_setopt($ch, CURLOPT_POSTFIELDS, $post);//POST内容 curl_exec($ch); curl_close($ch); ?>
浏览器运行返回如下代码,表示上传成功:
Array ( [filename] => Array ( [name] => aa.jpg [type] =>application/ octet-stream[tmp_name]=> /saetmp/598/fswange/1391861440_2694460154/ phpWnTRdO [error] => 0 [size] => 14685 ) )
小提示 $_FILES是PHP的系统函数,可以从客户计算机向远程服务器上传文件,它返回的是一个二维数组,含义如下:
$_FILES["filename"]["name"]:被上传文件的名称
$_FILES["filename"]["type"]:被上传文件的类型
$_FILES["filename"]["size"]:被上传文件的大小,以字节计
$_FILES["filename"]["tmp_name"]:存储在服务器中文件的临时副本的名称
$_FILES["filename"]["error"]:由文件上传导致的错误代码
curl函数功能强大,使用方法多样,本书仅介绍与微信开发相关的几种应用,有兴趣的读者可学习其他功能。