评论

微信支付下载微信平台证书 apiV3(2)

微信支付下载微信平台证书,微信示例代码不够清晰简洁明了。

这里用的是PHP,所以使用 wechatpay-guzzle-middleware 。

下载微信支付平台证书主要文件 CertificateDownloader.php

private function downloadCert($opts=[])
    {
        try {
            // 构造一个WechatPayMiddleware
            $builder = WechatPayMiddleware::builder()
                ->withMerchant($opts['mchid'], $opts['serialno'], PemUtil::loadPrivateKey($opts['privatekey'])); // 传入商户相关配置
            if (isset($opts['wechatpay-cert'])) {
                $builder->withWechatPay([ PemUtil::loadCertificate($opts['wechatpay-cert']) ]); // 使用平台证书验证
            }
            else {
                $builder->withValidator(new NoopValidator); // 临时"跳过”应答签名的验证
            }
            $wechatpayMiddleware = $builder->build();

            // 将WechatPayMiddleware添加到Guzzle的HandlerStack中
            $stack = HandlerStack::create();
            $stack->push($wechatpayMiddleware, 'wechatpay');

            // 创建Guzzle HTTP Client时,将HandlerStack传入
            $client = new Client(['handler' => $stack]);

            // 接下来,正常使用Guzzle发起API请求,WechatPayMiddleware会自动地处理签名和验签
            $resp = $client->request("GET", "https://api.mch.weixin.qq.com/v3/certificates", [
                'headers' => [ 'Accept' => 'application/json','User-Agent'=>'https://zh.wikipedia.org/wiki/User_agent' ]
            ]);
            if ($resp->getStatusCode() < 200 || $resp->getStatusCode() > 299) {
                echo "download failed, code={$resp->getStatusCode()}, body=[{$resp->getBody()}]\n";
                return;
            }

            $list = json_decode($resp->getBody(), true);

            $plainCerts = [];
            $x509Certs = [];

            $decrypter = new AesUtil($opts['key']);
            foreach ($list['data'] as $item) {
                $encCert = $item['encrypt_certificate'];
                $plain = $decrypter->decryptToString($encCert['associated_data'],
                    $encCert['nonce'], $encCert['ciphertext']);
                if (!$plain) {
                    echo "encrypted certificate decrypt fail!\n";
                    exit(1);
                }
                // 通过加载对证书进行简单合法性检验
                $cert = \openssl_x509_read($plain); // 从字符串中加载证书
                if (!$cert) {
                    echo "downloaded certificate check fail!\n";
                    exit(1);
                }
                $plainCerts[] = $plain;
                $x509Certs[] = $cert;
            }
            // 使用下载的证书再来验证一次应答的签名
            $validator = new WechatPay2Validator(new CertificateVerifier($x509Certs));
            if (!$validator->validate($resp)) {
                echo "validate response fail using downloaded certificates!";
                exit(1);
            }
            // 输出证书信息,并保存到文件
            foreach ($list['data'] as $index => $item) {
//                echo "Certificate {\n";
//                echo "    Serial Number: ".$item['serial_no']."\n";
//                echo "    Not Before: ".(new DateTime($item['effective_time']))->format('Y-m-d H:i:s')."\n";
//                echo "    Not After: ".(new DateTime($item['expire_time']))->format('Y-m-d H:i:s')."\n";
//                echo "    Text: \n    ".str_replace("\n", "\n    ", $plainCerts[$index])."\n";
//                echo "}\n";

                $outpath = $opts['output'].DIRECTORY_SEPARATOR.'wechatpay_'.$item['serial_no'].'.pem';
                file_put_contents($outpath, $plainCerts[$index]);
            }
//            return [$opts,$list['data'],$outpath,$plainCerts];
        }
        catch (RequestException $e) {
            echo "download failed, message=[{$e->getMessage()}] ";
            if ($e->hasResponse()) {
                echo "code={$e->getResponse()->getStatusCode()}, body=[{$e->getResponse()->getBody()}]\n";
            }
            exit(1);
        }
        catch (Exception $e) {
            echo "download failed, message=[{$e->getMessage()}]\n";
            echo $e;
            exit(1);
        }
    }




同级PHP文件 NoopValidator.php

最后一次编辑于  2021-01-19  
点赞 0
收藏
评论
登录 后发表内容