I am attempting to connect to a 3rd party API, and they require me to pass 3 certificate files they have given me: public cert, private cert, and CA cert. It works fine in cURL with the following settings:
if (empty($this->order['connector'])) {
curl_setopt($_curl, CURLOPT_SSLKEY, API_PRIVATE_CERT);
curl_setopt($_curl, CURLOPT_CAINFO, API_CA_CERT);
curl_setopt($_curl, CURLOPT_SSLCERT, API_PUBLIC_CERT);
}
Each value passed is a path to a physical file on the server. This works fine.
With one request, however, I have to pass a header 'Content-Type: Multipart/Related; boundary="---BOUNDARY123456"' with a MIME message that contains an XML file and a Base64 encoded PDF. This fails with a 500 error on their end. And in researching this, I have seen cURL cannot properly handle Content-Type: Multipart/Related posts.
https://stackoverflow.com/a/25998544/3434084
So I have tried to send it using stream_get_contents(), but I get no response back. So I am thinking my cert data is wrong. How can I pass the same values I use in cURL via stream_get_contents()?
Here's the code:
$payload = '----=FB498299F0F50D2A190B3C
Content-Type: application/x-ofx
<?xml version="1.0" encoding="ISO-8859-1"?>
<?OFX OFXHEADER="200" VERSION="201" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>
<OFX>
<SIGNONMSGSRQV1>
<SONRQ>
<LANGUAGE>ENG</LANGUAGE>
<APPID>TWEEN</APPID>
</SONRQ>
</SIGNONMSGSRQV1>
...
</OFX>
----=FB498299F0F50D2A190B3C
Content-Type: application/pdf
Content-Transfer-Encoding: base64
Content-Location: full1_1559588546.pdf
JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDM...PRgo=
----=FB498299F0F50D2A190B3C' . "
";
$params = [
'http' => [
'method' => 'POST',
'header' => 'Content-Type: Multipart/Related; boundary="----=FB498299F0F50D2A190B3C"',
'content' => $payload
],
'ssl' => [
'verify_peer' => true,
'local_pk' => API_PRIVATE_CERT,
'cafile' => API_CA_CERT,
'local_cert' => API_PUBLIC_CERT
]
];
$_stream = stream_context_create($params);
$response = @file_get_contents('https://blah/api/, FILE_TEXT, $_stream);
TIA!
try
$params = [
"ssl"=>[
"verify_peer"=> true,
"verify_peer_name"=> true,
"cafile" => "pem.pem",
],
];
$response = file_get_contents($URL, 0, stream_context_create($params)
It turns out my issues was with the original cURL code I had used that was failing. Here's the updated code I needed to use in this case to send multipart/related content via cURL, using the 3rd party's SSL certificate data provided to me to authenticate access.
$headers = [
'Content-Type: Multipart/Related; boundary="--' . $this->api_boundary . '";type=text/xml'
];
$_curl = curl_init();
curl_setopt($_curl, CURLOPT_URL, $this->api_url);
curl_setopt($_curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($_curl, CURLOPT_SSLCERTTYPE, FALSE);
curl_setopt($_curl, CURLOPT_POSTFIELDS, $this->api_xml);
curl_setopt($_curl, CURLOPT_POST, TRUE);
curl_setopt($_curl, CURLOPT_HTTPHEADER, $headers);
// TLS items
curl_setopt($_curl, CURLOPT_SSLKEY, API_PRIVATE_CERT); // path to private cert in .pem format
curl_setopt($_curl, CURLOPT_CAINFO, API_CA_CERT); // path to CA cert in .pem format
curl_setopt($_curl, CURLOPT_SSLCERT, API_PUBLIC_CERT); // path to public cert in .pem format
// process
$response = curl_exec($_curl);
// check for errors
if (curl_error($_curl)) {
// capture error here
}
$status = curl_getinfo($_curl);
curl_close($_curl);