credentials = $credentials; $this->validator = $validator; } /** * Use as Guzzle middleware * * @param callable $handler * * @return callable */ public function __invoke(callable $handler) { return function (RequestInterface $request, array $options) use ($handler) { if (!self::isWechatPayApiUrl($request->getUri())) { return $handler($request, $options); } $schema = $this->credentials->getSchema(); $token = $this->credentials->getToken($request); $request = $request->withHeader("Authorization", $schema.' '.$token); if (self::isUserAgentOverwritable($request)) { $request = $request->withHeader('User-Agent', self::getUserAgent()); } return $handler($request, $options)->then( function (ResponseInterface $response) use ($request) { $code = $response->getStatusCode(); if ($code >= 200 && $code < 300 && !$this->validator->validate($response)) { if (\class_exists('\\GuzzleHttp\\Exception\\ServerException')) { throw new \GuzzleHttp\Exception\ServerException( "应答的微信支付签名验证失败", $request, $response); } else { throw new \RuntimeException("应答的微信支付签名验证失败", $code); } } return $response; } ); }; } /** * Create a new builder * * @return WechatPayMiddlewareBuilder */ public static function builder() { return new WechatPayMiddlewareBuilder(); } /** * Check whether url is WechatPay API V3 url */ protected static function isWechatPayApiUrl(UriInterface $url) { if ($url->getScheme() !== 'https' || !\in_array($url->getHost(), self::$API_DOMAINS)) { return false; } foreach (self::$BASE_URLS as $baseUrl) { if (\substr($url->getPath(), 0, strlen($baseUrl)) === $baseUrl) { return true; } } return false; } /** * Get User Agent * @return string */ protected static function getUserAgent() { static $userAgent = ''; if (!$userAgent) { $agent = 'WechatPay-Guzzle/'.self::VERSION; if (\class_exists('\\GuzzleHttp\\Client')) { $agent .= ' GuzzleHttp/'.\GuzzleHttp\Client::VERSION; } if (extension_loaded('curl') && function_exists('curl_version')) { $agent .= ' curl/'.\curl_version()['version']; } $agent .= \sprintf(" (%s/%s) PHP/%s", PHP_OS, \php_uname('r'), PHP_VERSION); $userAgent = $agent; } return $userAgent; } private static function isUserAgentOverwritable(RequestInterface $request) { if (!$request->hasHeader('User-Agent')) { return true; } $headers = $request->getHeader('User-Agent'); $userAgent = $headers[\count($headers) - 1]; if (\function_exists('\\GuzzleHttp\\default_user_agent')) { return $userAgent === \GuzzleHttp\default_user_agent(); } return false; } }