tp5 微信新版本商家转到到零钱,v3秘钥,平台证书和平台证书序列号

<?php
class JsApiPay
{
    
    public $data = null;
    public $serial_no = '******';  //商户证书序列号 和平台证书序列号是两回事
    public $mchid='******';   //商户号
    public $mch_key_v3='***************';   //v3秘钥


    public function Unite($url,$http_method='GET',$body){
        $Authorization=$this->getSign($url,$http_method,$body);

        return $this->curl_request($url, $body, $http_method, $Authorization);
    }

    public function JsapiSign($prepay_id,$appid,$timestamp,$nonce){
        $mch_private_key = file_get_contents('../vendor/wxpay3/cacert/apiclient_key.pem'); //获取密钥文件内容
        $message = $appid."\n".
        $timestamp."\n".
        $nonce."\n".
        $prepay_id."\n";
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        return $sign;
    }
    
    public function getSign($url,$http_method='GET',$body){
        $serial_no=$this->serial_no;
        $merchant_id=$this->mchid;
        $timestamp=time();
        $nonce=$this->getNonceStr();
        $mch_private_key = file_get_contents('../vendor/wxpay3/cacert/apiclient_key.pem'); //获取密钥文件内容
        $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);
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
        $merchant_id, $nonce, $timestamp, $serial_no, $sign);
        return $schema.' '.$token;
    }

    /*验证签名*/
    public function verifysign($serial_no,$TIMESTAMP,$NONCE,$BODY,$SIGNATURE){
        $SIGNATURE=base64_decode($SIGNATURE);

        $message = $TIMESTAMP."\n".
        $NONCE."\n".
        $BODY."\n";

        $mch_private_key=$this->wx_ciphertext($serial_no);
        $pubkeyid = openssl_pkey_get_public($mch_private_key);
        $ok=openssl_verify($message, $SIGNATURE, $pubkeyid,OPENSSL_ALGO_SHA256);
        openssl_free_key($pubkeyid);
        if($ok==1){
            return true;
        }else{
            return false;
        }
    }

    /*获取微信支付平台证书
     
         serial_no:平台证书序列号
    */
    public function wx_ciphertext(){

        $url='https://api.mch.weixin.qq.com/v3/certificates';
        $certificates=$this->Unite($url,'GET','');
     
        $certificates=json_decode($certificates,true);
             
         //此处  dump(certificates);  serilal_no  为平台序列号

    
        // foreach ($certificates['data'] as $key => $value) {
        //     if($value['serial_no']==$this->serial_no){
        //         $associatedData=$value['encrypt_certificate']['associated_data'];
        //         $nonceStr=$value['encrypt_certificate']['nonce'];
        //         $ciphertext=$value['encrypt_certificate']['ciphertext'];
        //         break;
        //     }
        // }
        $data=$certificates['data'][0]['encrypt_certificate'];
       
        $associatedData=$data['associated_data'];
        $nonceStr=$data['nonce'];
        $ciphertext=$data['ciphertext'];
    
        $AesUtil = new \AesUtil($this->mch_key_v3);
        return $AesUtil->decryptToString($associatedData, $nonceStr, $ciphertext);  //此处获取平台证书。复制到文本里改为pem后缀

    }

    /**
     * 
     * 产生随机字符串,不长于32位
     * @param int $length
     * @return 产生的随机字符串
     */
    public static function getNonceStr($length = 32) 
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {  
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
        } 
        return $str;
    }

    /**
     * @Description: curl请求
     * @Author: Yang
     * @param $url
     * @param null $data
     * @param string $method
     * @param array $header
     * @param bool $https
     * @param int $timeout
     * @return mixed
     */
    function curl_request($url, $data=null, $method='get', $Authorization, $https=true, $timeout = 5){
         
        
        $header = array(
               'Content-Type: application/json',
               'Accept: application/json',
               'Wechatpay-Serial:******',//平台序列号
               'Authorization: '.$Authorization
        );
        

        $user_agent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36";

        $method = strtoupper($method);
        $ch = curl_init();//初始化
        curl_setopt($ch, CURLOPT_URL, $url);//访问的URL
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//只获取页面内容,但不输出
        if($https){
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//https请求 不验证证书
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//https请求 不验证HOST
        }
        if ($method != "GET") {
            if($method == 'POST'){
                curl_setopt($ch, CURLOPT_POST, true);//请求方式为post请求
            }
            if ($method == 'PUT' || strtoupper($method) == 'DELETE') {
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); //设置请求方式
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//请求数据
        }
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header); //模拟的header头
        curl_setopt($ch, CURLOPT_USERAGENT,$user_agent);
        //curl_setopt($ch, CURLOPT_HEADER, false);//设置不需要头信息
        $result = curl_exec($ch);//执行请求
        $httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
        if($result){
//            file_put_contents('./text.txt', '请求返回:'.$result.PHP_EOL, FILE_APPEND);
            $result=json_decode($result,true);
            $result['httpCode']=$httpCode;
            $result=json_encode($result,JSON_UNESCAPED_UNICODE);
        }else{
            $result=json_encode(['httpCode'=>$httpCode]);
        }
        curl_close($ch);//关闭curl,释放资源
        return $result;
    }

    /**
     * 敏感信息加密算法
     * @param $str
     * @return string
     */
    public function getEncrypt($str)
    {
        //$str是待加密字符串
        
        
        $public_key = file_get_contents('../vendor/wxpay3/cacert/pingtai_cert.pem'); //此处证书文件为平台证书
        $encrypted  = '';
        openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING);//这里 类型要设置为OPENSSL_PKCS1_OAEP_PADDING
        //base64编码
        $sign = base64_encode($encrypted);
        return $sign;
    }
}


class AesUtil{
      /**
    * AES key
    *
    * @var string
    */
      private $aesKey;

      const KEY_LENGTH_BYTE = 32;
      const AUTH_TAG_LENGTH_BYTE = 16;

      /**
    * Constructor
    */
      public function __construct($aesKey)
      {
          if (strlen($aesKey) != self::KEY_LENGTH_BYTE) {
              throw new InvalidArgumentException('无效的ApiV3Key,长度应为32个字节');
          }
          $this->aesKey = $aesKey;
      }

      /**
    * 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');
      }
          
      
      
}

其中wx_ciphertext方法是获取平台证书和平台证书序列号使用,获取平台证书需要安装php7.1以上

  public function  tixian($openid,$out_trade_no,$money,$desc,$user_name){
            //查询用户授权记录
            Vendor('wxpay3.WxPayJsApiPay');
            $input = new \JsApiPay();
            $url='https://api.mch.weixin.qq.com/v3/transfer/batches';
         
            $body['appid']='yourappid';
            $body['out_batch_no']='Y'.date('Ymdhis',time());
            $body['batch_name']='商户提现';
            $body['batch_remark']='合作分成';
            
            $body['total_amount']=$money*100;
            $body['total_num']=1;
      

            //订单风险金
            $detail=[
                      'out_detail_no'=>$out_trade_no,
                      'transfer_amount'=>$money*100,
                       'transfer_remark'=>'商户提现',
                       'openid'=>$openid,
                     'user_name'=>$input->getEncrypt($user_name),  //敏感信息加密
                     ];
          
            $body['transfer_detail_list'][]=$detail;
           
            $responseData=$input->Unite($url,'POST',json_encode($body));
               

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值