php、Thinkphp微信支付V3 、php、Thinkphp微信API V3、摒棄官方demo,自寫調用demo


以前一直使用v2,格式是xml格式,但是微信最新推出v3之后,只有以前的老用戶才能用v2,而新用戶只能用v3。閱讀了一下文檔,發現v3采用的是json格式和以前的xml大有不同。官方的demo又不清不白,用的是guzzle(關鍵我不會啊,研究又要太久時間,項目趕,沒辦法只有自己編寫一個demo了,希望可以幫助大家)

首先創建一個文件和類,如WxPayv3.php,請勿直接復制,因為可以看到這個類繼承了另一個類,功能有請求,加密,解密,我的環境為Tp6.0+,所以3.2的用戶需要做下小小的修改。

 WxPayv3.php如下 

<?php
namespace wx;
use wx\WxExtend;
class WxPayv3 extends WxExtend{
    
    /**
     * # +========================================================================
     * # | - @name        執行
     * # | - @author     cq <just_leaf@foxmail.com> 
     * # | - @copyright zmtek 2021-01-20
     * # +========================================================================
     */
    public function execute($url,$body = null,$http_method = 'POST') {
        
        # 轉化大寫
        $http_method = strtoupper($http_method);
        
        if($http_method == 'POST') {
            
            $body   = json_encode($body);
        }else{
            
            $url    = $url . '?' . http_build_query($body); 
            $body   = null;
        }
        
        # 分割符號
        $sign       = $this -> getV3Sign($url,$http_method,$body);
        
        $header[]   = 'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36';
        $header[]   = 'Accept: application/json';
        $header[]   = 'Content-Type: application/json;';
        $header[]   = 'Authorization: WECHATPAY2-SHA256-RSA2048 '.$sign;
    
        $exc        = $this -> Curl($url,$body,$http_method,$header);
        return $exc;
    }
    
    /**
     * # +========================================================================
     * # | - @name        調起小程序支付的簽名
     * # | - @author     cq <just_leaf@foxmail.com> 
     * # | - @copyright zmtek 2021-01-20
     * # +========================================================================
     */
    function getWechartSign($data){
        
        if(!isset($data['appid']) || $data['appid'] == '')          {echo 'appid 不能為空';die;}
        if(!isset($data['timeStamp']) || $data['timeStamp'] == '')  {echo 'timeStamp 不能為空';die;}
        if(!isset($data['package']) || $data['package'] == '')      {echo 'package 不能為空';die;}
        if(!isset($data['nonceStr']) || $data['nonceStr'] == '')    {echo 'nonceStr 不能為空';die;}
    
        $str        = $data['appid']."\n".$data['timeStamp']."\n".$data['nonceStr']."\n".$data['package']."\n";
        $str        = $this -> getSha256WithRSA($str);
        return $str;
    }
    
    /**
     * # +========================================================================
     * # | - @name        計算簽名
     * # | - @author     cq <just_leaf@foxmail.com> 
     * # | - @copyright zmtek 2021-01-20
     * # +========================================================================
     */ 
    function getSha256WithRSA($content){
        
        $privateKey         = file_get_contents($this -> SSLKEY_PATH);
        $binary_signature   = "";
        $algo               = "SHA256";
        openssl_sign($content, $binary_signature, $privateKey, $algo);
        $sign               = base64_encode($binary_signature);
        return $sign;
    }
    
    /**
     * # +========================================================================
     * # | - @name        請求
     * # | - @author     cq <just_leaf@foxmail.com> 
     * # | - @copyright zmtek 2021-01-20
     * # +========================================================================
     */
    public function Curl($url, $data, $http_method,$header = array(), $timeout = 30)
    {
        $opts = array(
            CURLOPT_TIMEOUT        => $timeout,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER     => $header,
            CURLOPT_URL            => $url,
            CURLOPT_HEADER         => 1 ,
        );
        
        # 根據請求類型設置特定參數
        if($http_method == 'POST') {
            
            # 判斷是否傳輸文件
            $opts[CURLOPT_POST] = 1;
            $opts[CURLOPT_POSTFIELDS] = $data;
        }
                
        # 初始化並執行curl請求
        $ch         = curl_init();
        curl_setopt_array($ch, $opts);
        
        $data       = curl_exec($ch);
        $error      = curl_error($ch);
        $httpCode   = curl_getinfo($ch,CURLINFO_HTTP_CODE); 
        curl_close($ch);
        if($error) throw new Exception('請求發生錯誤:' . $error);
        list($headers, $body) = explode("\r\n\r\n", $data, 2);
        
        $result['data']     = json_decode($body,true);
        $result['httpcode'] = $httpCode;
        $result['headers']  = explode("\r\n", $headers);
        return  $result;
    }
    
