I am tasked with building an API to receive inbound XML data. On my client, I have this code.
$url = "http://stackoverflow.com";
$xml = '<?xml version="1.0" encoding="UTF-8"?><Request PartnerID="asasdsadsa" Type="TrackSearch"> <TrackSearch> <Title>love</Title> <Tags> <MainGenre>Blues</MainGenre> </Tags> <Page Number="1" Size="20"/> </TrackSearch> </Request>';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt( $ch, CURLOPT_POSTFIELDS, "xml=".$payload );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$request = curl_exec($ch);
curl_close($ch);
On my remote server, I have this code
function TransmitRx()
{
$xml = trim(file_get_contents('php://input'));
file_put_contents("newStandard/".rand(100,500)."received.xml", $xml);
}
//Listen for inbound data
TransmitRx()
If I open up the server endpoint URL, there is an empty file saved. I don't know why. But when I run the client-side script. I get nothing. No errors. Nothing.
I have looked at several of the pages here and every one of them has a similar cURL statement to send data.
Why am I not receiving any post data at the API endpoint?
I have been unsuccessful at any information via the WWW.
UPDATE
Final Code that works:
function get_url($request_url, $payload)
{
$headers = [
"Access-Control-Allow-Origin: *",
"Content-type: text/xml",
"Content-length: " . strlen($payload),
"Connection: close",
];
$data = ['xml' => $payload];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request_url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$response = curl_exec($ch) or die(curl_error($ch));;
if (curl_errno($ch)) {
print curl_error($ch);
} else {
curl_close($ch);
}
return $response;
}
$request_url = 'https://stackoverflow.com/posts';
$response = get_url($request_url, $payload);
I wish I knew for sure what caused it to start working. I was reading this page last.
https://www.php.net/manual/en/curlfile.construct.php
Okay, so if adding the lines I suggested to disable certification / peer validation enabled the process to work, then that just means the remote server is using an SSL certificate that is not trusted by cURL.
Those lines are NOT the final fix. You never want to disable SSL validation in a real environment. I only suggested you temporarily disable them to see if that was truly the problem. If you leave them disabled, then you are leaving your code vulnerable to man-in-the-middle (MITM) attacks.
The correct fix is usually to point cURL at an updated CA bundle. The official cURL website graciously provides these here:
https://curl.haxx.se/docs/caextract.html
The process is that you download the CA bundle file and put it somewhere where your script can find it, and then add this curl option:
curl_setopt ($ch, CURLOPT_CAINFO, "full path to the CA bundle file.pem");
If the remote server's certificate came from any of the major CA vendors out there, this should be all you need to do.
If the remote server's certificate is self-signed or something then you might need to download the specific CA certificate and any supporting intermediate CA certificates and tell cURL to find them.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am trying to get Json Data from a https url.
I have tested and working code to do just this for http but I am yet to find a working version for https. This needs to be secure code.
This is my http version that works:
<?php
$key = "admin"; //user
$secret = "admin"; //pass
$api_ep = "http://$Hostname:$Port/$address";
if ($key && $secret){
$curl_opts = array(
CURLOPT_HTTPHEADER=>array("Accept: application/json"),
CURLOPT_VERBOSE=>false,
CURLOPT_HEADER=>false,
CURLOPT_POST=>false,
CURLOPT_RETURNTRANSFER=>true,
CURLOPT_HTTPAUTH=>CURLAUTH_DIGEST,
CURLOPT_USERPWD=>$key.":".$secret,
CURLOPT_URL=> $api_ep
);
}
function disp($opts,$var){
$ch = curl_init();
curl_setopt_array($ch, $opts);
$raw_resp = curl_exec($ch);
// $array_resp = json_decode($raw_resp);
//print_r($array_resp);
print_r($raw_resp);
curl_close($ch);
//$array = json_decode($raw_resp, true);
//print_r($array_resp);
//disp_table($array_resp, $var);
}
disp($curl_opts,$Type);
?>
If you don't have any sensitive data you can try setting CURLOPT_SSL_VERIFYPEER to FALSE
Else you will have to verify the certificate.
Since Curl doesn't have built-in root certificates. You need to explicitly point it to a cacert.pem file:
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/file/cacert.pem');
Without this, curl cannot verify the certificate sent back via ssl. This same root certificate file can be used every time you use SSL in curl.
You can get the cacert.pem file here: http://curl.haxx.se/docs/caextract.html
Note:
Setting CURLOPT_SSL_VERIFYPEER to false allows for man-in-the-middle-attacks. rmckay at webaware dot com dot au warns for this on nl3.php.net/manual/en/function.curl-setopt.php and gives an alternative solution that works: downloading a CA root certificate bundle at the curl website and saving it on your server. See at the given site, scroll down to the user comments
This code below works for https.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $basicAuthUrl);
$header = array();
$header[] = 'Content-length: 29';
$header[] = 'Content-type: application/x-www-form-urlencoded;charset=UTF-8';
$header[] = 'Authorization: Basic ' . $keyAndSecretEncoded;
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_credentials");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$result = curl_exec($ch);
curl_close($ch);
Add the following to disable SSL verification.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
Curl SSL fails to verify self signed certificates and hence, you will not be able to connect with https hosts if they are using self signed certificates.
function disp($opts,$var){
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt_array($ch, $opts);
$raw_resp = curl_exec($ch);
print_r($raw_resp);
curl_close($ch);
}
I am trying to implement an SOAP API. But I am not getting how to send request to the given URL.
I do not have any support for that API, just have few lines as an instruction.
I did not used SOAP before, can some one please help to understand how to create and send request as XML using a certificate.
Here is the instructions to use the API
Test API Link
https://202.82.66.148:8443/ptms4541/ws/CksServices
Worksite:BST-API
Account:BST-API01
Response to connect (Have to set header of the following)
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<tns:RequestSOAPHeader xmlns:tns="https://202.82.66.148:8443/ptms4541/ws/CksServices">
<tns:account xmlns="https://202.82.66.148:8443/ptms4541/ws/CksServices">BST-API01</tns:account>
<tns:timestamp xmlns="https://202.82.66.148:8443/ptms4541/ws/CksServices">201606211538</tns:timestamp>
<tns:pwd xmlns="https://202.82.66.148:8443/ptms4541/ws/CksServices">***********</tns:pwd>
<tns:worksite xmlns="https://202.82.66.148:8443/ptms4541/ws/CksServices">BST-API</tns:worksite>
<tns:discount_id xmlns="https://202.82.66.148:8443/ptms4541/ws/CksServices"/></tns:RequestSOAPHeader>
</soap:Header>
<soap:Body>
<ns2:getShippingLine xmlns:ns2="http://ws.service.gen.cks.com/"/> </soap:Body>
</soap:Envelope>
Certificates to installed attached in Email
getShippingLine()
Along with this I have an file that have .crt extension
I have tried CURL (from here : PHP & XML - How to generate a soap request in PHP from this XML?) and also SoapClient (did not understand how to create request in required format : Sending XML input to WSDL using SoapClient) to implement this but no luck.
Actually I am unable to understand that how to send request and what need to be send in that request in which manner.
Please help me to understand this.
Thanks
Php SOAP library does not support certificates and private key assertion as well wse-php rob richard library done so well for this case , i have to come this solution after long time :
function Curl_Soap_Request($request, $url)
{
/**
* #param request is your xml for soap request
* #param url is location of soap where your request with hit
*/
$keyFile = getcwd() . "\\privatekey.pem"; //
$caFile = getcwd() . "\\certificate.pem"; //
$certPass = "test123";
// xml post structure
$xml_post_string = $request; // data from the form, e.g. some ID number
$headers = array(
"Content-type: application/soap+xml; charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
// "SOAPAction: '/Imp1/ApplicantEligibilityService",
"Content-length: " . strlen($xml_post_string),
); //SOAPAction: your op URL
//$url = $soapUrl;
// PHP cURL for https connection with auth
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_URL, $url);
// The --key option - If your key file has a password, you will need to set
// this with CURLOPT_SSLKEYPASSWD
// curl_setopt($ch, CURLOPT_SSLKEY, $keyFile);
curl_setopt($ch, CURLOPT_SSLKEY, $keyFile);
// The --cacert option
curl_setopt($ch, CURLOPT_SSLCERT, $caFile);
// The --cert option
//curl_setopt($ch, CURLOPT_SSLCERT, $certFile);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $certPass);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($ch, CURLOPT_USERPWD, $soapUser.":".$soapPassword); // username and password - declared at the top of the doc
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_TIMEOUT, 180);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string); // the SOAP request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// converting
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
I have and xml url from a supplier which generates xml content dynamically with php like;
http://www.example.com/outputxml/index.php?xml_service_id=161
This url is valid for a static ip so I gave him my websites hosting ip. Is there a way to open that url in browser with data scraping? Because My internet connection has no static ip.
Thank you.
I have tried below code;
$url = 'http://www.example.com/outputxml/index.php?xml_service_id=161?';
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $xml );
$result = curl_exec($ch);
curl_close($ch);
echo $result;
But it gave html format.
Save the content on your server with something like a wget and then serve it. Please notice that you are probably going to infringe the policy of the xml's author (I don't know the consequences or the policy itself, but you should be careful), so you might consider to at least add a .htacces authentication on your server's page, just to not make the xml public.
I'm trying to make a bot for: https://coinroll.it/api
From the site:
The Coinroll API is a stateless interface which works over HTTPS. Requests are made using POST variables (application/x-www-form-urlencoded) while responses are encoded in JSON (application/json). A HTTPS connection is required for accessing the API.
I have the following code:
$ch = curl_init();
$data = array('user' => 'xxx', 'password' => 'yyy');
curl_setopt($ch, CURLOPT_URL, 'https://coinroll.it');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
echo $result;
When I run this code, it returns a blank page, what am I doing wrong?
EDIT
I don't actually need to use cURl, if there is a better solution, please tell me.
You can prevent cURL from trying to verify the SSL certificate by using CURLOPT_VERIFYPEER.
Also set the action in the URL:
$ch = curl_init();
$data = array('user' => 'xxx', 'password' => 'yyy');
curl_setopt($ch, CURLOPT_URL, 'https://coinroll.it/getbalance');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
echo $result;
You can use the following cURL option in order to see what happens with the HTTP connection:
curl_setopt($ch, CURLOPT_VERBOSE, true);
When TRUE it outputs verbose information.
Today I had the case where "It had been working fine until now.", but it stopped working when the FQDN changed, and I had to self-sign another certificate, with a different DN.
After a few experiments, it turned out to be that the Subject Alternate Name (aka SAN) was not matching the certificate name, and the curl call had not been set with CURLOPT_SSL_VERIFYHOST, 2.
Conclusion: by default, CURLOPT_SSL_VERIFYHOST is set to 2, but, if your cert SAN is wrong, it will fail, unless you deactivate CURLOPT_SSL_VERIFYHOST, and, with it, CURLOPT_SSL_VERIFYPEER.
It is obviously the best practice to set both, and have a SAN that matches the subject.
Reminder: this is how to quickly check the SAN using OpenSSH on command line:
openssl x509 -in /etc/ssl/certs/recette.pharmags.fr.crt -noout -text | grep -A1 "Subject Alternative Name"
I know nothing about implementing an API. I do know PHP a bit. I have a situation where I need to call a REST API method to purge cache on a CDN server. Can somebody help me with some sample code?
The following is the sample request:
PUT <<url>>
Authorization: TOK:12345-12345
Accept: application/json
Content-Type: application/json
Host: api.edgecast.com
Content-Length: 87
{
"MediaPath":"<<urlhere>>"
"MediaType":"3"
}
Can somebody help me with code to implement this rest api request?
Thanks in advance.
I had to find the hard way too. This has been tested (with slight modifications from my original code)
//## GoGrid PHP REST API Call
define('TOKEN','XXXXX-XXXXX-XXXXX-XXXXXX'); // found on the cdn admin My Settings
define('ACCOUNT_NUMBER','XXXX'); // found on the cdn admin Top Right corner
function purgeCacheFileFromCDN($urlToPurge) {
//## Build the request
$request_params = (object) array('MediaPath' => $urlToPurge, 'MediaType' => 8); // MediaType 8=small 3=large
$data = json_encode($request_params);
//## setup the connection and call.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.edgecast.com/v2/mcc/customers/'.ACCOUNT_NUMBER.'/edge/purge');
curl_setopt($ch, CURLOPT_PORT , 443);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1); // For debugging
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); // no caching
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1); // no caching
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: tok:'.TOKEN, 'Content-Type: application/json','Accept: application/json', 'Content-length: '.strlen($data)));
$head = curl_exec($ch);
$httpCode = curl_getinfo($ch);
curl_close($ch);
//## check if error
if ($httpCode['http_code'] != 200) {
echo 'Error reported: '.print_r(array($head,$httpCode),1); // output it to stdout this will be emailed to me via cron capture.
}
}
Was too lazy to write from the scratch so copied from amazingly pink site that Google advises in the first page of results.
$data = array("a" => $a);
$ch = curl_init($this->_serviceUrl . $id);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($data));
$response = curl_exec($ch);
if(!$response) {
return false;
}
PS: The source search request: http://www.google.ru/search?q=php+sample+put+request+curl
Here is my source gist for my fully implemented Grunt task for anyone else thinking about working with the EdgeCast API. You'll find in my example that I use a node module to execute the curl command which purges the CDN.
This was that I ended up with after spending hours trying to get an HTTP request to work within Node. I was able to get one working in Ruby and Python, but did not meet the requirements of this project.