diff --git a/src/Builders/BodyBuilder.php b/src/Builders/RequestBodyBuilder.php similarity index 69% rename from src/Builders/BodyBuilder.php rename to src/Builders/RequestBodyBuilder.php index 66d0fea..6cae228 100644 --- a/src/Builders/BodyBuilder.php +++ b/src/Builders/RequestBodyBuilder.php @@ -4,25 +4,32 @@ use IPay\Encryption\Encryptor; use Nette\Utils\Json; -use Nette\Utils\Random; /** * @psalm-type ValueType = string|int * @psalm-type ParametersType = array */ -final class BodyBuilder implements \Stringable, \JsonSerializable +final class RequestBodyBuilder implements \Stringable, \JsonSerializable { /** * @param ParametersType $parameters */ - public function __construct( + private function __construct( private array $parameters = [], ) { } - public function setSessionId(string $value): void + public static function new(): self { - $this->parameters['sessionId'] = $value; + return new self(); + } + + /** + * @param ParametersType $parameters + */ + public function enhance(array $parameters): self + { + return new self($parameters); } /** @@ -30,10 +37,7 @@ public function setSessionId(string $value): void */ public function build(array $parameters = []): self { - $data = array_merge([ - 'lang' => 'en', - 'requestId' => Random::generate(12, '0-9A-Z').'|'.time(), - ], $this->parameters, $parameters); + $data = array_merge($this->parameters, $parameters); ksort($data); $data['signature'] = md5(http_build_query($data)); diff --git a/src/Builders/TransactionBuilder.php b/src/Builders/TransactionBuilder.php index 751f59f..e347d82 100644 --- a/src/Builders/TransactionBuilder.php +++ b/src/Builders/TransactionBuilder.php @@ -6,7 +6,7 @@ use IPay\ValueObjects\Transaction; /** - * @psalm-import-type ParametersType from BodyBuilder + * @psalm-import-type ParametersType from RequestBodyBuilder * * @implements \IteratorAggregate */ diff --git a/src/IPayClient.php b/src/IPayClient.php index 6a6a78f..cea63be 100644 --- a/src/IPayClient.php +++ b/src/IPayClient.php @@ -13,7 +13,7 @@ use Http\Client\Common\PluginClient; use Http\Discovery\Psr17FactoryDiscovery; use Http\Discovery\Psr18ClientDiscovery; -use IPay\Builders\BodyBuilder; +use IPay\Builders\RequestBodyBuilder; use IPay\Builders\TransactionBuilder; use IPay\Captcha\CaptchaSolver; use IPay\Contracts\AbstractApi; @@ -26,7 +26,7 @@ use Symfony\Component\VarExporter\LazyGhostTrait; /** - * @phpstan-import-type ParametersType from BodyBuilder + * @phpstan-import-type ParametersType from RequestBodyBuilder */ final class IPayClient extends AbstractApi { @@ -37,9 +37,7 @@ final class IPayClient extends AbstractApi */ public static function fromCredentials(string $username, string $password): AbstractApi { - return new self( - $username, - $password, + $client = (new self( new HttpMethodsClient( new PluginClient(Psr18ClientDiscovery::find(), [ new BaseUriPlugin( @@ -52,30 +50,37 @@ public static function fromCredentials(string $username, string $password): Abst Psr17FactoryDiscovery::findRequestFactory(), Psr17FactoryDiscovery::findStreamFactory(), ), - ); + ))->login($username, $password); + + return $client; } + /** + * @param ParametersType $authenticatedParameters + */ private function __construct( - string $username, - string $password, private HttpMethodsClientInterface $client, - private BodyBuilder $bodyBuilder = new BodyBuilder(), + private array $authenticatedParameters = [], private ObjectMapper $objectMapper = new ObjectMapperUsingReflection( new DefinitionProvider( keyFormatter: new KeyFormatterWithoutConversion(), ), ), ) { + if ($authenticatedParameters) { + self::createLazyGhost( + initializer: $this->populateLazyProperties(...), + instance: $this, + ); + } + } + + private function login(string $userName, string $accessCode): self + { /** @var array{sessionId: string, ...} */ - $response = $this->post('signIn', [ - 'userName' => $username, - 'accessCode' => $password, - ] + $this->bypassCaptcha()); - $bodyBuilder->setSessionId($response['sessionId']); - self::createLazyGhost( - initializer: $this->populateLazyProperties(...), - instance: $this, - ); + $response = $this->post('signIn', get_defined_vars() + $this->bypassCaptcha()); + + return new self($this->client, ['sessionId' => $response['sessionId']]); } private function populateLazyProperties(): void @@ -143,12 +148,26 @@ private function post(string $uri, array $parameters = []): array $response = $this->client->post( sprintf('ipay/wa/%s', $uri), [], - $this->bodyBuilder->build($parameters)->encrypt(), + RequestBodyBuilder::new() + ->enhance($this->getRequiredParameters()) + ->build($parameters) + ->encrypt(), ); return Json::decode((string) $response->getBody(), true); } + /** + * @return ParametersType + */ + private function getRequiredParameters(): array + { + return array_merge([ + 'lang' => 'en', + 'requestId' => Random::generate(12, '0-9A-Z').'|'.time(), + ], $this->authenticatedParameters); + } + /** * @return array{captchaId:string,captchaCode:string} */