API call works in browser, fails with php curl

I'm having trouble making an API call with php and curl. If I enter the post url with query string data directly into a browser, I receive a response with the results I'm looking for, but I cannot get the correct response using curl.

Here is an example of the url that gives me the results I'm looking for:
'http://mydomain.com/api.svc/addJsonOrder?Customer={"FirstName":"Test","LastName":"Customer"}&CustomerShipAddress={"Address1":"123 Some St","City":"New City","State":"NY","Zipcode":"10012"}&Order={"PaymentTypeName":"Visa"}&OrderLineItem=[{"SKU":"R1827-1286-8","Quantity":"1","Price":"459.00"}]&UserCredentials={"UserName":"username","Password":"password"}'

Open in new window


And here's the request via curl that fails:
    
    $url = "http://mydomain.com/api.svc/addJsonOrder";
    $data_string = 'Customer={"FirstName":"Test","LastName":"Customer"}&CustomerShipAddress={"Address1":"123 Some St","City":"New City","State":"NY","Zipcode":"10012"}&Order={"PaymentTypeName":"Visa"}&OrderLineItem=[{"SKU":"R1827-1286-8","Quantity":"1","Price":"459.00"}]&UserCredentials={"UserName":"username","Password":"password"}';
    
    $headers = array(
      "Accept: application/json",
      "Content-type: application/json",
      "Content-length: " . strlen($data_string),
      "Connection: close"
    );
    
    $ch = curl_init();
    $f = fopen('request.log', 'w');

    curl_setopt_array($ch, array(
      CURLOPT_URL             => $url,
      CURLOPT_HTTPHEADER      => $headers,
      CURLOPT_POST            => 1,
      CURLOPT_CUSTOMREQUEST   => 'POST',
      CURLOPT_POSTFIELDS      => $data_string,

      CURLOPT_RETURNTRANSFER  => 1,
      CURLOPT_FOLLOWLOCATION  => 1,
      CURLOPT_VERBOSE         => 1,
      CURLOPT_STDERR          => $f
    ));

    $return = curl_exec($ch);
    fclose($f);
    curl_close($ch);

Open in new window


