diff --git a/CHANGELOG.md b/CHANGELOG.md index 55d368b..fd4d726 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# 7.1.2 +- Support the ability to have different spaces for differet sales channels +- Fixed issue where Twint would not appear sometimes + +# 7.1.1 +- Updated documentation +- Fixed issue with addresses not being correctly synced + # 7.1.0 ## Feature - Support subscription payment methods diff --git a/CHANGELOG_de-DE.md b/CHANGELOG_de-DE.md index c9edd2d..75bbf3e 100644 --- a/CHANGELOG_de-DE.md +++ b/CHANGELOG_de-DE.md @@ -1,3 +1,11 @@ +# 7.1.2 +- Unterstützung der Möglichkeit, unterschiedliche Bereiche für verschiedene Vertriebskanäle zu nutzen. +- Problem behoben, bei dem Twint manchmal nicht angezeigt wurde. + +# 7.1.1 +- Dokumentation aktualisiert +- Problem behoben, bei dem Adressen nicht korrekt synchronisiert wurden. + # 7.1.0 – Unterstützung für Abonnement-Zahlungsmethoden – Support für Shopware 6.7.2.0 diff --git a/README.md b/README.md index a340e4a..e457220 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,10 @@ Please note that this plugin is for versions 6.5, 6.6 or 6.7. For the 6.4 plugin ## Documentation -- For English documentation click [here](@WalleeDocPath(/docs/en/documentation.html)) -- Für die deutsche Dokumentation klicken Sie [hier](@WalleeDocPath(/docs/de/documentation.html)) -- Pour la documentation Française, cliquez [ici](@WalleeDocPath(/docs/fr/documentation.html)) -- Per la documentazione in tedesco, clicca [qui](@WalleeDocPath(/docs/it/documentation.html)) +- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.2/docs/en/documentation.html) +- Für die deutsche Dokumentation klicken Sie [hier](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.2/docs/de/documentation.html) +- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.2/docs/fr/documentation.html) +- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.2/docs/it/documentation.html) ## Installation diff --git a/composer.json b/composer.json index 9369199..6c0fd35 100644 --- a/composer.json +++ b/composer.json @@ -59,5 +59,5 @@ "vrpayment/sdk": "^4.0.0" }, "type": "shopware-platform-plugin", - "version": "7.1.1" + "version": "7.1.2" } diff --git a/docs/de/documentation.html b/docs/de/documentation.html index 62f6995..bfa1354 100644 --- a/docs/de/documentation.html +++ b/docs/de/documentation.html @@ -5,7 +5,7 @@ - + VR Payment Zahlungs-Plugin für Shopware 6 @@ -23,7 +23,7 @@
  • - + Source
  • diff --git a/docs/en/documentation.html b/docs/en/documentation.html index 7bb4681..cf691e6 100644 --- a/docs/en/documentation.html +++ b/docs/en/documentation.html @@ -5,7 +5,7 @@ - + VR Payment Shopware 6 Documentation @@ -23,7 +23,7 @@
  • - + Source
  • diff --git a/docs/fr/documentation.html b/docs/fr/documentation.html index a4acd00..25bcab2 100644 --- a/docs/fr/documentation.html +++ b/docs/fr/documentation.html @@ -5,7 +5,7 @@ - + VR Payment Plugin pour Shopware 6 @@ -23,7 +23,7 @@
  • - + Source
  • diff --git a/docs/it/documentation.html b/docs/it/documentation.html index 89f4e60..c9b5751 100644 --- a/docs/it/documentation.html +++ b/docs/it/documentation.html @@ -5,7 +5,7 @@ - + VR Payment Shopware 6 Documentation @@ -23,7 +23,7 @@
  • - + Source
  • diff --git a/src/Core/Api/PaymentMethodConfiguration/Service/PaymentMethodConfigurationService.php b/src/Core/Api/PaymentMethodConfiguration/Service/PaymentMethodConfigurationService.php index 60ec19b..223eb2c 100644 --- a/src/Core/Api/PaymentMethodConfiguration/Service/PaymentMethodConfigurationService.php +++ b/src/Core/Api/PaymentMethodConfiguration/Service/PaymentMethodConfigurationService.php @@ -251,9 +251,9 @@ class PaymentMethodConfigurationService { { $data = []; $paymentMethodData = []; - $salesChannelPaymentMethodData = []; - $criteria = (new Criteria())->addFilter(new EqualsFilter('state', 'ACTIVE')); + $criteria = (new Criteria())->addFilter(new EqualsFilter('state', 'ACTIVE')) + ->addFilter(new EqualsFilter('spaceId', $this->getSpaceId())); /** * @var $vRPaymentPMConfigurationRepository @@ -344,40 +344,67 @@ class PaymentMethodConfigurationService { $paymentMethodConfigurations = $this->getPaymentMethodConfigurations(); $this->logger->debug('Updating payment methods', $paymentMethodConfigurations); - /** - * @var $paymentMethodConfiguration \VRPayment\Sdk\Model\PaymentMethodConfiguration - */ foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) { - - $paymentMethodConfigurationEntity = $this->getPaymentMethodConfigurationEntity( - $paymentMethodConfiguration->getSpaceId(), - $paymentMethodConfiguration->getId(), - $context + $entity = $this->getPaymentMethodConfigurationEntity( + $paymentMethodConfiguration->getSpaceId(), + $paymentMethodConfiguration->getId(), + $context ); - $id = is_null($paymentMethodConfigurationEntity) ? Uuid::randomHex() : $paymentMethodConfigurationEntity->getId(); + $configId = $entity ? $entity->getId() : Uuid::randomHex(); + $technicalName = $paymentMethodConfiguration->getName(); + + $paymentMethodId = $this->getOrCreatePaymentMethodId( + $technicalName, + VRPaymentPaymentHandler::class, + $context + ); $data = [ - 'id' => $id, - 'paymentMethodConfigurationId' => $paymentMethodConfiguration->getId(), - 'paymentMethodId' => $id, - 'data' => json_decode(strval($paymentMethodConfiguration), true), - 'sortOrder' => $paymentMethodConfiguration->getSortOrder(), - 'spaceId' => $paymentMethodConfiguration->getSpaceId(), - 'state' => CreationEntityState::ACTIVE, + 'id' => $configId, + 'paymentMethodConfigurationId' => $paymentMethodConfiguration->getId(), + 'paymentMethodId' => $paymentMethodId, + 'data' => json_decode(strval($paymentMethodConfiguration), true), + 'sortOrder' => $paymentMethodConfiguration->getSortOrder(), + 'spaceId' => $paymentMethodConfiguration->getSpaceId(), + 'state' => CreationEntityState::ACTIVE, ]; - $this->upsertPaymentMethod($id, $paymentMethodConfiguration, $context); - - try { - $this->container->get(PaymentMethodConfigurationEntityDefinition::ENTITY_NAME . '.repository')->upsert([$data], $context); - } catch (\Exception $e) { - $this->logger->error($e->getMessage(), [$e->getTraceAsString()]); - } - + try { + $this->upsertPaymentMethod($paymentMethodId, $paymentMethodConfiguration, $context); + $this->container + ->get(PaymentMethodConfigurationEntityDefinition::ENTITY_NAME . '.repository') + ->upsert([$data], $context); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), [$e->getTraceAsString()]); + } } } + private function getOrCreatePaymentMethodId(string $technicalName, string $handlerIdentifier, Context $context): string + { + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('technicalName', $technicalName)); + $criteria->setLimit(1); + + $existing = $this->paymentMethodRepository->search($criteria, $context)->first(); + if ($existing !== null) { + return $existing->getId(); + } + + $paymentMethodId = Uuid::randomHex(); + + $this->paymentMethodRepository->upsert([[ + 'id' => $paymentMethodId, + 'handlerIdentifier' => $handlerIdentifier, + 'technicalName' => $technicalName, + 'name' => $technicalName, + 'active' => false, + ]], $context); + + return $paymentMethodId; + } + /** * Fetch active merchant payment methods from VRPayment API * @@ -467,53 +494,6 @@ class PaymentMethodConfigurationService { return $configurations->getElements(); } - /** - * Update or insert Payment Method - * - * @param string $id - * @param \VRPayment\Sdk\Model\PaymentMethodConfiguration $paymentMethodConfiguration - * @param \Shopware\Core\Framework\Context $context - * - * @throws \VRPayment\Sdk\ApiException - * @throws \VRPayment\Sdk\Http\ConnectionException - * @throws \VRPayment\Sdk\VersioningException - */ - protected function upsertPaymentMethod( - string $id, - PaymentMethodConfiguration $paymentMethodConfiguration, - Context $context - ): void - { - /** @var PluginIdProvider $pluginIdProvider */ - $pluginIdProvider = $this->container->get(PluginIdProvider::class); - $pluginId = $pluginIdProvider->getPluginIdByBaseClass( - VRPaymentPayment::class, - $context - ); - - $data = [ - 'id' => $id, - 'handlerIdentifier' => VRPaymentPaymentHandler::class, - 'pluginId' => $pluginId, - 'position' => $paymentMethodConfiguration->getSortOrder() - 100, - 'afterOrderEnabled' => true, - 'active' => true, - 'translations' => $this->getPaymentMethodConfigurationTranslation($paymentMethodConfiguration, $context), - 'technicalName' => $paymentMethodConfiguration->getName(), - ]; - - $data['mediaId'] = $this->upsertMedia($id, $paymentMethodConfiguration, $context); - - $data = array_filter($data); - - try { - $this->paymentMethodRepository->upsert([$data], $context); - } catch (\Exception $e) { - $this->logger->error($e->getMessage(), [$e->getTraceAsString()]); - } - - } - /** * @param \VRPayment\Sdk\Model\PaymentMethodConfiguration $paymentMethodConfiguration * @param \Shopware\Core\Framework\Context $context @@ -605,54 +585,95 @@ class PaymentMethodConfigurationService { } /** - * Upload Payment Method icons - * - * @param string $id - * @param \VRPayment\Sdk\Model\PaymentMethodConfiguration $paymentMethodConfiguration - * @param \Shopware\Core\Framework\Context $context - * - * @return string|null + * Update or insert Payment Method + */ + protected function upsertPaymentMethod( + string $id, + PaymentMethodConfiguration $paymentMethodConfiguration, + Context $context + ): void { + /** @var PluginIdProvider $pluginIdProvider */ + $pluginIdProvider = $this->container->get(PluginIdProvider::class); + $pluginId = $pluginIdProvider->getPluginIdByBaseClass( + VRPaymentPayment::class, + $context + ); + + $data = [ + 'id' => $id, + 'handlerIdentifier' => VRPaymentPaymentHandler::class, + 'pluginId' => $pluginId, + 'position' => $paymentMethodConfiguration->getSortOrder() - 100, + 'afterOrderEnabled' => true, + 'active' => true, + 'translations' => $this->getPaymentMethodConfigurationTranslation($paymentMethodConfiguration, $context), + 'technicalName' => $paymentMethodConfiguration->getName(), + ]; + + $mediaId = $this->upsertMedia($id, $paymentMethodConfiguration, $context); + if ($mediaId) { + $data['mediaId'] = $mediaId; + } + + try { + $this->paymentMethodRepository->upsert([$data], $context); + } catch (\Exception $e) { + $this->logger->error($e->getMessage(), [$e->getTraceAsString()]); + } + } + + /** + * Upload or update Payment Method icons */ protected function upsertMedia(string $id, PaymentMethodConfiguration $paymentMethodConfiguration, Context $context): ?string { try { - $existingRecord = $this->getMediaDefaultFolderForPaymentMethod($paymentMethodConfiguration, $context); + $folderKey = 'payment_method_' . $paymentMethodConfiguration->getId(); - if ($existingRecord->count() > 0) { - $id = $existingRecord->first()->getId(); + // Check existing default folder + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('entity', $folderKey)); + $existingFolder = $this->mediaDefaultFolderRepository->search($criteria, $context); + + $folderId = $id; + if ($existingFolder->count() > 0) { + $folderId = $existingFolder->first()->getId(); } + // Ensure default folder $this->mediaDefaultFolderRepository->upsert([ - [ - 'id' => $id, - 'associationFields' => [], - 'entity' => 'payment_method_' . $paymentMethodConfiguration->getId(), - ], + [ + 'id' => $folderId, + 'associationFields' => [], + 'entity' => $folderKey, + ], ], $context); + // Ensure media folder $this->mediaFolderRepository->upsert([ - [ - 'id' => $id, - 'defaultFolderId' => $id, - 'name' => $paymentMethodConfiguration->getName(), - 'useParentConfiguration' => false, - 'configuration' => [], - ], + [ + 'id' => $folderId, + 'defaultFolderId' => $folderId, + 'name' => $paymentMethodConfiguration->getName(), + 'useParentConfiguration' => false, + 'configuration' => [], + ], ], $context); - /** - * @var \Shopware\Core\Content\Media\MediaDefinition - */ + // Media insert/update $mediaDefinition = $this->container->get(MediaDefinition::class); $this->mediaSerializer->setRegistry($this->serializerRegistry); + $data = [ - 'id' => $id, - 'title' => $paymentMethodConfiguration->getName(), - 'url' => $paymentMethodConfiguration->getResolvedImageUrl(), - 'mediaFolderId' => $id, + 'id' => $id, + 'title' => $paymentMethodConfiguration->getName(), + 'url' => $paymentMethodConfiguration->getResolvedImageUrl(), + 'mediaFolderId' => $folderId, ]; + $data = $this->mediaSerializer->deserialize(new Config([], [], []), $mediaDefinition, $data); $this->mediaRepository->upsert([$data], $context); + return $id; } catch (\Exception $e) { $this->logger->critical($e->getMessage(), [$e->getTraceAsString()]); diff --git a/src/Core/Api/Transaction/Service/TransactionService.php b/src/Core/Api/Transaction/Service/TransactionService.php index c12951d..f364dad 100644 --- a/src/Core/Api/Transaction/Service/TransactionService.php +++ b/src/Core/Api/Transaction/Service/TransactionService.php @@ -15,6 +15,7 @@ use Shopware\Core\{ System\SalesChannel\SalesChannelContext }; use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent; +use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use VRPayment\Sdk\Model\{ AddressCreate, @@ -46,6 +47,9 @@ use VRPaymentPayment\Core\{ Util\Payload\CustomProducts\CustomProductsLineItemTypes, Util\Payload\TransactionPayload }; +use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity; +use Shopware\Core\Framework\Struct\ArrayEntity; +use Shopware\Commercial\Subscription\Framework\Struct\SubscriptionContextStruct; /** * Class TransactionService @@ -185,10 +189,20 @@ class TransactionService $orderTransaction->getPaymentMethodId(), $orderTransaction->getOrder()->getSalesChannelId() ); - $_SESSION['transactionId'] = null; - $_SESSION['arrayOfPossibleMethods'] = null; - $_SESSION['addressCheck'] = null; - $_SESSION['currencyCheck'] = null; + + $salesChannelContext->getContext()->addExtension( + 'checkoutState', + new ArrayEntity([ + 'transactionId' => null, + 'addressHash' => null, + 'currency' => null, + ]) + ); + + $salesChannelContext->getContext()->addExtension( + 'possibleMethods', + new ArrayEntity(['ids' => []]) + ); $this->holdDelivery($orderTransaction->getOrder()->getId(), $salesChannelContext->getContext()); @@ -502,24 +516,22 @@ class TransactionService /** * @param SalesChannelContext $salesChannelContext - * @param CheckoutConfirmPageLoadedEvent|null $event + * * @return int */ - public function createPendingTransaction(SalesChannelContext $salesChannelContext, ?CheckoutConfirmPageLoadedEvent $event = null): int + public function createPendingTransaction(SalesChannelContext $salesChannelContext, $event = null): int { $expiredTransaction = true; $transactionId = $_SESSION['transactionId'] ?? null; $settings = $this->settingsService->getValidSettings($salesChannelContext->getSalesChannel()->getId()); + if (!$settings) { + throw new \Exception('Space settings not configured'); + } if ($transactionId) { $transactionService = $settings->getApiClient()->getTransactionService(); $pendingTransaction = $transactionService->read($settings->getSpaceId(), $transactionId); - $failedStates = [ - TransactionState::DECLINE, - TransactionState::FAILED, - TransactionState::VOIDED, - ]; - if (!in_array($pendingTransaction->getState(), $failedStates)) { + if ($pendingTransaction->getState() === TransactionState::PENDING) { $expiredTransaction = false; } } @@ -530,12 +542,19 @@ class TransactionService $customer = $salesChannelContext->getCustomer(); $lineItems = []; if ($event) { - $cartLineItems = $event->getPage()->getCart()->getLineItems()->getElements(); - foreach ($cartLineItems as $cartLineItem) { - if ($cartLineItem->getType() === CustomProductsLineItemTypes::LINE_ITEM_TYPE_CUSTOMIZED_PRODUCTS) { - continue; + if ($event instanceof CheckoutConfirmPageLoadedEvent) { + $cartLineItems = $event->getPage()->getCart()->getLineItems()->getElements(); + foreach ($cartLineItems as $cartLineItem) { + if ($cartLineItem->getType() === CustomProductsLineItemTypes::LINE_ITEM_TYPE_CUSTOMIZED_PRODUCTS) { + continue; + } + $lineItems[] = $this->createTempLineItem($cartLineItem); + } + } elseif ($event instanceof AccountEditOrderPageLoadedEvent) { + $order = $event->getPage()->getOrder(); + foreach ($order->getLineItems() as $orderLineItem) { + $lineItems[] = $this->createTempLineItem($orderLineItem); } - $lineItems[] = $this->createTempLineItem($cartLineItem); } } @@ -551,6 +570,10 @@ class TransactionService $billingAddress = $this->buildAddress($salesChannelContext, $customer->getActiveBillingAddress()); $shippingAddress = $this->buildAddress($salesChannelContext, $customer->getActiveShippingAddress()); + if (!$settings) { + throw new \Exception('Space settings not configured'); + } + $transactionPayload = (new TransactionCreate()) ->setBillingAddress($billingAddress) ->setShippingAddress($shippingAddress) @@ -562,8 +585,11 @@ class TransactionService ->setCustomerEmailAddress($customer->getEmail()) ->setCustomerId($customerId) ->setSuccessUrl($homeUrl . '?success') - ->setFailedUrl($homeUrl . '?fail') - ->setTokenizationMode(TokenizationMode::FORCE_CREATION); + ->setFailedUrl($homeUrl . '?fail'); + + if($this->isSubscription($salesChannelContext)) { + $transactionPayload->setTokenizationMode(TokenizationMode::FORCE_CREATION); + } $transactionService = $settings->getApiClient()->getTransactionService(); $transaction = $transactionService->create($settings->getSpaceId(), $transactionPayload); @@ -685,22 +711,30 @@ class TransactionService return $chargeAttempts ? $chargeAttempts[0] : null; } - /** - * @param LineItem $productData - * @return LineItemCreate - */ - private function createTempLineItem(LineItem $productData): LineItemCreate - { - $lineItem = new LineItemCreate(); - $lineItem->setName($productData->getLabel()); - $lineItem->setUniqueId($productData->getId()); - $lineItem->setSku($productData->getId()); - $lineItem->setQuantity($productData->getQuantity()); - $lineItem->setAmountIncludingTax($productData->getPrice()->getUnitPrice()); - $lineItem->setType(LineItemType::PRODUCT); + private function createTempLineItem($productData): LineItemCreate + { + $lineItem = new LineItemCreate(); - return $lineItem; - } + if ($productData instanceof LineItem) { + $lineItem->setName($productData->getLabel()); + $lineItem->setUniqueId($productData->getId()); + $lineItem->setSku($productData->getReferencedId() ?? $productData->getId()); + $lineItem->setQuantity($productData->getQuantity()); + $lineItem->setAmountIncludingTax($productData->getPrice()->getUnitPrice()); + } elseif ($productData instanceof OrderLineItemEntity) { + $lineItem->setName($productData->getLabel()); + $lineItem->setUniqueId($productData->getId()); + $lineItem->setSku($productData->getProductId() ?? $productData->getIdentifier() ?? $productData->getId()); + $lineItem->setQuantity($productData->getQuantity()); + $lineItem->setAmountIncludingTax($productData->getUnitPrice()); + } else { + throw new \InvalidArgumentException('Unsupported line item type: ' . get_class($productData)); + } + + $lineItem->setType(LineItemType::PRODUCT); + + return $lineItem; + } /** * Build a VRPayment address from Shopware customer address. @@ -749,4 +783,21 @@ class TransactionService return $address; } + + /** + * Checks if it's subscription context. + * + * @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext + * @return bool + */ + private function isSubscription(SalesChannelContext $salesChannelContext): bool { + $extensionName = 'subscription'; + if (class_exists(\Shopware\Commercial\Subscription\Framework\Struct\SubscriptionContextStruct::class)) { + $extensionName = SubscriptionContextStruct::SUBSCRIPTION_EXTENSION; + } + if ($salesChannelContext->hasExtension($extensionName)) { + return true; + } + return false; + } } diff --git a/src/Core/Api/WebHooks/Controller/WebHookController.php b/src/Core/Api/WebHooks/Controller/WebHookController.php index 5658540..c6e42b2 100644 --- a/src/Core/Api/WebHooks/Controller/WebHookController.php +++ b/src/Core/Api/WebHooks/Controller/WebHookController.php @@ -224,8 +224,18 @@ class WebHookController extends AbstractController { // Configuration $salesChannelId = $salesChannelId == 'null' ? null : $salesChannelId; $this->settings = $this->settingsService->getSettings($salesChannelId); + $signature = $request->server->get('HTTP_X_SIGNATURE'); $requestJson = json_decode($request->getContent(), true); + + if ($requestJson['eventId'] == null && $requestJson['entityId'] == null && $requestJson['listenerEntityId'] == null && $requestJson['listenerEntityId'] == null && $requestJson['listenerEntityTechnicalName'] == null && $requestJson['spaceId'] == null) { + throw new \InvalidArgumentException('Empty webhook'); + } + + if (!$this->settings->getSpaceId() || !$this->settings->getUserId() || !$this->settings->getApplicationKey()) { + throw new \InvalidArgumentException('Not correct webhook configuration for salesChannelId: ' . $salesChannelId . ' Debug: ' . var_dump($requestJson)); + } + $apiClient = $this->settings->getApiClient(); $callBackData->assign($requestJson); diff --git a/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php b/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php index 9109457..91e402f 100644 --- a/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php +++ b/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php @@ -4,33 +4,41 @@ namespace VRPaymentPayment\Core\Storefront\Checkout\Subscriber; use Psr\Log\LoggerInterface; use Shopware\Core\{Checkout\Order\Aggregate\OrderTransaction\OrderTransactionCollection, - Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates, - Checkout\Order\OrderEntity, - Content\MailTemplate\Service\Event\MailBeforeValidateEvent}; + Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates, + Checkout\Order\OrderEntity, + Content\MailTemplate\Service\Event\MailBeforeValidateEvent}; +use Shopware\Core\Checkout\Payment\PaymentMethodCollection; +use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter; use Shopware\Core\System\SalesChannel\SalesChannelContext; +use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent; +use Shopware\Storefront\Page\Account\PaymentMethod\AccountPaymentMethodPageLoadedEvent; use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent; +use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use VRPaymentPayment\Core\{Api\Transaction\Service\OrderMailService, - Api\Transaction\Service\TransactionService, - Checkout\PaymentHandler\VRPaymentPaymentHandler, - Settings\Service\SettingsService, - Settings\Struct\Settings, - Util\PaymentMethodUtil}; +use VRPaymentPayment\Core\{Api\Transaction\Service\TransactionService, + Checkout\PaymentHandler\VRPaymentPaymentHandler, + Settings\Service\SettingsService, + Settings\Struct\Settings, + Util\PaymentMethodUtil}; use VRPaymentPayment\Core\Api\PaymentMethodConfiguration\Service\PaymentMethodConfigurationService; use VRPaymentPayment\Sdk\{Model\AddressCreate, - Model\ChargeAttempt, - Model\CreationEntityState, - Model\CriteriaOperator, - Model\EntityQuery, - Model\EntityQueryFilter, - Model\EntityQueryFilterType, - Model\LineItemAttributeCreate, - Model\LineItemCreate, - Model\LineItemType, - Model\TaxCreate, - Model\Transaction, - Model\TransactionCreate, - Model\TransactionPending}; + Model\ChargeAttempt, + Model\CreationEntityState, + Model\CriteriaOperator, + Model\EntityQuery, + Model\EntityQueryFilter, + Model\EntityQueryFilterType, + Model\LineItemAttributeCreate, + Model\LineItemCreate, + Model\LineItemType, + Model\TaxCreate, + Model\Transaction, + Model\TransactionCreate, + Model\TransactionPending}; +use Shopware\Core\Framework\Struct\ArrayEntity; /** * Class CheckoutSubscriber @@ -65,6 +73,9 @@ class CheckoutSubscriber implements EventSubscriberInterface */ private $paymentMethodUtil; + /** @var EntityRepository */ + private EntityRepository $paymentMethodRepository; + /** * CheckoutSubscriber constructor. * @@ -72,13 +83,15 @@ class CheckoutSubscriber implements EventSubscriberInterface * @param \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService $transactionService * @param \VRPaymentPayment\Core\Settings\Service\SettingsService $settingsService * @param \VRPaymentPayment\Core\Util\PaymentMethodUtil $paymentMethodUtil + * @param EntityRepository $paymentMethodRepository */ - public function __construct(PaymentMethodConfigurationService $paymentMethodConfigurationService, TransactionService $transactionService, SettingsService $settingsService, PaymentMethodUtil $paymentMethodUtil) + public function __construct(PaymentMethodConfigurationService $paymentMethodConfigurationService, TransactionService $transactionService, SettingsService $settingsService, PaymentMethodUtil $paymentMethodUtil, EntityRepository $paymentMethodRepository) { - $this->paymentMethodConfigurationService = $paymentMethodConfigurationService; - $this->transactionService = $transactionService; - $this->settingsService = $settingsService; - $this->paymentMethodUtil = $paymentMethodUtil; + $this->paymentMethodConfigurationService = $paymentMethodConfigurationService; + $this->transactionService = $transactionService; + $this->settingsService = $settingsService; + $this->paymentMethodUtil = $paymentMethodUtil; + $this->paymentMethodRepository = $paymentMethodRepository; } /** @@ -99,7 +112,9 @@ class CheckoutSubscriber implements EventSubscriberInterface public static function getSubscribedEvents(): array { return [ - CheckoutConfirmPageLoadedEvent::class => ['onConfirmPageLoaded', 1], + CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmLoaded', + AccountEditOrderPageLoadedEvent::class => 'onAccountOrderEditLoaded', + AccountPaymentMethodPageLoadedEvent::class => 'onAccountPaymentMethodLoaded', "subscription." . CheckoutConfirmPageLoadedEvent::class => ['onConfirmPageLoaded', 1], MailBeforeValidateEvent::class => ['onMailBeforeValidate', 1], ]; @@ -154,9 +169,10 @@ class CheckoutSubscriber implements EventSubscriberInterface } /** - * @param \Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent $event + * @param CheckoutConfirmPageLoadedEvent $event + * @return void */ - public function onConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void + public function onCheckoutConfirmLoaded(CheckoutConfirmPageLoadedEvent $event): void { try { $salesChannelContext = $event->getSalesChannelContext(); @@ -169,7 +185,7 @@ class CheckoutSubscriber implements EventSubscriberInterface $createdTransactionId = $this->transactionService->createPendingTransaction($salesChannelContext, $event); $this->updateTempTransactionIfNeeded($salesChannelContext, $createdTransactionId); - $this->getAvailablePaymentMethods($settings, $createdTransactionId); + $this->getAvailablePaymentMethods($settings, $createdTransactionId, $salesChannelContext); $this->setPossiblePaymentMethods($settings->getSpaceId(), $event); } catch (\Exception $e) { $this->logger->error($e->getMessage()); @@ -177,10 +193,74 @@ class CheckoutSubscriber implements EventSubscriberInterface } } + /** + * @param AccountEditOrderPageLoadedEvent $event + * @return void + */ + public function onAccountOrderEditLoaded(AccountEditOrderPageLoadedEvent $event): void + { + try { + $this->handlePaymentMethodFiltering($event); + } catch (\Throwable $e) { + $this->logger->error($e->getMessage()); + $this->removeVRPaymentPaymentMethodFromConfirmPage($event); + } + } + + /** + * @param AccountPaymentMethodPageLoadedEvent $event + * @return void + */ + public function onAccountPaymentMethodLoaded(AccountPaymentMethodPageLoadedEvent $event): void + { + try { + $this->handlePaymentMethodFiltering($event); + } catch (\Throwable $e) { + $this->logger->error($e->getMessage()); + $this->removeVRPaymentPaymentMethodFromConfirmPage($event); + } + } + /** * @param \Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent $event */ - private function removeVRPaymentPaymentMethodFromConfirmPage(CheckoutConfirmPageLoadedEvent $event): void + public function onConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void + { + try { + $this->handlePaymentMethodFiltering($event); + } catch (\Throwable $e) { + $this->logger->error($e->getMessage()); + $this->removeVRPaymentPaymentMethodFromConfirmPage($event); + } + } + + /** + * @param $event + * @return void + */ + private function handlePaymentMethodFiltering($event): void + { + $salesChannelContext = $event->getSalesChannelContext(); + $settings = $this->settingsService->getValidSettings($salesChannelContext->getSalesChannel()->getId()); + + if (is_null($settings)) { + $this->logger->notice('Removing payment methods because settings are invalid'); + $this->removeVRPaymentPaymentMethodFromConfirmPage($event); + return; + } + + $createdTransactionId = $this->transactionService->createPendingTransaction($salesChannelContext, $event); + $this->updateTempTransactionIfNeeded($salesChannelContext, $createdTransactionId); + + $this->getAvailablePaymentMethods($settings, $createdTransactionId, $salesChannelContext); + $this->setPossiblePaymentMethods($settings->getSpaceId(), $event); + } + + /** + * @param $event + * @return void + */ + private function removeVRPaymentPaymentMethodFromConfirmPage($event): void { $paymentMethodCollection = $event->getPage()->getPaymentMethods(); $paymentMethodIds = $this->paymentMethodUtil->getVRPaymentPaymentMethodIds($event->getContext()); @@ -194,7 +274,7 @@ class CheckoutSubscriber implements EventSubscriberInterface * @param int $createdTransactionId * @return void */ - private function getAvailablePaymentMethods(Settings $settings, int $createdTransactionId): void + private function getAvailablePaymentMethods(Settings $settings, int $createdTransactionId, SalesChannelContext $salesChannelContext): void { $transactionService = $settings->getApiClient()->getTransactionService(); $possiblePaymentMethods = $transactionService->fetchPaymentMethods( @@ -204,9 +284,13 @@ class CheckoutSubscriber implements EventSubscriberInterface ); $arrayOfPossibleMethods = []; foreach ($possiblePaymentMethods as $possiblePaymentMethod) { - $arrayOfPossibleMethods[] = $possiblePaymentMethod->getid(); + $arrayOfPossibleMethods[] = $possiblePaymentMethod->getId(); } - $_SESSION['arrayOfPossibleMethods'] = $arrayOfPossibleMethods; + + $salesChannelContext->getContext()->addExtension( + 'possibleMethods', + new ArrayEntity(['ids' => $arrayOfPossibleMethods]) + ); } /** @@ -214,48 +298,101 @@ class CheckoutSubscriber implements EventSubscriberInterface * @param CheckoutConfirmPageLoadedEvent $event * @return void */ - private function setPossiblePaymentMethods(int $spaceId, CheckoutConfirmPageLoadedEvent $event): void + private function setPossiblePaymentMethods(int $spaceId, $event): void { - $localPaymentMethods = []; - $paymentMethodConfigurations = $this->paymentMethodConfigurationService->getAllPaymentMethodConfigurations($spaceId, $event->getSalesChannelContext()->getContext()); - foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) { - $localPaymentMethods[$paymentMethodConfiguration->getId()] = $paymentMethodConfiguration->getPaymentMethodConfigurationId(); + $paymentIds = []; + $paymentMethodCollection = $event->getPage()->getPaymentMethods(); + + foreach ($paymentMethodCollection as $paymentMethodCollectionItem) { + $isVRPaymentPM = VRPaymentPaymentHandler::class === $paymentMethodCollectionItem->getHandlerIdentifier(); + if (!$isVRPaymentPM) { + $paymentIds[] = $paymentMethodCollectionItem->getId(); + } } - $paymentMethodCollection = $event->getPage()->getPaymentMethods(); - foreach ($paymentMethodCollection as $paymentMethodCollectionItem) { - $isVRPaymentPM = VRPaymentPaymentHandler::class == $paymentMethodCollectionItem->getHandlerIdentifier(); - if (!$isVRPaymentPM) { + $allowedWLMethods = []; + $paymentMethodConfigurations = $this->paymentMethodConfigurationService + ->getAllPaymentMethodConfigurations($spaceId, $event->getSalesChannelContext()->getContext()); + + foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) { + if ($paymentMethodConfiguration->getPaymentMethod() === null) { continue; } - $paymentMethodConfigurationId = $localPaymentMethods[$paymentMethodCollectionItem->getId()]; - if (!\in_array($paymentMethodConfigurationId, $_SESSION['arrayOfPossibleMethods'])) { - $paymentMethodCollection->remove($paymentMethodCollectionItem->getId()); + $pmId = $paymentMethodConfiguration->getPaymentMethod()->getId(); + $pmConfigId = $paymentMethodConfiguration->getPaymentMethodConfigurationId(); + $allowedIds = $this->getAllowedPaymentMethodIds($event->getSalesChannelContext()); + + if ($paymentMethodConfiguration->getSpaceId() === $spaceId + && \in_array($pmConfigId, $allowedIds, true)) { + $allowedWLMethods[] = $pmId; } } - } - /** - * @param SalesChannelContext $salesChannelContext - * @param int $createdTransactionId - * @return void - */ - private function updateTempTransactionIfNeeded(SalesChannelContext $salesChannelContext, int $createdTransactionId): void - { - $addressCheck = $_SESSION['addressCheck'] ?? null; - $currencyCheck = $_SESSION['currencyCheck'] ?? null; + $allPaymentIds = array_unique(array_merge($paymentIds, $allowedWLMethods)); + $collection = new PaymentMethodCollection(); + if (!empty($allPaymentIds)) { + $criteria = new Criteria($allPaymentIds); + $criteria->addFilter(new EqualsFilter('active', true)); + $criteria->addFilter( + new EqualsFilter('salesChannels.id', $event->getSalesChannelContext()->getSalesChannelId()) + ); - $customer = $salesChannelContext->getCustomer(); - $addressHash = md5(json_encode((array)$customer)); - $currency = $salesChannelContext->getCurrency()->getIsoCode(); - if (($addressCheck && $currencyCheck) && $addressCheck !== $addressHash || $currencyCheck !== $currency) { - if ($createdTransactionId) { - $this->transactionService->updateTempTransaction($salesChannelContext, $createdTransactionId); + $result = $this->paymentMethodRepository->search($criteria, $event->getContext()); + foreach ($result->getEntities() as $method) { + if (!$collection->has($method->getId())) { + $collection->add($method); + } } - $_SESSION['arrayOfPossibleMethods'] = null; - $_SESSION['addressCheck'] = $addressHash; - $_SESSION['currencyCheck'] = $currency; } + + $event->getPage()->setPaymentMethods($collection); } + + /** + * @param SalesChannelContext $salesChannelContext + * @param int $createdTransactionId + * @return void + */ + private function updateTempTransactionIfNeeded(SalesChannelContext $salesChannelContext, int $createdTransactionId): void + { + $ctx = $salesChannelContext->getContext(); + + /** @var ArrayEntity|null $ext */ + $ext = $ctx->getExtension('checkoutState'); + + $oldAddressHash = $ext instanceof ArrayEntity ? $ext->get('addressHash') : null; + $oldCurrency = $ext instanceof ArrayEntity ? $ext->get('currency') : null; + + $customer = $salesChannelContext->getCustomer(); + $addressHash = md5(json_encode((array) $customer)); + $currency = $salesChannelContext->getCurrency()->getIsoCode(); + + $needsUpdate = ($oldAddressHash !== $addressHash) || ($oldCurrency !== $currency); + + if ($needsUpdate) { + if ($createdTransactionId) { + $this->transactionService->updateTempTransaction($salesChannelContext, $createdTransactionId); + } + + $ctx->addExtension('possibleMethods', new ArrayEntity(['ids' => []])); + $ctx->addExtension( + 'checkoutState', + new ArrayEntity([ + 'addressHash' => $addressHash, + 'currency' => $currency, + ]) + ); + } + } + + /** + * @param SalesChannelContext $salesChannelContext + * @return array + */ + private function getAllowedPaymentMethodIds(SalesChannelContext $salesChannelContext): array + { + $ext = $salesChannelContext->getContext()->getExtension('possibleMethods'); + return $ext instanceof ArrayEntity ? ($ext->get('ids') ?? []) : []; + } } diff --git a/src/Core/Util/Analytics/Analytics.php b/src/Core/Util/Analytics/Analytics.php index 674fcec..a71c907 100644 --- a/src/Core/Util/Analytics/Analytics.php +++ b/src/Core/Util/Analytics/Analytics.php @@ -25,7 +25,7 @@ class Analytics { self::SHOP_SYSTEM => 'shopware', self::SHOP_SYSTEM_VERSION => '6', self::SHOP_SYSTEM_AND_VERSION => 'shopware-6', - self::PLUGIN_SYSTEM_VERSION => '7.1.1', + self::PLUGIN_SYSTEM_VERSION => '7.1.2', ]; } diff --git a/src/Core/Util/Payload/TransactionPayload.php b/src/Core/Util/Payload/TransactionPayload.php index 30368e8..29dc8f1 100644 --- a/src/Core/Util/Payload/TransactionPayload.php +++ b/src/Core/Util/Payload/TransactionPayload.php @@ -231,9 +231,16 @@ class TransactionPayload extends AbstractPayload ->setShippingAddress($shippingAddress) ->setShippingMethod($transactionData['shipping_method']); - $paymentConfiguration = $this->getPaymentConfiguration($this->salesChannelContext->getPaymentMethod()->getId()); + $paymentConfiguration = $this->getPaymentConfiguration( + $this->salesChannelContext->getPaymentMethod()->getId(), + $this->settings->getSpaceId() + ); - $transactionPayload->setAllowedPaymentMethodConfigurations([$paymentConfiguration->getPaymentMethodConfigurationId()]); + if ($paymentConfiguration) { + $transactionPayload->setAllowedPaymentMethodConfigurations([ + $paymentConfiguration->getPaymentMethodConfigurationId() + ]); + } $successUrl = $this->transaction->getReturnUrl() . '&status=paid'; $failedUrl = $this->getFailUrl($this->order->getId()) . '&status=fail'; @@ -899,19 +906,21 @@ class TransactionPayload extends AbstractPayload return $addressPayload; } - /** - * @param string $id - * - * @return \VRPaymentPayment\Core\Api\PaymentMethodConfiguration\Entity\PaymentMethodConfigurationEntity - */ - protected function getPaymentConfiguration(string $id): PaymentMethodConfigurationEntity - { - $criteria = (new Criteria([$id])); + /** + * @param string $paymentMethodId + * @param int $spaceId + * @return PaymentMethodConfigurationEntity|null + */ + protected function getPaymentConfiguration(string $paymentMethodId, int $spaceId): ?PaymentMethodConfigurationEntity + { + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('paymentMethodId', $paymentMethodId)); + $criteria->addFilter(new EqualsFilter('spaceId', $spaceId)); - return $this->container->get('vrpayment_payment_method_configuration.repository') - ->search($criteria, $this->salesChannelContext->getContext()) - ->getEntities()->first(); - } + return $this->container->get('vrpayment_payment_method_configuration.repository') + ->search($criteria, $this->salesChannelContext->getContext()) + ->first(); + } /** * Get failure URL diff --git a/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-credentials/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-credentials/index.html.twig index 117ac2d..fe5986f 100644 --- a/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-credentials/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-credentials/index.html.twig @@ -14,7 +14,7 @@ {% block vrpayment_settings_content_card_channel_config_credentials_card_container_settings_space_id %}