Postman is an API testing interface that I can use to make my specific API call successfully. I'm trying to do the same thing in PHP using CURL, but am having an issue with the way the API expects the format...
Let's say my URL is /post. The only variable after /post is "auth=asdf1234etc", and then XML data. So using postman I put
/post?auth=asdf1234etc
That goes in the URL section, and it has a raw XML data post section, where I put My XML:
<?xml version="1.0" encoding="UTF-8"?><usageReports><usageReport></usageReport></usageReports>
My problem is that the XML is not a variable, where asdf1234etc is the value of the key auth, my XML is a value with no key -- so I don't know how to make the post using CURL.
Here's my PHP that doesn't work -- I get 401 unauthorized because the program thinks everything after ?auth="..." is the auth token. But it also doesn't work if I put an & after the auth token, because after an & I would have to do key=value, where I don't have a key.
$URL = "/post?auth=asdf1234etc";
$usage_report = '<?xml version="1.0" encoding="UTF-8"?><usageReports><usageReport></usageReport></usageReports>';
$fields = array("Host" => "/post",
"Content-type" => "application/xml",
"Content-length" => strlen($usage_report),
"data" => $usage_report);//note that my xml is not a variable and I don't expect this specific line to work.
$fields_string = "&";
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
//open connection
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $URL);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $fields);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
$array_data = json_decode(json_encode(simplexml_load_string($result)), true);
//view response
echo "\n\n";
print_r($array_data);
echo "\n";
What would be really helpful is if postman had an output that was a literal URL with everything in it, post URL base + authtoken + the XML -- because I can do it in postman(200 OK), just can't get the PHP to do the same.
I turned on CURLOPT_VERBOSE, and here might be some useful information:
POST /post?asdf123etc HTTP/1.1
Host: hidden.domain.com
Accept: */*
Content-Length: 335 //Why 335? strlen($usage_report) is 248?
Content-Type: application/x-www-form-urlencoded //why is it changing from application/xml to this?
-it’s not a certificate issue
-it’s not a connection to host issue
-it’s kindof an auth issue, because it thinks that everything after ? is the auth token
-it’s an interesting problem because I can’t set the xml to a key in the fields array
-the xml constructed and urls I use work when using postman
-not an issue of xml format
p.s. if you think you've found a duplicate, make sure they are also asking what to do when POSTing XML that isn't a httpheader. (not something like this)
Remove these lines from your code:
$fields = array("Host" => "/post",
"Content-type" => "application/xml",
"Content-length" => strlen($usage_report),
"data" => $usage_report);//note that my xml is not a variable and I don't expect this specific line to work.
$fields_string = "&";
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
Now, first fix your xml string. You didn't escape the quotes from your xml. So use this one:
$usage_report = '<?xml version="1.0" encoding="UTF-8"?><usageReports><usageReport></usageReport></usageReports>';
Replace these two curl options with your existing one. Here its posting XML data:
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: application/xml")); // or text/xml
curl_setopt($ch, CURLOPT_POSTFIELDS, $usage_report);
Your verbose output says you have used a proper url. But still to double check, make sure the url is correct. Currently its using URI instead of URL in your code:
$URL = "/post?auth=asdf1234etc";
You can get postman code for all languages and use it:
for example for your question you can copy the php-guzzle code easily and use it.
On the right side of the page, there is a button to show the code.
in the below photo, you can find it.
#postman #PHP #Guzzle #Laravel
Related
I am trying to get a token to use the Microsoft Graph API (https://learn.microsoft.com/en-us/graph/auth-v2-user?context=graph%2Fapi%2F1.0&view=graph-rest-1.0) via Curl. I have set up a simple Php file with this function:
function getToken() {
echo "start gettoken";
var_dump(extension_loaded('curl'));
$jsonStr = http_build_query(Array(
"client_id" => "***",
"scope" => "https://graph.microsoft.com/.default",
"client_secret" => "***",
"grant_type" => "client_credentials"
));
$headers = Array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($jsonStr));
$ch = curl_init("https://login.microsoftonline.com/***.onmicrosoft.com/oauth2/v2.0/token");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$token = curl_exec($ch);
echo "test after curl";
return $token;
curl_error($ch);
}
However, what I want to know is why the curl request is not working. Also the echo after the curl codeblock is not being executed, while 'start gettoken' is. PHP_curl is enabled in my WAMP. Why is this?
Are you sure CURL is enabled because that code you have posted is ok and giving echo response before and after curl execution.
you're sending the token request in a JSON-format, and then you're lying to the server saying it's application/x-www-form-urlencoded-encoded when it's actually application/json-encoded! since these 2 formats are completely incompatible, the server fails to parse it, and... ideally it should have responded HTTP 400 bad request (because your request can't be parsed as x-www-form-urlencoded)
anyhow, to actually send it in the application/x-www-form-urlencoded-format, replace json_encode() with http_build_query()
also get rid of the "Content-Length:"-header, it's easy to mess up (aka error-prone) if you're doing it manually (and indeed, you messed it up! there's supposed to be a space between the : and the number, you didn't add the space, but the usual error is supplying the wrong length), but if you don't do it manually, then curl will create the header for you automatically, which is not error-prone.
I am new at programming Slash commands in Slack. For one of my commands, I have a username and need to retrieve the user icon URL. I am using PHP to code them.
I was planning on using users.profile.get, since the tutorial here shows that one of the fields returned is the user icon URL.
However, I am trying to find examples on how to make a call to this method and have not found any. Could anybody give me a quick example of the call, including how to send the parameters?
This is how far I got:
$slack_profile_url = "https://slack.com/api/users.profile.get";
$fields = urlencode($data);
$slack_call = curl_init($slack_profile_url);
curl_setopt($slack_call, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($slack_call, CURLOPT_POSTFIELDS, $fields);
curl_setopt($slack_call, CURLOPT_CRLF, true);
curl_setopt($slack_call, CURLOPT_RETURNTRANSFER, true);
curl_setopt($slack_call, CURLOPT_HTTPHEADER, array(
"Content-Type: application/x-www-form-urlencoded",
"Content-Length: " . strlen($fields))
);
$profile = curl_exec($slack_call);
curl_close($slack_call);
I basically have $token and $user_name and need to get the profile picture URL. How do I format $token and $username as $data? Is the call correct?
If anybody recommends doing this a different way, I would appreciate any advice as well.
Thank you so much!
To get data into the right format to post to Slack is pretty straight forward. There's two options (POST body or application/x-www-form-urlencoded).
The query string for application/x-www-form-urlencoded is formatted like a get URL string.
https://slack.com/api/users.profile.get?token={token}&user={user}
// Optionally you can add pretty=1 to make it more readable
https://slack.com/api/users.profile.get?token={token}&user={user}&pretty=1
Just request that URL and you will retrieve the data.
The POST body format will use a similar code to what you have above.
$loc = "https://slack.com/api/users.profile.get";
$POST['token'] = "{token}";
$POST['user'] = "{user}";
$ch = curl_init($loc);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $POST);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
if ($error = curl_errno($ch)) { echo $error; }
//close connection
curl_close($ch);
echo $result;
I need to send an XML string via HTTP POST to another server using the settings below...
POST /xmlreceive.asmx/CaseApplicationZipped HTTP/1.1
Host: www.dummyurl.co.uk
Content-Type: application/x-www-form-urlencoded
Content-Length: length
XMLApplication=XMLstring&byArray=base64string
I'm guessing I need to set this up via cURL or maybe fsockopen.
I've tried the following but not having any luck at getting it to work.
$url = "http://www.dummyurl.co.uk/XMLReceive.asmx/CaseApplicationZipped";
$headers = array(
"Content-Type: application/x-www-form-urlencoded"//,
);
$post = http_build_query(array('XMLApplication' => $XML, 'byArray' => $base64));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo "response: ".$response;
The remote server gives the following response...
"Object reference not set to an instance of an object."
Not enough rep yet to comment, so I'll post this as an answer.
PHP's cURL automatically send the Host (from $url) and the Content-Length headers, so you don't need to specify those manually.
A handy function exists for building the $post string: http_build_query. It'll handle properly encoding your POST body. It would look something like
$post = http_build_query(array('XMLApplication' => $XML, 'byArray' => $base64));
If you want to log out the headers you received, check the curl_getopt function.
As for the error you received, it seems like you're passing the remote site things it doesn't expect. I can't speak for what you're passing or what the site's expecting, but Input string was not in a correct format seems to imply that your $XML is not formatted correctly, or is being passed as an incorrect parameter.
I've never worked with JSON objects before but I think this is probably the best route for what I'm trying to achieve (if you think there is a better option please let me know, though I cannot use SOAP)
I am trying to submit some data via POST to an API in order to add some data to a newsletter list which is stored as XML. Here is the documentation for the request I am trying to complete: https://api.dotmailer.com/v2/help/wadl#PostAddressBookContacts
When visiting the API url and authenticating I see data laid out in the following:
<ArrayOfApiContact xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://apiconnector.com">
<ApiContact>
<Id>1058905201</Id>
<Email>email#email.co.uk</Email>
<OptInType>Unknown</OptInType>
<EmailType>Html</EmailType>
<DataFields i:nil="true"/>
<Status>Subscribed</Status>
</ApiContact>
</ArrayOfApiContact>
So I have attempted to replicate as such, using a variable instead of a hardcoded email:
$xml = array(
'id' => urlencode('123456789'),
'email' => urlencode($useremail),
'optInType' => urlencode('Unknown'),
'emailType' => urlencode('Html'),
'dataFields' => urlencode(':null'),
'status' => urlencode('Subscribed')
);
I am combining the array here:
foreach($xml as $key=>$value) { $xml_string .= $key.'='.$value.'&'; }
And then using cURL to POST the request to the API, with my authentication (apipassword and apiemail which the username)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$auth_url);
curl_setopt($ch,CURLOPT_POST, count($xml));
curl_setopt($ch,CURLOPT_POSTFIELDS, $xml_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_USERPWD, "$apiemail:$apipassword");
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //get status code
$result = curl_exec ($ch);
curl_close ($ch);
I have already tested this without the POST and I do indeed get the data back in this form:
[{"id":1058905201,"email":"email#email.co.uk","optInType":"Unknown","emailType":"Html","dataFields":null,"status":"Subscribed"}]
So I know the auth is working and the data is coming back correctly, but now when I try to POST my data I get:
{"message":"Content type \"application/x-www-form-urlencoded\" is not supported. Please use one of: application/json,application/xml ERROR_CONTENT_TYPE_IS_NOT_SUPPORTED"}
So how do I convert my array which is URL encoded into something readable by the API?
Try a content type of application/json like so:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('content-type: application/json'));
Two things here (a) content-type header JSON missing and (b) payload not JSON.
// setup request to send json via POST.
$payload = json_encode(array("json"=> $data)); // or json_encode(array($data));
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
// set proper content-type for sending JSON
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
I've found that if I try a PHP POST curl, the postvars are sent fine. Once I add the httpheader of content-type: application/json the postvars don't go across any more. I've tried the postvars as a JSON string and as a query string.
Showing some code:
$ch = curl_init();
$post = json_encode(array('p1' => 'blahblahblah', 'p2' => json_encode(array(4,5,6))));
$arr = array();
array_push($arr, 'Content-Type: application/json; charset=utf-8');
curl_setopt($ch, CURLOPT_HTTPHEADER, $arr);
curl_setopt($ch, CURLOPT_URL, 'https://example.com/file.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_exec($ch);
curl_close($ch);
A real HTTP Post, that gets broken into an array automagically by PHP must be formatted in name=value pairs, the best way to do this in PHP is using the http_build_query function.
http://ca2.php.net/manual/en/function.http-build-query.php
There is an example that works in the PHP Manual using curl:
http://ca2.php.net/manual/en/function.curl-exec.php#98628
What you're doing is a 'RAW' post, see this other question:
How to post JSON to PHP with curl
A quick snippet to get the RAW Json data.
<?php
print_r(json_decode(file_get_contents('php://input')));