    /**
     * # +========================================================================
     * # | - @name        簽名
     * # | - @author     cq <just_leaf@foxmail.com> 
     * # | - @copyright zmtek 2021-01-20
     * # +========================================================================
     */
    public function getV3Sign($url,$http_method,$body) {
        
        # 商戶號
        $merchant_id    = $this -> MCHID;
        # 隨機字符串
        $nonce          = strtoupper($this -> getNoncestr());
        # 商戶序列號
        $serial_no      = $this -> merchantSerialNumber;
        # 時間搓
        $timestamp      = time();
        # url
        $url_parts      = parse_url($url);
        # 獲取絕對路徑
        $canonical_url  = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        # 密鑰key
        $private_key    = $this -> getPrivateKey($this -> SSLKEY_PATH);
        # 拼接參數
        $message        = 
        $http_method."\n".
        $canonical_url."\n".
        $timestamp."\n".
        $nonce."\n".
        $body."\n";
        
        # 獲取簽名             
        openssl_sign($message, $raw_sign, $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;
    }

    /**
     * # +========================================================================
     * # | - @name        獲取私鑰
     * # | - @author     cq <just_leaf@foxmail.com> 
     * # | - @copyright zmtek 2019-12-26
     * # +========================================================================
     */
    public function getPrivateKey($filepath) {
        
        return openssl_get_privatekey(file_get_contents($filepath));
    }
    
    /**
     * # +========================================================================
     * # | - @name        獲取隨機數
     * # | - @author     cq <just_leaf@foxmail.com> 
     * # | - @copyright zmtek 2021-01-20
     * # +========================================================================
     */
    public 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;
    }
    
    /**
     * # +========================================================================
     * # | - @name        解密
     * # | - @author     cq <just_leaf@foxmail.com> 
     * # | - @copyright zmtek 2021-01-20
     * # +========================================================================
     */
    public function decryptToString($associatedData, $nonceStr, $ciphertext)
    {
    
        $aesKey = $this -> v3key;
        
        $ciphertext = \base64_decode($ciphertext , true);
        
        if (strlen($ciphertext) <= 16) {
            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, $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, $aesKey);
        }
        
        // PHP >= 7.1
        if(PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods()) ){
            $ctext      = substr($ciphertext, 0, -16);
            $authTag    = substr($ciphertext, -16);
            return \openssl_decrypt($ctext, 'aes-256-gcm', $aesKey, \OPENSSL_RAW_DATA, $nonceStr,$authTag, $associatedData);
        }
    
        throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安裝libsodium-php');
    }
}
WxExtend.php如下
<?php
namespace wx;
class WxExtend
{

    //=======【基本信息設置】=====================================
    //微信公眾號身份的唯一標識。審核通過后,在微信發送的郵件中查看
    public     $APPID;
    //受理商ID,身份標識
    public     $MCHID;
    //商戶支付密鑰Key。審核通過后,在微信發送的郵件中查看
    public     $KEY;
    //微信v3
    public    $v3key;
    //JSAPI接口中獲取openid,審核后在公眾平台開啟開發模式后可查看
    public     $APPSECRET;
    //=======【證書路徑設置】=====================================
    //證書路徑,注意應該填寫絕對路徑
    public     $SSLCERT_PATH;
    public     $SSLKEY_PATH;
    //商戶API證書序列號
    public    $merchantSerialNumber;
    //小程序appid
    public    $appletappid;
    //小程序密鑰
    public    $appletsecret;
    //=======【curl超時設置】===================================
    //本例程通過curl使用HTTP POST方法,此處可修改其超時時間,默認為30秒
    public     $CURL_TIMEOUT = 30;
    //服務service_id,微信分特有
    public    $service_id;
function __construct() {
        //小程序appid
        $this->appletappid  ='000000';
        //小程序密鑰
        $this->appletsecret ='000';
        //微信公眾號身份的唯一標識。審核通過后,在微信發送的郵件中查看
        $this->APPID         = '000' ;
        //JSAPI接口中獲取openid,審核后在公眾平台開啟開發模式后可查看
        $this->APPSECRET     = '000' ;
        //受理商ID,身份標識
        $this->MCHID         = '000' ;
        //商戶支付密鑰Key。審核通過后,在微信發送的郵件中查看
        $this->KEY             = '000';
        $this->v3key        = '000';
        //商戶API證書序列號
        $this->merchantSerialNumber = '000';
        //服務service_id,微信分特有
        $this->service_id = '000';
        
        //=======【證書路徑設置】=====================================
        //證書路徑,注意應該填寫絕對路徑
        $this->SSLCERT_PATH    = app()->getRootPath().'extend/wx/cacert/apiclient_cert.pem' ;
        $this->SSLKEY_PATH     = app()->getRootPath().'extend/wx/cacert/apiclient_key.pem';
    }
}
 
         
         
        

 然后再new再調用就完事了

/**
         * # +========================================================================
         * # | - @name        查詢用戶
         * # | - @author     cq <just_leaf@foxmail.com> 
         * # | - @copyright zmtek 2020-11-24
         * # +------------------------------------------------------------------------
         * # | - 1.msg
         * # +========================================================================
         */
        public function permissions_openid(WxPayv3 $WxPayv3,WxExtend $WxExtend) {
            
            $url    = 'https://api.mch.weixin.qq.com/v3/payscore/permissions/openid/xxxx';
            $authorization_code = $WxPayv3 -> getNoncestr();
            $data   = array(
                'appid'                 => $WxExtend -> appletappid ,
                'service_id'            => $WxExtend -> service_id,
            );
            
            $result = $WxPayv3 -> execute($url,$data,'GET');
            pf($result);
            // $data   = json_decode($result['data'],true);
            // return $this -> success($data);
        }

 

 

好,我們來看調用結果

啊呀,好家伙,是不是我這個方法有問題呢?結果趕緊看下官方文檔,原來是微信那邊掛了。不信?看下圖

好啦,之后就可以愉快的調用任何接口了。


免責聲明!

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



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