woocommerce对接第三方支付之RSA签名方式总结

行云流水
2024-06-05 / 0 评论 / 183 阅读 / 正在检测是否收录...

前言

在对接各种支付的过程中,md5签名方式比较常见。而采用rsa签名的比较少。rsa的性能开销相对于md5大一些。

rsa签名方法

rsa签名的方法生成一个类,方便调用。

<?php
class RsaUtils{

    /**
     * 签名算法,SHA256WithRSA
     */
    private const SIGNATURE_ALGORITHM = OPENSSL_ALGO_SHA256;

    /**
     * RSA最大加密明文大小
     */
    private const MAX_ENCRYPT_BLOCK = 117;

    /**
     * RSA最大解密密文大小
     */
    private const MAX_DECRYPT_BLOCK = 128;

    private $publicKey; // 私有化公钥内容,不要头尾和换行符,只要内容
    private $privateKey; // 私有化私钥内容,不要头尾和换行符,只要内容

    public function __construct($publicKey, $privateKey) {
        $this->publicKey = $publicKey;
        $this->privateKey = $privateKey;
    }

    /**
     * 获取完整的私钥
     * @return bool|resource
     */
    private function _getPrivateKey()
    {
        $privateKey = "-----BEGIN RSA PRIVATE KEY-----" . PHP_EOL;
        $privateKey .= wordwrap($this->privateKey, 64, "\n", true);
        $privateKey .= "\n-----END RSA PRIVATE KEY-----";

    $privateKey = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $privateKey);

        //return openssl_pkey_get_private($privateKey);
        return $privateKey;
    }

    /**
     * 获取完整的公钥
     * @return bool|resource
     */
    private function _getPublicKey()
    {
        $publicKey = "-----BEGIN PUBLIC KEY-----" . PHP_EOL;
        $publicKey .= wordwrap($this->publicKey, 64, "\n", true);
        $publicKey .= "\n-----END PUBLIC KEY-----";

        $publicKey = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $publicKey);

        //return openssl_pkey_get_public($publicKey);
        return $publicKey;
    }

    /**
     * 使用公钥将数据加密
     * @param $data string 需要加密的数据
     * @param $publicKey string 公钥
     * @return string 返回加密串(base64编码)
     */
    public function publicEncrypt($data){
    $publicKey = $this->_getPublicKey();
        $data = str_split($data, self::MAX_ENCRYPT_BLOCK);

        $encrypted = '';
        foreach($data as & $chunk){
            if(!openssl_public_encrypt($chunk, $encryptData, $publicKey)){
                return '';
            }else{
                $encrypted .= $encryptData;
            }
        }
        return $this->_urlSafeBase64encode($encrypted);
    }

    /**
     * 使用私钥解密
     * @param $data string 需要解密的数据
     * @param $privateKey string 私钥
     * @return string 返回解密串
     */
    public function privateDecrypt($data){
    $privateKey = $this->_getPrivateKey();
        $data = str_split($this->_urlSafeBase64decode($data), self::MAX_DECRYPT_BLOCK);

        $decrypted = '';
        foreach($data as & $chunk){
            if(!openssl_private_decrypt($chunk, $decryptData, $privateKey)){
                return '';
            }else{
                $decrypted .= $decryptData;
            }
        }
        return $decrypted;
    }

    /**
     * 使用私钥将数据加密
     * @param $data string 需要加密的数据
     * @param $privateKey string 私钥
     * @return string 返回加密串(base64编码)
     */
    public function privateEncrypt($data){
    $privateKey = $this->_getPrivateKey();
        $data = str_split($data, self::MAX_ENCRYPT_BLOCK);

    //error_log(__METHOD__ . PHP_EOL .print_r($privateKey, true));

        $encrypted = '';
        foreach($data as & $chunk){
            if(!openssl_private_encrypt($chunk, $encryptData, $privateKey)){
                return '';
            }else{
                $encrypted .= $encryptData;
            }
        }
        return $this->_urlSafeBase64encode($encrypted);
    }


    /**
     * 使用公钥解密
     * @param $data string 需要解密的数据
     * @param $publicKey string 公钥
     * @return string 返回解密串
     */
    public function publicDecrypt($data){
    $publicKey = $this->getPublicKey();
        $data = str_split($this->urlSafeBase64decode($data), self::MAX_DECRYPT_BLOCK);
        $decrypted = '';
        foreach($data as & $chunk){
            if(!openssl_public_decrypt($chunk, $decryptData, $publicKey)){
                return '';
            }else{
                $decrypted .= $decryptData;
            }
        }
        return $decrypted;
    }


    /**
     * 私钥加签名
     * @param $data 被加签数据
     * @param $privateKey 私钥
     * @return mixed|string
     */
    public function rsaSign($data){
        if(openssl_sign($data, $sign, $privateKey, self::SIGNATURE_ALGORITHM)){
            return $this->_urlSafeBase64encode($sign);
        }
        return '';
    }

    /**
     * 公钥验签
     * @param $data 被加签数据
     * @param $sign 签名
     * @param $publicKey 公钥
     * @return bool
     */
    public function verifySign($data, $sign):bool {
    $publicKey = $this->_getPublicKey();
        return (1 == openssl_verify($data, $this->_urlSafeBase64decode($sign), $publicKey, self::SIGNATURE_ALGORITHM));
    }

    /**
     * url base64编码
     * @param $string
     * @return mixed|string
     */
    private function _urlSafeBase64encode($string){
        $data = str_replace(array('+','/','='), array( '-','_',''), base64_encode($string));
        return $data;
    }

    /**
     * url base64解码
     * @param $string
     * @return bool|string
     */
    private function _urlSafeBase64decode($string){
        $data = str_replace(array('-','_'), array('+','/'), $string);
        $mod4 = strlen($data) % 4;
        if($mod4){
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }
}

调用代码

调用上面类的示例代码
            //获取加密字符串
            require_once('rsa.php');
            $rsa = new RsaUtils($this->rsa_public_key, $this->rsa_private_key);

            //字段名按照ASCII从小到大排序
            ksort($Body);

            $sign_str=[];
            foreach($Body as $pk=>$pv){
                if (empty($pv)) {
                    continue;
                }
                array_push($sign_str, "{$pk}={$pv}");
            }

            $unsignstr=join("&", $sign_str);

            //error_log(__METHOD__ . PHP_EOL .print_r($unsignstr, true));

                        $checksum = $rsa->privateEncrypt($unsignstr);

                        $Body["sign"] = $checksum;

完整支付插件

【支付插件】woocommerce对接第三方支付smtmpay

评论 (0)

取消
只有登录/注册用户才可评论