-
Notifications
You must be signed in to change notification settings - Fork 0
[QRD-7899] feat(configuration-webhook): add affiliate config topic #64
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
base: master
Are you sure you want to change the base?
Changes from all commits
65decde
ed1716a
e4f14cf
2c4f05c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,8 @@ | |
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Controller\ConfigurationWebhookController; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\GetAdvancedSettingsHandler; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\AdvancedSettings\SaveAdvancedSettingsHandler; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Affiliate\GetAffiliateSettingsHandler; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Affiliate\SaveAffiliateSettingsHandler; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\GetBannerSettingsHandler; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\BannerSettings\SaveBannerSettingsHandler; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Enums\Topics; | ||
|
|
@@ -40,6 +42,8 @@ | |
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\WidgetSettings\SaveWidgetSettingsHandler; | ||
| use SeQura\Core\BusinessLogic\DataAccess\AdvancedSettings\Entities\AdvancedSettings; | ||
| use SeQura\Core\BusinessLogic\DataAccess\AdvancedSettings\Repositories\AdvancedSettingsRepository; | ||
| use SeQura\Core\BusinessLogic\DataAccess\Affiliate\Entities\AffiliateSettings; | ||
| use SeQura\Core\BusinessLogic\DataAccess\Affiliate\Repositories\AffiliateSettingsRepository; | ||
| use SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Entities\BannerSettings; | ||
| use SeQura\Core\BusinessLogic\DataAccess\BannerSettings\Repositories\BannerSettingsRepository; | ||
| use SeQura\Core\BusinessLogic\DataAccess\ConnectionData\Entities\ConnectionData; | ||
|
|
@@ -67,6 +71,8 @@ | |
| use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\RepositoryContracts\AdvancedSettingsRepositoryInterface; | ||
| use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedLoggerSettingsProvider; | ||
| use SeQura\Core\BusinessLogic\Domain\AdvancedSettings\Services\AdvancedSettingsService; | ||
| use SeQura\Core\BusinessLogic\Domain\Affiliate\RepositoryContracts\AffiliateSettingsRepositoryInterface; | ||
| use SeQura\Core\BusinessLogic\Domain\Affiliate\Services\AffiliateSettingsService; | ||
| use SeQura\Core\BusinessLogic\Domain\BannerSettings\RepositoryContracts\BannerSettingsRepositoryInterface; | ||
| use SeQura\Core\BusinessLogic\Domain\BannerSettings\Services\BannerSettingsService; | ||
| use SeQura\Core\BusinessLogic\Domain\Integration\Banner\BannerServiceInterface; | ||
|
|
@@ -332,6 +338,16 @@ static function () { | |
| ); | ||
| } | ||
| ); | ||
|
|
||
| ServiceRegister::registerService( | ||
| AffiliateSettingsRepositoryInterface::class, | ||
| static function () { | ||
| return new AffiliateSettingsRepository( | ||
| RepositoryRegistry::getRepository(AffiliateSettings::getClassName()), | ||
| ServiceRegister::getService(StoreContext::class) | ||
| ); | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -384,7 +400,8 @@ static function () { | |
| ServiceRegister::getService(ConnectionProxyInterface::class), | ||
| ServiceRegister::getService(CredentialsRepositoryInterface::class), | ||
| ServiceRegister::getService(CountryConfigurationRepositoryInterface::class), | ||
| ServiceRegister::getService(PaymentMethodRepositoryInterface::class) | ||
| ServiceRegister::getService(PaymentMethodRepositoryInterface::class), | ||
| ServiceRegister::getService(AffiliateSettingsService::class) | ||
| ); | ||
| } | ||
| ); | ||
|
|
@@ -667,6 +684,15 @@ static function () { | |
| } | ||
| ); | ||
|
|
||
| ServiceRegister::registerService( | ||
| AffiliateSettingsService::class, | ||
| static function () { | ||
| return new AffiliateSettingsService( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outbound side isn't wired in the core. Only the inbound config services are registered here. The conversion/cancellation postbacks the plugin emits are owned by the core as well (the plugin must not make HTTP calls directly), but there's no affiliate proxy under Include the outbound affiliate proxy here, or split it into the immediate next core change and link it — but it shouldn't be left implicit, since the consumer plugin is already blocked on it.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed this belongs in the core, but I would keep it out of this PR and ship it as the immediate follow up. Reasoning: this PR is the inbound config half, which is what unblocks the plugin, and the outbound proxy also depends on timon phase 2 routing, so coupling them would hold back config delivery. I will open the follow up for the affiliate proxy under
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Follow up created: QRD-7949 (https://sequra.atlassian.net/browse/QRD-7949), the integration-core outbound AffiliateProxy, sibling of QRD-7933 (timon Phase 2). Keeping it out of this PR so the inbound config can merge and tag v5.5.0. |
||
| ServiceRegister::getService(AffiliateSettingsRepositoryInterface::class) | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| ServiceRegister::registerService( | ||
| LoggerSettingsProviderInterface::CLASS_NAME, | ||
| static function () { | ||
|
|
@@ -1056,6 +1082,16 @@ protected static function initTopicHandlers(): void | |
| SaveAdvancedSettingsHandler::class | ||
| ); | ||
|
|
||
| TopicHandlerRegistry::register( | ||
| Topics::GET_AFFILIATE_SETTINGS, | ||
| GetAffiliateSettingsHandler::class | ||
| ); | ||
|
|
||
| TopicHandlerRegistry::register( | ||
| Topics::SAVE_AFFILIATE_SETTINGS, | ||
| SaveAffiliateSettingsHandler::class | ||
| ); | ||
|
|
||
| TopicHandlerRegistry::register( | ||
| Topics::GET_BANNER_SETTINGS, | ||
| GetBannerSettingsHandler::class | ||
|
|
@@ -1189,6 +1225,24 @@ static function () { | |
| } | ||
| ); | ||
|
|
||
| ServiceRegister::registerService( | ||
| GetAffiliateSettingsHandler::class, | ||
| static function () { | ||
| return new GetAffiliateSettingsHandler( | ||
| ServiceRegister::getService(AffiliateSettingsService::class) | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| ServiceRegister::registerService( | ||
| SaveAffiliateSettingsHandler::class, | ||
| static function () { | ||
| return new SaveAffiliateSettingsHandler( | ||
| ServiceRegister::getService(AffiliateSettingsService::class) | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| ServiceRegister::registerService( | ||
| GetBannerSettingsHandler::class, | ||
| static function () { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| <?php | ||
|
|
||
| namespace SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Affiliate; | ||
|
|
||
| use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\TopicHandlerInterface; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\Affiliate\AffiliateSettingsResponse; | ||
| use SeQura\Core\BusinessLogic\Domain\Affiliate\Services\AffiliateSettingsService; | ||
|
|
||
| /** | ||
| * Class GetAffiliateSettingsHandler | ||
| * | ||
| * @package SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Affiliate | ||
| */ | ||
| class GetAffiliateSettingsHandler implements TopicHandlerInterface | ||
| { | ||
| /** | ||
| * @var AffiliateSettingsService | ||
| */ | ||
| protected $affiliateSettingsService; | ||
|
|
||
| /** | ||
| * @param AffiliateSettingsService $affiliateSettingsService | ||
| */ | ||
| public function __construct(AffiliateSettingsService $affiliateSettingsService) | ||
| { | ||
| $this->affiliateSettingsService = $affiliateSettingsService; | ||
| } | ||
|
|
||
| /** | ||
| * @param mixed[] $payload | ||
| * | ||
| * @return Response | ||
| */ | ||
| public function handle(array $payload): Response | ||
| { | ||
| // GET is a boolean-state read: return only whether the feature is enabled, never echo the | ||
| // offer id or security token. The service always yields settings (disabled by default when | ||
| // none are stored), so the response is enabled=false when nothing is configured. | ||
| return new AffiliateSettingsResponse($this->affiliateSettingsService->getAffiliateSettings()->isEnabled()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| <?php | ||
|
|
||
| namespace SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Affiliate; | ||
|
|
||
| use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\TopicHandlerInterface; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Requests\Affiliate\SaveAffiliateSettingsRequest; | ||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\SuccessResponse; | ||
| use SeQura\Core\BusinessLogic\Domain\Affiliate\Services\AffiliateSettingsService; | ||
|
|
||
| /** | ||
| * Class SaveAffiliateSettingsHandler | ||
| * | ||
| * @package SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Handlers\Affiliate | ||
| */ | ||
| class SaveAffiliateSettingsHandler implements TopicHandlerInterface | ||
| { | ||
| /** | ||
| * @var AffiliateSettingsService | ||
| */ | ||
| protected $affiliateSettingsService; | ||
|
|
||
| /** | ||
| * @param AffiliateSettingsService $affiliateSettingsService | ||
| */ | ||
| public function __construct(AffiliateSettingsService $affiliateSettingsService) | ||
| { | ||
| $this->affiliateSettingsService = $affiliateSettingsService; | ||
| } | ||
|
|
||
| /** | ||
| * @inheritDoc | ||
| */ | ||
| public function handle(array $payload): Response | ||
| { | ||
| $request = SaveAffiliateSettingsRequest::fromPayload($payload); | ||
| $this->affiliateSettingsService->setAffiliateSettings($request->transformToDomainModel()); | ||
|
|
||
| return new SuccessResponse(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,6 +77,14 @@ interface Topics | |
| * @var string | ||
| */ | ||
| public const GET_STORE_INFO = 'get-store-info'; | ||
| /** | ||
| * @var string | ||
| */ | ||
| public const GET_AFFILIATE_SETTINGS = 'get-affiliate-settings'; | ||
| /** | ||
| * @var string | ||
| */ | ||
| public const SAVE_AFFILIATE_SETTINGS = 'save-affiliate-settings'; | ||
|
Comment on lines
+83
to
+87
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Docs need updating to reflect the new topics + entity. The PR adds the topics but not the matching documentation:
(
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added in 2c4f05c. Both handlers are now listed under TopicHandlerRegistry in the README, and there is a CHANGELOG entry for the affiliate topics, entity and service plus the connect time provisioning. Heads up on your note: the CHANGELOG had drifted, its top was v1.0.13 while the tags reached v5.4.0, so I added the entry as v5.5.0 at the top but the 5.x history in between is still missing. Worth a separate cleanup if the team wants the changelog accurate again. |
||
| /** | ||
| * @var string[] | ||
| */ | ||
|
|
@@ -97,6 +105,8 @@ interface Topics | |
| self::GET_SHOP_CATEGORIES, | ||
| self::GET_SHOP_PRODUCTS, | ||
| self::GET_SELLING_COUNTRIES, | ||
| self::GET_STORE_INFO | ||
| self::GET_STORE_INFO, | ||
| self::GET_AFFILIATE_SETTINGS, | ||
| self::SAVE_AFFILIATE_SETTINGS | ||
| ]; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| <?php | ||
|
|
||
| namespace SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Requests\Affiliate; | ||
|
|
||
| use SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Requests\ConfigurationWebhookRequest; | ||
| use SeQura\Core\BusinessLogic\Domain\Affiliate\Models\AffiliateSettings; | ||
|
|
||
| /** | ||
| * Class SaveAffiliateSettingsRequest. | ||
| * | ||
| * @package SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Requests\Affiliate | ||
| */ | ||
| class SaveAffiliateSettingsRequest extends ConfigurationWebhookRequest | ||
| { | ||
| /** | ||
| * @var bool $isEnabled | ||
| */ | ||
| private $isEnabled; | ||
|
|
||
| /** | ||
| * @var string $offerId | ||
| */ | ||
| private $offerId; | ||
|
|
||
| /** | ||
| * @var string $securityToken | ||
| */ | ||
| private $securityToken; | ||
|
|
||
| /** | ||
| * @param bool $isEnabled | ||
| * @param string $offerId | ||
| * @param string $securityToken | ||
| */ | ||
| public function __construct(bool $isEnabled, string $offerId, string $securityToken) | ||
| { | ||
| $this->isEnabled = $isEnabled; | ||
| $this->offerId = $offerId; | ||
| $this->securityToken = $securityToken; | ||
| } | ||
|
|
||
| /** | ||
| * @param mixed[] $payload | ||
| * | ||
| * @return self | ||
| */ | ||
| public static function fromPayload(array $payload): object | ||
| { | ||
| return new self( | ||
| $payload['isEnabled'] ?? false, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Decision needed — Decide whether the core should require non-empty
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Decided to guard it in the core, in ed1716a. The |
||
| (string)($payload['offerId'] ?? ''), | ||
| (string)($payload['securityToken'] ?? '') | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @return AffiliateSettings | ||
| */ | ||
| public function transformToDomainModel(): AffiliateSettings | ||
| { | ||
| return new AffiliateSettings($this->isEnabled, $this->offerId, $this->securityToken); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| <?php | ||
|
|
||
| namespace SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\Affiliate; | ||
|
|
||
| use SeQura\Core\BusinessLogic\AdminAPI\Response\Response; | ||
|
|
||
| /** | ||
| * Class AffiliateSettingsResponse | ||
| * | ||
| * @package SeQura\Core\BusinessLogic\ConfigurationWebhookAPI\Responses\Affiliate | ||
| */ | ||
| class AffiliateSettingsResponse extends Response | ||
| { | ||
| /** | ||
| * @var bool $isEnabled | ||
| */ | ||
| protected $isEnabled; | ||
|
|
||
| /** | ||
| * @param bool $isEnabled | ||
| */ | ||
| public function __construct(bool $isEnabled) | ||
| { | ||
| $this->isEnabled = $isEnabled; | ||
| } | ||
|
|
||
| /** | ||
| * @inheritDoc | ||
| */ | ||
| public function toArray(): array | ||
| { | ||
| return ['isEnabled' => $this->isEnabled]; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Versioning note: this is a SemVer MINOR and is safe to release as one — no breaking change for existing consumers.
I checked whether updating to this version without a consumer registering the
AffiliateSettingsentity would break existing integrations. It doesn't, because resolution is lazy and per-topic:ConfigurationWebhookController::handleRequest()resolves onlygetHandlerForTopic($topic)for the incoming topic.Topics::ALL_TOPICSisn't iterated anywhere (it's referenced only inTopics.php), so adding the two entries has no eager effect.getHandlerForTopic()→ServiceRegister::getService()runs the handler closure only when that topic actually arrives;initTopicHandlers()/registerService()only register lazy closures at boot.So this
getRepository(AffiliateSettings::getClassName())is reached only when aget/save-affiliate-settingswebhook is handled — which is opt-in (only sent to stores enrolled in the feature). A consumer that bumps without registering the entity boots fine and keeps all existing behaviour; the worst case is a single 500 on an affiliate webhook for an unconfigured store, not a regression of existing functionality.Per SemVer that's a MINOR (additive, backward-compatible) — e.g.
5.2.0on the current5.1.xline. Heads-up for consumers: registering the entity is required to use the feature (an integration step), not to survive the upgrade.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, agreed it is a backward compatible MINOR. Targeting v5.5.0 as the release tag since the tags already reached v5.4.0 (so not 5.2.0). The plugin will register the entity and bump its constraint to that tag when it consumes this.