Here's the error that gets spit out to my log file…
* About to connect() to mydomain.com port 80 (#0)
* connected
* Connected to mydomain.com (xx.xxx.xx.xx) port 80 (#0)
> POST /api.svc/addJsonOrder HTTP/1.1
Host: mydomain.com
Accept: application/json
Content-type: application/json
Content-length: 905
Connection: close

* upload completely sent off: 905 out of 905 bytes
< HTTP/1.1 405 Method Not Allowed
< Cache-Control: no-cache
< Pragma: no-cache
< Allow: GET
< Content-Length: 1565
< Content-Type: text/html; charset=UTF-8
< Expires: -1
< Server: Microsoft-IIS/7.5
< X-AspNet-Version: 4.0.30319
< Set-Cookie: lang=1; path=/
< X-Powered-By: ASP.NET
< Date: Tue, 08 Apr 2014 02:37:55 GMT
< Connection: close
< 
* Closing connection #0

Open in new window


I'm probably way off here, but in the 405 response, it states "Allow: GET" which I'm assuming means that it will only accept a GET request. I've tried this also with no success.

Any code examples would be great, curl is making my brain bleed.
matthewamundsonAsked:
Who is Participating?
 
Dave BaldwinConnect With a Mentor Fixer of ProblemsCommented:
You need to get rid of these fields, they are for POST, not GET.
     CURLOPT_POST            => 1,
      CURLOPT_CUSTOMREQUEST   => 'POST',
      CURLOPT_POSTFIELDS      => $data_string,

Open in new window

From http://us3.php.net/manual/en/function.curl-setopt.php
CURLOPT_HTTPGET       TRUE to reset the HTTP request method to GET. Since GET is the default, this is only necessary if the request method has been changed.
And finally, just use the same URL with the query string that you used in your browser.  If you are passing variable data then you might want to urlencode the data (not the names) and concatenate it to the URL querystring.
0
 
Dan CraciunIT ConsultantCommented:
What is the error when you use GET?
0
 
Dave BaldwinConnect With a Mentor Fixer of ProblemsCommented:
Here are two simple files that demonstrate the simplicity of a basic GET with curl.

The curl file from Example #1 on http://us3.php.net/manual/en/function.curl-exec.php    You need to put in your own server address to test this.  You could probably use the URL from your browser in this code and see the response on your screen.
<?php
// create a new cURL resource
$ch = curl_init();

// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://10.202.46.40/dibtest/PHPechonames.php?fname=Fred&lname=Flintstone");
curl_setopt($ch, CURLOPT_HEADER, 0);

// grab URL and pass it to the browser
curl_exec($ch);

// close cURL resource, and free up system resources
curl_close($ch);
?>

Open in new window

The response file.
<?php
if (!isset($_GET['fname'])){$fname = "";} else {$fname = $_GET['fname'];}
if (!isset($_GET['lname'])){$lname = "";} else {$lname = $_GET['lname'];}
echo "Your first name is $fname and your last name is $lname.";
?>

Open in new window

0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
Ray PaseurCommented:
I'm with DaveBaldwin here.  This is an important message (emphasis added):

HTTP/1.1 405 Method Not Allowed

Method is a term of art in HTTP client/server programming.  In almost all cases, the method is either GET or POST.  Other methods are defined but are rarely used.  GET requests are information-only and idempotent.  POST requests must be used if the request can change the state of the data model.  A GET request is anything you can type into the address bar of a browser, including request arguments to the right of the ? at the end of the URL.

In PHP, you can find the request arguments in $_GET and $_POST.  There must be a similar distinction in ASP.NET.

Here is my teaching example showing how to make a GET request.  Note that the term POST is nowhere in sight!

<?php // /demo/curl_get_example.php
error_reporting(E_ALL);


// DEMONSTRATE THE BASICS OF CURL
// SOMETHING LIKE demo/curl_get_example.php?url=http://twitter.com


// YOU COULD HAVE SOMETHING LIKE THIS
$url = isset($_GET["url"]) ? $_GET["url"] : 'http://twitter.com';

// BUT SINCE IT IS ON MY SERVER, I HAVE HARD-CODED THIS
$url = 'https://twitter.com/RayPaseur';

// TRY THE REMOTE WEB SERVICE
$htm = my_curl($url);

// SHOW THE WORK PRODUCT OR BARK OUT ERROR MESSAGES
echo "<pre>";
echo PHP_EOL . '<strong>' . $url . '</strong>' . PHP_EOL;
echo PHP_EOL . htmlentities($htm);
echo PHP_EOL;


// A FUNCTION TO RUN A CURL-GET CLIENT CALL TO A FOREIGN SERVER
function my_curl
( $url
, $timeout=5
, $error_report=TRUE
)
{
    $curl = curl_init();

    // HEADERS AND OPTIONS APPEAR TO BE A FIREFOX BROWSER REFERRED BY GOOGLE
    $header[] = "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
    $header[] = "Cache-Control: max-age=0";
    $header[] = "Connection: keep-alive";
    $header[] = "Keep-Alive: 300";
    $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";
    $header[] = "Accept-Language: en-us,en;q=0.5";
    $header[] = "Pragma: "; // BROWSERS USUALLY LEAVE THIS BLANK

    // SET THE CURL OPTIONS - SEE http://php.net/manual/en/function.curl-setopt.php
    curl_setopt( $curl, CURLOPT_URL,            $url  );
    curl_setopt( $curl, CURLOPT_USERAGENT,      'Mozilla/5.0 (Windows NT 6.1; rv:22.0) Gecko/20100101 Firefox/22.0'  );
    curl_setopt( $curl, CURLOPT_HTTPHEADER,     $header  );
    curl_setopt( $curl, CURLOPT_REFERER,        'http://www.google.com'  );
    curl_setopt( $curl, CURLOPT_ENCODING,       'gzip,deflate'  );
    curl_setopt( $curl, CURLOPT_AUTOREFERER,    TRUE  );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, TRUE  );
    curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, TRUE  );
    curl_setopt( $curl, CURLOPT_TIMEOUT,        $timeout  );
    curl_setopt( $curl, CURLOPT_VERBOSE,        TRUE   );

    // IF USING SSL, THESE MAY BE IMPORTANT
    curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, FALSE  );
    curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, FALSE  );
    curl_setopt( $curl, CURLOPT_SSLVERSION,     3      );

    // RUN THE CURL REQUEST AND GET THE RESULTS
    $htm = curl_exec($curl);

    // ON FAILURE HANDLE ERROR MESSAGE
    if ($htm === FALSE)
    {
        if ($error_report)
        {
            $err = curl_errno($curl);
            $inf = curl_getinfo($curl);
            echo "CURL FAIL: $url TIMEOUT=$timeout, CURL_ERRNO=$err";
            var_dump($inf);
        }
        curl_close($curl);
        return FALSE;
    }

    // ON SUCCESS RETURN XML / HTML STRING
    curl_close($curl);
    return $htm;
}

