diff --git a/CHANGELOG.md b/CHANGELOG.md index fc98e69d2..8411cf3ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ -## TBD - v3.7.5 +## v3.7.5 + +### fixed + +- fix: 支付宝响应空签名时签名验证逻辑错误的问题(#998) ### optimized diff --git a/src/Exception/Exception.php b/src/Exception/Exception.php index 1085168ff..73801209e 100644 --- a/src/Exception/Exception.php +++ b/src/Exception/Exception.php @@ -44,6 +44,8 @@ class Exception extends \Exception public const RESPONSE_MISSING_NECESSARY_PARAMS = 9305; + public const RESPONSE_BUSINESS_CODE_WRONG = 9306; + /* * 关于配置. */ diff --git a/src/Plugin/Alipay/V2/ResponsePlugin.php b/src/Plugin/Alipay/V2/ResponsePlugin.php index 5ceafa7e8..36f2870e6 100644 --- a/src/Plugin/Alipay/V2/ResponsePlugin.php +++ b/src/Plugin/Alipay/V2/ResponsePlugin.php @@ -6,14 +6,19 @@ use Closure; use Yansongda\Artful\Contract\PluginInterface; +use Yansongda\Artful\Exception\InvalidResponseException; use Yansongda\Artful\Logger; use Yansongda\Artful\Rocket; +use Yansongda\Pay\Exception\Exception; use Yansongda\Supports\Collection; use function Yansongda\Artful\should_do_http_request; class ResponsePlugin implements PluginInterface { + /** + * @throws InvalidResponseException + */ public function assembly(Rocket $rocket, Closure $next): Rocket { /* @var Rocket $rocket */ @@ -26,9 +31,16 @@ public function assembly(Rocket $rocket, Closure $next): Rocket $resultKey = str_replace('.', '_', $payload->get('method')).'_response'; if (should_do_http_request($rocket->getDirection()) && $destination instanceof Collection) { + $sign = $destination->get('sign', ''); + $response = $destination->get($resultKey, $destination->all()); + + if (empty($sign) && '10000' !== ($response['code'] ?? 'null')) { + throw new InvalidResponseException(Exception::RESPONSE_BUSINESS_CODE_WRONG, '支付宝网关响应异常: '.($response['sub_msg'] ?? $response['msg'] ?? '未知错误,请查看支付宝原始响应'), $rocket->getDestination()); + } + $rocket->setDestination(new Collection(array_merge( - ['_sign' => $destination->get('sign', '')], - $destination->get($resultKey, $destination->all()) + ['_sign' => $sign], + $response ))); } diff --git a/tests/Plugin/Alipay/V2/ResponsePluginTest.php b/tests/Plugin/Alipay/V2/ResponsePluginTest.php index db93a5db1..951b990ad 100644 --- a/tests/Plugin/Alipay/V2/ResponsePluginTest.php +++ b/tests/Plugin/Alipay/V2/ResponsePluginTest.php @@ -2,6 +2,8 @@ namespace Yansongda\Pay\Tests\Plugin\Alipay\V2; +use Yansongda\Artful\Exception\InvalidResponseException; +use Yansongda\Pay\Exception\Exception; use Yansongda\Pay\Plugin\Alipay\V2\ResponsePlugin; use Yansongda\Artful\Rocket; use Yansongda\Pay\Tests\TestCase; @@ -82,4 +84,27 @@ public function testErrorResponseWithNoMethodKey() self::assertEquals(array_merge(['_sign' => '123'], $destination), $result->getDestination()->all()); } + + public function testErrorResponseWithEmptySignKey() + { + self::expectException(InvalidResponseException::class); + self::expectExceptionCode(Exception::RESPONSE_BUSINESS_CODE_WRONG); + self::expectExceptionMessage('支付宝网关响应异常: 无效的AppID参数'); + + $destination = [ + 'alipay_fund_trans_uni_transfer_response' => [ + 'code' => '40002', + 'msg' => 'Invalid Arguments', + 'sub_code' => 'isv.invalid-app-id', + 'sub_msg' => '无效的AppID参数', + ], + 'sign' => '' + ]; + + $rocket = (new Rocket()) + ->mergePayload(['method' => 'alipay_fund_trans_uni_transfer']) + ->setDestination(new Collection($destination)); + + $this->plugin->assembly($rocket, function ($rocket) {return $rocket; }); + } }