Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

API call works in browser, fails with php curl

Posted on 2014-04-07
9
Medium Priority
?
1,164 Views
Last Modified: 2016-05-21
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.
0
Comment
Question by:matthewamundson
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
  • +1
9 Comments
 
LVL 35

Expert Comment

by:Dan Craciun
ID: 39985173
What is the error when you use GET?
0
 
LVL 84

Accepted Solution

by:
Dave Baldwin earned 1336 total points
ID: 39985364
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
 
LVL 84

Assisted Solution

by:Dave Baldwin
Dave Baldwin earned 1336 total points
ID: 39985390
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 111

Expert Comment

by:Ray Paseur
ID: 39985597
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
 

Author Comment

by:matthewamundson
ID: 39986093
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
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 39986194
What is the actual URL?  It's not mydomain.com, right?
0
 
LVL 111

Assisted Solution

by:Ray Paseur
Ray Paseur earned 664 total points
ID: 39986229
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
 

Author Comment

by:matthewamundson
ID: 39994836
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

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
This article discusses four methods for overlaying images in a container on a web page
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

604 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question