-
Notifications
You must be signed in to change notification settings - Fork 19
Feature/pre 3469 #305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
jhoaraupp
wants to merge
11
commits into
develop
Choose a base branch
from
feature/PRE-3469
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Feature/pre 3469 #305
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
690d9f5
PRE-3469: Validate contracts with Sylius
jhoaraupp b97c69d
PRE-3469: Promote unified-plugin-core to a real dependency
jhoaraupp 29b4b8d
PRE-3469: Remove design spec accidentally committed in b97c69d
jhoaraupp e6ad438
PRE-3469: Promote SyliusOrderStateMutator to PayplugOrderStateMutator
jhoaraupp 463c79c
PRE-3469: Promote SyliusTokenCache to PayplugTokenCache
jhoaraupp 753ded3
PRE-3469: Promote SyliusConfigurationRepository to PayplugConfigurati…
jhoaraupp d770af8
PRE-3469: Wire PayplugOrderStateMutator into NotifyPaymentRequestHandler
jhoaraupp 1a89a34
PRE-3469: Fix phpstan error in NotifyPaymentRequestHandler's mutator …
jhoaraupp ddb7742
PRE-3469: Update VALIDATION.md for the promoted contracts
jhoaraupp f0cd2a8
PRE-3469: Add explicit service alias for IOrderStateMutator
jhoaraupp 779530d
PRE-3469: Guard PayplugOrderStateMutator call against multi-payment o…
jhoaraupp File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace PayPlug\SyliusPayPlugPlugin\Migrations; | ||
|
|
||
| use Doctrine\DBAL\Schema\Schema; | ||
| use Doctrine\Migrations\AbstractMigration; | ||
|
|
||
| /** | ||
| * PRE-3469 spike only: schema for the throwaway PayplugOperation entity (src/Spike/Entity). | ||
| * A real migration — not a manual step or a SchemaTool call from the test — because the | ||
| * mapping is registered whenever kernel.environment=test (see | ||
| * PayPlugSyliusPayPlugExtension::prependSpikeDoctrineMapping()), which includes routine | ||
| * `sylius:fixtures:load` runs on a fresh checkout, not just the spike's own integration test. | ||
| * Without this migration, `sylius:fixtures:load` fails for anyone setting up the test | ||
| * application from scratch — found by testing this on a clean database, not by reasoning about | ||
| * it. Guarded to APP_ENV=test in both directions so a real merchant deployment never gets this | ||
| * table created (up) or, if it somehow did, never gets it dropped outside test either (down) — | ||
| * a normal plugin migration otherwise runs unconditionally, including in production. Drop this | ||
| * migration together with src/Spike/ once the spike is closed. | ||
| */ | ||
| final class Version20260720100000 extends AbstractMigration | ||
| { | ||
| public function getDescription(): string | ||
| { | ||
| return 'PRE-3469 spike: add payplug_operation table for the throwaway PayplugOperation entity.'; | ||
| } | ||
|
|
||
| public function up(Schema $schema): void | ||
| { | ||
| $this->skipIf( | ||
| 'test' !== ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null), | ||
| 'PRE-3469 spike-only schema, not applied outside the test environment.', | ||
| ); | ||
|
|
||
| $this->addSql('CREATE TABLE payplug_operation ( | ||
| id INT AUTO_INCREMENT NOT NULL, | ||
| operation_id VARCHAR(255) NOT NULL, | ||
| exec_code VARCHAR(255) NOT NULL, | ||
| outcome VARCHAR(255) NOT NULL, | ||
| amount INT NOT NULL, | ||
| order_id VARCHAR(255) NOT NULL, | ||
| treated TINYINT(1) NOT NULL, | ||
| treated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', | ||
| created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', | ||
| UNIQUE INDEX payplug_operation_id_unique (operation_id), | ||
| INDEX payplug_operation_order_id_idx (order_id), | ||
| PRIMARY KEY(id) | ||
| ) DEFAULT CHARACTER SET UTF8 COLLATE `UTF8_unicode_ci` ENGINE = InnoDB'); | ||
| } | ||
|
|
||
| public function down(Schema $schema): void | ||
| { | ||
| $this->skipIf( | ||
| 'test' !== ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null), | ||
| 'PRE-3469 spike-only schema, not applied outside the test environment.', | ||
| ); | ||
|
|
||
| $this->addSql('DROP TABLE payplug_operation'); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
src/ConfigurationRepository/PayplugConfigurationRepository.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace PayPlug\SyliusPayPlugPlugin\ConfigurationRepository; | ||
|
|
||
| use PayplugUnifiedCore\Contracts\IConfigurationRepository; | ||
| use PayplugUnifiedCore\Exceptions\ApiException; | ||
| use Sylius\Component\Payment\Model\GatewayConfigInterface; | ||
|
|
||
| /** | ||
| * PRE-3469: real implementation of IConfigurationRepository against Sylius's | ||
| * GatewayConfigInterface. | ||
| * | ||
| * IConfigurationRepository assumes one flat set of credentials, but Sylius scopes gateway | ||
| * config per PaymentMethod *and* per live/test mode (`config['live_client']` vs | ||
| * `config['test_client']`, selected by `config['live']`, exactly as PayPlugApiClientFactory | ||
| * already does). So a single PayplugConfigurationRepository instance has to be constructed per | ||
| * GatewayConfigInterface (i.e. per PaymentMethod) rather than shared as one repository-wide | ||
| * service — a factory, not a singleton. Not blocking, but worth flagging if the Unified API | ||
| * client this feeds ever assumes one repository == one merchant. | ||
| * | ||
| * getPublicKeyId()/getPublicKeyValue() default to an empty string rather than throwing: unlike | ||
| * client_id/client_secret, no production code writes public_key_id/public_key_value yet | ||
| * (Hosted Fields isn't built) — requiring them would make the contract unimplementable until a | ||
| * future ticket adds that writer. | ||
| * | ||
| * Sylius already ships an (experimental) GatewayConfigEncrypter that transparently encrypts the | ||
| * whole `getConfig()` array at rest (Sylius\Component\Payment\Encryption) — if wired up, | ||
| * CLIENT_SECRET benefits from that for free. What this class must still guarantee on its own is | ||
| * that a *decrypted* secret never leaks into a log line or exception message, which is why | ||
| * requireString() below only ever interpolates the config *key name*, never its value. | ||
| */ | ||
| final class PayplugConfigurationRepository implements IConfigurationRepository | ||
| { | ||
| public function __construct(private readonly GatewayConfigInterface $gatewayConfig) | ||
| { | ||
| } | ||
|
|
||
| public function get(string $key): ?string | ||
| { | ||
| $client = $this->activeClientConfig(); | ||
| $value = $client[$key] ?? null; | ||
|
|
||
| return \is_string($value) ? $value : null; | ||
| } | ||
|
|
||
| public function set(string $key, string $value): void | ||
| { | ||
| $config = $this->gatewayConfig->getConfig(); | ||
| $scope = $this->activeScope($config); | ||
| $client = $config[$scope] ?? []; | ||
| if (!\is_array($client)) { | ||
| $client = []; | ||
| } | ||
| $client[$key] = $value; | ||
| $config[$scope] = $client; | ||
|
|
||
| // Persisting $config is the caller's responsibility (Doctrine flush), same as every | ||
| // other GatewayConfigInterface mutation in this plugin (see UnifiedAuthenticationController). | ||
| $this->gatewayConfig->setConfig($config); | ||
| } | ||
|
|
||
| public function getClientId(): string | ||
| { | ||
| return $this->requireString('client_id'); | ||
| } | ||
|
|
||
| public function getClientSecret(): string | ||
| { | ||
| return $this->requireString('client_secret'); | ||
| } | ||
|
|
||
| public function getPublicKeyId(): string | ||
| { | ||
| return $this->get('public_key_id') ?? ''; | ||
| } | ||
|
|
||
| public function getPublicKeyValue(): string | ||
| { | ||
| return $this->get('public_key_value') ?? ''; | ||
| } | ||
|
|
||
| private function requireString(string $key): string | ||
| { | ||
| $value = $this->get($key); | ||
| if (null === $value || '' === $value) { | ||
| // Never interpolate the resolved *value* here, only the key name and factory name. | ||
| throw new ApiException(\sprintf( | ||
| 'Missing "%s" in gateway configuration "%s".', | ||
| $key, | ||
| $this->gatewayConfig->getFactoryName() ?? 'unknown', | ||
| )); | ||
| } | ||
|
|
||
| return $value; | ||
| } | ||
|
|
||
| /** | ||
| * @return array<string, mixed> | ||
| */ | ||
| private function activeClientConfig(): array | ||
| { | ||
| $config = $this->gatewayConfig->getConfig(); | ||
| $client = $config[$this->activeScope($config)] ?? []; | ||
| if (!\is_array($client)) { | ||
| return []; | ||
| } | ||
|
|
||
| /** @var array<string, mixed> $typedClient */ | ||
| $typedClient = $client; | ||
|
|
||
| return $typedClient; | ||
| } | ||
|
|
||
| /** | ||
| * @param array<string, mixed> $config | ||
| */ | ||
| private function activeScope(array $config): string | ||
| { | ||
| return true === ($config['live'] ?? false) ? 'live_client' : 'test_client'; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.