对接微信订单投诉不得已用到了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;
}