I am trying to make a call to an API using curl (from the backend of my application directly). It is the first time I use it so I digged around to learn how to do it.
The documentation say that this is the request:
curl --location -g --request POST '{{url}}/api/rest/issues/' \
--header 'Authorization: {{token}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"summary": "This is a test issue",
"description": "This is a test description",
"category": {
"name": "General"
},
"project": {
"name": "project1"
}
}'
This should be the code if I execute it from the terminal (if I get it right). If I want to move execute it in a php script I have to convert this to something like:
<?php
$pars=array(
'nome' => 'pippo',
'cognome' => 'disney',
'email' => 'pippo#paperino.com',
);
//step1
$curlSES=curl_init();
//step2
curl_setopt($curlSES,CURLOPT_URL,"http://www.miosito.it");
curl_setopt($curlSES,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curlSES,CURLOPT_HEADER, false);
curl_setopt($curlSES, CURLOPT_POST, true);
curl_setopt($curlSES, CURLOPT_POSTFIELDS,$pars);
curl_setopt($curlSES, CURLOPT_CONNECTTIMEOUT,10);
curl_setopt($curlSES, CURLOPT_TIMEOUT,30);
//step3
$result=curl_exec($curlSES);
//step4
curl_close($curlSES);
//step5
echo $result;
?>
that I will adapt to my needs. Is this correct? Is there another way to keep it as simple as the documented curl request?
I would use an HTTP client like Guzzle.
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'http://www.miosito.it', [
'form_params' => [
'nome' => 'pippo',
'cognome' => 'disney',
'email' => 'pippo#paperino.com',
]
]);
echo (string) $response->getBody();
There are several ways to do curl. Your code seems okay, you can try out my code too.
$pars=array(
'nome' => 'pippo',
'cognome' => 'disney',
'email' => 'pippo#paperino.com',
);
If sometimes you need to send json encoded parameters then use below line.
// $post_json = json_encode($pars);
Curl code as per below
$apiURL = 'http://www.miosito.it';
$ch = #curl_init();
#curl_setopt($ch, CURLOPT_POST, true);
#curl_setopt($ch, CURLOPT_POSTFIELDS, $pars);
#curl_setopt($ch, CURLOPT_URL, $apiURL);
#curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
#curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = #curl_exec($ch);
$status_code = #curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curl_errors = curl_error($ch);
#curl_close($ch);
echo "<br>Curl Errors: " . $curl_errors;
echo "<br>Status code: " . $status_code;
echo "<br>Response: " . $response;
Please let me know if there you need something else.
Related
I am receiving a "INVALID_BODY" error with the message "body could not be parsed as JSON" when sending a curl request through php to create a plaid link token.
I have the header and body formatted this way:
$ch=curl_init("https://development.plaid.com/link/token/create");
$username = array(
"client_user_id"=>"cus_L7tpXAO0PXsPsh"
);
$headers = array(
'Content-type: application/json'
);
$data = array(
'client_id'=>'ID',
'secret'=>'SECRET',
'client_name'=>'Plaid App',
'user'=>$username,
'products'=>'auth',
'country_codes'=>'US',
'language'=>'en',
'webhook'=>'https://webhook.sample.com'
);
$hstring = http_build_query($headers);
$string = http_build_query($data);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$token = curl_exec($ch);
echo $token;
$return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
?>
There is probably a very obvious formatting issue but I can't see it as is. Appreciate any suggestions or criticisms.
I should also mention building out the POST in Postman also gives invalid body error.
I was getting the same error, but for a different reason. The problem in your code is how you are sending your country codes and products. They are expected to be arrays of strings despite the documentation seeming to say otherwise. Also, I don't think you're sending the data in JSON either... Try this:
$data =[
"client_id" => $plaidID,
"secret" => $plaidSecret,
"client_name" => $clientName,
"user" => [
"client_user_id" => $userID
],
"products" => ["auth"],
"country_codes"=>["US"],
"language" => "en"
];
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,"https://".$apiMode.".plaid.com/link/token/create");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch,CURLOPT_HTTPHEADER,["content-type: application/json"]);
curl_setopt($ch,CURLOPT_POSTFIELDS,json_encode((object)$data,JSON_HEX_APOS | JSON_HEX_QUOT ));
$response = curl_exec($ch);
The instructions I have for using an api gives two options.
One requires a zipCode input and one does not.
Using PHP I have successfully built a curl resource using curl_setop for the case that uses the zipCode but not the case that omits the zipCode. The case without the zipCode is supposed to have an extra option after the URL.
All I have been given for instructions is that the curl should be like:
curl -i -X POST -H "Content-Type:application/json" -H "authToken:12345" https://connect.apisite.com/api/v1/users -d'
[{
"firstName": "John",
"lastName": "Smith",
"emailAddress": {
"address": "johnsmith#test.com"
}
}]'
for the case without the zipCode
and with the zipCode
curl -i -X POST -H "Content-Type:application/json" -H
"authToken:12345" https://connect.apisite.com/api/v1/users '
[{
"firstName": "John",
"lastName": "Smith",
"emailAddress": { "address": "johnsmith#test.com" },
"homeAddress" : { "postalCode" : "48124" }
}
}]'
My problem is that I do not know how to add the -d to the curl resource that appears in the first case just after the URL
This works for me:
$url = "https://connect.apisite.com/api/v1/users";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$request_headers = array();
$request_headers[] = 'authToken: ' . $authResponse;
$request_headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
$response = curl_exec($ch);
I tried just appending the -d to the URL as
$url = "https://connect.apisite.com/api/v1/users -d";
That did not work.
My guess is there is a constant I need to use like
curl_setop($ch, CURLOPT_XXXXX, '-d');
but I do not know what CURLOPT_XXXX should be.
Any help would be appreciated.
I'm not sure why you use curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); as your call structure seems could be done by a regular POST call which could be handled by:
curl_setopt(CURLOPT_POST, true);
which in turn will call the -d flag of cURL as per PHP document:
CURLOPT_POST: TRUE to do a regular HTTP POST. This POST is the normal application/x-www-form-urlencoded kind, most commonly used by HTML forms.
Also, you need to change curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); because doing this will make cURL to pass the data as multipart/form-data. Instead, structure your data as a URL-encoded string, something like
curl_setopt($ch, CURLOPT_POSTFIELDS, urlencode(json_encode($postData)));
(note: I haven't tested the latter line above but you can test it and adjust as per your requirements), as per PHP documentation note:
Note:
Passing an array to CURLOPT_POSTFIELDS will encode the data as multipart/form-data, while passing a URL-encoded string will encode the data as application/x-www-form-urlencoded.
Thanks everyone for your help and suggestions.
As was mentioned I did not need to do anything to add the -d
I got the response I need using the following for postData
$postData = json_encode(array(array('emailAddress' => $emailObj, 'firstName' => $firstName, 'lastName' => $lastName)));
or
$postData = json_encode(array(array('emailAddress' => $emailObj, 'firstName' => $firstName, 'lastName' => $lastName, 'homePostalAddress' => $homePostalObj)));
In both request the method is POST, as the previous answer you can set CURLOPT_POST option. I see the only different is about the data you are sending, in one without zipCode and another with. So, you can just prepare the data before including the zipCode or not in your array of data. You can try something like below.
$dataRequest = [
'firstName' => "John",
'lastName' => "Smith",
'emailAddress' => [
'address' => 'johnsmith#test.com'
],
'homeAddress' => [ //dont send this key in the case you dont want zipCode in the request.
'postalCode'=> '48124'
],
];
$url = "https://connect.apisite.com/api/v1/users";
$authToken = '12345';
$ch = curl_init();
/**
the idea with urldecode is because some api does not accept the
encoded urls in your case is not important due your data does not
contains any url but if tomorrow you want to include smth like
'customerUrl'=>'https://myhomepage.com' the result of http_build_query
will be like 'https%3A%2F%2Fmyhomepage.com'
*/
$data = urldecode(http_build_query($dataRequest));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, "{$authToken}:");
$headers = [];
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
if (!curl_errno($ch)) {
/**
HANDLE RESPONSE, CHECK FOR PROPER HTTP CODE DEPENDING OF THE API RESPONSE,
IN YOUR CASE I GUESS IS CREATE USER YOUR GOAL, SO MAYBE RESPONSE IS 'HTTP_CREATED'
BUT IF THIS FUNCTION WILL BE GENERIC BETTER SWITCH LIKE THIS:
switch ($http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE)) {
case Response::HTTP_OK:
case Response::HTTP_CREATED:
case Response::HTTP_ACCEPTED:
$response = json_decode($response, true);
break;
default:
$response = [];
}
*/
}
curl_close($ch);
return $response;
This example is with content-type not in json format, you can change it if is requirement of api.
I can't get the folling script to work:
I'm using an api called swiftdil. Their example is as follows:
Example request:
curl -X POST https://sandbox.swiftdil.com/v1/oauth2/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-u 'your_username:your_password'
Example output:
{
"access_token":"your_access_token",
"expires_in": 3600,
"refresh_expires_in": 1800,
"refresh_token": "your_refresh_token",
"token_type": "bearer",
"not-before-policy": 0,
"session_state": "your_session_state"
}
So the url I've to submit my credentials to is https://sandbox.swiftdil.com/v1/oauth2/token
I've tried the following code:
// Api Credentials
$url = 'https://sandbox.swiftdil.com/v1/oauth2/token';
$username = "my_username";
$password = "my_password";
// Set up api environment
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:
application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_USERPWD, $username . ":" .
$password);
// Give back curl result
$output = curl_exec($ch);
$info = curl_getinfo($ch);
$curl_error = curl_error($ch);
curl_close($ch);
print_r($output);
print_r($info);
print_r($curl_error);
?>
The script is giving me back the following result:
HTTP/1.1 400 Bad Request Server: nginx/1.13.8 Date: Tue, 15 May 2018 09:17:26 GMT Content-Type: text/html Content-Length: 173 Connection: close
400 Bad Request.
Am I missing something? I do fullfill the needs of the example given above right? I do make a postcall, give all the credenatials as asked, but still can't get anything back.
I am not a PHP developer, I mostly do JavaScript. When I integrate with other REST services I tend to use Postman (https://www.getpostman.com/).
Try the following:
Attempt to successfully connect with the API using Postman (should be relatively straightforward).
When successful, Postman has the ability to generate PHP code automatically, which you can then copy and paste. Works like a charm with JavaScript, don't see why it will be any different with PHP.
I just filled in the details in postman based on what you provided:
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://sandbox.swiftdil.com/v1/oauth2/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => array(
"Authorization: Basic bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=",
"Content-Type: application/x-www-form-urlencoded"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
Please note, 'Authorization: Basic' can be used as basic authorization mechanism instead of 'Bearer' (it should work too). So replace 'bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ' with the base64 encoded string 'username:password' (use actual username and password).
You also need to set the curl post fields by setting the below option as per your data.
"curl_setopt($ch, CURLOPT_POSTFIELDS, array(
'code' => $code,
'client_id' => $client_id,
'client_secret' => $client_secret,
'redirect_uri' => $redirect_uri,
'grant_type' => 'authorization_code'
))";
If still not work, you can find the curl error as :
if(curl_error($ch))
{
echo 'error:' . curl_error($ch);
}
I have the following Curl code, which I used the curl to PHP converter to convert to PHP code
curl https://a.klaviyo.com/api/v1/list/dqQnNW/members \
-X POST \
-d api_key=API_KEY \
-d email=george.washington#example.com \
-d properties='{ "$first_name" : "George", "Birthday" : "02/22/1732" }' \
-d confirm_optin=true
The code I got was
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://a.klaviyo.com/api/v1/list/dqQnNW/members");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "api_key=API_KEY&email=george.washington#example.com&properties='{&confirm_optin=true");
curl_setopt($ch, CURLOPT_POST, 1);
$headers = array();
$headers[] = "Content-Type: application/x-www-form-urlencoded";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
However this doesn't seem right because of the "properties" line which doesn't get translated into the PHP code.
How do I incorporate the "properties" line with a $first_name variable into my PHP code?
yeah it's definitely not correct, the converter screwed up the CURLOPT_POSTFIELDS line.
try
curl_setopt($ch,CURLOPT_POSTFIELDS,'api_key=API_KEY&email=george.washington#example.com&properties={ "$first_name" : "George", "Birthday" : "02/22/1732" }&confirm_optin=true');
instead. and if you can be arsed, send a bugreport to the author of the converter, this is definitely a bug.
and protip, in php, you might wanna use the http_build_query function instead for application/x-www-form-urlencoded-encoding, and json_encode for json encodig, eg
curl_setopt ( $ch, CURLOPT_POSTFIELDS, http_build_query ( array (
'api_key' => 'API_KEY',
'email' => 'george.washington#example.com',
'properties' => json_encode ( array (
'$first_name' => 'George',
'Birthday' => '02/22/1732'
) ),
'confirm_option' => true
) ) );
also note, are you sure you're using this api correctly in your curl example? it's mixing application/x-www-form-urlencoded-encoding with json-encoding, that's unusual. a weird design choice if correct. i'd double-check if that's the correct behavior with the docs if i were you.
I made some php code and I was able to send notifications to devices using the regId.
I also managed to create a group of regId successfully receiving the notification_key as describe on the google documentation.
But I'm not able to send notifications to the group. I tried to use the same method to send the notification but instead of using the regId I am using the notification_key I received from GCM when creating the group, but this approach did not work, it gives me the NotRegistered error.
If i try to register with the same notification_key_name GCM say it is already registered.
I am not sure if I have to send it through another method or if I am doing something wrong.
When I send the notifications using the regId I receive this message
from GCM:
{"multicast_id":517...442,"success":2,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:140...ecd"},{"message_id":"0:140...ecd"}]}
When I create the group I receive this message from GCM:
{"notification_key":"APA91....nz9Q"}
When I try to send the message to the group using the notification_key i received on the message above I receive this message from GCM:
{"multicast_id":80...63,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"NotRegistered"}]}
When I try to create the group again with the same notification_key_name I receive this message from GCM:
{"error":"notification_key already exists"}
Below is the code I am using.
<?php
class GCM {
const GOOGLE_API_KEY= " *** MY API KEY ***"; // Place your Google API Key
const PROJECT_KEY= " *** MY PROJECT KEY ***";
function __construct() {
}
/**
* Sending Push Notification
*/
public function send_notification($registatoin_ids, $message) {
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => $registatoin_ids,
'data' => $message
);
$headers = array(
'Authorization: key=' . self::GOOGLE_API_KEY,
'Content-Type: application/json'
);
// Open connection
$ch = curl_init();
// Set the url, number of POST vars, POST data
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Disabling SSL Certificate support temporarly
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
// Close connection
curl_close($ch);
echo $result;
}
public function requestNotificationKeyFromGCM($registatoin_ids, $username) {
//Google cloud messaging GCM-API url
$url = 'https://android.googleapis.com/gcm/notification';
$request = array(
'operation' => 'create',
'notification_key_name' => $username,
'registration_ids' => $registatoin_ids,
);
$headers = array(
'Authorization: key=' . self::GOOGLE_API_KEY,
'project_id: ' . self::PROJECT_KEY,
'content-type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request));
$result = curl_exec($ch);
if ($result === FALSE) {
die('Curl failed: ' . curl_error($ch));
}
curl_close($ch);
echo $result;
}
}
?>
I had similar issues while trying to send a gcm's with notification key. There is an issue in the documentation.
Instead of using:
curl -vvv -X POST --header "Content-Type: application/json" --header "project_id: <YOUR-PROJECT-ID>" --header "Authorization: key=<YOUR-PROJECT-SECRET-KEY>" --data #- "https://android.googleapis.com/gcm/send" << EOF
{
"registration_ids": ["<REGISTRATION-ID-FROM-DEVICE>"],
"data": {},
}
EOF
You have to use:
curl -vvv -X POST --header "Content-Type: application/json" --header "project_id: <YOUR-PROJECT-ID>" --header "Authorization: key=<YOUR-PROJECT-SECRET-KEY>" --data #- "https://android.googleapis.com/gcm/send" << EOF
{
"to": "<NOTIFICATION-ID>",
"data": {},
}
EOF
You can see more in my blog post: https://medium.com/appunite-edu-collection/d7df385b0ff4
I followed the documentation from Google's Documentation
(I'm pushing to both iOS and Android).
{
"to": "your_token_ID",
"data": {
"hello": "This is a Firebase Cloud Messaging Device Group Message!",
}
}
But it's not working so I tried:
{
"to": "your_token_ID",
"notification": {
"sound": "default",
"gcmSandbox": "true",
"badge": 1,
"title" : "Push Title",
"body": "Push Body"
}
}
This method is working for me, hope it helps somebody else.