PHP如何支持CURL字符串證書傳輸

背景php

最近在對接微信支付的時候,須要在退款處用到證書,因爲咱們是SAAS平臺,要支持多方多渠道支付,若是把全部證書文件保存在應用服務器會受到SLB的影響,會致使某臺機器文件不一樣步而阻礙退款流程,但把文件存在OSS的話,後端又要從OSS下載到應用服務器來保證一致性。思來想去,最終決定將證書內容保存在數據庫,不一樣客戶各對應一份證書文件,不管幾臺機器作集羣都能保證文件的一致性,同時也避免了多餘的下載步驟。

問題git

可是剛作就遇到了問題,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    }?>express

比較悲哀的是,經過這個方法返回的路徑根本讀不到內容,甚至一度覺得是否是被騙了

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-----MIIEbDCCA9WgAwIBAgIEAWJKHDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNVBAoTB1RlbmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEfMB0GCSqGSIb3DQEJARYQbW1wYXltY2hAdGVuY2VudDAeFw0xNzA4MDcwOTIxNDdaFw0yNzA4MDUwOTIxNDdaMIGbMQswCQYDVQQGEwJDTjESMBAGA1UECBMJR3Vhbmdkb25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEOMAwGA1UECxMFTU1QYXkxMDAuBgNVBAMUJ+a3seWcs+W4guaYjua6kOi9r+S7tuiCoeS7veaciemZkOWFrOWPuDERMA8GA1UEBBMIMTAyNTkyODEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDg2D3++uOxY/yMGQPBnROvyYimnCsfGE0dnqdGUTCykqBhyfv82zE1/St/4DQX2QDiIvLif+sMGcYwF4bkzdY+HgitYLI0k5o/5LCNZOMctuiokdYC2bNdWHq2y9S5UWLQR1Zvq+6QyPBVBVY9yq9xtQhIlUTsZnICAp3iQLfQUR3laEdH9IERoRUIkbyb8oX5ONQz4P9jOeE9C5iwx0QrH4s01NFhkhr8JHlugRLpo9vAxGgi/48fOlONj6wWal5Gt0OvvEbIwgQwya15KBX2YeGnZvYBQa+lQMeXEqZSFie3G+wGvbtlONczQEtp+JDxLZLUS/FT7U0TQN/t8JDvAgMBAAGjggFGMIIBQjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh0iQ0VTLUNBIEdlbmVyYXRlIENlcnRpZmljYXRlIjAdBgNVHQ4EFgQUjDJ75bu3Roog7XOH6uFAdZ6kpcIwgb8GA1UdIwSBtzCBtIAUPgUm9iJitBVbiM1kfrDUYqflhnShgZCkgY0wgYoxCzAJBgNVBAYTAkNOMRIwEAYDVQQIEwlHdWFuZ2RvbmcxETAPBgNVBAcTCFNoZW56aGVuMRAwDgYDVQQKEwdUZW5jZW50MQwwCgYDVQQLEwNXWEcxEzARBgNVBAMTCk1tcGF5bWNoQ0ExHzAdBgkqhkiG9w0BCQEWEG1tcGF5bWNoQHRlbmNlbnSCCQC7VJcrvADoVzAOBgNVHQ8BAf8EBAMCBsAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAucJLJkkHxlqQCEapZOWmySutqNVZxFbqyG//UXxxpA/1yG4e+KmufKZWv+c+MtYI8i0KDDCv/UE+kkFIrHYDDKsdLRpxrYOUHGoqq0c7yBJ6Dimgy6m8U8FsEv3HtUR28g5xrg2Tc5MPWEp9ncEw575hGk0CXLDGOkI1nU+pGqk=-----END CERTIFICATE-----微信

下面就能夠把生成的臨時文件地址設置到 CURLOPT_SSLCERT



<?php    $sslCertPath = getTmpPathByContent($content);    curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath);    //......?>curl

相關文章
相關標籤/搜索