tags:

views:

225

answers:

5

I am having problems consuming a WCF web service (PaySimple's v3.00 API) using php curl. I am trying to post an xml payload to the service and I keep getting a 400 - Bad Request error. When I using Firefox's Poster add-on, I can post the very same payload and I get the expected response - 200 OK with an XML response containing the required response. Here's a snippet of my code:

        $ch = curl_init();
        $payload = $createPayload();
        $length = strlen($payload);
        $headers = array("Expect:");
        if($isPost)
        {
            curl_setopt($ch, CURLOPT_POST, TRUE);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
            $headers[] = "Content-length: $length";
        }
        else {
            curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
        }
        if($requestType == 'xml')
        {
            $headers[] = 'Content-Type: text/xml; charset: utf-8';
            $headers[] = 'Accept: application/xml';
        }
        else {
            $headers[] = 'Content-Type: application/json; charset: utf-8';
            $headers[] = 'Accept: application/json';
        }            
        $headers[] = "Connection: close";
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
        //debugging
        curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
        $fh = fopen('curl_debug.txt', 'w');
        curl_setopt($ch, CURLOPT_STDERR, $fh);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);            
        $response = curl_exec($ch);
        curl_close($ch);

$payload contains the following value:

<AddCustomer xmlns="http://api.paysimple.com"&gt;&lt;userkey&gt;APIUser1989&lt;/userkey&gt;&lt;apikey&gt;pxTbp4F6y7JuaMu36qazEw51JiqUA7lGme0j62r3UeQyNojvEfpNo7tn4pLq0yEULHz5KykHWV6AjNQJEyskCw0tXSKZ0vcP5mCynh1IgfQEH4NdXRkXeMNAGEdx6Ee0&lt;/apikey&gt;&lt;customer xmlns="http://api.paysimple.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"&gt;&lt;ApiConsumerData/&gt;&lt;PsReferenceId&gt;0&lt;/PsReferenceId&gt;&lt;AltEmail&gt;[email protected]&lt;/AltEmail&gt;&lt;AltPhone/&gt;&lt;BillingAddress1&gt;TestBillingAddress1&lt;/BillingAddress1&gt;&lt;BillingAddress2/&gt;&lt;BillingCity&gt;TestBillingCity&lt;/BillingCity&gt;&lt;BillingCountryCode/&gt;&lt;BillingPostalCode&gt;80202&lt;/BillingPostalCode&gt;&lt;BillingState&gt;6&lt;/BillingState&gt;&lt;CompanyName&gt;TestCompany&lt;/CompanyName&gt;&lt;CreatedOn&gt;0001-01-01T00:00:00&lt;/CreatedOn&gt;&lt;Email&gt;[email protected]&lt;/Email&gt;&lt;Fax/&gt;&lt;FirstName&gt;TestFirstName&lt;/FirstName&gt;&lt;LastModified&gt;0001-01-01T00:00:00&lt;/LastModified&gt;&lt;LastName&gt;TestLastName&lt;/LastName&gt;&lt;MiddleName/&gt;&lt;Notes/&gt;&lt;Phone&gt;5551234567&lt;/Phone&gt;&lt;ShippingAddress1/&gt;&lt;ShippingAddress2/&gt;&lt;ShippingCity/&gt;&lt;ShippingCountryCode/&gt;&lt;ShippingPostalCode/&gt;&lt;ShippingSameAsBilling&gt;true&lt;/ShippingSameAsBilling&gt;&lt;ShippingState&gt;0&lt;/ShippingState&gt;&lt;WebSite/&gt;&lt;/customer&gt;&lt;/AddCustomer&gt;

