PHP cURL giving a different result than native cURL - php

When I run the following cURL call natively I get an expected result.
curl -X POST -H "Accept:application/json" -H "Content-Type: application/x-www-form-urlencoded" "https://XXXX" -d 'grant_type=authorization_code&code=YYYY
When I run the cURL call via PHP I get a different response.
$curl = curl_init('https://XXXX');
curl_setopt_array($curl, array(
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'Content-type: application/x-www-form-urlencoded'
),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => array(
'grant_type' => 'authorization_code',
'code' => 'YYYY'
),
));
$response = curl_exec($curl);
curl_close($curl);
Is there any functional difference between the native call and the PHP approach? Thanks.

The problem is that PHP's cURL doesn't trust the server's HTTPS certificate. Differently command line curl by default does.
The quick fix is to configure cURL to always trust the server:
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
The proper fix is described here
http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/

Related

PHP curl PUT does not continue respectively send payload/data

I need to PUT some json data to an API endpoint, which works as expected via command line curl, but not via php curl and I don't have any idea, why it doesn't.
my command is
curl -v --insecure --request PUT --url <https://blabla/blablabla> --user 'username:password' --header 'Content-Type: application/json' --data '<valid json data>'
but it doesn't work this way within php:
// get cURL resource
$curl = curl_init();
// set cURL options
$curloptions = array(
CURLOPT_PUT => true, // set method to PUT
CURLOPT_RETURNTRANSFER => true, // return the transfer as a string
CURLOPT_VERBOSE => true, // output verbose information
CURLOPT_SSL_VERIFYHOST => false, // ignore self signed certificates
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERNAME => $config['uag']['user'], // set username
CURLOPT_PASSWORD => $config['uag']['pass'], // set password
CURLOPT_HTTPHEADER => array( // set headers
"Content-Type: application/json",
),
CURLOPT_POSTFIELDS => $jsondata // set data to post / put
);
curl_setopt_array($curl, $curloptions);
foreach($serverurilist as $uri) {
// set url
curl_setopt($curl, CURLOPT_URL, $uri);
// send the request and save response to $response
$response = curl_exec($curl);
// stop if fails
if(!$response) {
die('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
}
var_dump($response);
}
// close curl resource to free up system resources
curl_close($curl);
What doesn't work? The payload / data doesn't get submitted. If I tcpdump the command line und php version without encryption, I can see, that the command line submits the data right after the Expect: 100-continue request and the HTTP/1.1 100 Continue response from the server. The php version doesn't do anything after the HTTP/1.1 100 Continue response and quits after reaching the timeout.
From documentation:
CURLOPT_PUT - true to HTTP PUT a file. The file to PUT must be set with CURLOPT_INFILE and CURLOPT_INFILESIZE.
and you are not using any file to provide content.
You should use CURLOPT_CUSTOMREQUEST => 'PUT'.
This is your same cUrl request exported from Postman:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://blabla/blablabla',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS =>'<valid json data>',
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ='
],
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
You should use this CURLOPT_CUSTOMREQUEST=>'PUT'

How to translate curl arguments to php-curl?

(i've seen SOME version of this question so many times, hoping to make a thread with a comprihensive-ish list of answers)
for example, what is the php-curl translation of:
curl -v https://api-m.sandbox.paypal.com/v1/oauth2/token \
-H "Accept: application/json" \
-H "Accept-Language: en_US" \
-u "client_id:secret" \
-d "grant_type=client_credentials"
-v translates to
curl_setopt($ch,CURLOPT_VERBOSE, 1);
PS! by default, curl sends this data to stderr, and stderr is usually visible when running curl from the terminal, but when running php-curl behind a webserver ala nginx/apache, it's not uncommon that stderr is linked to *the web-server's errorlog*, hence the VERBOSE log may arrive in the server error log, rather than the browser. a quickfix to this would be to set a custom CURLOPT_STDERR, ala:
$php_output_handle = fopen("php://output", "wb");
curl_setopt_array($ch, array(
CURLOPT_VERBOSE => 1,
CURLOPT_STDERR => $php_output_handle
));
but because of php garbage collection, when using this quickfix, keep in mind that it will break if php garabge collector closes $php_output_handle before the last curl_exec() call to the same handle.. it's usually not a problem, but it can happen.
.. moving on,
https://api-m.sandbox.paypal.com/v1/oauth2/token translates to:
curl_setopt($ch,CURLOPT_URL, 'https://api-m.sandbox.paypal.com/v1/oauth2/token');
and
-H "Accept: application/json" \
-H "Accept-Language: en_US" \
translates to
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Accept: application/json",
"Accept-Language: en_US"
));
and -u "client_id:secret" translates to:
curl_setopt($ch,CURLOPT_USERPWD, "client_id:secret");
and -d "grant_type=client_credentials" (aka --data) translates to:
curl_setopt_array($ch, array(
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query(array(
"grant_type" => "client_credentials"
))
));
hence the full translation is:
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_VERBOSE => 1,
CURLOPT_URL => 'https://api-m.sandbox.paypal.com/v1/oauth2/token',
CURLOPT_HTTPHEADER => array(
"Accept: application/json",
"Accept-Language: en_US"
),
CURLOPT_USERPWD => 'client_id:secret',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query(array(
"grant_type" => "client_credentials"
))
));
curl_exec($ch);
what is the translation of curl -F grant_type=client_credentials ?
it's:
curl_setopt_array($ch, array(
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => array(
"grant_type" => "client_credentials"
)
));
what about uploading files, what's the translation of curl -F file=#file/path/to/upload.ext ?
it's:
curl_setopt_array($ch, array(
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => array(
"file" => new CURLFile("filepath/to/upload.ext")
)
));
what's the translation of --location ? it's
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
how to upload JSON? like this:
curl_setopt_array($ch, array(
CURLOPT_HTTPHEADER => array(
"Content-Type: application/json"
),
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => json_encode(array(
"whatever_key" => "whatever_data"
))
));
-X PUT translates to
curl_setopt($ch,CURLOPT_PUT,1);
as for --upload-file , there are several ways to do it,
if you're dealing with small files which easily fits in ram, the easiest way to do it would be:
curl_setopt_array($ch, array(
CURLOPT_PUT => 1,
CURLOPT_POSTFIELDS => file_get_contents($file)
));
but if you need to support big files which you don't want to put in RAM,
$file = "file.ext";
$file_handle = fopen($file,"rb");
$file_size = filesize($file);
curl_setopt_array($ch, array(
CURLOPT_UPLOAD => 1,
CURLOPT_INFILESIZE=>$file_size,
CURLOPT_INFILE=>$file_handle
));

