微信 支付即服務 服務人員注冊 和 AEAD_AES_256_GCM 的使用 (sodium_crypto_aead_aes256gcm_decrypt 或者 sodium_crypto_aead_aes256gcm_is_available() )無法使用 的解決方案


sodium_crypto_aead_aes256gcm_decrypt 無法使用需要安裝 sodium 

其實在 >=php7.2 以上的版本都自帶了  這個模塊 不用重新安裝只需 將 

extension=sodium.so   前的 ;分號去掉保存  就可以了

 

如果您使用的是 windows  phpstudy  只需切換到 php >=7.2  勾選模塊后重啟即可 

 

 

 

 

直接上代碼

 

<?php

class Test
{
    public $mch_id;
    public $api_serial_no;
    public $serial_no_obj;
    const KEY_LENGTH_BYTE = 32;
    const AUTH_TAG_LENGTH_BYTE = 16;
    public $aesKey;

    public function __construct()
    {
        $this->mch_id = '16xxxxxxx6'; //商戶號
        $this->api_serial_no = '321xxxxxxxxxx347'; //證書的序號
        $this->aesKey = 'zih3xxxxxxxxxxxxxxxxxxxxxnae'; //密鑰
    }

    /**
     * 獲取平台證書內容
     */
    public function get_Certificates($type)
    {
        if ($this->serial_no_obj) {
            $serial_no_obj = $this->serial_no_obj;
        } else {
            $sign = $this->get_Sign("https://api.mch.weixin.qq.com/v3/certificates", "GET", "", $this->get_Privatekey(), $this->mch_id, $this->api_serial_no);//$http_method要大寫
            $header[] = 'User-Agent: */*';
            $header[] = 'Accept: application/json';
            $header[] = 'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $sign;
            $back = $this->http_Request("https://api.mch.weixin.qq.com/v3/certificates", $header);
            $serial_no_obj = json_decode($back);
            $this->serial_no_obj = $serial_no_obj;
        }
        if ($type == 1) {
            $serial_no_new = $serial_no_obj->data[0]->serial_no;
        } else if ($type == 2) {
            $serial_no_new = $serial_no_obj->data[0]->encrypt_certificate;
        } else {
            return $serial_no_obj;
        }
        return $serial_no_new;
    }

