Post JSON encoded and normal string data using CURL in PHP - php

I typically send an array of strings using CURL in PHP, something like this:
$data = array(
"key1" => $value,
"key2" => $value,
"key3" => $value,
"key4" => $value
);
Then, among other curl_setop settings, post using:
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
This all works fine. But now in addition to those strings, I have 1 dataset that is JSON encoded and I want to post it at the same time. JSON looks like this:
Array ( [ad_info] => {"MoPubAdUnitInteractions":"a","MoPubAdUnitConversations":"b","MoPubAdUnitGroups":"c"} )
I think I figured out how to do it by setting a header saying I'm going to be passing in JSON like this:
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
But then, can I simply add another line for the post, but in this case the JSON encoded value like this:
curl_setopt($curl, CURLOPT_POSTFIELDS, $json_data);
I'm kinda shooting in the dark, any suggestions on how I should be thinking about this?
Ok, here is the full example:
From Processing The Form Post:
$community_id = $_POST["communityid"];
$community_name = $_POST["communityname"];
$community_apns_name = $_POST["communityapnsname"];
$community_download_url = $_POST["communitydownloadurl"];
$community_open_tagging = $_POST["communityopentagging"];
$community_pull_content = $_POST["communitypullcontent"];
$community_push_content = $_POST["communitypushcontent"];
$community_ad_info = json_encode($_POST["ad_info"]);
$data = array(
"name" => $community_name,
"apns_name" => $community_apns_name,
"download_url" => $community_download_url,
"open_tagging" => $community_open_tagging,
"pull_content" => $community_pull_content,
"push_content" => $community_push_content,
);
$json_data = array("ad_info" => $community_ad_info);
$api_querystring = $gl_app_api_url . "communities";
$response = CallAPI('PATCH', $api_querystring, $data, $device_id = null, $community_id = null, $json_data);
And the Function in PHP I'm calling to do the CURL:
function CallAPI($method, $url, $data = false, $device_id = false, $community_id = false, $json_data = false) {
if (!$community_id) { // IF NO COMMUNITY ID IS PROVIDED
global $gl_community_id;
$community_id = $gl_community_id;
}
$curl = curl_init();
switch ($method)
{
case "POST":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PUT":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PATCH":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH');
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
default:
if ($data)
$url = sprintf("%s?%s", $url, http_build_query($data));
}
// Optional Authentication:
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_USERPWD, "XXXX:XXXXX");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// Disable the SSL verificaiton process
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
if ($device_id)
curl_setopt($curl, CURLOPT_HTTPHEADER, array("device_id:" . $device_id));
if ($community_id)
curl_setopt($curl, CURLOPT_HTTPHEADER, array("X-Afty-Community:" . $community_id));
if ($json_data)
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($curl, CURLOPT_POSTFIELDS, $json_data);
// Confirm cURL gave a result, if not, write the error
$response = curl_exec($curl);
if ($response === FALSE) {
die("Curl Failed: " . curl_error($curl));
} else {
return $response;
}
}
Any help is greatly appreciated.

You use wrong approach. Setting CURLOPT_POSTFIELDS option twice doesn't lead to result you expected since each setting call discards effect of previous one.
Instead of this, you have to append extra data ($community_ad_info) to the main POST data ($data) before passing it to CURLOPT_POSTFIELDS option.
...
$community_ad_info = json_encode($_POST["ad_info"]);
$data = array(
"name" => $community_name,
"apns_name" => $community_apns_name,
"download_url" => $community_download_url,
"open_tagging" => $community_open_tagging,
"pull_content" => $community_pull_content,
"push_content" => $community_push_content,
"ad_info" => $community_ad_info
);
$response = CallAPI('PATCH', $api_querystring, $data, $device_id = null, $community_id = null);
...

This is untested of course but it should do what you need.
function CallAPI($method, $url, $data = false, $device_id = false, $community_id = false, $json_data = false) {
if (!$community_id) { // IF NO COMMUNITY ID IS PROVIDED
global $gl_community_id;
$community_id = $gl_community_id;
}
$curl = curl_init();
switch ($method)
{
case "POST":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PUT":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PATCH":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH');
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
default:
if ($data)
$url = sprintf("%s?%s", $url, http_build_query($data));
}
// Optional Authentication:
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_USERPWD, "XXXX:XXXXX");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// Disable the SSL verificaiton process
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
if ($device_id)
curl_setopt($curl, CURLOPT_HTTPHEADER, array("device_id:" . $device_id));
if ($community_id)
curl_setopt($curl, CURLOPT_HTTPHEADER, array("X-Afty-Community:" . $community_id));
// Confirm cURL gave a result, if not, write the error
$response = curl_exec($curl);
if ($response === FALSE) {
die("Curl Failed: " . curl_error($curl));
} else {
return $response;
}
}
And now the actualy logic
$community_id = $_POST["communityid"];
$community_name = $_POST["communityname"];
$community_apns_name = $_POST["communityapnsname"];
$community_download_url = $_POST["communitydownloadurl"];
$community_open_tagging = $_POST["communityopentagging"];
$community_pull_content = $_POST["communitypullcontent"];
$community_push_content = $_POST["communitypushcontent"];
$community_ad_info = json_encode($_POST["ad_info"]);
$data = array(
"name" => $community_name,
"apns_name" => $community_apns_name,
"download_url" => $community_download_url,
"open_tagging" => $community_open_tagging,
"pull_content" => $community_pull_content,
"push_content" => $community_push_content,
"ad_info" => $community_ad_info
);
$api_querystring = $gl_app_api_url . "communities";
$response = CallAPI('PATCH', $api_querystring, $data, $device_id = null, $community_id = null);
The things to note here are,
the new content tyoe header tells it to be processed as a form post.
removal of the $json_data array, the "ad_info" key is not just added into the $data array
When you process this on the other side you can access the ad_info like this
$ad_info = json_decode($_POST['ad_info']);
You can access the other fields with
$apns_name = $_POST['apns_name'];

