因爲做支付寶APP支付需要把訂單信息結合支付密鑰進行加密,所以需要一個完成加密的接口。
整體代碼下面會有,不過在代碼之前有幾個需要注意的點。
首先,php擴展openssl需要打開,這個可以phpinfo查看是否開啓。
Linux寶塔是上安裝的php是默認開啓的
接着,在php.ini文件中搜索extension,找到extension = openssl去掉前面的冒號
在phpstudy中是extension = openssl.dll
這裏有一點,好多博文都沒有提到,所以我踩過這個坑。(就是密鑰和公鑰的格式問題)
private static $PRIVATE_KEY = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
這裏是密鑰內容
-----END RSA PRIVATE KEY-----
EOD;
private static $PUBLIC_KEY = <<<EOD
-----BEGIN PUBLIC KEY-----
這裏是公鑰內容
-----END PUBLIC KEY-----
EOD;
如果想把代碼放到.pem文件中,也用這種格式,之後使用file_get_contents()函數獲取到即可
還有一點需要注意,PHP傳參會自動轉義,如果是把加密功能寫成一個接口,那麼需要加密的數據就會以參數的形式傳進來,就需要解決PHP轉義這個問題。
假設 $data是傳來的參數
$str = htmlspecialchars_decode($data);
這個函數,可以把參數進行反轉義,變回最初的樣子。
下面是一個可以單獨執行的php代碼,可以直接測試加密和驗證
<?php
class Rsa2
{
private static $PRIVATE_KEY = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
////////
-----END RSA PRIVATE KEY-----
EOD;
private static $PUBLIC_KEY = <<<EOD
-----BEGIN PUBLIC KEY-----
\\\\\\\\
-----END PUBLIC KEY-----
EOD;
/**
* 獲取私鑰
* @return bool|resource
*/
private static function getPrivateKey()
{
$privKey = self::$PRIVATE_KEY;
return openssl_pkey_get_private($privKey);
}
/**
* 獲取公鑰
* @return bool|resource
*/
private static function getPublicKey()
{
$publicKey = self::$PUBLIC_KEY;
return openssl_pkey_get_public($publicKey);
}
/**
* 創建簽名
* @param string $data 數據
* @return null|string
*/
public function createSign($data = '')
{
if (!is_string($data)) {
return null;
}
return openssl_sign(
$data,
$sign,
self::getPrivateKey(),
OPENSSL_ALGO_SHA256
) ? urlencode(base64_encode($sign)) : null;
}
/**
* 驗證簽名
* @param string $data 數據
* @param string $sign 簽名
* @return bool
*/
public function verifySign($data = '', $sign = '')
{
if (!is_string($sign) || !is_string($sign)) {
return false;
}
return (bool)openssl_verify(
$data,
base64_decode($sign),
self::getPublicKey(),
OPENSSL_ALGO_SHA256
);
}
}
$rsa2 = new Rsa2();
$content = 'app_id=2019121069836088&biz_content={"timeout_express":"30m","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.01","subject":"1","body":"我是測試數據","out_trade_no":"12345678"}&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2×tamp=2020-01-04 16:55:53&version=1.0'; //待簽名字符串
$strSign = $rsa2->createSign($content); //生成簽名
echo "原文 --> $content\n";
echo "簽名後 --> $strSign\n";
$is_ok = $rsa2->verifySign($content, $strSign); //驗證簽名0
echo "驗證簽名 --> $is_ok\n";