    /**
     * 獲取sign
     * @param $url
     * @param $http_method [POST GET 必讀大寫]
     * @param $body [請求報文主體(必須進行json編碼)]
     * @param $mch_private_key [商戶私鑰]
     * @param $merchant_id [商戶號]
     * @param $serial_no [證書編號]
     * @return string
     */
    private function get_Sign($url, $http_method, $body, $mch_private_key, $merchant_id, $serial_no)
    {
        $timestamp = time();//時間戳
        $nonce = $timestamp . rand(10000, 99999);//隨機字符串
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message =
            $http_method . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $body . "\n";
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $merchant_id, $nonce, $timestamp, $serial_no, $sign);
        return $token;
    }

    /**
     * 讀取商戶私鑰
     * @return false|resource
     */
    public function get_Privatekey()
    {
        $private_key_file = 'apiclient_key.pem';//私鑰文件路徑 如linux服務器秘鑰地址地址:/www/wwwroot/...../apiclient_key.pem"
        $mch_private_key = openssl_get_privatekey(file_get_contents($private_key_file));//獲取私鑰
        return $mch_private_key;
    }

    /**
     * 數據請求
     * @param $url
     * @param array $header 獲取頭部
     * @param string $post_data POST數據,不填寫默認以GET方式請求
     * @return bool|string
     */
    public function http_Request($url, $header = array(), $post_data = "")
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 2);
        if ($post_data != "") {
            curl_setopt($ch, CURLOPT_POST, TRUE);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); //設置post提交數據
        }
        //判斷當前是不是有post數據的發
        $output = curl_exec($ch);
        if ($output === FALSE) {
            $output = "curl 錯誤信息: " . curl_error($ch);
        }
        curl_close($ch);
        return $output;
    }


    /**
     *敏感信息加密
     **/
    public function getEncrypt($str)
    {
        //返回的是加密后的平台證書,需要對證書進行解密
        $public_key_all = $this->get_Certificates(2);
        //解密證書,獲取到平台證書得公鑰
        $public_key = $this->decryptToString($public_key_all->associated_data, $public_key_all->nonce, $public_key_all->ciphertext);
        $encrypted = '';
        //$sign是加密后的字符串
        if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
            //base64編碼
            $sign = base64_encode($encrypted);
        } else {
            $sign = '';
        }
        return $sign;
    }

    /**
     * Decrypt AEAD_AES_256_GCM ciphertext
     *
     * @param string $associatedData AES GCM additional authentication data
     * @param string $nonceStr AES GCM nonce
     * @param string $ciphertext AES GCM cipher text
     *
     * @return string|bool      Decrypted string on success or FALSE on failure
     */
    public function decryptToString($associatedData, $nonceStr, $ciphertext)
    {
        $ciphertext = \base64_decode($ciphertext);
        if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
            return false;
        }

        // ext-sodium (default installed on >= PHP 7.2)
        if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&
            \sodium_crypto_aead_aes256gcm_is_available()) {
            return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey);
        }

        // ext-libsodium (need install libsodium-php 1.x via pecl)
        if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&
            \Sodium\crypto_aead_aes256gcm_is_available()) {
            return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey);
        }

        // openssl (PHP >= 7.1 support AEAD)
        if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
            $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
            $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);

            return \openssl_decrypt($ctext, 'aes-256-gcm', $this->aesKey, \OPENSSL_RAW_DATA, $nonceStr,
                $authTag, $associatedData);
        }

        throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安裝libsodium-php');
    }

    //生成v3 Authorization
    public function createAuthorization($url, $body, $method = 'GET')
    {
        if (!in_array('sha256WithRSAEncryption', \openssl_get_md_methods(true))) {
            throw new \RuntimeException("當前PHP環境不支持SHA256withRSA");
        }
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));

        //API證書私鑰地址
        $mch_private_key = $this->get_Privatekey();
        //當前時間戳
        $timestamp = time();
        //隨機字符串
        $nonce = $timestamp . rand(10000, 99999);;
        //POST請求時 需要 轉JSON字符串
        $message = "{$method}\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $body . "\n";
        //生成簽名
        openssl_sign($message, $raw_sign, openssl_get_privatekey($mch_private_key), 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        //生成簽名信息
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $this->mch_id, $this->api_serial_no, $nonce, $timestamp, $sign);
        $header = [
            'Content-Type: application/json',
            'Accept: application/json',
            'User-Agent: */*',
            'Authorization: WECHATPAY2-SHA256-RSA2048' . ' ' . $token,
            'Wechatpay-Serial: ' . $this->get_Certificates(1)
        ];
        return $header;
    }

    /**
     * 服務人員注冊
     * @return array
     */
    function addWaiter()
    {
        //組合post信息,並對敏感信息加密
        $register = array(
            "corpid" => 'wwxxxxxxxxxxxxxx72',
            "store_id" => 100000000, //必須int類型
            "name" => $this->getEncrypt('小明明'),
            "mobile" => $this->getEncrypt('15xxxxxxxxx1'),
            "qr_code" => 'https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxxxxxxx1',
            "avatar" => "https://wework.qpic.cn/wwhead/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2qNxnJiboNbZHp7hU/0",
            "userid" => '15xxxxxxxxx1'
        );
        $registerJson = json_encode($register, JSON_UNESCAPED_UNICODE);
        //接口API
        $url = 'https://api.mch.weixin.qq.com/v3/smartguide/guides';
        //獲取請求頭(簽名)
        $hearder = $this->createAuthorization($url, $registerJson, 'POST');
        $returnData = $this->http_Request($url, $hearder, $registerJson);
        //返回結果 {"guide_id" : "LLA3WJ6DSZUfiaZDS79FH5Wm5m4X69TBic"}
        exit($returnData);
    }
}

$aa = new Test();
echo $aa->addWaiter();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM