Question

I wrote a really basic wrapper class for Highrise's API. It works perfectly for Reads (GET), and I'm just starting to test it for Creates (POST). As far as I can tell, these two requests (one on the command line, one via PHP's cURL library) are identical. Same XML, same options set....just one works, and the other doesn't.

Any help is appreciated. I posted this question to 37signals developer mailing list also, but stackoverflow is generally faster at spotting my dumb mistakes...

This is the error I get with PHP's cURL (makes me think Highrise is having a problem parsing the XML string):

<?xml version="1.0" encoding="UTF-8"?> <errors> <error>First name can't be blank</error> </errors> 

This is what works on the command line:

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

Here's my wrapper class:

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;
    }

}
?>

And the simple testpage I'm using:

<!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>
Was it helpful?

Solution 2

In my wrapper class, the line:

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

should have been:

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

OTHER TIPS

try this lines instead of what you have in your script

   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);
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top