123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- <?php
- declare(strict_types=1);
- namespace Yansongda\Pay\Provider;
- use GuzzleHttp\Psr7\Utils;
- use Psr\Http\Client\ClientInterface;
- use Psr\Http\Message\MessageInterface;
- use Throwable;
- use Yansongda\Pay\Contract\HttpClientInterface;
- use Yansongda\Pay\Contract\PluginInterface;
- use Yansongda\Pay\Contract\ProviderInterface;
- use Yansongda\Pay\Contract\ShortcutInterface;
- use Yansongda\Pay\Direction\ArrayDirection;
- use Yansongda\Pay\Event;
- use Yansongda\Pay\Exception\ContainerException;
- use Yansongda\Pay\Exception\Exception;
- use Yansongda\Pay\Exception\InvalidConfigException;
- use Yansongda\Pay\Exception\InvalidParamsException;
- use Yansongda\Pay\Exception\InvalidResponseException;
- use Yansongda\Pay\Exception\ServiceNotFoundException;
- use Yansongda\Pay\Logger;
- use Yansongda\Pay\Pay;
- use Yansongda\Pay\Rocket;
- use Yansongda\Supports\Collection;
- use Yansongda\Supports\Pipeline;
- use function Yansongda\Pay\should_do_http_request;
- abstract class AbstractProvider implements ProviderInterface
- {
- /**
- * @return null|array|Collection|MessageInterface
- *
- * @throws ContainerException
- * @throws InvalidParamsException
- * @throws ServiceNotFoundException
- */
- public function call(string $plugin, array $params = [])
- {
- if (!class_exists($plugin) || !in_array(ShortcutInterface::class, class_implements($plugin))) {
- throw new InvalidParamsException(Exception::SHORTCUT_NOT_FOUND, "[{$plugin}] is not incompatible");
- }
- /* @var ShortcutInterface $money */
- $money = Pay::get($plugin);
- $plugins = $money->getPlugins($params);
- if (empty($params['_no_common_plugins'])) {
- $plugins = $this->mergeCommonPlugins($plugins);
- }
- return $this->pay($plugins, $params);
- }
- /**
- * @return null|array|Collection|MessageInterface
- *
- * @throws ContainerException
- * @throws InvalidParamsException
- */
- public function pay(array $plugins, array $params)
- {
- Logger::info('[AbstractProvider] 即将进行 pay 操作', func_get_args());
- Event::dispatch(new Event\PayStarted($plugins, $params, null));
- $this->verifyPlugin($plugins);
- /* @var Pipeline $pipeline */
- $pipeline = Pay::make(Pipeline::class);
- /* @var Rocket $rocket */
- $rocket = $pipeline
- ->send((new Rocket())->setParams($params)->setPayload(new Collection()))
- ->through($plugins)
- ->via('assembly')
- ->then(fn ($rocket) => $this->ignite($rocket))
- ;
- Event::dispatch(new Event\PayFinish($rocket));
- $destination = $rocket->getDestination();
- if (ArrayDirection::class === $rocket->getDirection() && $destination instanceof Collection) {
- return $destination->toArray();
- }
- return $destination;
- }
- /**
- * @throws ContainerException
- * @throws ServiceNotFoundException
- * @throws InvalidResponseException
- * @throws InvalidConfigException
- */
- public function ignite(Rocket $rocket): Rocket
- {
- if (!should_do_http_request($rocket->getDirection())) {
- return $rocket;
- }
- /* @var HttpClientInterface $http */
- $http = Pay::get(HttpClientInterface::class);
- if (!$http instanceof ClientInterface) {
- throw new InvalidConfigException(Exception::HTTP_CLIENT_CONFIG_ERROR);
- }
- Logger::info('[AbstractProvider] 准备请求支付服务商 API', $rocket->toArray());
- Event::dispatch(new Event\ApiRequesting($rocket));
- try {
- $response = $http->sendRequest($rocket->getRadar());
- $contents = (string) $response->getBody();
- $rocket->setDestination($response->withBody(Utils::streamFor($contents)))
- ->setDestinationOrigin($response->withBody(Utils::streamFor($contents)))
- ;
- } catch (Throwable $e) {
- Logger::error('[AbstractProvider] 请求支付服务商 API 出错', ['message' => $e->getMessage(), 'rocket' => $rocket->toArray(), 'trace' => $e->getTrace()]);
- throw new InvalidResponseException(Exception::REQUEST_RESPONSE_ERROR, $e->getMessage(), [], $e);
- }
- Logger::info('[AbstractProvider] 请求支付服务商 API 成功', ['response' => $response, 'rocket' => $rocket->toArray()]);
- Event::dispatch(new Event\ApiRequested($rocket));
- return $rocket;
- }
- abstract public function mergeCommonPlugins(array $plugins): array;
- /**
- * @throws InvalidParamsException
- */
- protected function verifyPlugin(array $plugins): void
- {
- foreach ($plugins as $plugin) {
- if (is_callable($plugin)) {
- continue;
- }
- if ((is_object($plugin)
- || (is_string($plugin) && class_exists($plugin)))
- && in_array(PluginInterface::class, class_implements($plugin))) {
- continue;
- }
- throw new InvalidParamsException(Exception::PLUGIN_ERROR, "[{$plugin}] is not incompatible");
- }
- }
- }
|