From 93f24a2cac8a2e6cee0b8f089aa7386774f4be71 Mon Sep 17 00:00:00 2001 From: andrewrowanwallee Date: Wed, 29 Apr 2026 11:43:34 +0200 Subject: [PATCH] Release 7.3.3 --- CHANGELOG.md | 5 ++ CHANGELOG_de-DE.md | 5 ++ README.md | 8 +- composer.json | 2 +- docs/de/documentation.html | 2 +- docs/en/documentation.html | 2 +- docs/fr/documentation.html | 2 +- docs/it/documentation.html | 2 +- .../Service/TransactionService.php | 43 ++++++++++- .../VRPaymentPaymentHandler.php | 2 +- .../Service/PaymentIntegrationService.php | 24 +++++- .../Service/PaymentMethodFilterService.php | 77 +++++++------------ src/Core/Util/Analytics/Analytics.php | 2 +- src/Core/Util/LocaleCodeProvider.php | 20 +++++ .../page/vrpayment-settings/index.html.twig | 13 ++-- .../page/vrpayment-settings/index.js | 28 +++++-- .../v-r-payment-payment.js | 2 +- .../services/core/checkout_services.xml | 2 +- .../administration/.vite/entrypoints.json | 2 +- .../public/administration/.vite/manifest.json | 2 +- .../assets/v-r-payment-payment-CPfpiGQp.js | 2 + .../v-r-payment-payment-CPfpiGQp.js.map | 1 + .../assets/v-r-payment-payment-D_mm2NL2.js | 2 - .../v-r-payment-payment-D_mm2NL2.js.map | 1 - 24 files changed, 163 insertions(+), 88 deletions(-) create mode 100644 src/Resources/public/administration/assets/v-r-payment-payment-CPfpiGQp.js create mode 100644 src/Resources/public/administration/assets/v-r-payment-payment-CPfpiGQp.js.map delete mode 100644 src/Resources/public/administration/assets/v-r-payment-payment-D_mm2NL2.js delete mode 100644 src/Resources/public/administration/assets/v-r-payment-payment-D_mm2NL2.js.map diff --git a/CHANGELOG.md b/CHANGELOG.md index 58f2d2b..ce5b0a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 7.3.3 +- Shopware 6.7.9.0 compatible +- Fix for only showing 25 sales channels in selector +- Fixed bug with discount occasionally blocking payment methods + # 7.3.2 - Fix for partial refunds using standard refund option - Fixed issue with undefined array key diff --git a/CHANGELOG_de-DE.md b/CHANGELOG_de-DE.md index 2bd6511..47e3d4d 100644 --- a/CHANGELOG_de-DE.md +++ b/CHANGELOG_de-DE.md @@ -1,3 +1,8 @@ +# 7.3.3 +- Kompatibel mit Shopware 6.7.9.0 +- Problem behoben, dass im Selektor nur 25 Vertriebskanäle angezeigt wurden +- Fehler behoben, der gelegentlich dazu führte, dass Rabatte Zahlungsmethoden blockierten + # 7.3.2 - Problem mit Teilrückerstattungen über die Standardrückerstattungsoption behoben - Problem mit undefiniertem Array-Schlüssel behoben diff --git a/README.md b/README.md index a49c04c..cdc6a8c 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](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.3.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.3.2/docs/de/documentation.html) -- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.3.2/docs/fr/documentation.html) -- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.3.2/docs/it/documentation.html) +- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.3.3/docs/en/documentation.html) +- Für die deutsche Dokumentation klicken Sie [hier](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.3.3/docs/de/documentation.html) +- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.3.3/docs/fr/documentation.html) +- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.3.3/docs/it/documentation.html) ## Installation diff --git a/composer.json b/composer.json index f879647..1a0d5ab 100644 --- a/composer.json +++ b/composer.json @@ -59,5 +59,5 @@ "vrpayment/sdk": "^4.0.0" }, "type": "shopware-platform-plugin", - "version": "7.3.2" + "version": "7.3.3" } diff --git a/docs/de/documentation.html b/docs/de/documentation.html index fbab069..778f8fa 100644 --- a/docs/de/documentation.html +++ b/docs/de/documentation.html @@ -23,7 +23,7 @@
  • - + Source
  • diff --git a/docs/en/documentation.html b/docs/en/documentation.html index eed16e0..4d7b37d 100644 --- a/docs/en/documentation.html +++ b/docs/en/documentation.html @@ -23,7 +23,7 @@
  • - + Source
  • diff --git a/docs/fr/documentation.html b/docs/fr/documentation.html index 47f5c69..6f62905 100644 --- a/docs/fr/documentation.html +++ b/docs/fr/documentation.html @@ -23,7 +23,7 @@
  • - + Source
  • diff --git a/docs/it/documentation.html b/docs/it/documentation.html index c8b3bf3..4d44c60 100644 --- a/docs/it/documentation.html +++ b/docs/it/documentation.html @@ -23,7 +23,7 @@
  • - + Source
  • diff --git a/src/Core/Api/Transaction/Service/TransactionService.php b/src/Core/Api/Transaction/Service/TransactionService.php index d1aea07..836f69a 100644 --- a/src/Core/Api/Transaction/Service/TransactionService.php +++ b/src/Core/Api/Transaction/Service/TransactionService.php @@ -624,11 +624,14 @@ class TransactionService throw new \Exception('Space settings not configured'); } + $language = $this->localeCodeProvider->getLocaleCodeFromContext($salesChannelContext->getContext()); + $transactionPayload = (new TransactionCreate()) ->setBillingAddress($billingAddress) ->setShippingAddress($shippingAddress) ->setLineItems($lineItems) ->setCurrency($currency) + ->setLanguage($language) ->setSpaceViewId($settings->getSpaceViewId()) ->setAutoConfirmationEnabled(false) ->setChargeRetryEnabled(false) @@ -668,7 +671,10 @@ class TransactionService $currency = $salesChannelContext->getCurrency()->getIsoCode(); + $language = $this->localeCodeProvider->getLocaleCodeFromContext($salesChannelContext->getContext()); + $pendingTransaction->setCurrency($currency); + $pendingTransaction->setLanguage($language); $billingAddress = $this->buildAddress($salesChannelContext, $salesChannelContext->getCustomer()->getActiveBillingAddress()); $shippingAddress = $this->buildAddress($salesChannelContext, $salesChannelContext->getCustomer()->getActiveShippingAddress()); @@ -807,20 +813,26 @@ class TransactionService { $lineItem = new LineItemCreate(); - $roundedPrice = $this->round($productData->getPrice()->getUnitPrice()); + $price = $productData->getPrice(); + $unit = $price->getUnitPrice(); + + // Expects discounts as separate items, avoid negative prices + if ($unit < 0) { + return $this->mapDiscountLineItem($productData); + } if ($productData instanceof LineItem) { $lineItem->setName($productData->getLabel()); $lineItem->setUniqueId($productData->getId()); $lineItem->setSku($productData->getReferencedId() ?? $productData->getId()); $lineItem->setQuantity($productData->getQuantity()); - $lineItem->setAmountIncludingTax($roundedPrice); + $lineItem->setAmountIncludingTax($this->round($unit)); } 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($roundedPrice); + $lineItem->setAmountIncludingTax($this->round($unit)); } else { throw new \InvalidArgumentException('Unsupported line item type: ' . get_class($productData)); } @@ -991,4 +1003,29 @@ class TransactionService // Store in session for Storefront. $_SESSION['transactionId'] = $transactionId; } + + /** + * Creates a discount line item for negative-priced cart entries. + * + * @param $productData + * @return LineItemCreate + * + */ + private function mapDiscountLineItem($productData): LineItemCreate + { + $price = $productData->getPrice(); + + $lineItem = new LineItemCreate(); + + $amount = abs($price->getTotalPrice()); + + $lineItem->setName($productData->getLabel() ?: 'Discount'); + $lineItem->setUniqueId('discount-' . $productData->getId()); + $lineItem->setSku('discount'); + $lineItem->setQuantity(1); + $lineItem->setAmountIncludingTax($this->round($amount)); + $lineItem->setType(LineItemType::DISCOUNT); + + return $lineItem; + } } diff --git a/src/Core/Checkout/PaymentHandler/VRPaymentPaymentHandler.php b/src/Core/Checkout/PaymentHandler/VRPaymentPaymentHandler.php index 8f3a734..4057afa 100644 --- a/src/Core/Checkout/PaymentHandler/VRPaymentPaymentHandler.php +++ b/src/Core/Checkout/PaymentHandler/VRPaymentPaymentHandler.php @@ -137,7 +137,7 @@ class VRPaymentPaymentHandler extends AbstractPaymentHandler } $contextToken = $this->getContextToken($request); - $parameters = new SalesChannelContextServiceParameters($salesChannelContextId, $contextToken, originalContext: $context); + $parameters = new SalesChannelContextServiceParameters($salesChannelContextId, $contextToken, languageId: $context->getLanguageId(), originalContext: $context); $salesChannelContext = $this->salesChannelContextService->get($parameters); $redirectUrl = $transaction->getReturnUrl(); diff --git a/src/Core/Checkout/Service/PaymentIntegrationService.php b/src/Core/Checkout/Service/PaymentIntegrationService.php index 5d97c53..bfb5c88 100644 --- a/src/Core/Checkout/Service/PaymentIntegrationService.php +++ b/src/Core/Checkout/Service/PaymentIntegrationService.php @@ -12,6 +12,7 @@ use VRPaymentPayment\Core\Api\Transaction\Service\TransactionService; use VRPaymentPayment\Core\Settings\Options\Integration; use VRPaymentPayment\Core\Settings\Service\SettingsService; use VRPaymentPayment\Core\Checkout\Struct\PaymentConfigStruct; +use VRPaymentPayment\Core\Util\LocaleCodeProvider; use VRPayment\Sdk\Model\TransactionState; /** @@ -44,22 +45,30 @@ class PaymentIntegrationService */ private RouterInterface $router; + /** + * @var LocaleCodeProvider + */ + private LocaleCodeProvider $localeCodeProvider; + /** * @param TransactionService $transactionService * @param SettingsService $settingsService * @param TransactionManagementService $transactionManagementService * @param RouterInterface $router + * @param LocaleCodeProvider $localeCodeProvider */ public function __construct( TransactionService $transactionService, SettingsService $settingsService, TransactionManagementService $transactionManagementService, - RouterInterface $router + RouterInterface $router, + LocaleCodeProvider $localeCodeProvider ) { $this->transactionService = $transactionService; $this->settingsService = $settingsService; $this->transactionManagementService = $transactionManagementService; $this->router = $router; + $this->localeCodeProvider = $localeCodeProvider; } /** @@ -82,7 +91,9 @@ class PaymentIntegrationService $transactionId ); - $javascriptUrl = $this->getTransactionJavaScriptUrl($settings, $transactionId); + $localeCode = $this->localeCodeProvider->getLocaleCodeFromContext($salesChannelContext->getContext()); + $paymentPageLocale = $this->localeCodeProvider->mapToPaymentPageLocale($localeCode); + $javascriptUrl = $this->getTransactionJavaScriptUrl($settings, $transactionId, $paymentPageLocale); $possiblePaymentMethods = $settings->getApiClient() ->getTransactionService() @@ -161,9 +172,10 @@ class PaymentIntegrationService * * @param mixed $settings The plugin settings. * @param int $transactionId The transaction ID. + * @param string $paymentPageLocale The payment page locale. * @return string The absolute URL to the JavaScript component. */ - private function getTransactionJavaScriptUrl($settings, int $transactionId): string + private function getTransactionJavaScriptUrl($settings, int $transactionId, string $paymentPageLocale = ''): string { $javascriptUrl = ''; switch ($settings->getIntegration()) { @@ -176,6 +188,12 @@ class PaymentIntegrationService ->javascriptUrl($settings->getSpaceId(), $transactionId); break; } + + if ($javascriptUrl && $paymentPageLocale) { + $separator = str_contains($javascriptUrl, '?') ? '&' : '?'; + $javascriptUrl .= $separator . 'language=' . $paymentPageLocale; + } + return $javascriptUrl; } diff --git a/src/Core/Checkout/Service/PaymentMethodFilterService.php b/src/Core/Checkout/Service/PaymentMethodFilterService.php index 4fddcfa..5f26758 100644 --- a/src/Core/Checkout/Service/PaymentMethodFilterService.php +++ b/src/Core/Checkout/Service/PaymentMethodFilterService.php @@ -5,12 +5,8 @@ declare(strict_types=1); namespace VRPaymentPayment\Core\Checkout\Service; 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\System\SalesChannel\SalesChannelContext; use Shopware\Core\Checkout\Cart\SalesChannel\CartService; -use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting; use VRPaymentPayment\Core\Api\PaymentMethodConfiguration\Service\PaymentMethodConfigurationService; use VRPaymentPayment\Core\Api\Transaction\Service\TransactionService; use VRPaymentPayment\Core\Checkout\PaymentHandler\VRPaymentPaymentHandler; @@ -50,12 +46,6 @@ class PaymentMethodFilterService */ private PaymentMethodUtil $paymentMethodUtil; - /** - * @var EntityRepository - * Repository for Shopware payment methods. - */ - private EntityRepository $paymentMethodRepository; - /** * @var LoggerInterface */ @@ -77,15 +67,14 @@ class PaymentMethodFilterService * @param TransactionService $transactionService * @param PaymentMethodConfigurationService $paymentMethodConfigurationService * @param PaymentMethodUtil $paymentMethodUtil - * @param EntityRepository $paymentMethodRepository * @param TransactionManagementService $transactionManagementService + * @param CartService $cartService */ public function __construct( SettingsService $settingsService, TransactionService $transactionService, PaymentMethodConfigurationService $paymentMethodConfigurationService, PaymentMethodUtil $paymentMethodUtil, - EntityRepository $paymentMethodRepository, TransactionManagementService $transactionManagementService, CartService $cartService ) { @@ -93,7 +82,6 @@ class PaymentMethodFilterService $this->transactionService = $transactionService; $this->paymentMethodConfigurationService = $paymentMethodConfigurationService; $this->paymentMethodUtil = $paymentMethodUtil; - $this->paymentMethodRepository = $paymentMethodRepository; $this->transactionManagementService = $transactionManagementService; $this->cartService = $cartService; } @@ -208,8 +196,12 @@ class PaymentMethodFilterService /** * Builds a filtered PaymentMethodCollection based on allowed IDs. * - * @param PaymentMethodCollection $paymentMethodCollection Original collection. - * @param string[] $allowedIds List of allowed configuration IDs. + * Filters the original collection (which already has Shopware's availability rules applied) + * to only include WhitelabelMachineName methods that are also allowed by the API. + * Non-WhitelabelMachineName methods are kept as-is. + * + * @param PaymentMethodCollection $paymentMethodCollection Original collection (already rule-filtered by Shopware). + * @param string[] $allowedIds List of allowed configuration IDs from the WhitelabelMachineName API. * @param int $spaceId WhitelabelMachineName space ID. * @param SalesChannelContext $salesChannelContext The context. * @return PaymentMethodCollection The final collection. @@ -220,21 +212,12 @@ class PaymentMethodFilterService int $spaceId, SalesChannelContext $salesChannelContext ): PaymentMethodCollection { - $paymentIds = []; - // Extract non-WhitelabelMachineName payment methods first. - foreach ($paymentMethodCollection as $paymentMethodCollectionItem) { - $isVRPaymentPM = VRPaymentPaymentHandler::class === $paymentMethodCollectionItem->getHandlerIdentifier(); - if (!$isVRPaymentPM) { - $paymentIds[] = $paymentMethodCollectionItem->getId(); - } - } - - $allowedWLMethods = []; // Fetch all WhitelabelMachineName payment method configurations for the space. $paymentMethodConfigurations = $this->paymentMethodConfigurationService ->getAllPaymentMethodConfigurations($spaceId, $salesChannelContext->getContext()); - // Check each configuration against the list of allowed IDs from WhitelabelMachineName API. + // Build a map of Shopware payment method ID => configuration for methods allowed by the API. + $allowedWLConfigByPmId = []; foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) { if ($paymentMethodConfiguration->getPaymentMethod() === null) { continue; @@ -247,39 +230,31 @@ class PaymentMethodFilterService $paymentMethodConfiguration->getSpaceId() === $spaceId && \in_array($pmConfigId, $allowedIds, true) ) { - $allowedWLMethods[] = $pmId; + $allowedWLConfigByPmId[$pmId] = $paymentMethodConfiguration; } } - // Combine non-WhitelabelMachineName and allowed WhitelabelMachineName payment methods. - $allPaymentIds = array_unique(array_merge($paymentIds, $allowedWLMethods)); + // Filter the original collection to preserve Shopware's availability rule filtering. + // Non-WLM methods pass through unchanged; WLM methods are kept only if allowed by the API. $collection = new PaymentMethodCollection(); + foreach ($paymentMethodCollection as $method) { + $isVRPaymentPM = VRPaymentPaymentHandler::class === $method->getHandlerIdentifier(); - if (!empty($allPaymentIds)) { - $criteria = new Criteria($allPaymentIds); - $criteria->addFilter(new EqualsFilter('active', true)); - $criteria->addFilter( - new EqualsFilter('salesChannels.id', $salesChannelContext->getSalesChannelId()) - ); - $criteria->addSorting(new FieldSorting('position', FieldSorting::ASCENDING)); - $criteria->addAssociation('media'); - // Re-fetch the entities to ensure we have valid objects with all associations. - $result = $this->paymentMethodRepository->search($criteria, $salesChannelContext->getContext()); - /** @var \Shopware\Core\Checkout\Payment\PaymentMethodEntity $method */ - foreach ($result->getEntities() as $method) { - if (!$collection->has((string)$method->getId())) { - // Attach the configuration to the payment method as an extension for Twig access. - foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) { - if ($paymentMethodConfiguration->getPaymentMethodId() === $method->getId()) { - $method->addExtension('vrpayment_config', $paymentMethodConfiguration); - break; - } - } - $collection->add($method); - } + if (!$isVRPaymentPM) { + $collection->add($method); + continue; + } + + if (isset($allowedWLConfigByPmId[$method->getId()])) { + $method->addExtension('vrpayment_config', $allowedWLConfigByPmId[$method->getId()]); + $collection->add($method); } } + $collection->sort(function ($a, $b) { + return ($a->getPosition() ?? 0) <=> ($b->getPosition() ?? 0); + }); + return $collection; } } diff --git a/src/Core/Util/Analytics/Analytics.php b/src/Core/Util/Analytics/Analytics.php index f9adc82..42ab496 100644 --- a/src/Core/Util/Analytics/Analytics.php +++ b/src/Core/Util/Analytics/Analytics.php @@ -26,7 +26,7 @@ class Analytics { self::SHOP_SYSTEM => 'shopware', self::SHOP_SYSTEM_VERSION => '6', self::SHOP_SYSTEM_AND_VERSION => 'shopware-6', - self::PLUGIN_SYSTEM_VERSION => '7.3.2', + self::PLUGIN_SYSTEM_VERSION => '7.3.3', ]; } diff --git a/src/Core/Util/LocaleCodeProvider.php b/src/Core/Util/LocaleCodeProvider.php index 041c6d5..4b8af8b 100644 --- a/src/Core/Util/LocaleCodeProvider.php +++ b/src/Core/Util/LocaleCodeProvider.php @@ -91,6 +91,26 @@ class LocaleCodeProvider { return $language->getLocale() ? $language->getLocale()->getCode() : $defaultLocale; } + /** + * Maps a locale code to a VRPayment-supported payment page locale by matching the language prefix. + * E.g. de-CH -> de-DE, fr-CH -> fr-FR, en-US -> en-GB, it-CH -> it-IT. + * + * @param string $localeCode + * @return string + */ + public function mapToPaymentPageLocale(string $localeCode): string + { + $supportedLocales = [ + 'de' => self::LOCALE_GERMANY_GERMAN, + 'fr' => self::LOCALE_FRANCE_FRENCH, + 'it' => self::LOCALE_ITALY_ITALIAN, + 'en' => self::LOCALE_GREAT_BRITAIN_ENGLISH, + ]; + + $languagePrefix = substr($localeCode, 0, 2); + + return $supportedLocales[$languagePrefix] ?? self::LOCALE_GREAT_BRITAIN_ENGLISH; + } /** * @param \Shopware\Core\Framework\Context $context diff --git a/src/Resources/app/administration/src/module/vrpayment-settings/page/vrpayment-settings/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-settings/page/vrpayment-settings/index.html.twig index 397b72c..600cd64 100644 --- a/src/Resources/app/administration/src/module/vrpayment-settings/page/vrpayment-settings/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-settings/page/vrpayment-settings/index.html.twig @@ -35,6 +35,7 @@ {% block vrpayment_settings_content_card_channel_config %} @@ -45,14 +46,10 @@ {% block vrpayment_settings_content_card_channel_config_sales_channel_card_title %} - + + {% endblock %} {% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer %}