mirror of
https://gitee.com/yansongda/pay.git
synced 2024-11-29 18:58:38 +08:00
feat: 微信查询投诉单详情自动解密用户手机号 (#912)
This commit is contained in:
parent
1ac094086f
commit
1dfbea1253
@ -4,6 +4,8 @@
|
||||
|
||||
- feat: 新增 `InvalidSignException`(#903)
|
||||
- feat: 新增 `DecryptException`(#906)
|
||||
- feat: 新增 `decrypt_wechat_contents` 解密微信加密内容(#912)
|
||||
- feat: `\Yansongda\Pay\Plugin\Wechat\Extend\Complaints\QueryDetailPlugin` 自动解密用户手机号(#912)
|
||||
|
||||
### changed
|
||||
|
||||
|
@ -109,6 +109,8 @@ class Exception extends \Exception
|
||||
|
||||
public const DECRYPT_WECHAT_DECRYPTED_METHOD_INVALID = 7003;
|
||||
|
||||
public const DECRYPT_WECHAT_ENCRYPTED_CONTENTS_INVALID = 7004;
|
||||
|
||||
public mixed $extra;
|
||||
|
||||
public function __construct(string $message = '未知异常', int $code = self::UNKNOWN_ERROR, mixed $extra = null, ?Throwable $previous = null)
|
||||
|
@ -273,6 +273,15 @@ function encrypt_wechat_contents(string $contents, string $publicKey): ?string
|
||||
return null;
|
||||
}
|
||||
|
||||
function decrypt_wechat_contents(string $encrypted, array $config): ?string
|
||||
{
|
||||
if (openssl_private_decrypt(base64_decode($encrypted), $decrypted, get_private_cert($config['mch_secret_cert'] ?? ''), OPENSSL_PKCS1_OAEP_PADDING)) {
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
|
@ -6,10 +6,17 @@ namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\decrypt_wechat_contents;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/query-complaint-v2.html
|
||||
@ -19,6 +26,9 @@ class QueryDetailPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
* @throws InvalidConfigException
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
@ -38,6 +48,25 @@ class QueryDetailPlugin implements PluginInterface
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][QueryDetailPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
/** @var Rocket $rocket */
|
||||
$rocket = $next($rocket);
|
||||
|
||||
Logger::debug('[Wechat][Extend][Complaints][QueryDetailPlugin] 插件开始后置装载', ['rocket' => $rocket]);
|
||||
|
||||
$destination = $rocket->getDestination();
|
||||
|
||||
if ($destination instanceof Collection && !empty($payerPhone = $destination->get('payer_phone'))) {
|
||||
$decryptPayerPhone = decrypt_wechat_contents($payerPhone, get_wechat_config($rocket->getParams()));
|
||||
|
||||
if (empty($decryptPayerPhone)) {
|
||||
throw new InvalidConfigException(Exception::DECRYPT_WECHAT_ENCRYPTED_CONTENTS_INVALID, '参数异常: 查询投诉单详情,参数 `payer_phone` 解密失败');
|
||||
}
|
||||
|
||||
$destination->set('payer_phone', $decryptPayerPhone);
|
||||
}
|
||||
|
||||
Logger::debug('[Wechat][Extend][Complaints][QueryDetailPlugin] 插件后置装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $rocket;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ use Yansongda\Pay\Provider\Wechat;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Supports\Str;
|
||||
use function Yansongda\Pay\decrypt_wechat_contents;
|
||||
use function Yansongda\Pay\decrypt_wechat_resource;
|
||||
use function Yansongda\Pay\decrypt_wechat_resource_aes_256_gcm;
|
||||
use function Yansongda\Pay\encrypt_wechat_contents;
|
||||
@ -316,6 +317,16 @@ class FunctionTest extends TestCase
|
||||
self::assertIsString($result);
|
||||
}
|
||||
|
||||
public function testDecryptWechatContents()
|
||||
{
|
||||
$encrypted = 'WIesmK+dSJycwdhTTkNmv0Lk2wb9o7NGODovccjhyotNnRkEeh+sxRK1gNSRNMJJgkQ30m4HwcuweSO24mehFeXVNTVAKFVef/3FlHnYDZfE1c3mCLToEef7e8J/Z8TwFH1ecn3t+Jk9ZaBpQKNHdQ0Q8jcL7AnL48h0D9BcZxDekPqX6hNnKfISoKSv4TXFcgvBLFeAe4Q3KM0Snq0N5IvI86D9xZqVg6mY+Gfz0782ymQFxflau6Qxx3mJ+0etHMocNuCdgctVH390XYYMc0u+V2FCJ5cU5h/M/AxzP9ayrEO4l0ftaxL6lP0HjifNrkPcAAb+q9I67UepKO9iGw==';
|
||||
|
||||
$config = get_wechat_config();
|
||||
|
||||
self::assertEquals('yansongda', decrypt_wechat_contents($encrypted, $config));
|
||||
self::assertNull(decrypt_wechat_contents('invalid', $config));
|
||||
}
|
||||
|
||||
public function testReloadWechatPublicCerts()
|
||||
{
|
||||
$response = new Response(
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace Yansongda\Pay\Tests\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\Extend\Complaints\QueryDetailPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
@ -48,4 +49,50 @@ class QueryDetailPluginTest extends TestCase
|
||||
'_service_url' => 'v3/merchant-service/complaints-v2/yansongda',
|
||||
], $result->getPayload()->all());
|
||||
}
|
||||
|
||||
public function testNormalWithEncryptedContents()
|
||||
{
|
||||
$payload = [
|
||||
"complaint_id" => "yansongda",
|
||||
];
|
||||
|
||||
$rocket = new Rocket();
|
||||
$rocket->setPayload(new Collection($payload));
|
||||
|
||||
$result = $this->plugin->assembly($rocket, function ($rocket) {
|
||||
$rocket->setDestination(new Collection([
|
||||
'payer_phone' => 'WIesmK+dSJycwdhTTkNmv0Lk2wb9o7NGODovccjhyotNnRkEeh+sxRK1gNSRNMJJgkQ30m4HwcuweSO24mehFeXVNTVAKFVef/3FlHnYDZfE1c3mCLToEef7e8J/Z8TwFH1ecn3t+Jk9ZaBpQKNHdQ0Q8jcL7AnL48h0D9BcZxDekPqX6hNnKfISoKSv4TXFcgvBLFeAe4Q3KM0Snq0N5IvI86D9xZqVg6mY+Gfz0782ymQFxflau6Qxx3mJ+0etHMocNuCdgctVH390XYYMc0u+V2FCJ5cU5h/M/AxzP9ayrEO4l0ftaxL6lP0HjifNrkPcAAb+q9I67UepKO9iGw==',
|
||||
]));
|
||||
|
||||
return $rocket;
|
||||
});
|
||||
|
||||
self::assertEquals([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/merchant-service/complaints-v2/yansongda',
|
||||
'_service_url' => 'v3/merchant-service/complaints-v2/yansongda',
|
||||
], $result->getPayload()->all());
|
||||
self::assertEquals('yansongda', $result->getDestination()->all()['payer_phone']);
|
||||
}
|
||||
|
||||
public function testNormalWithEncryptedContentsWrong()
|
||||
{
|
||||
$payload = [
|
||||
"complaint_id" => "yansongda",
|
||||
];
|
||||
|
||||
$rocket = new Rocket();
|
||||
$rocket->setPayload(new Collection($payload));
|
||||
|
||||
self::expectException(InvalidConfigException::class);
|
||||
self::expectExceptionCode(Exception::DECRYPT_WECHAT_ENCRYPTED_CONTENTS_INVALID);
|
||||
|
||||
$this->plugin->assembly($rocket, function ($rocket) {
|
||||
$rocket->setDestination(new Collection([
|
||||
'payer_phone' => 'invalid',
|
||||
]));
|
||||
|
||||
return $rocket;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user