Почему этот запрос cURL работает в командной строке, а не в PHP?
Я написал действительно базовый класс-обертку для API Highrise. Он отлично работает для Reads (GET), и я только начинаю тестировать его для Creates (POST). Насколько я могу судить, эти два запроса (один в командной строке, другой через библиотеку cURL в PHP) идентичны. Тот же XML, те же параметры установлены... только один работает, а другой нет.
Любая помощь приветствуется. Я также отправил этот вопрос в список рассылки для разработчиков 37signals, но, как правило, стековый поток быстрее обнаруживает мои глупые ошибки...
Это ошибка, которую я получаю с PHP cURL (заставляет меня думать, что у Highrise возникла проблема с анализом строки XML):
<?xml version="1.0" encoding="UTF-8"?> <errors> <error>First name can't be blank</error> </errors>
Вот что работает в командной строке:
curl -u 'my_api_key:X'
-H 'Content-type: application/xml'
-d '<?xml version="1.0" encoding="UTF-8"?> <person><first-name>Savos</first-name><last-name>Aren</last-name><title>Archmage</title><company-name>Winterhold College</company-name><contact-data><email-addresses/><phone-numbers><phone-number><number>555-555-5555</number><location>Home</location></phone-number><phone-number><number>555-555-5555</number><location>Work</location></phone-number><phone-number><number>555-555-5555</number><location>Mobile</location></phone-number></phone-numbers><addresses><address><city>Winterhold</city><country>Tamriel</country><state>Skyrim</state><street>Hall of the Elements, College of Winterhold</street><zip>99999</zip><location>Work</location></address></addresses></contact-data></person>'
https://myuserid.highrisehq.com/people.xml
Вот мой класс оболочки:
class HighriseAPICall {
protected $_timeout = 120;
protected $_url_prefix = 'https://';
protected $_url_suffix = '.highrisehq.com';
protected $_password = 'X';
protected $_userpwd;
protected $_url;
public function __construct($api_key, $username) {
$this->_userpwd= $api_key . ':' . $this->_password;
$this->_url = $this->_url_prefix . $username . $this->_url_suffix;
}
/**
* Make the specified API call.
* @param string $action one of the four HTTP verbs supported by Highrise
* @param string $resource_name the Highrise resource to be accessed
* @param string $xml a well-formed XML string for a Highrise create, update, or delete request
*
* $xml parameter should include any query parameters as suggested by Highrise API documentation
* eg, if you want to GET all People, pass in "/people.xml"
* and if you want to get People by search term where field=value,
* then pass in "/people/search.xml?criteria[field]=value"
*/
public function makeAPICall($action,$resource_name,$xml=null) {
/* initialize curl session and set defaults for new API call */
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->_url . $resource_name);
curl_setopt($curl, CURLOPT_USERPWD, $this->_userpwd);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->_timeout);
/* if xml was passed in, set header and postfields */
if (isset($xml)) {
curl_setopt($curl, CURLOPT_HTTPHEADER, 'Content-type: application/xml');
curl_setopt($curl, CURLOPT_POSTFIELDS, "$xml");
}
/* set action as custom request */
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $action);
/* get the string response from executing the curl session */
$result = curl_exec($curl);
curl_close($curl);
// return the response as a simpleXMLElement
try {
$result_simplexml = new SimpleXMLElement($result);
}
catch (Exception $e) {
throw new Exception("Highrise API Call Error: " . $e->getMessage() . ", Response: " . $result);
}
if (!is_object($result_simplexml)) {
throw new Exception("Highrise API Call Error: Could not parse XML, Response: " . $result);
}
return $result_simplexml;
}
}
?>
И простая тестовая страница, которую я использую:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<?php
require_once('HighriseAPICall.class.php');
$highrise_api_key = 'OBSCURED';
$highrise_username = 'OBSCURED';
$highrise_api = new HighriseAPICall($highrise_api_key, $highrise_username);
$person_xml ='<?xml version="1.0" encoding="UTF-8"?> <person><first-name>Savos</first-name><last-name>Aren</last-name><title>Archmage</title><company-name>Winterhold College</company-name><contact-data><email-addresses/><phone-numbers><phone-number><number>555-555-5555</number><location>Home</location></phone-number><phone-number><number>555-555-5555</number><location>Work</location></phone-number><phone-number><number>555-555-5555</number><location>Mobile</location></phone-number></phone-numbers><addresses><address><city>Winterhold</city><country>Tamriel</country><state>Skyrim</state><street>Hall of the Elements, College of Winterhold</street><zip>99999</zip><location>Work</location></address></addresses></contact-data></person>';
$response = $highrise_api->makeAPICall('POST', '/people.xml', $person_xml);
echo htmlentities($response->asXML());
?>
</body>
</html>
2 ответа
В моем классе-обёртке строка:
curl_setopt($curl, CURLOPT_HTTPHEADER, 'Content-type: application/xml');
должно было:
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/xml'));
Попробуйте эти строки вместо того, что у вас есть в вашем скрипте
if (isset($xml)) {
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/xml'));
curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST ,false);
}