Not getting expected PHP cURL response

I have the following PHP code:
<?php
$data = array("client_id" => "sipgate-app-web", "grant_type" => "password", "username" => "my_username", "password" => "my_password");
$data_string = json_encode($data);
$ch = curl_init('https://api.sipgate.com/login/sipgate-apps/protocol/openid-connect/token');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/json'
));
$result = curl_exec($ch);
echo $result;
?>
Unfortunately, I'm not getting the expected response. The response I'm receiving is:
{"error":"invalid_request","error_description":"Missing form
parameter: grant_type"}
When using an online cURL tool like https://onlinecurl.com with the same data (URL, header, data) as in my cURL PHP code, I'm getting the right response. This means, there's something wrong with my PHP code. I'm not getting any error in the PHP error log.
The manual says I have to use the following cURL code:
curl \
--request POST \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Accept: application/json' \
--data-urlencode "client_id=sipgate-app-web" \
--data-urlencode "grant_type=password" \
--data-urlencode "username=my_username" \
--data-urlencode "password=my_password" \
https://api.sipgate.com/login/sipgate-apps/protocol/openid-connect/token
Since I'm new to cURL, after googling a lot, I have no idea what I'm doing wrong.
Can anybody help me?
EDIT: You can test my PHP code above as it is. You should get the following response, if the code is working:
{"error":"invalid_grant","error_description":"Invalid user
credentials"}
As per the manual, your request needs to have the Content-Type of application/x-www-form-urlencoded which looks like this:
key1=value1&key2=value2
Thus you need to convert your array into such a string either manually or with http_build_query, like so:
$data_string = http_build_query( $data );
I am consuming one of the API using following PHP CURL, Give this a try and pass your credentials i.e username and password in "your username" and "your password".
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.sipgate.com/login/sipgate-apps/protocol/openid-
connect/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS =>"{\r\n\client_id:\"sipgate-app-
web\",\r\n\tgrant_type\"password\",\r\n\tusername:\"your
username\",\r\n\tpassword:\"your password\"\r\n}",
CURLOPT_HTTPHEADER => array(
"Accept: application/json",
"Content-Type: application/json"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
} ?>

PHP curl requests with 404, curl request itself works fine

I have a curl request:
curl -X PUT \
--header "Content-Type: application/json" \
--header "Accept: application/json" \
--header "x-api-token: API_TOKEN" \
--header "x-api-user: API_USER" \
--data '{"connection_id":"533905657015830359"}' \
"https://someserver/origination/numbers/%2B17032638425"
that works fine from the command line. when i try run this with a php script it fails with a 404 in the verbose response.
$url = "https://someServer/origination/numbers/%2B17032638425";
$postdata = json_encode(array('connection_id'=>'533905657015830359'));
$ch = curl_init($url);
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_VERBOSE => TRUE,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $postdata
));
$headers = ['Content-Type: application/json','Accept: application/json','x-api-user: SOME-USER','x-api-token: SOME-TOKEN'];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
I am doing anything blindingly wrong here with the php request?
Correct me if i'm wrong, but it seems to me you are using a PUT request in your shell CURL and a POST request in the PHP version. The two HTTP methods, while quite close in their meaning, are not generally managed in the same way by API endpoints.

PHP cURL JSON Object formatting issues

I'm running into an issue with formatting using the curl_setopt functions in PHP. I'm basically trying to re-create the cURL request below, but my code returns a bad request from the server. I'm pretty sure it has to do with poor formatting, but I can't figure out where I went wrong.
//This code returns the data back successfully
curl -H "Content-Type: application/json" -d '{"bio_ids": ["1234567"]}' http://localhost:9292/program
<?php //This code returns a bad request from the server
$bio = array('bio_ids'=>'1234567');
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'http://localhost:9292/program',
CURLOPT_POST => 1, // -d
CURLOPT_POSTFIELDS => $bio,
CURLOPT_HTTPHEADER => array('Content-Type: application/json'), // -H
));
$resp = curl_exec($curl);
curl_close($curl);
?>
There are two issues:
You need to make sure that the structure of $bio matches what you are expected to pass, so the $bio declaration needs to be:
$bio = array('bio_ids' => array('1234567'));
Secondly you need to json_encode this data structure before sending it to the server:
CURLOPT_POSTFIELDS => json_encode($bio),
<?php //This code returns a bad request from the server
$bio = array('bio_ids'=>'1234567');
$bio = json_encode($bio);
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'http://localhost:9292/program',
CURLOPT_POST => 1, // -d
CURLOPT_POSTFIELDS => $bio,
CURLOPT_HTTPHEADER => array('Content-Type: application/json'), // -H
));
$resp = curl_exec($curl);
curl_close($curl);
?>

Categories