How to send a curl request with pem certificate via PHP? - php

I have a php script in my Apache server that have to send a curl request to a partner's server.
Partner give me a .pem file that I have to attach to every call I do to its api.
My php script is the follow:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSLCERT, "test.pem" );
curl_setopt($ch,CURLOPT_SSLCERTTYPE,"PEM");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, True);
curl_setopt($ch, CURLOPT_POST, True);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_VERBOSE, true);
$result = curl_exec($ch);
if(!$result)
{
echo "Curl Error: " . curl_error($ch);
}
else
{
echo "Success: ". $result;
}
curl_close($ch);
It returns:
Curl Error: unable to set private key file: 'test.pem' type PEM
Consider that it sends me .pem file and says "it has no passphrase"

I think that you need to use the tmpfile() and stream_get_meta_data.
$pemFile = tmpfile();
fwrite($pemFile, "test.pem");//the path for the pem file
$tempPemPath = stream_get_meta_data($pemFile);
$tempPemPath = $tempPemPath['uri'];
curl_setopt($ch, CURLOPT_SSLCERT, $tempPemPath);
Source: This answer here in SO helps me with similar problem.

I think you're missing
curl_setopt($ch, CURLOPT_CAINFO, 'test.pem');
Have a look at cURL is unable to use client certificate , in local server
for more about using client certificates in curl via PHP

Related

Undefined constant http/2

I am trying to work out how to send push notifications to apple iOS devices from a php site. I had a php script that was working before the new http/2 way but since they do not support it anymore, it of course does not work.
The new script I have is this:
<?php
$ch = curl_init();
$device_token = 'correctDevice';
$pem_file = 'correctPemfile';
$pem_secret = 'correctCode';
$apns_topic = 'correctAppID';
//curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("apns-topic: $apns_topic"));
curl_setopt($ch, CURLOPT_SSLCERT, $pem_file);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $pem_secret);
curl_setopt($ch, CURLOPT_VERBOSE , true);
echo "Try 1 ================================================" . PHP_EOL;
//setup and send first push message
$url = "https://api.development.push.apple.com/3/device/$device_token";
curl_setopt($ch, CURLOPT_URL, "{$url}");
$sample_alert = '{"aps":{"alert":"hi #1","sound":"default"}}';
curl_setopt($ch, CURLOPT_POSTFIELDS, $sample_alert);
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch);
//var_dump($response);
//var_dump($httpcode);
echo "Try 2 ================================================" . PHP_EOL;
//setup and send second push message
$url = "https://api.development.push.apple.com/3/device/$device_token";
curl_setopt($ch, CURLOPT_URL, "{$url}");
$sample_alert = '{"aps":{"alert":"hi #2","sound":"default"}}';
curl_setopt($ch, CURLOPT_POSTFIELDS, $sample_alert);
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch);
//var_dump($response);
//var_dump($httpcode);
curl_close($ch);
?>
I've blocked out the device token, pem file, secret and app ID of course, but they are all correct.
The issue with it is that I get this error:
Warning: Use of undefined constant CURL_HTTP_VERSION_2_0 - assumed 'CURL_HTTP_VERSION_2_0' (this will throw an Error in a future version of PHP)
What could this issue be? I tried echoing phpinfo() and see if it supports http/2 and I found this:
From the documentation:
CURL_HTTP_VERSION_2_0 (int)
Available since cURL 7.33.0
Check the cURL version (e.g. by using phpinfo()).

Curl Request working but not inside laravel

Hi everyone i have crul request when i use it in single php page without laravel it work fine but if i put it inside laraevl controller to use it not working and return code status 0
My Request
$data = '{"PaymentInquiryV4RequestMessage":{"RefNum":"123456"}}';
$ch = curl_init('https://b2btest.stcpay.com.sa/B2B.DirectPayment.WebApi/DirectPayment/V4/PaymentInquiry');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($ch, CURLOPT_SSLCERT, 'crt.crt');
curl_setopt($ch, CURLOPT_SSLKEY, 'key.key');
curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'X-ClientCode: XXXXXXXXXXX'
)
);
$result = curl_exec($ch);
$result = json_decode($result, true);
print_r ($result);
when dealing with curl always start by debugging errors, which you can enable like
$result = curl_exec($ch);
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
echo $error_msg;
}
and as you mentioned in comment, you received below error after adding above code:
could not load PEM client certificate, OpenSSL error error:02001002:system library:fopen:No such file or directory, (no key found, wrong pass phrase, or wrong file format?)
It clearly indicate it can't find your certificate files, update path to those files in your call , like if your certificates are in directory /var/www/certificate/, your code would be
curl_setopt($ch, CURLOPT_SSLCERT, '/var/www/certificate/crt.crt');
curl_setopt($ch, CURLOPT_SSLKEY, '/var/www/certificate/key.key');
and make sure cert files are readable by setting proper permissions.
p.s you can also use Laravel helpers to get the path
base_path(); // '/var/www/mysite'
app_path(); // '/var/www/mysite/app'
storage_path(); // '/var/www/mysite/storage'
so you call will contain like
curl_setopt($ch, CURLOPT_SSLCERT, base_path().'/certificate/crt.crt');
curl_setopt($ch, CURLOPT_SSLKEY, base_path().'/certificate/key.key');