Related

PHP POST API no file received

Our team is working on developing a web application for accessing a 3D printer remotely in PHP. We tried implementing the POST print_job part using the multipart/form-data but it doesn't work, which shows no file received. This API would check id and key. Here is the code. Any help is appreciated!
It's running on Apache 2.4.39, PHP 7.3.5, XAMPP Control Panel 3.2.2.
The details are:
<?php
function callAPI($method, $url, $data){
$curl = curl_init();
switch ($method){
case "POST":
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_POST, 1);
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PUT":
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
default:
if ($data)
$url = sprintf("%s?%s", $url, http_build_query($data));
}
$username = "";
$password = "";
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($curl, CURLOPT_USERPWD, $username . ":" . $password);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 90);
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// EXECUTE:
$result = curl_exec($curl);
if(!$result){die("Connection Failure");}
curl_close($curl);
return $result;
}
?>
<?php
include('api.php');
$_SESSION['ip'] = "";
$_SESSION['url'] = "http://".$_SESSION['ip']."/api/v1";
$target_dir = "../uploads/";
$target_file = $target_dir . basename($_FILES["file"]["name"]);
move_uploaded_file($_FILES["file"]["tmp_name"], $target_file);
$filedata = $_FILES["file"]["tmp_name"];
echo $target_file;
$data_array = array(
"jobname" => "file",
"file" => "new \CURLFile(realpath($filedata))"
);
$_SESSION['size'] = $_FILES['file']['size'];
//$make_call = callAPI('POST', $_SESSION['url']."/print_job", $data_array);
$response = callAPI('POST', $_SESSION['url']."/print_job", $data_array);
$_SESSION['print'] = $response;
header('location: ../index.php');
?>
Ps: If I want to upload the file which was got from front-end to the remote API, I may have to store it locally. Then I tried it as the following code. It works.
file_put_contents("E:/xyz/test.gcode",file_get_contents("../uploads/".$_FILES["file"]["name"]));
$filedata='E:/xyz/test.gcode';
if(!is_readable(realpath($filedata))){throw new \RuntimeException("upload file not readable!");}
$data_array = array(
'jobname' => 'file',
'file' => new \CURLFile($filedata)
);
first off, don't set the Content-Type:multipart/form-data header manually because you'll corrupt the boundary if you do. the full header looks something like:
Content-Type: multipart/form-data; boundary=------------------------777d48028c332f50
so remove this:
$headers = array("Content-Type:multipart/form-data");
and let curl set it for you. (curl will automatically set that header, with the correct boundary, when setting CURLOPT_POSTFIELDS to array.)
second, you're not sending an actual file here, you're just sending the literal string
new \CURLFile(realpath($filedata))
.. if you want to send the file pointed to by $filedata , do
$data_array = array(
"jobname" => "test",
"file" => new \CURLFile(realpath($filedata))
);
instead.

Send secret key to API

My API have AUTH_KEY in .env file. I want to check this KEY trough middleware.
I send all my requests to API(another domain) with cURL. And I can't understand how I can send this Key with every request.
Especially, how can I check it. I found some way to send it:
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'AUTH_KEY: secret'
));
I didn't know work it or not, because I don't understand how to get access to this Variable?
UPD. Its my own API) There is now instructions how to send it)
Here is my Request.php
class Request
{
//Return Array of objects with parameters 'id', 'name'
public static function sendRequest($request_type, $url, $param = null)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "backend_service.com/api/$url");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'AUTH_KEY: secret'
));
switch ($request_type) {
case "GET":
$server_output = json_decode(curl_exec($ch));
break;
case "POST":
$query = http_build_query(array(
"name" => $param->name,
"description" => $param->description,
"category_id" => 2,
"type_id" => 3)
);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
$server_output = curl_exec($ch);
break;
case "PUT":
$query = http_build_query(array(
"name" => $param->name,
"description" => $param->description,
"category_id" => $param->category_id,
"type_id" => $param->type_id)
);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_type);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
$server_output = curl_exec($ch);
break;
case "DELETE":
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request_type);
curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
$server_output = curl_exec($ch);
break;
}
curl_close($ch);
return $server_output;
}
}
Try the following on the API end:
<?php
$auth = isset(getallheaders()['AUTH_KEY']) ? getallheaders()['AUTH_KEY'] : '';
var_dump($auth);
It will provide you the header parameter AUTH_KEY. for more info getallheaders()

