景
最近在對接微信支付的時候,需要在退款處用到證書,由于我們是SAAS平臺,要支持多方多渠道支付,如果把所有證書文件保存在應用服務器會受到SLB的影響,會導致某臺機器文件不同步而阻礙退款流程,但把文件存在OSS的話,后端又要從OSS下載到應用服務器來保證一致性。思來想去,最終決定將證書內容保存在數據庫,不同客戶各對應一份證書文件,無論幾臺機器做集群都能保證文件的一致性,同時也避免了多余的下載步驟。
問題
但是剛做就遇到了問題,PHP的CURL證書并不支持字符串的傳輸,只能填寫證書路徑(以下是官方的說法)
1
Client certificates must be specified by a path expression to a certificate store.
解決過程
我第一個想到的就是創建空白文件,將證書內容寫進去,等證書使用完畢后再將文件刪除,但是創建實體文件再刪除的操作消耗性能不說,還非常麻煩,有沒有創建臨時文件的方法呢?有,tmpfile()函數就可以幫我們創建臨時文件并拿到文件路徑,于是我寫了一個獲取臨時文件路徑的方法
1
2
3
4
5
6
7
8
9
<?php
public function getTmpPathByContent($content)
{
$tmpFile=tmpfile();
fwrite($tmpFile, $content);
$tempPemPath=stream_get_meta_data($tmpFile);
return $tempPemPath['uri']; ///tmp/phpXZCtAO
}
?>
比較悲哀的是,通過這個方法返回的路徑根本讀不到內容,甚至一度以為是不是被騙了
1
file_get_contents(/tmp/phpyyiOZv): failed to open stream: No such file or directory
看了官方文檔才找到原因,如果tmpfile()返回的句柄引用計數為0的話就會將臨時文件回收,臨時路徑自然也就失效了,顯然方法getTmpPathByContent()執行完后,局部變量$tmpFile的生命周期就結束了(官方文檔如下)
1
The file is automatically removed when closed (for example, by calling fclose(), or when there are no remaining references to the file handle returned by tmpfile()), or when the script ends.
確認了根源,那我們現在亟需找到一個生命周期隨進程結束而終止的變量類型來保存句柄,什么類型能滿足條件呢?靜態變量。靜態變量與局部變量不同的是,在PHP生命周期開始時便會為其分配內存空間,并會把它存儲在全局變量區域,而全局變量是在模塊關閉階段銷毀的,這樣的話,聲明靜態變量就可以使$tmpFile引用計數持續保持大于0的狀態,那我們的代碼就可以做出如下處理
1
2
3
4
5
6
7
8
9
10
<?php
public function getTmpPathByContent($content)
{
static $tmpFile=null;
$tmpFile=tmpfile();
fwrite($tmpFile, $content);
$tempPemPath=stream_get_meta_data($tmpFile);
return $tempPemPath['uri'];
}
?>
再執行一次就成功讀取了臨時文件的內容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-----BEGIN CERTIFICATE-----
MIIEbDCCA9WgAwIBAgIEAWJKHDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
Q04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNV
BAoTB1RlbmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEf
MB0GCSqGSIb3DQEJARYQbW1wYXltY2hAdGVuY2VudDAeFw0xNzA4MDcwOTIxNDda
Fw0yNzA4MDUwOTIxNDdaMIGbMQswCQYDVQQGEwJDTjESMBAGA1UECBMJR3Vhbmdk
b25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEOMAwGA1UE
CxMFTU1QYXkxMDAuBgNVBAMUJ+a3seWcs+W4guaYjua6kOi9r+S7tuiCoeS7veac
iemZkOWFrOWPuDERMA8GA1UEBBMIMTAyNTkyODEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDg2D3++uOxY/yMGQPBnROvyYimnCsfGE0dnqdGUTCykqBh
yfv82zE1/St/4DQX2QDiIvLif+sMGcYwF4bkzdY+HgitYLI0k5o/5LCNZOMctuio
kdYC2bNdWHq2y9S5UWLQR1Zvq+6QyPBVBVY9yq9xtQhIlUTsZnICAp3iQLfQUR3l
aEdH9IERoRUIkbyb8oX5ONQz4P9jOeE9C5iwx0QrH4s01NFhkhr8JHlugRLpo9vA
xGgi/48fOlONj6wWal5Gt0OvvEbIwgQwya15KBX2YeGnZvYBQa+lQMeXEqZSFie3
G+wGvbtlONczQEtp+JDxLZLUS/FT7U0TQN/t8JDvAgMBAAGjggFGMIIBQjAJBgNV
HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh0iQ0VTLUNBIEdlbmVyYXRlIENlcnRpZmlj
YXRlIjAdBgNVHQ4EFgQUjDJ75bu3Roog7XOH6uFAdZ6kpcIwgb8GA1UdIwSBtzCB
tIAUPgUm9iJitBVbiM1kfrDUYqflhnShgZCkgY0wgYoxCzAJBgNVBAYTAkNOMRIw
EAYDVQQIEwlHdWFuZ2RvbmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdU
ZW5jZW50MQwwCgYDVQQLEwNXWEcxEzARBgNVBAMTCk1tcGF5bWNoQ0ExHzAdBgkq
hkiG9w0BCQEWEG1tcGF5bWNoQHRlbmNlbnSCCQC7VJcrvADoVzAOBgNVHQ8BAf8E
BAMCBsAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEA
ucJLJkkHxlqQCEapZOWmySutqNVZxFbqyG//UXxxpA/1yG4e+KmufKZWv+c+MtYI
8i0KDDCv/UE+kkFIrHYDDKsdLRpxrYOUHGoqq0c7yBJ6Dimgy6m8U8FsEv3HtUR2
8g5xrg2Tc5MPWEp9ncEw575hGk0CXLDGOkI1nU+pGqk=
-----END CERTIFICATE-----
下面就可以把生成的臨時文件地址設置到CURLOPT_SSLCERT了
1
2
3
4
5
<?php
$sslCertPath=getTmpPathByContent($content);
curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath);
//......
?>
以上就是PHP如何支持CURL字符串證書傳輸 ?的詳細內容,更多請關注其它相關文章!
更多技巧請《轉發 + 關注》哦!
篇文章給大家帶來的內容是關于PHP支持CURL字符串證書傳輸的方法介紹(代碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。
最近在對接微信支付的時候,需要在退款處用到證書,由于我們是SAAS平臺,要支持多方多渠道支付,如果把所有證書文件保存在應用服務器會受到SLB的影響,會導致某臺機器文件不同步而阻礙退款流程,但把文件存在OSS的話,后端又要從OSS下載到應用服務器來保證一致性。思來想去,最終決定將證書內容保存在數據庫,不同客戶各對應一份證書文件,無論幾臺機器做集群都能保證文件的一致性,同時也避免了多余的下載步驟。
問題
但是剛做就遇到了問題,PHP的CURL證書并不支持字符串的傳輸,只能填寫證書路徑(以下是官方的說法)
Client certificates must be specified by a path expression to a certificate store.
解決過程
我第一個想到的就是創建空白文件,將證書內容寫進去,等證書使用完畢后再將文件刪除,但是創建實體文件再刪除的操作消耗性能不說,還非常麻煩,有沒有創建臨時文件的方法呢?有,tmpfile()函數就可以幫我們創建臨時文件并拿到文件路徑,于是我寫了一個獲取臨時文件路徑的方法
<?php
public function getTmpPathByContent($content)
{
$tmpFile=tmpfile();
fwrite($tmpFile, $content);
$tempPemPath=stream_get_meta_data($tmpFile);
return $tempPemPath['uri']; ///tmp/phpXZCtAO
}
?>
比較悲哀的是,通過這個方法返回的路徑根本讀不到內容,甚至一度以為是不是被騙了
file_get_contents(/tmp/phpyyiOZv): failed to open stream: No such file or directory
看了官方文檔才找到原因,如果tmpfile()返回的句柄引用計數為0的話就會將臨時文件回收,臨時路徑自然也就失效了,顯然方法getTmpPathByContent()執行完后,局部變量$tmpFile的生命周期就結束了(官方文檔如下)
The file is automatically removed when closed (for example, by calling fclose(), or when there are no remaining references to the file handle returned by tmpfile()), or when the script ends.
確認了根源,那我們現在亟需找到一個生命周期隨進程結束而終止的變量類型來保存句柄,什么類型能滿足條件呢?靜態變量。靜態變量與局部變量不同的是,在PHP生命周期開始時便會為其分配內存空間,并會把它存儲在全局變量區域,而全局變量是在模塊關閉階段銷毀的,這樣的話,聲明靜態變量就可以使$tmpFile引用計數持續保持大于0的狀態,那我們的代碼就可以做出如下處理
<?php
public function getTmpPathByContent($content)
{
static $tmpFile=null;
$tmpFile=tmpfile();
fwrite($tmpFile, $content);
$tempPemPath=stream_get_meta_data($tmpFile);
return $tempPemPath['uri'];
}
?>
再執行一次就成功讀取了臨時文件的內容
-----BEGIN CERTIFICATE-----
MIIEbDCCA9WgAwIBAgIEAWJKHDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
Q04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNV
BAoTB1RlbmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEf
MB0GCSqGSIb3DQEJARYQbW1wYXltY2hAdGVuY2VudDAeFw0xNzA4MDcwOTIxNDda
Fw0yNzA4MDUwOTIxNDdaMIGbMQswCQYDVQQGEwJDTjESMBAGA1UECBMJR3Vhbmdk
b25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEOMAwGA1UE
CxMFTU1QYXkxMDAuBgNVBAMUJ+a3seWcs+W4guaYjua6kOi9r+S7tuiCoeS7veac
iemZkOWFrOWPuDERMA8GA1UEBBMIMTAyNTkyODEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDg2D3++uOxY/yMGQPBnROvyYimnCsfGE0dnqdGUTCykqBh
yfv82zE1/St/4DQX2QDiIvLif+sMGcYwF4bkzdY+HgitYLI0k5o/5LCNZOMctuio
kdYC2bNdWHq2y9S5UWLQR1Zvq+6QyPBVBVY9yq9xtQhIlUTsZnICAp3iQLfQUR3l
aEdH9IERoRUIkbyb8oX5ONQz4P9jOeE9C5iwx0QrH4s01NFhkhr8JHlugRLpo9vA
xGgi/48fOlONj6wWal5Gt0OvvEbIwgQwya15KBX2YeGnZvYBQa+lQMeXEqZSFie3
G+wGvbtlONczQEtp+JDxLZLUS/FT7U0TQN/t8JDvAgMBAAGjggFGMIIBQjAJBgNV
HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh0iQ0VTLUNBIEdlbmVyYXRlIENlcnRpZmlj
YXRlIjAdBgNVHQ4EFgQUjDJ75bu3Roog7XOH6uFAdZ6kpcIwgb8GA1UdIwSBtzCB
tIAUPgUm9iJitBVbiM1kfrDUYqflhnShgZCkgY0wgYoxCzAJBgNVBAYTAkNOMRIw
EAYDVQQIEwlHdWFuZ2RvbmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdU
ZW5jZW50MQwwCgYDVQQLEwNXWEcxEzARBgNVBAMTCk1tcGF5bWNoQ0ExHzAdBgkq
hkiG9w0BCQEWEG1tcGF5bWNoQHRlbmNlbnSCCQC7VJcrvADoVzAOBgNVHQ8BAf8E
BAMCBsAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEA
ucJLJkkHxlqQCEapZOWmySutqNVZxFbqyG//UXxxpA/1yG4e+KmufKZWv+c+MtYI
8i0KDDCv/UE+kkFIrHYDDKsdLRpxrYOUHGoqq0c7yBJ6Dimgy6m8U8FsEv3HtUR2
8g5xrg2Tc5MPWEp9ncEw575hGk0CXLDGOkI1nU+pGqk=
-----END CERTIFICATE-----
下面就可以把生成的臨時文件地址設置到CURLOPT_SSLCERT了
<?php
$sslCertPath=getTmpPathByContent($content);
curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath);
//......
?>
本篇文章到這里就已經全部結束了,更多其他精彩內容可以關注的php視頻教程欄目!
以上就是PHP支持CURL字符串證書傳輸的方法介紹(代碼)的詳細內容,更多請關注其它相關文章!
更多技巧請《轉發 + 關注》哦!
、通知短信:當您需要快速通知用戶時,通知短信是最快捷有效的方式。短信通知支持三大運營商以及虛擬運營商,我們提供電信級運維保障、獨享專用通道。
地址:https://www.apispace.com/eolink/api/sms-notify/introduction?utm_source=tth&utm_content=tuijian&utm_term=tongzhiduanxin
Java 接入示例:
OkHttpClient client=new OkHttpClient().newBuilder().build();
MediaType mediaType=MediaType.parse("application/json");
RequestBody body=RequestBody.create(mediaType, "{\"msg\":\"\",\"params\":\"\",\"sendtime\":\"\",\"extend\":\"\",\"uid\":\"\"}");
Request request=new Request.Builder()
.url("https://eolink.o.apispace.com/sms-notify/notify")
.method("POST",body)
.addHeader("X-APISpace-Token","")
.addHeader("Authorization-Type","apikey")
.addHeader("Content-Type","")
.build();
Response response=client.newCall(request).execute();
System.out.println(response.body().string());
2、空氣質量查詢:支持國內3400+個城市的整點觀測,并附帶空氣質量監測點(全國共2335個)的整點觀測數據。
地址:https://www.apispace.com/eolink/api/34324/introduction?utm_source=tth&utm_content=tuijian&utm_term=kqzl
Python 接入示例:
import requests
url="https://eolink.o.apispace.com/34324/air/v001/aqi"
payload={"areacode" : "101010100","lonlat" : "116.407526,39.904030"}
headers={
"X-APISpace-Token":"",
"Authorization-Type":"apikey"
}
response=requests.request("GET", url, params=payload, headers=headers)
print(response.text)
3、二維碼識別OCR:對圖片中的二維碼、條形碼進行檢測和識別,返回存儲的文字內容。
PHP 接入示例:
<?php
$curl=curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL=> "https://eolink.o.apispace.com/ocrbarcode/ocr/v1/barcode",
CURLOPT_RETURNTRANSFER=> true,
CURLOPT_ENCODING=> "",
CURLOPT_MAXREDIRS=> 10,
CURLOPT_TIMEOUT=> 30,
CURLOPT_HTTP_VERSION=> CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST=> "POST",
CURLOPT_POSTFIELDS=> "{\"image\":null,\"url\":null,\"pdf\":null,\"pdf_page\":null}",
CURLOPT_HTTPHEADER=> array(
"X-APISpace-Token:",
"Authorization-Type:apikey",
"Content-Type:application/json"
),
));
$response=curl_exec($curl);
$err=curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
4、發票核驗:發票真偽驗證服務,根據發票類型代碼和發票四要素獲取發票全票面信息,支持全國增值稅專用發票、增值稅普通發票(含電子普通發票、卷式發票、通行費發票)、機動車銷售統一發票、貨物運輸業增值稅專用發票、二手車銷售統一發票等不同發票的驗真。
JavaScript 接入示例:
var data="{\"date\":\"20180101\",\"number\":\"12341234\",\"code\":\"1234123412\",\"verifyCode\":\"123132\",\"priceWithoutTax\":\"123.12\",\"type\":\"01\"}"
var xhr=new XMLHttpRequest();
xhr.withCredentials=false;
xhr.addEventListener("readystatechange", function () {
if (this.readyState===4) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://eolink.o.apispace.com/fphy2/fapiao2");
xhr.setRequestHeader("X-APISpace-Token","");
xhr.setRequestHeader("Authorization-Type","apikey");
xhr.setRequestHeader("Content-Type","application/json");
xhr.send(data);
5、全國快遞物流地圖軌跡查詢:通過物流單號和收寄件地址,自動評估物流時效,并在地圖中展示包裹運輸軌跡。包括順豐、圓通、申通等主流快遞公司。自動識別快遞公司及單號,實時查詢,穩定高效,服務器毫秒響應,數據及時準確。
微信小程序接入示例:
var data="{\"cpCode\":null,\"mailNo\":null,\"phone\":null,\"origin\":null,\"destination\":null,\"receiveAddress\":null,\"responseModel\":null}"
wx.request({
"url":"https://eolink.o.apispace.com/wldtgj1/paidtobuy_api/trace_map",
"method": "POST",
"header": {
"X-APISpace-Token":"",
"Authorization-Type":"apikey",
"Content-Type":""
},
"data": data,
"success": (response)=> {
console.log(response.data)
}
})
6、空號檢測:通過手機號碼查詢其在網活躍度,返回包括空號、實號、停機、庫無、沉默號、風險號等狀態。
NodeJS 接入示例:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。