对接微信新版SDKv3版
签名生成规则,微信的官方文档里面说明的还算可以吧,不过个人觉得不太理想- -。 自己调试的时候调试了半天才找了错误原因。
https://wechatpay-api.gitbook.io/wechatpay-api-v3
微信v3接口更换了新版签名方式
Authorization
传递,具体说明请见签名生成指南。401 Unauthorized
。//生成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\'); }
请发表评论