2012-04-13 1 views
0

Я написал действительно базовый класс-оболочку для API Highrise. Он отлично работает для Reads (GET), и я только начинаю тестировать его для создания (POST). Насколько я могу судить, эти два запроса (один в командной строке, один через библиотеку cURL PHP) идентичны. Один и тот же XML, тот же набор параметров ... только один работает, а другой нет.Почему этот запрос cURL работает в командной строке, но не в PHP?

Любая помощь приветствуется. Я отправил этот вопрос в список рассылки для разработчиков 37signals, но stackoverflow, как правило, быстрее обнаруживает мои немые ошибки ...

Это ошибка, которую я получаю с помощью cURL PHP (заставляет меня думать, что в 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> 
+0

Можете ли вы использовать параметр -D curl и CURLOPT_WRITEHEADER, чтобы сбрасывать заголовки в обоих случаях и публиковать их здесь? –

+0

@ SebastiánGrignoli, только что увидел это. Я сделаю это в понедельник утром, спасибо за подсказку. Из других чтений я думаю, что это может быть проблема. –

ответ

1

В моем классе обертки, линия:

curl_setopt($curl, CURLOPT_HTTPHEADER, 'Content-type: application/xml'); 

должно быть:

curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/xml')); 
2

попробовать эти строки вместо того, что у вас есть в вашем сценарии

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); 
    } 
+0

Я попробовал это, фактически, подумав, что это проблема с запросом клиента. Я сделал это снова сейчас, чтобы дважды проверить, комментировать запрос настройки линии и добавить строку, чтобы установить CURL_POST в true, но ничего не изменилось, такая же ошибка. –

+0

Какая ошибка вы получаете? добавьте эту строку после строки 'curl_exec': ' if ($ result === false) die (curl_error ($ curl)); ' –

+0

Ошибка, которую я получаю, является первой строкой XML в моем исходном сообщении. –