Here's what shows up in curl_debug.txt:

  • About to connect() to sandbox-api.paysimple.com port 443 (#0)
  • Trying 165.193.50.51... * connected
  • Connected to sandbox-api.paysimple.com (165.193.50.51) port 443 (#0)
  • successfully set certificate verify locations:
  • CAfile: none CApath: /etc/ssl/certs
  • SSL connection using RC4-MD5
  • Server certificate:
  • subject: C=US; ST=Colorado; L=Denver; O=PaySimple, Inc.; OU=PaySimple; CN=*.paysimple.com
  • start date: 2010-05-04 00:00:00 GMT
  • expire date: 2011-06-29 23:59:59 GMT
  • issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert High Assurance CA-3
  • SSL certificate verify ok.

POST /3.00/paysimpleapi.svc/xml/listcustomers HTTP/1.1
Host: sandbox-api.paysimple.com
Content-length: 1153
Content-Type: text/xml; charset: utf-8
Accept: application/xml
Connection: close

HTTP/1.1 400 Bad Request
Connection: close
Date: Fri, 27 Aug 2010 11:07:21 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Set-Cookie: ASP.NET_SessionId=oxpese454u4rr3552evybjue; path=/; HttpOnly
Cache-Control: private
Content-Length: 0

Closing connection #0

F1! F1!

A: 

Your POST's Content-Type should probably be application/x-www-form-urlencoded or multipart/form-data, and not application/xml

Sjon
Unlikely. He is not submitting a form, and the posted data is not urlencoded.
Sjoerd
It's not about sending a form, but about telling the server what to expect. And servers expect either application/x-www-form-urlencoded, or multipart/form-data. The first for regular key/value pairs, the second to upload binary data.It's the first thing i look for when getting a 400 error
Sjon
Thanks, Sjon. Changing this to either of those causes the same error as I have put as the one that Sjoerd's suggestion about the text/xml and application/xml causes.
Tash Pemhiwa
A: 

The problem is probably in one of these:

Content-Type: text/xml; charset: utf-8
Accept: application/xml

Try text/xml or application/xml for both, try uppercase UTF-8. Try to send the same headers as Firefox.

Sjoerd
Tried both. Still fails.. besides, this can't be the problem since I am using Poster to send the exact same headers. My guess is it's something to do with curl, I just can't figure out what it is.
Tash Pemhiwa
In fact, when I change the Content-Type to application/xml, I get the following: The server encountered an error processing the request. The exception message is 'The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml', 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.'. See server logs for more details. The exception stack trace is:...
Tash Pemhiwa
After some more tinkering around, I discovered that your first answer was actually the closest to correct. Indeed the source of the problem was Content-Type: text/xml; charset: utf-8 Removing the charset: utf-8 part did it. Strangely, it works with that part when sending GET requests? Could it be a bug in curl's implementation or on the WCF side?
Tash Pemhiwa
A: 

Tash You are posting to POST /3.00/paysimpleapi.svc/xml/listcustomers HTTP/1.1

but yet you are adding customer (i.e use POST /3.00/paysimpleapi.svc/xml/listcustomers HTTP/1.1)

I am going to email you a screen shot of a call made via Fiddler.

Melody
A: 

sorry tash thought I had touched up the url

but yet you are adding customer (i.e use POST /3.00/paysimpleapi.svc/xml/addcustomer HTTP/1.1)

Melody
A: 

Tash

Post to https://sandbox-api.paysimple.com/3.00/PaysimpleApi.svc/xml/addcustomer http/1.1

use header: Content-length: 1262 Content-type: application/xml; charset=utf-8 Accept: application/xml Method: invokeMethod UserAgent: PaySimple Host: sandbox-api.paysimple.com

Try request SandboxMelody qUWzSPxkcxDR6RJiR2ypzbznV4m6jva5N8kaosnNqQJYqNTGcVouWhKbN5NPGiZxJdmx2QnapYNcwq1bjtfmGwLhBcdMT6x3z7IdPVYA3H7HDBUqwW6eJDyaf8dhKqr0 0 1122 Boogie Woogie Avenue#6City 801116CompanyName99999 0001-01-01T00:00:[email protected]:00:00 LastNameThis is a new customer...from Fiddler3035551212 1122 Boogie Woogie Avenue#5City 80111true6

USE ADDCUSTOMER in both post url and request body

Melody