could not load PEM client certificate, OpenSSL

I have four files provided from client side.
test.jks
test.pem
key.pub
test.p12
I have to send json array on this url using curl. so i'm confused what is the use of other files ? like .p12 , .jks. what is the key from above files ?
I started with .pem file included using this link :
How to send a curl request with pem certificate via PHP?
So , I got following errors.
Error :
Curl Error: could not load PEM client certificate, OpenSSL error
error:0906D06C:PEM routines:PEM_read_bio:no start line, (no key found,
wrong pass phrase, or wrong file format?)No HTTP code was returned
Code :
$url = "https://adfapi.adftest.rightmove.com/v1/property/sendpropertydetails";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
$pemFile = tmpfile();
fwrite($pemFile, "test.pem");//the path for the pem file
$tempPemPath = stream_get_meta_data($pemFile);
$tempPemPath = $tempPemPath['uri'];
curl_setopt($ch, CURLOPT_SSLCERT, $tempPemPath);
//curl_setopt($ch, CURLOPT_SSLCERT, "test.pem" );
curl_setopt($ch,CURLOPT_SSLCERTTYPE,"PEM");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, True);
curl_setopt($ch, CURLOPT_POST, True);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
curl_setopt($ch, CURLOPT_VERBOSE, true);
$result = curl_exec($ch);
if(!$result)
{
echo "Curl Error: " . curl_error($ch);
}
else
{
echo "Success: ". $result;
}
$info = curl_getinfo($ch);
curl_close($ch); // close cURL handler
if (empty($info['http_code'])) {
die("No HTTP code was returned");
} else {
// load the HTTP codes
$http_codes = parse_ini_file("path/to/the/ini/file/I/pasted/above");
// echo results
echo "The server responded: <br />";
echo $info['http_code'] . " " . $http_codes[$info['http_code']];
}
Since you are using the filename - Try an absolute path.
e.g
curl_setopt($ch, CURLOPT_SSLCERT, 'c:/wamp64/www/bit-tool/www/testcert.pem');

Using cURL to read from https response

I am using the following code to access a URL (the URL uses the https protocol, and has a valid certificate)
// Initialize session and set URL.
$url = https://my url;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
// Set so curl_exec returns the result instead of outputting it.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Get the response and close the channel.
$response = curl_exec($ch);
curl_close($ch);
But the output i get is this:
Failed: Error Number: 60. Reason: SSL certificate problem, verify that
the CA cert is OK. Details: error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Can somebody please guide me?
use 'CURLOPT_RETURNTRANSFER'
$res = curl_init ('url');
curl_setopt($res,CURLOPT_RETURNTRANSFER,true);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$out = curl_exec($res);
curl_close($res);
echo $out;
for more info read this
Try adding:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

Send File to HTTPS URL using CURL and PHP

I am attempting to send a file to an Https URL with this code:
$file_to_upload = array('file_contents'=>'#'.$target_path);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSER, FALSE);
curl_setopt($ch, CURLOPT_UPLOAD, TRUE);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'file='.$file_to_upload);
$result = curl_exec($ch);
$error = curl_error($ch);
curl_close ($ch);
echo " Server response: ".$result;
echo " Curl Error: ".$error;
But for some reason I'm getting this response:
Curl Error: Failed to open/read local data from file/application
Any advice would help thanks!
UPDATE: When I take out CURLOPT_UPLOAD, I get a response from the target server but it says that there was no file in the payload
You're passing a rather strange argument to CURLOPT_POSTFIELDS. Try something more like:
<?
$postfields = array('file' => '#' . $target_path);
// ...
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
?>
Also, you probably want CURLOPT_RETURNTRANSFER to be true, otherwise $result won't get the output, it'll instead be sent directly to the buffer/browser.
This example from php.net might be of use as well:
<?php
$ch = curl_init();
$data = array('name' => 'Foo', 'file' => '#/home/user/test.png');
curl_setopt($ch, CURLOPT_URL, 'http://localhost/upload.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_exec($ch);
?>
On top of coreward's answer:
According to how to upload file using curl with php, starting from php 5.5 you need to use curl_file_create($path) instead of "#$path".
Tested: it does work.
With the # way no file gets uploaded.

Categories