【发布时间】:2019-10-19 09:52:11
【问题描述】:
我正在尝试连接到第 3 方 API,他们要求我通过他们给我的 3 个证书文件:公共证书、私有证书和 CA 证书。使用以下设置在 cURL 中运行良好:
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);
}
传递的每个值都是服务器上物理文件的路径。这很好用。
但是,对于一个请求,我必须传递一个标头 'Content-Type: Multipart/Related; boundary="---BOUNDARY123456"' 带有包含 XML 文件和 Base64 编码 PDF 的 MIME 消息。这失败了,最后出现 500 错误。在对此进行研究时,我发现 cURL 无法正确处理 Content-Type: Multipart/Related posts。
https://stackoverflow.com/a/25998544/3434084
所以我尝试使用 stream_get_contents() 发送它,但没有得到回复。所以我认为我的证书数据是错误的。如何通过 stream_get_contents() 传递我在 cURL 中使用的相同值?
代码如下:
$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' . "\r\n\r\n";
$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!
【问题讨论】:
-
您在示例中抑制错误,我猜这会阻止故障排除。要进一步排除故障,您可以尝试挂钩流通知(事件),也许将超时设置为低值也有助于排除故障。请参阅 php.net/manual/en/stream.errors.php 和 php.net/manual/en/function.stream-notification-callback.php - 最后但并非最不重要的一点,这个问答材料看起来也很有趣:stackoverflow.com/q/40999726/367456
-
在 PHP 相关问答中找到另一个 multipart/related w/ curl,即使答案已被接受:stackoverflow.com/a/9252130/367456 /e:它特别指出:“注意,最后一个边界有一个额外的
--在末尾。”您的有效负载中的行也没有 \r\n 终止,我不知道具体的 mime 类型,但详细信息应该在这里:tools.ietf.org/html/rfc2387(也许) -
@hakre 感谢您的链接!我以为我已经看过每一页,并在这里尝试了关于多部分/相关的每个示例。会看看。
-
总是这样,信息溢出。从我目前看到的情况来看,并不是 curl 本身不能做到这一点,只是您需要对自己的有效负载进行编码,因为 curl 无法编码多部分/相关,但是发送它(和使用您的 SSL 选项)确实如您所说的那样工作。所以我想说这不应该成为使用 curl 的阻碍(但是关于 HTTP/SSL 流出了什么问题的另一个问题也很有趣)。但是由于您已经使用 curl 处理证书,因此我只关注作为多部分/相关的有效负载编码。
-
@hakre 现在在 PHP 5.6 上运行,但明年需要在 7.x 上运行。我也在尝试github.com/robtimus/php-multipart 看看它是否也能做到。