这几天合作商家给了一个订单接口以供调用,于是我就使用php惯用的curl方式调用:
$url = 'http://www.someapi.com/api';
$body = '<?xml version="1.0" encoding="utf-8"?>
<returndata>
<somexml></somexml>
</returndata>';
$result = api_notice_increment($url,$body);
echo '<pre>';print_r($result);exit;
function api_notice_increment($url, $data)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$lst['rst'] = curl_exec($ch);
$lst['info'] = curl_getinfo($ch);
curl_close($ch);
return $lst;
}
可是调用时总是没有返回正常的值,总是返回500,于是我从网上寻找可以模拟http请求的工具,找到了这个:
可是我使用这个在线工具的时候:
却可以正常返回,后来我发现,我选择ContentType为text/html时就可以正常返回,而在选择为application/x-www-form-urlencoded时便发生跟我一样的相同错误,返回:
返回的HTML:
远程服务器返回错误: (500) 内部服务器错误。
所以我猜测也许问题就发生在设置的头部ContentType,于是我修改了我的代码,加入了设置header头的部分:
$url = 'http://www.someapi.com/api';
$body = '<?xml version="1.0" encoding="utf-8"?>
<returndata>
<somexml></somexml>
</returndata>';
$result = api_notice_increment($url,$body);
echo '<pre>';print_r($result);exit;
function api_notice_increment($url, $data)
{
$ch = curl_init();
<span style="background-color: rgb(255, 255, 0);">curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/html", "Content-length: ".strlen($data))); </span>
curl_setopt($ch, CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$lst['rst'] = curl_exec($ch);
$lst['info'] = curl_getinfo($ch);
curl_close($ch);
return $lst;
}
于是,奇迹发生了!结果果然正常了~~~ ^_<!
我猜测,也许curl默认是对发送的内容进行了urlencode加密所以导致对方商家服务器端不能接收到正常的请求~~
其实php可以使用CURLOPT_HTTPHEADER来设置所有你想设置的头,甚至是这样伪造一个header头:
$headers = array();
$headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
$headers[] = 'Connection: Keep-Alive';
$headers[] = 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3';
$headers[] = 'Accept-Encoding: gzip, deflate';
$headers[] = 'Host: 4pda.ru';
$headers[] = 'User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0';
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
以后当使用curl时发生了什么错误的时候,记得看看是不是header中需要调整~~~
至于具体application/x-www-form-urlencoded的意义:
application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的编码格式。 multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。 text/plain: 窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。
补充
form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded。 当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2...),然后把这个字串append到url后面,用?分割,加载这个新的url。 当action为post时候,浏览器把form数据封装到http body中,然后发送到server。 如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。 但是如果有type=file的话,就要用到multipart/form-data了。浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary)。