PHP實(shí)現(xiàn)支持CURL字符串證書(shū)傳輸?shù)姆椒?/h1>
更新時(shí)間:2019年03月23日 14:56:57 作者:了不起的廠長(zhǎng)
這篇文章主要給大家介紹了關(guān)于PHP實(shí)現(xiàn)支持CURL字符串證書(shū)傳輸?shù)南嚓P(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用php具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
背景
最近在對(duì)接微信支付的時(shí)候,需要在退款處用到證書(shū),由于我們是SAAS平臺(tái),要支持多方多渠道支付,如果把所有證書(shū)文件保存在應(yīng)用服務(wù)器會(huì)受到SLB的影響,會(huì)導(dǎo)致某臺(tái)機(jī)器文件不同步而阻礙退款流程,但把文件存在OSS的話,后端又要從OSS下載到應(yīng)用服務(wù)器來(lái)保證一致性。思來(lái)想去,最終決定將證書(shū)內(nèi)容保存在數(shù)據(jù)庫(kù),不同客戶各對(duì)應(yīng)一份證書(shū)文件,無(wú)論幾臺(tái)機(jī)器做集群都能保證文件的一致性,同時(shí)也避免了多余的下載步驟。
問(wèn)題
但是剛做就遇到了問(wèn)題,PHP的CURL證書(shū)并不支持字符串的傳輸,只能填寫(xiě)證書(shū)路徑(以下是官方的說(shuō)法)
Client certificates must be specified by a path expression to a certificate store.
解決過(guò)程
我第一個(gè)想到的就是創(chuàng)建空白文件,將證書(shū)內(nèi)容寫(xiě)進(jìn)去,等證書(shū)使用完畢后再將文件刪除,但是創(chuàng)建實(shí)體文件再刪除的操作消耗性能不說(shuō),還非常麻煩,有沒(méi)有創(chuàng)建臨時(shí)文件的方法呢?有,tmpfile()函數(shù)就可以幫我們創(chuàng)建臨時(shí)文件并拿到文件路徑,于是我寫(xiě)了一個(gè)獲取臨時(shí)文件路徑的方法
<?php
public function getTmpPathByContent($content)
{
$tmpFile = tmpfile();
fwrite($tmpFile, $content);
$tempPemPath = stream_get_meta_data($tmpFile);
return $tempPemPath['uri']; ///tmp/phpXZCtAO
}
?>
比較悲哀的是,通過(guò)這個(gè)方法返回的路徑根本讀不到內(nèi)容,甚至一度以為是不是被騙了
file_get_contents(/tmp/phpyyiOZv): failed to open stream: No such file or directory
看了官方文檔才找到原因,如果tmpfile()返回的句柄引用計(jì)數(shù)為0的話就會(huì)將臨時(shí)文件回收,臨時(shí)路徑自然也就失效了,顯然方法getTmpPathByContent()執(zhí)行完后,局部變量$tmpFile的生命周期就結(jié)束了(官方文檔如下)
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.
確認(rèn)了根源,那我們現(xiàn)在亟需找到一個(gè)生命周期隨進(jìn)程結(jié)束而終止的變量類(lèi)型來(lái)保存句柄,什么類(lèi)型能滿足條件呢?靜態(tài)變量。靜態(tài)變量與局部變量不同的是,在PHP生命周期開(kāi)始時(shí)便會(huì)為其分配內(nèi)存空間,并會(huì)把它存儲(chǔ)在全局變量區(qū)域,而全局變量是在模塊關(guān)閉階段銷(xiāo)毀的,這樣的話,聲明靜態(tài)變量就可以使$tmpFile引用計(jì)數(shù)持續(xù)保持大于0的狀態(tài),那我們的代碼就可以做出如下處理
<?php
public function getTmpPathByContent($content)
{
static $tmpFile = null;
$tmpFile = tmpfile();
fwrite($tmpFile, $content);
$tempPemPath = stream_get_meta_data($tmpFile);
return $tempPemPath['uri'];
}
?>
再執(zhí)行一次就成功讀取了臨時(shí)文件的內(nèi)容
-----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-----
下面就可以把生成的臨時(shí)文件地址設(shè)置到CURLOPT_SSLCERT了
<?php
$sslCertPath = getTmpPathByContent($content);
curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath);
//......
?>
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
您可能感興趣的文章:- PHP生成短網(wǎng)址的思路以及實(shí)現(xiàn)方法的詳解
- PHP錯(cuò)誤提示It is not safe to rely on the system……的解決方法
- PHP隨機(jī)數(shù)函數(shù)rand()與mt_rand()的講解
- php微信掃碼支付 php公眾號(hào)支付
- 詳解PHP變量傳值賦值和引用賦值變量銷(xiāo)毀
- PHP使用OB緩存實(shí)現(xiàn)靜態(tài)化功能示例
- PHP使用mysqli同時(shí)執(zhí)行多條sql查詢語(yǔ)句的實(shí)例
- PHP中命名空間的使用例子
- PHP SESSION機(jī)制的理解與實(shí)例
- PHP自動(dòng)載入類(lèi)文件函數(shù)__autoload的使用方法
相關(guān)文章
-
PHP開(kāi)發(fā)過(guò)程中常用函數(shù)收藏
此中將收藏我在工作中用到的一些PHP函數(shù)。有自己寫(xiě)的,也會(huì)有網(wǎng)上收集的。此文不斷更新中
2009-12-12
-
PHP設(shè)計(jì)模式之裝飾器模式實(shí)例詳解
這篇文章主要介紹了PHP設(shè)計(jì)模式之裝飾器模式,簡(jiǎn)單介紹了裝飾器模式的概念、功能并結(jié)合實(shí)例形式詳細(xì)分析了php實(shí)現(xiàn)與使用裝飾器模式的相關(guān)操作技巧,需要的朋友可以參考下 2018-02-02
-
ThinkPHP自動(dòng)轉(zhuǎn)義存儲(chǔ)富文本編輯器內(nèi)容導(dǎo)致讀取出錯(cuò)的解決方法
這篇文章主要介紹了ThinkPHP自動(dòng)轉(zhuǎn)義存儲(chǔ)富文本編輯器內(nèi)容導(dǎo)致讀取出錯(cuò)的解決方法,需要的朋友可以參考下 2014-08-08
-
php函數(shù)之子字符串替換 str_replace
php函數(shù)str_replace: 返回一個(gè)字符串或者數(shù)組。該字符串或數(shù)組是將 subject 中全部的 search 都被 replace 替換之后的結(jié)果。 2011-03-03
最新評(píng)論
背景
最近在對(duì)接微信支付的時(shí)候,需要在退款處用到證書(shū),由于我們是SAAS平臺(tái),要支持多方多渠道支付,如果把所有證書(shū)文件保存在應(yīng)用服務(wù)器會(huì)受到SLB的影響,會(huì)導(dǎo)致某臺(tái)機(jī)器文件不同步而阻礙退款流程,但把文件存在OSS的話,后端又要從OSS下載到應(yīng)用服務(wù)器來(lái)保證一致性。思來(lái)想去,最終決定將證書(shū)內(nèi)容保存在數(shù)據(jù)庫(kù),不同客戶各對(duì)應(yīng)一份證書(shū)文件,無(wú)論幾臺(tái)機(jī)器做集群都能保證文件的一致性,同時(shí)也避免了多余的下載步驟。
問(wèn)題
但是剛做就遇到了問(wèn)題,PHP的CURL證書(shū)并不支持字符串的傳輸,只能填寫(xiě)證書(shū)路徑(以下是官方的說(shuō)法)
Client certificates must be specified by a path expression to a certificate store.
解決過(guò)程
我第一個(gè)想到的就是創(chuàng)建空白文件,將證書(shū)內(nèi)容寫(xiě)進(jìn)去,等證書(shū)使用完畢后再將文件刪除,但是創(chuàng)建實(shí)體文件再刪除的操作消耗性能不說(shuō),還非常麻煩,有沒(méi)有創(chuàng)建臨時(shí)文件的方法呢?有,tmpfile()函數(shù)就可以幫我們創(chuàng)建臨時(shí)文件并拿到文件路徑,于是我寫(xiě)了一個(gè)獲取臨時(shí)文件路徑的方法
<?php public function getTmpPathByContent($content) { $tmpFile = tmpfile(); fwrite($tmpFile, $content); $tempPemPath = stream_get_meta_data($tmpFile); return $tempPemPath['uri']; ///tmp/phpXZCtAO } ?>
比較悲哀的是,通過(guò)這個(gè)方法返回的路徑根本讀不到內(nèi)容,甚至一度以為是不是被騙了
file_get_contents(/tmp/phpyyiOZv): failed to open stream: No such file or directory
看了官方文檔才找到原因,如果tmpfile()返回的句柄引用計(jì)數(shù)為0的話就會(huì)將臨時(shí)文件回收,臨時(shí)路徑自然也就失效了,顯然方法getTmpPathByContent()執(zhí)行完后,局部變量$tmpFile的生命周期就結(jié)束了(官方文檔如下)
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.
確認(rèn)了根源,那我們現(xiàn)在亟需找到一個(gè)生命周期隨進(jìn)程結(jié)束而終止的變量類(lèi)型來(lái)保存句柄,什么類(lèi)型能滿足條件呢?靜態(tài)變量。靜態(tài)變量與局部變量不同的是,在PHP生命周期開(kāi)始時(shí)便會(huì)為其分配內(nèi)存空間,并會(huì)把它存儲(chǔ)在全局變量區(qū)域,而全局變量是在模塊關(guān)閉階段銷(xiāo)毀的,這樣的話,聲明靜態(tài)變量就可以使$tmpFile引用計(jì)數(shù)持續(xù)保持大于0的狀態(tài),那我們的代碼就可以做出如下處理
<?php public function getTmpPathByContent($content) { static $tmpFile = null; $tmpFile = tmpfile(); fwrite($tmpFile, $content); $tempPemPath = stream_get_meta_data($tmpFile); return $tempPemPath['uri']; } ?>
再執(zhí)行一次就成功讀取了臨時(shí)文件的內(nèi)容
-----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-----
下面就可以把生成的臨時(shí)文件地址設(shè)置到CURLOPT_SSLCERT了
<?php $sslCertPath = getTmpPathByContent($content); curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath); //...... ?>
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
- PHP生成短網(wǎng)址的思路以及實(shí)現(xiàn)方法的詳解
- PHP錯(cuò)誤提示It is not safe to rely on the system……的解決方法
- PHP隨機(jī)數(shù)函數(shù)rand()與mt_rand()的講解
- php微信掃碼支付 php公眾號(hào)支付
- 詳解PHP變量傳值賦值和引用賦值變量銷(xiāo)毀
- PHP使用OB緩存實(shí)現(xiàn)靜態(tài)化功能示例
- PHP使用mysqli同時(shí)執(zhí)行多條sql查詢語(yǔ)句的實(shí)例
- PHP中命名空間的使用例子
- PHP SESSION機(jī)制的理解與實(shí)例
- PHP自動(dòng)載入類(lèi)文件函數(shù)__autoload的使用方法
相關(guān)文章
PHP開(kāi)發(fā)過(guò)程中常用函數(shù)收藏
此中將收藏我在工作中用到的一些PHP函數(shù)。有自己寫(xiě)的,也會(huì)有網(wǎng)上收集的。此文不斷更新中2009-12-12PHP設(shè)計(jì)模式之裝飾器模式實(shí)例詳解
這篇文章主要介紹了PHP設(shè)計(jì)模式之裝飾器模式,簡(jiǎn)單介紹了裝飾器模式的概念、功能并結(jié)合實(shí)例形式詳細(xì)分析了php實(shí)現(xiàn)與使用裝飾器模式的相關(guān)操作技巧,需要的朋友可以參考下2018-02-02ThinkPHP自動(dòng)轉(zhuǎn)義存儲(chǔ)富文本編輯器內(nèi)容導(dǎo)致讀取出錯(cuò)的解決方法
這篇文章主要介紹了ThinkPHP自動(dòng)轉(zhuǎn)義存儲(chǔ)富文本編輯器內(nèi)容導(dǎo)致讀取出錯(cuò)的解決方法,需要的朋友可以參考下2014-08-08php函數(shù)之子字符串替換 str_replace
php函數(shù)str_replace: 返回一個(gè)字符串或者數(shù)組。該字符串或數(shù)組是將 subject 中全部的 search 都被 replace 替換之后的結(jié)果。2011-03-03