Open in new window

0
 
matthewamundsonAuthor Commented:
Thanks all!

While it seems that GET is the correct method here, using the most basic curl command from Dave Baldwin is returning "HTTP Error 400. The request is badly formed."

I assume this means there's an error in my request url, but I'm confused because it works just fine in a browser. Here's the actual url, and notice the json array. I've tried urlencoding it as well, with no luck.

http://mydomain.com/api.svc/addJsonOrder?Customer={"FirstName":"Matthew","LastName":"Amundson","Email":"matthew@test.com"}&CustomerShipAddress={"Email":"matthew@test.com","Address1":"123 Some St","City":"New York","State":"NY","Zipcode":"10012"}&Order={"PaymentTypeName":"Visa","ShippingTypeName":"flatrate_flatrate","TotalShipping":"5.00","TotalHandling":"0.00","ProductTotalPrice":"459.00","ThirdPartyOrderNumber":"100000024","TotalCreditCardCharge":"459.00"}&OrderLineItem=[{"SKU":"R1827-1286-8","Quantity":"1","Price":"459.00"}]&UserCredentials={"UserName":"username","Password":"password"}

Open in new window


Is there another type of encoding that needs to be done before sending with GET?
0
 
Ray PaseurCommented:
What is the actual URL?  It's not mydomain.com, right?
0
 
Ray PaseurConnect With a Mentor Commented:
Here is what I can discern about the request variables.  They look OK, but we would need to see the API documentation to learn more.  You may need to urlencode() the values if you're sending with cURL.

http://iconoun.com/demo/temp_matthew.php?Customer={"FirstName":"Matthew","LastName":"Amundson","Email":"matthew@test.com"}&CustomerShipAddress={"Email":"matthew@test.com","Address1":"123 Some St","City":"New York","State":"NY","Zipcode":"10012"}&Order={"PaymentTypeName":"Visa","ShippingTypeName":"flatrate_flatrate","TotalShipping":"5.00","TotalHandling":"0.00","ProductTotalPrice":"459.00","ThirdPartyOrderNumber":"100000024","TotalCreditCardCharge":"459.00"}&OrderLineItem=[{"SKU":"R1827-1286-8","Quantity":"1","Price":"459.00"}]&UserCredentials={"UserName":"username","Password":"password"}

<?php // demo/temp_matthew.php
error_reporting(E_ALL);
echo '<pre>';

// VISUALIZE THE REQUEST VARIABLES
echo '<pre>';
print_r($_GET);

foreach ($_GET as $key => $jso)
{
    echo PHP_EOL . $key;
    $obj = json_decode($jso);
    var_dump($obj);
}

Open in new window

0
 
matthewamundsonAuthor Commented:
Thanks for the suggestions! Tried all solutions but starting to think there's an issue with the API.

Contacted the developer and will comment again if there's any light shed.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.