最近、WeChat 支払いに接続するときに、返金ポイントで証明書を使用する必要があります。当社は SAAS プラットフォームであるため、マルチパーティおよびマルチチャネル支払いをサポートする必要があります。アプリケーション サーバー内のすべての証明書ファイルが SLB の影響を受けると、特定のマシン上のファイルが同期されなくなり、払い戻しプロセスが妨げられます。ただし、ファイルが OSS に保存されている場合、バックエンドは OSS からファイルをダウンロードする必要があります。アプリケーションサーバーで一貫性を確保します。熟慮の末、最終的に証明書の内容をデータベースに保存することにしました。異なる顧客が 1 つの証明書ファイルに対応します。クラスター内で使用されるマシンの数に関係なく、ファイルの一貫性が確保され、冗長なダウンロード手順を回避できます。 。
しかし、実行直後に問題が発生しました。PHP の CURL 証明書は文字列の送信をサポートしておらず、証明書のパスを埋めることしかできません (以下は公式声明です) )
クライアント証明書は、証明書ストアへのパス式で指定する必要があります。
最初に考えたのは、空のファイルを作成することです。証明書の内容を書き込み、証明書が使用されるのを待ってファイルを削除しますが、エンティティファイルを作成して削除するという操作はパフォーマンスを消費する上に非常に面倒です。ファイル?はい、tmpfile()
関数は一時ファイルの作成とファイル パスの取得に役立ちます。そのため、一時ファイル パスを取得するメソッドを書きました。
<?php public function getTmpPathByContent($content) { $tmpFile = tmpfile(); fwrite($tmpFile, $content); $tempPemPath = stream_get_meta_data($tmpFile); return $tempPemPath['uri']; ///tmp/phpXZCtAO } ?>
悲しいのは、 this メソッドが返したパスの内容が全く読めません。騙されたのかと思ったほどです。
file_get_contents(/tmp/phpyyiOZv): failed to open stream: No such file or directory
公式ドキュメントを読んで理由が分かりました。Iftmpfile()
返されたハンドル参照カウントは 0 です。その場合、一時ファイルはリサイクルされ、一時パスは当然無効になります。明らかに、メソッド getTmpPathByContent()
が実行された後、ローカル変数 $tmpFile
は終了します (公式ドキュメントは以下の通り)
ファイルは閉じられると (たとえば、fclose() を呼び出すことによって)、またはファイルが残っていない場合に自動的に削除されます。 tmpfile()) によって返されるファイル ハンドルへの参照、またはスクリプトの終了時。
根本原因を確認した後、プロセスの終了時にライフサイクルが終了する変数の型を緊急に見つける必要があります。ハンドルを保存するにはどのようなタイプが条件を満たすのでしょうか?静的変数。静的変数とローカル変数の違いは、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 文字列証明書の送信をどのようにサポートしていますか (詳細な解決プロセス)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。