zoukankan      html  css  js  c++  java
  • 微信 支付即服务 服务人员注册 和 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 . "
    " .
                $canonical_url . "
    " .
                $timestamp . "
    " .
                $nonce . "
    " .
                $body . "
    ";
            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('Sodiumcrypto_aead_aes256gcm_is_available') &&
                Sodiumcrypto_aead_aes256gcm_is_available()) {
                return Sodiumcrypto_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}
    " .
                $canonical_url . "
    " .
                $timestamp . "
    " .
                $nonce . "
    " .
                $body . "
    ";
            //生成签名
            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();
  • 相关阅读:
    <s:iterator>各种遍历用法
    hibernate4整合spring3事务问题
    web服务器部署过程记录
    svn一次性add/delete所有文件
    svn回退版本/取消修改
    sdk接入
    论坛遇到附件上传失败问题总结(discuz)
    linux下部署monogoDB服务(以及安装php mogodb扩展)
    linux部署svn服务器
    linux下给php安装memcached及memcache扩展(转)
  • 原文地址:https://www.cnblogs.com/handle/p/13926047.html
Copyright © 2011-2022 走看看