LinkedIn API - Couldn't parse share document - Json

So i'm working with the LinkedIn API and i'm trying to share something to my wall but i'm getting the following error:
Couldn't parse share document: error: Unexpected end of file after null
I think something is going wrong with with adding the HTTPHEADERS:
Content-Type: application/json
x-li-format: json
So this is what i'm trying to do:
$parameters = array("comment" => "Check out developer.linkedin.com, I'm currently testing it myself!",
"content" => array( "title" => "LinkedIn Developers Resources",
"description" => "Leverage LinkedIn's APIs to maximize engagement",
"submitted-url" => "https://developer.linkedin.com",
"ubmitted-image-url" => "https://example.com/logo.png"
),
"visibility" => array("visibility" => "anyone")
);
$result = $connection->post("people/~/shares", $parameters);
var_dump($result);
var_dump($result); shows the error message above.
And these are the functions i'm using:
public function post($path, $parameters = []){
$url = $this->createUrl($path);
$parameters = json_encode($parameters);
return $this->curlRequest('POST', $url, $parameters);
}
this is the post function, wich is using the following functions:
private function createUrl($path) {
return self::API_HOST . "/v" . self::API_VERSION . "/" . $path . "?" . self::FORMAT;
}
private function curlRequest($method, $url, $postData = NULL, $accessToken = false){
$curl = curl_init();
switch($method) {
case 'GET':
break;
case 'POST':
curl_setopt($curl, CURLOPT_POST, true);
if($accessToken) {
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postData));
} else {
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
}
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'x-li-format: json'));
break;
}
if ($accessToken) {
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
} else {
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Bearer ' . $this->accessToken));
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_URL, $url);
$result = curl_exec($curl);
curl_close($curl);
return json_decode($result, true);
}
Hope someone can help me with this problem.

passing value to array from api php

I want to pass value from API to array but I am not able to figureout what code I need to write. currently it returns [1481367,7546218] how can I pass this in array
$content = array($result) ;
Below is the API Code
$Login = 8632465; #Must be Changed
$apiPassword = "Kcfve123*"; #Must be Changed
$data = array("Login" => $Login, "Password" => $apiPassword);
$data_string = json_encode($data);
$ch = curl_init('http://client-api.instaforex.com/api/Authentication/RequestPartnerApiToken');
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/json', 'Content-Length: ' . strlen($data_string)));
$token = curl_exec($ch);
curl_close($ch);
$apiMethodUrl = 'partner/GetReferralAccounts/'; #possibly Must be Changed
$parameters = $Login; #possibly Must be Changed. Depends on the method param
$ch = curl_init('http://client-api.instaforex.com/'.$apiMethodUrl.$parameters);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); # Turn it ON to get result to the variable
curl_setopt($ch, CURLOPT_HTTPHEADER, array('passkey: '.$token));
$result = curl_exec($ch);
//$result = trim(preg_replace('[]','',curl_exec($ch)));
curl_close($ch);
If the CURL result is "[1481367,7546218]", then to convert this into an array:
`$content = json_decode($result,TRUE); //Here $result = "[1481367,7546218]"`
Printing the variable $content using var_dump() variable will output:
array(2) {
[0] => int(1481367)
[1] => int(7546218)
}

POST in PHP data format error

I'm trying to POST using php. In the API it's suggested the following format.
// post url, keys are added here.
{
"EmailAddress": "john.smith#acmeconsulting.co",
"ActivityEvent": 112,
"ActivityNote": "Note for the activity",
"ActivityDateTime": "yyyy-mm-dd hh:mm:ss",
"FirstName": "John",
"LastName" : "Smith",
"Phone" : "+919845098450",
"Score": 10
}
My code in PHP :
$firstName='Test5';
$activityEvent=201;
$emailAddress='test10#test.com';
$activityNote='Note note note';
$phone='999999999';
$date='2015-07-21 12:48:10';
$data_string['ActivityEvent']=$activityEvent;
$data_string['EmailAddress']=$emailAddress;
$data_string['ActivityNote']=$activityNote;
$data_string['Phone']=$phone;
$data_string['ActivityDateTime']=$date;
//json_encode($data_string);
try
{
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Content-Type:application/json',
'Content-Length:'.strlen($data_string)
));
$json_response = curl_exec($curl);
curl_close($curl);
} catch (Exception $ex) {
curl_close($curl);
}
This code is not working as expected. I'm not getting any update there. Is the code correct?
Have you tried this?
$object = new StdClass;
$object->ActivityEvent = 201;
$object->EmailAddress = 'john.smith#acmeconsulting.co';
//add more properties here
echo json_encode($object);
$datastring = array(
'firstName' => 'John',
'lastName' => 'Smith',
...........);
$ch = curl_init("YOUR_URL_HERE");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $datastring );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
the result will be stored in the $result variable

Categories