Recently when connecting to WeChat payment, we need to use certificates at the refund point. Since we are a SAAS platform, we need to support multi-party and multi-channel payments. If we save all certificate files in the application server, it will Affected by SLB, the files on a certain machine will be out of sync and hinder the refund process. However, if the files are stored in OSS, the backend must download them from OSS to the application server to ensure consistency. After much deliberation, we finally decided to save the certificate content in the database. Different customers correspond to one certificate file. No matter how many machines are used in the cluster, the consistency of the file can be ensured and redundant downloading steps can be avoided.
But I encountered a problem just after I did it. PHP's CURL certificate does not support the transmission of strings, and can only fill in the certificate path (the following is the official statement)
Client certificates must be specified by a path expression to a certificate store.
My first thought is to create a blank file, write the certificate content into it, and then delete the file after the certificate is used. However, the operation of creating an entity file and then deleting it consumes performance. It's very troublesome. Is there any way to create temporary files? Yes, the tmpfile()
function can help us create a temporary file and get the file path, so I wrote a method to get the temporary file path
<?php public function getTmpPathByContent($content) { $tmpFile = tmpfile(); fwrite($tmpFile, $content); $tempPemPath = stream_get_meta_data($tmpFile); return $tempPemPath['uri']; ///tmp/phpXZCtAO } ?>
What is sad is that through this The content of the path returned by the method cannot be read at all. I even thought that I had been cheated.
file_get_contents(/tmp/phpyyiOZv): failed to open stream: No such file or directory
I found the reason after reading the official documentation. Iftmpfile()
the handle reference count returned is 0 If so, the temporary file will be recycled, and the temporary path will naturally become invalid. Obviously, after the method getTmpPathByContent()
is executed, the life cycle of the local variable $tmpFile
will end (official document As follows)
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.
After confirming the root cause, we now urgently need to find a variable type whose life cycle terminates when the process ends to save the handle. What type can meet the conditions? static variables. The difference between static variables and local variables is that memory space is allocated for them at the beginning of the PHP life cycle and stored in the global variable area. Global variables are destroyed during the module shutdown phase. In this case, declare static variables You can make $tmpFile
the reference count continue to remain greater than 0, then our code can do the following processing
<?php public function getTmpPathByContent($content) { static $tmpFile = null; $tmpFile = tmpfile(); fwrite($tmpFile, $content); $tempPemPath = stream_get_meta_data($tmpFile); return $tempPemPath['uri']; } ?>
Execute it again and successfully read the contents of the temporary file
-----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-----
Now you can set the generated temporary file address to CURLOPT_SSLCERT
<?php $sslCertPath = getTmpPathByContent($content); curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath); //...... ?>
The above is the detailed content of How does PHP support CURL string certificate transfer?. For more information, please follow other related articles on the PHP Chinese website!