最近因为调用Ping++支付的原因,可是把我给难为到了,主要还是自己自我解决问题的能力不太强,下面试报错信息:
其实根据报错的信息可以找到错误的路程,最终定在了AppiRequestor.php文件中的第316行,本人一直不明白为啥本地就是一直报错,看了大神的解决思路就发现了原来是Curl抓取的问题,恍然大悟,此时才明白,自己之所以找不到解决之法归根结底还是因为对于这个curl的使用不太了解,今天就给自己总结一下,也希望能帮助到你们!
PHP手册---搜索CURL的使用,点击查看手册使用详解
一般分为四步:
Step1: curl_init()初始化
curl_init(【String $url】):参数可以为空,单独初始化一个cURl资源,要是有参数,则代表curl_setopt()中的CUTLOPT_URL选 项被设置成这个值,也可以手动使用curl_setopt()函数设置这个值,成功返回cURL句柄,失败返回false,
Step2:curl_setopt()设置cURL传输选项
bool curl_setopt ( resource $ch
, int $option
, mixed $value
) //option 需要设置的CURLOPT_XXX选项;value为值
其中主要有几个常用的选项设置:
CURLOPT_HEADER: 启用时会将头文件信息作为输出流输出; 一般为false
CURLOPT_RETURNTRANSER:TRUE时将curl_exec()获取的信息以字符串返回,而不是直接输出
CURLOPT_SSL_VERIFYPEER: FALSE指禁用cURL验证对等证书,像微信开发中一般https访问的需要设置这个选项
CURLOPT_SSL_VERIFYHOST : 设置了不做服务器端的认证,那么客户端也不需要认证,为false
CURLOPT_POST: true时指定发送post请求,不设置默认为get方式
CURLOPT_POSTFIELDS: 设置了post方式请求,那么就要处理post请求的数据,,这个在使用curl_setopt()设置选项的时 候会多一个参数,$data,它就是post发送的参数
Step3:curl_exec()执行cURL回话
它是在初始化一个cURL回话后并全部选项被设置后调用
curl_exec($ch) //$ch是初始化的cURL资源
Step4:curl_close() 关闭资源
curl_close($ch) //关闭cURL资源,并且释放系统资源
下面试封好的方法,仅供参考使用
1.分开设置curl_setopt参数
public static function https_request($curl, $data=null, $https=true, $method='post'){
$ch = curl_init();//初始化
curl_setopt($ch, CURLOPT_URL, $curl);//设置访问的URL
curl_setopt($ch, CURLOPT_HEADER, false);//设置不需要头信息
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//只获取页面内容,但不输出
if($https){
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//不做服务器认证
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//不做客户端认证
}
if($method == 'post'){
curl_setopt($ch, CURLOPT_POST, true);//设置请求是POST方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置POST请求的数据
}
$str = curl_exec($ch);//执行访问,返回结果
curl_close($ch);//关闭curl,释放资源
return $str;
}
此方法通用于微信公众号的开发使用当中,http和https两种协议都支持
2.直接数组的形式设置curl_setopt参数,使用curl_setopt_array()方法
private function _curlRequest($method, $absUrl, $headers, $params)
{
$curl = curl_init();
$method = strtolower($method);
$opts = array();
$dataToBeSign = '';
$requestTime = null;
if ($method === 'get' || $method === 'delete') {
if ($method === 'get') {
$opts[CURLOPT_HTTPGET] = 1;
} else {
$opts[CURLOPT_CUSTOMREQUEST] = 'DELETE';
}
$dataToBeSign .= parse_url($absUrl, PHP_URL_PATH);
if (count($params) > 0) {
$encoded = self::encode($params);
$absUrl = "$absUrl?$encoded";
$dataToBeSign .= '?' . $encoded;
}
$requestTime = time();
} elseif ($method === 'post' || $method === 'put') {
if ($method === 'post') {
$opts[CURLOPT_POST] = 1;
} else {
$opts[CURLOPT_CUSTOMREQUEST] = 'PUT';
}
$rawRequestBody = $params !== null ? json_encode($params) : '';
$opts[CURLOPT_POSTFIELDS] = $rawRequestBody;
$dataToBeSign .= $rawRequestBody;
if ($this->_signOpts !== null) {
if (isset($this->_signOpts['uri']) && $this->_signOpts['uri']) {
$dataToBeSign .= parse_url($absUrl, PHP_URL_PATH);
}
if (isset($this->_signOpts['time']) && $this->_signOpts['time']) {
$requestTime = time();
}
}
} else {
throw new Error\Api("Unrecognized method $method");
}
$absUrl = Util\Util::utf8($absUrl);
$opts[CURLOPT_URL] = $absUrl; //设置路径,也可以在curl_init()初始化回话的时候
$opts[CURLOPT_RETURNTRANSFER] = true; //true代表将curl_exec()获取的信息以字符串返回,而不是直接输出
$opts[CURLOPT_CONNECTTIMEOUT] = 30; //在尝试连接时等待的秒数。设置为0,则无限等待
$opts[CURLOPT_TIMEOUT] = 80; //允许 cURL 函数执行的最长秒数
$opts[CURLOPT_HTTPHEADER] = $headers; //设置 HTTP 头字段的数组。格式: array('Content-type: text/plain','Content- length: 100')
$opts[CURLOPT_SSL_VERIFYPEER] = false; //FALSE禁止 cURL 验证对等证书
if (!Pingpp::$verifySslCerts) {
$opts[CURLOPT_SSL_VERIFYPEER] = false;
}
curl_setopt_array($curl, $opts);
$rbody = curl_exec($curl);
if (!defined('CURLE_SSL_CACERT_BADFILE')) {
define('CURLE_SSL_CACERT_BADFILE', 77); // constant not defined in PHP
}
$errno = curl_errno($curl);
if ($errno == CURLE_SSL_CACERT ||
$errno == CURLE_SSL_PEER_CERTIFICATE ||
$errno == CURLE_SSL_CACERT_BADFILE) {
array_push(
$headers,
'X-Pingpp-Client-Info: {"ca":"using Pingpp-supplied CA bundle"}'
);
$cert = $this->caBundle();
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_CAINFO, $cert);
$rbody = curl_exec($curl);
}
if ($rbody === false) {
$errno = curl_errno($curl);
$message = curl_error($curl);
curl_close($curl);
$this->handleCurlError($errno, $message);
}
$rcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
return array($rbody, $rcode);
}
注意:在封装的时候一定要考虑到post的方式,以及HTTPS协议的情况,一个使用 CURLOPT_POST 给curl_setopt()设置参数,另一个使用 CURLOPT_SSL_VERIFYPEER 给curl_setopt()设置参数