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函数功能强大,使用方法多样,本书仅介绍与微信开发相关的几种应用,有兴趣的读者可学习其他功能。