• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

php微信支付v3版签名生成,代金券、微信支付分、支付即服务等 ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

对接微信新版SDKv3版

签名生成规则,微信的官方文档里面说明的还算可以吧,不过个人觉得不太理想- -。  自己调试的时候调试了半天才找了错误原因。

https://wechatpay-api.gitbook.io/wechatpay-api-v3

 

微信v3接口更换了新版签名方式

  商户需要使用自身的私钥对API URL、消息体等关键数据的组合进行SHA-256 with RSA签名。
       请求的签名信息通过HTTP头Authorization传递,具体说明请见签名生成指南
       没有携带签名或者签名验证不通过的请求,都不会被执行,并返回401 Unauthorized
 
 
 
官方有给提供了类库和SDK
     不过我这里是旧项目没有用着composer, 使用官方提供的话  需要改动太大,所以这里就自己做了一个简单的封装, 所以不清楚官方提供的库具体如何。
 
 
//生成v3 Authorization
    protected function createAuthorization( $url , $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\']}" : ""));

        //私钥地址
        $mch_private_key = $this->mch_private_key;
        //商户号
        $merchant_id = $this->mch_id;
        //当前时间戳
        $timestamp =  time();
        //随机字符串
        $nonce = $this->createNoncestr();
        //POST请求时 需要 转JSON字符串
        $body =  $this->body ;
        $message = "{$method}\n".
            $canonical_url."\n".
            $timestamp."\n".
            $nonce."\n".
            $body."\n";

        //生成签名
        openssl_sign($message, $raw_sign, openssl_get_privatekey(file_get_contents($mch_private_key)), \'sha256WithRSAEncryption\');
        $sign = base64_encode($raw_sign);
        //Authorization 类型  
        $schema = \'WECHATPAY2-SHA256-RSA2048\';
        //生成token
        $token = sprintf(\'mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"\', $merchant_id,$this->serial_no, $nonce, $timestamp,  $sign);

        $header = [
            \'Content-Type:application/json\',
            \'Accept:application/json\',
            \'User-Agent:*/*\',
            \'Authorization: \'.  $schema . \' \' . $token
        ];
        return $header;
    }
/**
     *  作用:产生随机字符串,不长于32位
     */
    public function createNoncestr( $length = 32 )
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

 

    获取平台证书及平台证书序列号,加密解密,个别V3接口需要用到。

官方地址:https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/wei-xin-zhi-fu-ping-tai-zheng-shu-geng-xin-zhi-yin
    

/**
* 支付及服务 - 服务人员注册
* 1. 获取平台证书序列号 serial_no与 商户支付证书不是一个
* 2. 解密平台证书,拿到平台证书信息
* 3. 加密请求参数时 需要用户 平台证书进行加密
*/ public function regguide( $post ,$serial_no){ $url = "https://api.mch.weixin.qq.com/v3/smartguide/guides"; $this->setBody( $post ); //生成V3请求 header认证信息 $header = $this->createAuthorization( $url , \'POST\' ); //增加平台证书序列号 , 平台证书序列号方法 getcertificates()
$header[] = \'Wechatpay-Serial:\' . $serial_no; $data = $this->postXmlCurl(json_encode($post , JSON_UNESCAPED_UNICODE) , $url , 30 , $header ); return json_decode($data , true); }

 

    /**
     * 获取平台证书, 与商户证书不是一个内容
     */
    public function getcertificates(){

        $url="https://api.mch.weixin.qq.com/v3/certificates";

        //生成V3请求 header认证信息
        $header = $this->createAuthorization( $url );

        $header[] = \'User-Agent : https://zh.wikipedia.org/wiki/User_agent\';

        $data = $this->getXmlCurl( $url  , $this->curl_timeout , $header );

        return json_decode($data , true);

    }
   /**
     * V3加密
     */
    public function getEncrypt($str){ 
        //$str是待加密字符串 
        $public_key_path = \'证书地址\'; //看情况使用证书, 个别接口证书 使用的是 平台证书而不是 api证书
        $public_key = file_get_contents($public_key_path); 
        $encrypted = \'\'; 
        
        if (openssl_public_encrypt($str,$encrypted,$public_key,OPENSSL_PKCS1_OAEP_PADDING)) { 
            //base64编码 
            $sign = base64_encode($encrypted);
        } else {
            throw new Exception(\'encrypt failed\');
        }
        return $sign;
    }


/**
     * Decrypt AEAD_AES_256_GCM ciphertext  V3签名解密
     * @param stingr    $aesKey             V3签名
     * @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($aesKey ,$associatedData, $nonceStr, $ciphertext)
    {

        if (strlen($aesKey) != 32 ) {
            throw new InvalidArgumentException(\'无效的ApiV3Key,长度应为32个字节\');
        }

        $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\');
    }

 

注意:
     我这里缺少代码直接获取商户序列号的方法,serial_no
     可以自己查看官方文档或者 我这里是直接 获取的证书信息里面的序列号, 也可以通过  https://myssl.com/cert_decode.html   去查看证书的序列号。
     如果是GET请求方式的$url 需要是完整地址 host+path+query  。
     如果是POST等其他请求方式 时, 请求BODY需要与query参数一致,且转JSON字符串
 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap