php对接微信支付v3api,wechatpay-api-v3,分享Hyperf和tp5的食用方法

尹正奇
2023-12-01

对接微信订单投诉不得已用到了v3的api,官方没有直接能够使用的api,在此做个记录,前面是Hyperf单独测试的方法,后面是tp5简单封装了一下,首次对接遇到问题的可以参考,

官方API文档:https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml

<?php

//Hyperf

use Hyperf\Utils\ApplicationContext;
use Hyperf\Guzzle\ClientFactory;  


//通用配置
$mch_private_key = '***';  //私钥参考生成地址:https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu
$merchant_id     = '***'; //微信商户id
$serial_no       = '***'; //证书序列号,登陆商户平台【API安全】->【API证书】->【查看证书】,可查看商户API证书序列号。



//get无需参数接口:

$url             = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications';
$http_method     = 'GET';
$timestamp       = time();
$nonce           = uniqid();
$body            = '';

// Authorization: <schema> <token>
$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);

$factory  = ApplicationContext::getContainer()->get(ClientFactory::class);
$client   = $factory->create(['timeout' => 10]);
$response = $client->get($url,[
    'headers' =>
        [
            'authorization' => $schema . " " . $token,
            'Connection'    => 'keep-alive',
            'Accept'        => 'application/json',
        ],
]);

$data = $response->getBody()->getContents();
var_export([' $data' => $data]);



//get需参数接口:

        $url             = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaints' . '?begin_date=2021-01-05&end_date=2021-02-01';   //注意参数是直接放在请求url上面,body请求报文依旧为空
        $http_method     = 'GET';
        $timestamp       = time();
        $nonce           = uniqid();
        $body            = '';

        // Authorization: <schema> <token>
        $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);


        $factory  = ApplicationContext::getContainer()->get(ClientFactory::class);
        $client   = $factory->create(['timeout' => 10]);
        $response = $client->get($url,[
            'headers' =>
                [
                    'authorization' => $schema . " " . $token,
                    'Connection'    => 'keep-alive',
                    'Accept'        => 'application/json',
                ],
//            'body' =>$body
        ]);

        $data = $response->getBody()->getContents();
        var_export([' $data' => $data]);




//post:

        $url             = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications';
        $http_method     = 'POST';
        $timestamp       = time();
        $nonce           = uniqid();
        $body            =  json_encode([
            'url' => 'https://just.xxx.cn/uin/qwe'
        ]);

        // Authorization: <schema> <token>
        $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);


        $factory  = ApplicationContext::getContainer()->get(ClientFactory::class);
        $client   = $factory->create(['timeout' => 10]);
        $response = $client->post($url,[
            'headers' =>
                [
                    'authorization' => $schema . " " . $token,
                    'Connection'    => 'keep-alive',
                    'Accept'        => 'application/json', 
                    'content-type'  => 'application/json', //请求头必须填上content-type,否则报错,仅在$body报文不为空时添加
                ],
            'body' =>$body   //必须把请求参数带上,否则报错
        ]);

        $data = $response->getBody()->getContents();
        var_export([' $data' => $data]);



//put,除了请求方式,其他和post一样

        $url             = 'https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications';
        $http_method     = 'PUT';
        $timestamp       = time();
        $nonce           = uniqid();
        $body            =  json_encode([
            'url' => 'https://just.xxx.cn/qwe'
        ]);

        // Authorization: <schema> <token>
        $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);


        $factory  = ApplicationContext::getContainer()->get(ClientFactory::class);
        $client   = $factory->create(['timeout' => 10]);
        $response = $client->put($url,[
            'headers' =>
                [
                    'authorization' => $schema . " " . $token,
                    'Connection'    => 'keep-alive',
                    'Accept'        => 'application/json', 
                    'content-type'  => 'application/json', //请求头必须填上content-type,否则报错,仅在$body报文不为空时添加
                ],
            'body' =>$body   //必须把请求参数带上,否则报错
        ]);

        $data = $response->getBody()->getContents();
        var_export([' $data' => $data]);



//delete:
        $url             = 'ht
        tps://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications';
        $http_method     = 'DELETE';  //注意大写,官方说的是小写,但小写并不能通过验证
        $timestamp       = time();
        $nonce           = uniqid();
        $body            = '';

        // Authorization: <schema> <token>
        $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);


        $factory  = ApplicationContext::getContainer()->get(ClientFactory::class);
        $client   = $factory->create(['timeout' => 10]);
        $response = $client->delete($url,[
            'headers' =>
                [
                    'authorization' => $schema . " " . $token,
                    'Connection'    => 'keep-alive',
                    'Accept'        => 'application/json',
//                    'content-type'  => 'application/json',
                ],
//            'body' =>$body 
        ]);

        $data = $response->getBody()->getContents();
        var_export([' $data' => $data]);
<?php

//tp5

use GuzzleHttp\Client;
use think\Config;

    private $config = null;

    public function __construct()
    {
        //TODO: 配置信息
        $this->config = [
        'merchant_id' => '',
        'serial_no'=>'',
        'mch_private_key' => '',
        ];
    }
    
    /**
     * 获取最近投诉列表
     */
    public function getNotificationsList() : array
    {
        $params = [
            'begin_date' => date("Y-m-d", (strtotime(date("Y-m-d")) - 86400*29)),
            'end_date' => date("Y-m-d"),
        ];
        $res = $this->get('https://api.mch.weixin.qq.com/v3/merchant-service/complaints', $params);
        return $res;
    }


    public function get(string $url, array $params = []) : array
    {
        $res = $this->withRequest('GET', $url, $params);
        return json_decode($res->getBody()->getContents(), true);
    }
    

    private function withRequest(string $http_method, string $url, array $params = []) : \GuzzleHttp\Psr7\Response
    {
        $body = '';
        $query = http_build_query($params);
        if ($http_method === 'GET') {
            $uri = $url . (!empty($params) ? '?' . $query : '');
        }
        if ($http_method === 'POST' || $http_method === 'PUT') {
            $uri  = $url;
            $body = (!empty($params) ? '?' . json_encode($params) : '');
        }
        if ($http_method === 'DELETE') {
            $uri = $url . (!empty($params) ? '?' . $query : '');
        }

        $timestamp = time();
        $nonce     = uniqid();

        // Authorization: <schema> <token>
        $url_parts     = parse_url($uri);
        $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, $this->config['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"',
            $this->config['merchant_id'], $nonce, $timestamp, $this->config['serial_no'], $sign);

        $client = new \GuzzleHttp\Client(['timeout' => 10]);

        $headers = [
            'authorization' => $schema . " " . $token,
            'Connection'    => 'keep-alive',
            'Accept'        => 'application/json',
        ];

        if ($http_method === 'POST' || $http_method === 'PUT') {
            $headers = array_merge(['content-type' => 'application/json']);
        }

        $response = $client->{$http_method}($uri,
            [
                'headers' => $headers,
            ]);
        return $response;
    }

 类似资料: