diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a56aac..55d368b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,23 @@ -# 6.1.15 +# 7.1.0 +## Feature +- Support subscription payment methods +- Support Shopware 6.7.2.0 + +## Bugfix - Fixed issue with shipping costs not being processed correctly +# 7.0.1 +## Feature +- Add plugin version metric + +## Bugfix +- Fixed error message when refund amount exceeds total +- Fixed bug where only 25 sales channels showed in the dropdown +- Removed erroneous logs + +# 7.0.0 +- Compatibility with Shopware 6.7.0 + # 6.1.14 - Disable Recreate Cart for Headless Storefront Order - Added the correct Exception Type to the finalize method diff --git a/CHANGELOG_de-DE.md b/CHANGELOG_de-DE.md index d490c5a..c9edd2d 100644 --- a/CHANGELOG_de-DE.md +++ b/CHANGELOG_de-DE.md @@ -1,5 +1,16 @@ -# 6.1.15 -- Problem behoben, bei dem die Versandkosten nicht korrekt verarbeitet wurden +# 7.1.0 +– Unterstützung für Abonnement-Zahlungsmethoden +– Support für Shopware 6.7.2.0 +– Problem mit fehlerhafter Bearbeitung der Versandkosten behoben + +# 7.0.1 +- Plugin-Versionsmetrik hinzugefügt +- Fehlermeldung behoben, wenn der Rückerstattungsbetrag den Gesamtbetrag überschreitet +- Fehler behoben, bei dem nur 25 Vertriebskanäle in der Dropdown-Liste angezeigt wurden +- Fehlerhafte Protokolle entfernt + +# 7.0.0 +- Kompatibilität mit Shopware 6.7.0 # 6.1.14 – Warenkorb neu erstellen für Headless Storefront Order deaktivieren diff --git a/README.md b/README.md index ef56503..812ce19 100644 --- a/README.md +++ b/README.md @@ -3,21 +3,20 @@ VR Payment Integration for Shopware 6 ============================= -## **Overview** -The VR Payment Payment Plugin integrates modern payment processing into Shopware 6, offering features like iFrame-based payments, refunds, captures, and PCI compliance. It supports seamless integration with the [VR Payment Portal](https://gateway.vr-payment.de/) for managing transactions and payment methods. +The VR Payment plugin wraps around the VR Payment API. This library facilitates your interaction with various services such as transactions. +Please note that this plugin is for versions 6.5, 6.6 or 6.7. For the 6.4 plugin please visit [our Shopware 6.4 plugin](https://github.com/vr-payment/shopware-6-4). ## Requirements -- **Shopware Version:** 6.5.x or 6.6.x (see [compatibility table](#compatibility)). -- **PHP:** Minimum version as required by your Shopware installation (e.g., 7.4+). -- **VR Payment Account:** Obtain `Space ID`, `User ID`, and `API Key` from the [VR Payment Dashboard](https://gateway.vr-payment.de/). +- Shopware 6.7.x, 6.6.x or 6.5.x. See table below. +- PHP minimum version supported by the each shop version. ## Documentation -- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.0/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.0/docs/de/documentation.html) -- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.0/docs/fr/documentation.html) -- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.0/docs/it/documentation.html) +- 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)) ## Installation @@ -62,12 +61,15 @@ Configure supported methods (e.g., credit cards, Apple Pay) via the [VR Payment **Automatic Updates**: Payment methods sync dynamically via the VRPayment API. +**Subscriptions**: Make recurring payments with Subscriptions (Shopware Commercial) and VRPayment. + ## Compatibiliity ___________________________________________________________________________________ | Shopware 6 version | Plugin major version | Supported until | |-------------------------------|------------------------|------------------------| -| Shopware 6.6.x | 6.x | Further notice | +| Shopware 6.7.x | 7.x | Further notice | +| Shopware 6.6.x | 6.x | December 2025 | | Shopware 6.5.x | 5.x | October 2024 | ----------------------------------------------------------------------------------- diff --git a/composer.json b/composer.json index c0ce698..5392c9e 100644 --- a/composer.json +++ b/composer.json @@ -53,11 +53,11 @@ "ext-json": "*", "ext-mbstring": "*", "php": ">=8.2", - "shopware/core": "~6.6.0", - "shopware/administration": "~6.6.0", - "shopware/storefront":"~6.6.0", + "shopware/core": "~6.7.0", + "shopware/administration": "~6.7.0", + "shopware/storefront":"~6.7.0", "vrpayment/sdk": "^4.0.0" }, "type": "shopware-platform-plugin", - "version": "6.1.15" + "version": "7.1.0" } diff --git a/docs/de/documentation.html b/docs/de/documentation.html index fe6017f..049ae0d 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
  • @@ -52,7 +52,7 @@
    @@ -714,10 +720,20 @@ Die Tokenisierung ist für Gast-Checkouts nicht verfügbar +
    +
    +

    + 8.7Wiederkehrende Zahlungen

    +
    +
    +
    +

    Shopware bietet das Paket "Shopware Commercial" mit zusätzlichen Funktionen, unter anderem Abonnements. Dieses Plugin unterstützt Zahlungen, die für Abonnements geeignet sind. Solange der Konnektor der Zahlungsmethode +Tokenisierung unterstützt, kann er für Abonnements verwendet werden. Die wiederkehrende Zahlung wird vollständig vom Shopware Commercial Plugin verwaltet. Weitere Informationen finden Sie in deren Dokumentation.

    +

    - 8.7Hauptfunktionen

    + 8.8Hauptfunktionen
    @@ -734,12 +750,15 @@ Die Tokenisierung ist für Gast-Checkouts nicht verfügbar
  • Automatic Updates: Zahlungsmethoden werden dynamisch über die VR Payment API synchronisiert.

  • +
  • +

    Wiederkehrende Zahlungen: Führen Sie wiederkehrende Zahlungen mit Abonnements (Shopware Commercial) und VRPayment durch.

    +
  • - 8.8Fehlerbehebung

    + 8.9Fehlerbehebung
    @@ -771,7 +790,7 @@ tail -f var/log/whitelabelname_payment*.log

    - 8.9FAQs

    + 8.10FAQs
    @@ -965,18 +984,23 @@ A: Ja, das Plugin unterstützt Wallets wie Apple Pay.

    Tokenisierung diff --git a/docs/de/resource/api-key.png b/docs/de/resource/api-key.png new file mode 100644 index 0000000..c74fe13 Binary files /dev/null and b/docs/de/resource/api-key.png differ diff --git a/docs/de/resource/application-users.png b/docs/de/resource/application-users.png new file mode 100644 index 0000000..51a97b9 Binary files /dev/null and b/docs/de/resource/application-users.png differ diff --git a/docs/de/resource/assign-role.png b/docs/de/resource/assign-role.png new file mode 100644 index 0000000..616a1dd Binary files /dev/null and b/docs/de/resource/assign-role.png differ diff --git a/docs/de/resource/bogus-processor.png b/docs/de/resource/bogus-processor.png new file mode 100644 index 0000000..db79bb1 Binary files /dev/null and b/docs/de/resource/bogus-processor.png differ diff --git a/docs/de/resource/capture-transaction.png b/docs/de/resource/capture-transaction.png new file mode 100644 index 0000000..5fb2044 Binary files /dev/null and b/docs/de/resource/capture-transaction.png differ diff --git a/docs/de/resource/cc-disable.png b/docs/de/resource/cc-disable.png new file mode 100644 index 0000000..88048c8 Binary files /dev/null and b/docs/de/resource/cc-disable.png differ diff --git a/docs/de/resource/cc-enable.png b/docs/de/resource/cc-enable.png new file mode 100644 index 0000000..9b7e655 Binary files /dev/null and b/docs/de/resource/cc-enable.png differ diff --git a/docs/de/resource/connectors.png b/docs/de/resource/connectors.png new file mode 100644 index 0000000..056a892 Binary files /dev/null and b/docs/de/resource/connectors.png differ diff --git a/docs/de/resource/loading-roles.png b/docs/de/resource/loading-roles.png new file mode 100644 index 0000000..5d0d501 Binary files /dev/null and b/docs/de/resource/loading-roles.png differ diff --git a/docs/de/resource/name-processor.png b/docs/de/resource/name-processor.png new file mode 100644 index 0000000..d028107 Binary files /dev/null and b/docs/de/resource/name-processor.png differ diff --git a/docs/de/resource/order-confirmation-email.png b/docs/de/resource/order-confirmation-email.png new file mode 100644 index 0000000..b7e8d57 Binary files /dev/null and b/docs/de/resource/order-confirmation-email.png differ diff --git a/docs/de/resource/payment-method-configuration.png b/docs/de/resource/payment-method-configuration.png new file mode 100644 index 0000000..c84e6c0 Binary files /dev/null and b/docs/de/resource/payment-method-configuration.png differ diff --git a/docs/de/resource/payment-methods.png b/docs/de/resource/payment-methods.png new file mode 100644 index 0000000..4bbea90 Binary files /dev/null and b/docs/de/resource/payment-methods.png differ diff --git a/docs/de/resource/payment-settings.png b/docs/de/resource/payment-settings.png new file mode 100644 index 0000000..bd758a5 Binary files /dev/null and b/docs/de/resource/payment-settings.png differ diff --git a/docs/de/resource/plugin-configuration.png b/docs/de/resource/plugin-configuration.png new file mode 100644 index 0000000..1fa6bd4 Binary files /dev/null and b/docs/de/resource/plugin-configuration.png differ diff --git a/docs/de/resource/plugin-installation.png b/docs/de/resource/plugin-installation.png new file mode 100644 index 0000000..5b32274 Binary files /dev/null and b/docs/de/resource/plugin-installation.png differ diff --git a/docs/de/resource/refund-transaction.png b/docs/de/resource/refund-transaction.png new file mode 100644 index 0000000..a03d38c Binary files /dev/null and b/docs/de/resource/refund-transaction.png differ diff --git a/docs/de/resource/roles.png b/docs/de/resource/roles.png new file mode 100644 index 0000000..6dd3548 Binary files /dev/null and b/docs/de/resource/roles.png differ diff --git a/docs/de/resource/save-role.png b/docs/de/resource/save-role.png new file mode 100644 index 0000000..b5d30cb Binary files /dev/null and b/docs/de/resource/save-role.png differ diff --git a/docs/de/resource/shopware_6_stage_graph_delivery.svg b/docs/de/resource/shopware_6_stage_graph_delivery.svg new file mode 100644 index 0000000..03e5a1d --- /dev/null +++ b/docs/de/resource/shopware_6_stage_graph_delivery.svg @@ -0,0 +1,3 @@ + + +
    Hold
    Hold
    Open
    Open
    Open
    Open
    Transaction fullfil 
    Transaction ful...
    Transaction confirm
    Transaction c...
    Canceled
    Canceled
    Transaction decline / fail / void
    Transaction de...
    1
    1
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/de/resource/shopware_6_stage_graph_order.svg b/docs/de/resource/shopware_6_stage_graph_order.svg new file mode 100644 index 0000000..89a9ea7 --- /dev/null +++ b/docs/de/resource/shopware_6_stage_graph_order.svg @@ -0,0 +1,3 @@ + + +
    In Progress
    In Progress
    Paid
    Paid
    Open
    Open
    Transaction Invoice paid / not applicable
    Transaction Inv...
    Transaction authorized
    Transaction a...
    Transaction failed
    Transaction fai...
    Canceled
    Canceled
    Transaction decline / void
    Transaction de...
    Failed
    Failed
    1
    1
    4
    4
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/de/resource/state_graph_order.svg b/docs/de/resource/state_graph_order.svg new file mode 100644 index 0000000..46dbc35 --- /dev/null +++ b/docs/de/resource/state_graph_order.svg @@ -0,0 +1,2 @@ + +
    Clarification required
    [Not supported by viewer]
    Ready for delivery
    [Not supported by viewer]
    Open
    [Not supported by viewer]
    Transaction fulfill
    [Not supported by viewer]
    Transaction authorized
    [Not supported by viewer]
    Transaction failed
    [Not supported by viewer]
    Canceled / Rejected
    [Not supported by viewer]
    Depending on configuration
    [Not supported by viewer]
    Transaction decline / void
    [Not supported by viewer]
    Order is
    removed
    [Not supported by viewer]
    1
    [Not supported by viewer]
    4
    [Not supported by viewer]
    5
    [Not supported by viewer]
    2
    [Not supported by viewer]
    3
    [Not supported by viewer]
    \ No newline at end of file diff --git a/docs/de/resource/state_graph_payment_state.svg b/docs/de/resource/state_graph_payment_state.svg new file mode 100644 index 0000000..d09a614 --- /dev/null +++ b/docs/de/resource/state_graph_payment_state.svg @@ -0,0 +1,3 @@ + + +
    In Progress
    In Progress
    Paid
    Paid
    Open
    Open
    Transaction complete / fulfill
    Transaction com...
    Transaction authorized
    Transaction a...
    Transaction failed
    Transaction fai...
    Canceled
    Canceled
    Transaction decline / void
    Transaction de...
    Failed
    Failed
    1
    1
    4
    4
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/de/resource/token.png b/docs/de/resource/token.png new file mode 100644 index 0000000..15be72e Binary files /dev/null and b/docs/de/resource/token.png differ diff --git a/docs/de/resource/user.png b/docs/de/resource/user.png new file mode 100644 index 0000000..5673a04 Binary files /dev/null and b/docs/de/resource/user.png differ diff --git a/docs/de/resource/void-transaction.png b/docs/de/resource/void-transaction.png new file mode 100644 index 0000000..8037d28 Binary files /dev/null and b/docs/de/resource/void-transaction.png differ diff --git a/docs/de/resource/webhook-listeners.png b/docs/de/resource/webhook-listeners.png new file mode 100644 index 0000000..7b7f2b4 Binary files /dev/null and b/docs/de/resource/webhook-listeners.png differ diff --git a/docs/de/resource/webhooks.png b/docs/de/resource/webhooks.png new file mode 100644 index 0000000..27a58e1 Binary files /dev/null and b/docs/de/resource/webhooks.png differ diff --git a/docs/en/documentation.html b/docs/en/documentation.html index 7270334..713d26a 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
  • @@ -50,11 +50,13 @@
    -

    Shopware Version: 6.5.x or 6.6.x (see compatibility table).

    +

    Shopware Version: 6.5.x, 6.6.x or 6.7.x (see compatibility table).

    PHP: Minimum version as required by your Shopware installation (e.g., 7.4+).

    VR Payment Account: Obtain Space ID, User ID, and API Key from VR Payment Portal (see Portal Start-up Guide).

    +
    +

    For using recurring payments, you also need Showpare Commercial package, which is a paid product.

    @@ -77,10 +79,16 @@

    Support Until

    +

    6.7.x

    +

    7.x.x

    +

    PHP 8.2 and 8.3

    +

    Ongoing

    + +

    6.6.x

    6.x.x

    PHP 8.2 and 8.3

    -

    Ongoing

    +

    December 2025

    6.5.x - Deprecated

    @@ -727,10 +735,20 @@ Tokenization is not available for guest checkouts.
    +
    +
    +

    + 8.7Recurring payments

    +
    +
    +
    +

    Shopware provides the package "Shopware Commercial" with additional features, among others, subscriptions. This plugin supports making payments that are suitable for subscriptions. As long as the payment method’s conector supports +tokenization, it can be used for subscriptions. The recurring payment is fully managed by Shopware Commercial plugin. Please refer to their documentation for more information.

    +

    - 8.7Key Features

    + 8.8Key Features
    @@ -747,12 +765,15 @@ Tokenization is not available for guest checkouts.
  • Automatic Updates: Payment methods sync dynamically via the VR Payment API.

  • +
  • +

    Recurring payments: Make recurring payments with Subscriptions (Shopware Commercial) and VRPayment.

    +
  • - 8.8Troubleshooting

    + 8.9Troubleshooting
    @@ -783,7 +804,7 @@ Tokenization is not available for guest checkouts.

    - 8.9FAQs

    + 8.10FAQs
    @@ -980,18 +1001,23 @@ Tokenization is not available for guest checkouts. Tokenization diff --git a/docs/en/resource/api-key.png b/docs/en/resource/api-key.png new file mode 100644 index 0000000..c74fe13 Binary files /dev/null and b/docs/en/resource/api-key.png differ diff --git a/docs/en/resource/application-users.png b/docs/en/resource/application-users.png new file mode 100644 index 0000000..51a97b9 Binary files /dev/null and b/docs/en/resource/application-users.png differ diff --git a/docs/en/resource/assign-role.png b/docs/en/resource/assign-role.png new file mode 100644 index 0000000..616a1dd Binary files /dev/null and b/docs/en/resource/assign-role.png differ diff --git a/docs/en/resource/bogus-processor.png b/docs/en/resource/bogus-processor.png new file mode 100644 index 0000000..db79bb1 Binary files /dev/null and b/docs/en/resource/bogus-processor.png differ diff --git a/docs/en/resource/capture-transaction.png b/docs/en/resource/capture-transaction.png new file mode 100644 index 0000000..5fb2044 Binary files /dev/null and b/docs/en/resource/capture-transaction.png differ diff --git a/docs/en/resource/cc-disable.png b/docs/en/resource/cc-disable.png new file mode 100644 index 0000000..88048c8 Binary files /dev/null and b/docs/en/resource/cc-disable.png differ diff --git a/docs/en/resource/cc-enable.png b/docs/en/resource/cc-enable.png new file mode 100644 index 0000000..9b7e655 Binary files /dev/null and b/docs/en/resource/cc-enable.png differ diff --git a/docs/en/resource/connectors.png b/docs/en/resource/connectors.png new file mode 100644 index 0000000..056a892 Binary files /dev/null and b/docs/en/resource/connectors.png differ diff --git a/docs/en/resource/loading-roles.png b/docs/en/resource/loading-roles.png new file mode 100644 index 0000000..5d0d501 Binary files /dev/null and b/docs/en/resource/loading-roles.png differ diff --git a/docs/en/resource/name-processor.png b/docs/en/resource/name-processor.png new file mode 100644 index 0000000..d028107 Binary files /dev/null and b/docs/en/resource/name-processor.png differ diff --git a/docs/en/resource/order-confirmation-email.png b/docs/en/resource/order-confirmation-email.png new file mode 100644 index 0000000..b7e8d57 Binary files /dev/null and b/docs/en/resource/order-confirmation-email.png differ diff --git a/docs/en/resource/payment-method-configuration.png b/docs/en/resource/payment-method-configuration.png new file mode 100644 index 0000000..c84e6c0 Binary files /dev/null and b/docs/en/resource/payment-method-configuration.png differ diff --git a/docs/en/resource/payment-methods.png b/docs/en/resource/payment-methods.png new file mode 100644 index 0000000..4bbea90 Binary files /dev/null and b/docs/en/resource/payment-methods.png differ diff --git a/docs/en/resource/payment-settings.png b/docs/en/resource/payment-settings.png new file mode 100644 index 0000000..bd758a5 Binary files /dev/null and b/docs/en/resource/payment-settings.png differ diff --git a/docs/en/resource/plugin-configuration.png b/docs/en/resource/plugin-configuration.png new file mode 100644 index 0000000..1fa6bd4 Binary files /dev/null and b/docs/en/resource/plugin-configuration.png differ diff --git a/docs/en/resource/plugin-installation.png b/docs/en/resource/plugin-installation.png new file mode 100644 index 0000000..5b32274 Binary files /dev/null and b/docs/en/resource/plugin-installation.png differ diff --git a/docs/en/resource/refund-transaction.png b/docs/en/resource/refund-transaction.png new file mode 100644 index 0000000..a03d38c Binary files /dev/null and b/docs/en/resource/refund-transaction.png differ diff --git a/docs/en/resource/roles.png b/docs/en/resource/roles.png new file mode 100644 index 0000000..6dd3548 Binary files /dev/null and b/docs/en/resource/roles.png differ diff --git a/docs/en/resource/save-role.png b/docs/en/resource/save-role.png new file mode 100644 index 0000000..b5d30cb Binary files /dev/null and b/docs/en/resource/save-role.png differ diff --git a/docs/en/resource/shopware_6_stage_graph_delivery.svg b/docs/en/resource/shopware_6_stage_graph_delivery.svg new file mode 100644 index 0000000..03e5a1d --- /dev/null +++ b/docs/en/resource/shopware_6_stage_graph_delivery.svg @@ -0,0 +1,3 @@ + + +
    Hold
    Hold
    Open
    Open
    Open
    Open
    Transaction fullfil 
    Transaction ful...
    Transaction confirm
    Transaction c...
    Canceled
    Canceled
    Transaction decline / fail / void
    Transaction de...
    1
    1
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/en/resource/shopware_6_stage_graph_order.svg b/docs/en/resource/shopware_6_stage_graph_order.svg new file mode 100644 index 0000000..89a9ea7 --- /dev/null +++ b/docs/en/resource/shopware_6_stage_graph_order.svg @@ -0,0 +1,3 @@ + + +
    In Progress
    In Progress
    Paid
    Paid
    Open
    Open
    Transaction Invoice paid / not applicable
    Transaction Inv...
    Transaction authorized
    Transaction a...
    Transaction failed
    Transaction fai...
    Canceled
    Canceled
    Transaction decline / void
    Transaction de...
    Failed
    Failed
    1
    1
    4
    4
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/en/resource/state_graph_order.svg b/docs/en/resource/state_graph_order.svg new file mode 100644 index 0000000..46dbc35 --- /dev/null +++ b/docs/en/resource/state_graph_order.svg @@ -0,0 +1,2 @@ + +
    Clarification required
    [Not supported by viewer]
    Ready for delivery
    [Not supported by viewer]
    Open
    [Not supported by viewer]
    Transaction fulfill
    [Not supported by viewer]
    Transaction authorized
    [Not supported by viewer]
    Transaction failed
    [Not supported by viewer]
    Canceled / Rejected
    [Not supported by viewer]
    Depending on configuration
    [Not supported by viewer]
    Transaction decline / void
    [Not supported by viewer]
    Order is
    removed
    [Not supported by viewer]
    1
    [Not supported by viewer]
    4
    [Not supported by viewer]
    5
    [Not supported by viewer]
    2
    [Not supported by viewer]
    3
    [Not supported by viewer]
    \ No newline at end of file diff --git a/docs/en/resource/state_graph_payment_state.svg b/docs/en/resource/state_graph_payment_state.svg new file mode 100644 index 0000000..d09a614 --- /dev/null +++ b/docs/en/resource/state_graph_payment_state.svg @@ -0,0 +1,3 @@ + + +
    In Progress
    In Progress
    Paid
    Paid
    Open
    Open
    Transaction complete / fulfill
    Transaction com...
    Transaction authorized
    Transaction a...
    Transaction failed
    Transaction fai...
    Canceled
    Canceled
    Transaction decline / void
    Transaction de...
    Failed
    Failed
    1
    1
    4
    4
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/en/resource/token.png b/docs/en/resource/token.png new file mode 100644 index 0000000..15be72e Binary files /dev/null and b/docs/en/resource/token.png differ diff --git a/docs/en/resource/user.png b/docs/en/resource/user.png new file mode 100644 index 0000000..5673a04 Binary files /dev/null and b/docs/en/resource/user.png differ diff --git a/docs/en/resource/void-transaction.png b/docs/en/resource/void-transaction.png new file mode 100644 index 0000000..8037d28 Binary files /dev/null and b/docs/en/resource/void-transaction.png differ diff --git a/docs/en/resource/webhook-listeners.png b/docs/en/resource/webhook-listeners.png new file mode 100644 index 0000000..7b7f2b4 Binary files /dev/null and b/docs/en/resource/webhook-listeners.png differ diff --git a/docs/en/resource/webhooks.png b/docs/en/resource/webhooks.png new file mode 100644 index 0000000..27a58e1 Binary files /dev/null and b/docs/en/resource/webhooks.png differ diff --git a/docs/fr/documentation.html b/docs/fr/documentation.html index 7347056..96bf5c0 100644 --- a/docs/fr/documentation.html +++ b/docs/fr/documentation.html @@ -5,7 +5,7 @@ - + Wallee Payment Plugin pour Shopware 6 @@ -23,7 +23,7 @@
  • - + Source
  • @@ -50,7 +50,7 @@
    -

    Shopware Version: 6.5.x or 6.6.x (voir tableau de compatibilité).

    +

    Shopware Version: 6.5.x, 6.6.x or 6.7.x (voir tableau de compatibilité).

    PHP: Version minimale requise pour votre installation Shopware (e.g., 7.4+).

    @@ -71,22 +71,28 @@ -

    Shopware Version

    -

    Plugin Version

    -

    PHP Version

    -

    Support Until

    +

    Version Shopware

    +

    Version du Plugin

    +

    Version PHP

    +

    Support jusqu’à

    + + +

    6.7.x

    +

    7.x.x

    +

    PHP 8.2 et 8.3

    +

    En cours

    6.6.x

    6.x.x

    -

    PHP 8.2 and 8.3

    -

    En cours

    +

    PHP 8.2 et 8.3

    +

    Décembre 2025

    -

    6.5.x - Deprecated

    +

    6.5.x – Obsolète

    5.x.x

    -

    PHP 8.2 and 8.3

    -

    October 2024

    +

    PHP 8.2 et 8.3

    +

    Octobre 2024

    @@ -705,10 +711,19 @@ La tokenisation n’est pas disponible pour les paiements par les invités.
    +
    +
    +

    + 8.7Paiements récurrents

    +
    +
    +
    +

    Shopware fournit le package "Shopware Commercial" avec des fonctionnalités supplémentaires, entre autres, les abonnements. Ce plugin prend en charge les paiements adaptés aux abonnements. Tant que le connecteur de la méthode de paiement prend en charge la tokenisation, il peut être utilisé pour les abonnements. Le paiement récurrent est entièrement géré par le plugin Shopware Commercial. Veuillez vous référer à leur documentation pour plus d’informations.

    +

    - 8.7Caractéristiques Pricinpales

    + 8.8Caractéristiques Pricinpales
    @@ -725,12 +740,15 @@ La tokenisation n’est pas disponible pour les paiements par les invités.
  • Mises à jour automatiques: Les méthodes de paiement se synchronisent dynamiquement via l’API Wallee.

  • +
  • +

    Paiements récurrents: Effectuez des paiements récurrents avec les abonnements (Shopware Commercial) et VRPayment.

    +
  • - 8.8Troubleshooting

    + 8.9Troubleshooting
    @@ -761,7 +779,7 @@ La tokenisation n’est pas disponible pour les paiements par les invités.

    - 8.9FAQs

    + 8.10FAQs
    @@ -954,18 +972,23 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.

    Tokenisation diff --git a/docs/fr/resource/api-key.png b/docs/fr/resource/api-key.png new file mode 100644 index 0000000..c74fe13 Binary files /dev/null and b/docs/fr/resource/api-key.png differ diff --git a/docs/fr/resource/application-users.png b/docs/fr/resource/application-users.png new file mode 100644 index 0000000..51a97b9 Binary files /dev/null and b/docs/fr/resource/application-users.png differ diff --git a/docs/fr/resource/assign-role.png b/docs/fr/resource/assign-role.png new file mode 100644 index 0000000..616a1dd Binary files /dev/null and b/docs/fr/resource/assign-role.png differ diff --git a/docs/fr/resource/bogus-processor.png b/docs/fr/resource/bogus-processor.png new file mode 100644 index 0000000..db79bb1 Binary files /dev/null and b/docs/fr/resource/bogus-processor.png differ diff --git a/docs/fr/resource/capture-transaction.png b/docs/fr/resource/capture-transaction.png new file mode 100644 index 0000000..5fb2044 Binary files /dev/null and b/docs/fr/resource/capture-transaction.png differ diff --git a/docs/fr/resource/cc-disable.png b/docs/fr/resource/cc-disable.png new file mode 100644 index 0000000..88048c8 Binary files /dev/null and b/docs/fr/resource/cc-disable.png differ diff --git a/docs/fr/resource/cc-enable.png b/docs/fr/resource/cc-enable.png new file mode 100644 index 0000000..9b7e655 Binary files /dev/null and b/docs/fr/resource/cc-enable.png differ diff --git a/docs/fr/resource/connectors.png b/docs/fr/resource/connectors.png new file mode 100644 index 0000000..056a892 Binary files /dev/null and b/docs/fr/resource/connectors.png differ diff --git a/docs/fr/resource/loading-roles.png b/docs/fr/resource/loading-roles.png new file mode 100644 index 0000000..5d0d501 Binary files /dev/null and b/docs/fr/resource/loading-roles.png differ diff --git a/docs/fr/resource/name-processor.png b/docs/fr/resource/name-processor.png new file mode 100644 index 0000000..d028107 Binary files /dev/null and b/docs/fr/resource/name-processor.png differ diff --git a/docs/fr/resource/order-confirmation-email.png b/docs/fr/resource/order-confirmation-email.png new file mode 100644 index 0000000..b7e8d57 Binary files /dev/null and b/docs/fr/resource/order-confirmation-email.png differ diff --git a/docs/fr/resource/payment-method-configuration.png b/docs/fr/resource/payment-method-configuration.png new file mode 100644 index 0000000..c84e6c0 Binary files /dev/null and b/docs/fr/resource/payment-method-configuration.png differ diff --git a/docs/fr/resource/payment-methods.png b/docs/fr/resource/payment-methods.png new file mode 100644 index 0000000..4bbea90 Binary files /dev/null and b/docs/fr/resource/payment-methods.png differ diff --git a/docs/fr/resource/payment-settings.png b/docs/fr/resource/payment-settings.png new file mode 100644 index 0000000..bd758a5 Binary files /dev/null and b/docs/fr/resource/payment-settings.png differ diff --git a/docs/fr/resource/plugin-configuration.png b/docs/fr/resource/plugin-configuration.png new file mode 100644 index 0000000..1fa6bd4 Binary files /dev/null and b/docs/fr/resource/plugin-configuration.png differ diff --git a/docs/fr/resource/plugin-installation.png b/docs/fr/resource/plugin-installation.png new file mode 100644 index 0000000..5b32274 Binary files /dev/null and b/docs/fr/resource/plugin-installation.png differ diff --git a/docs/fr/resource/refund-transaction.png b/docs/fr/resource/refund-transaction.png new file mode 100644 index 0000000..a03d38c Binary files /dev/null and b/docs/fr/resource/refund-transaction.png differ diff --git a/docs/fr/resource/roles.png b/docs/fr/resource/roles.png new file mode 100644 index 0000000..6dd3548 Binary files /dev/null and b/docs/fr/resource/roles.png differ diff --git a/docs/fr/resource/save-role.png b/docs/fr/resource/save-role.png new file mode 100644 index 0000000..b5d30cb Binary files /dev/null and b/docs/fr/resource/save-role.png differ diff --git a/docs/fr/resource/shopware_6_stage_graph_delivery.svg b/docs/fr/resource/shopware_6_stage_graph_delivery.svg new file mode 100644 index 0000000..03e5a1d --- /dev/null +++ b/docs/fr/resource/shopware_6_stage_graph_delivery.svg @@ -0,0 +1,3 @@ + + +
    Hold
    Hold
    Open
    Open
    Open
    Open
    Transaction fullfil 
    Transaction ful...
    Transaction confirm
    Transaction c...
    Canceled
    Canceled
    Transaction decline / fail / void
    Transaction de...
    1
    1
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/fr/resource/shopware_6_stage_graph_order.svg b/docs/fr/resource/shopware_6_stage_graph_order.svg new file mode 100644 index 0000000..89a9ea7 --- /dev/null +++ b/docs/fr/resource/shopware_6_stage_graph_order.svg @@ -0,0 +1,3 @@ + + +
    In Progress
    In Progress
    Paid
    Paid
    Open
    Open
    Transaction Invoice paid / not applicable
    Transaction Inv...
    Transaction authorized
    Transaction a...
    Transaction failed
    Transaction fai...
    Canceled
    Canceled
    Transaction decline / void
    Transaction de...
    Failed
    Failed
    1
    1
    4
    4
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/fr/resource/state_graph_order.svg b/docs/fr/resource/state_graph_order.svg new file mode 100644 index 0000000..46dbc35 --- /dev/null +++ b/docs/fr/resource/state_graph_order.svg @@ -0,0 +1,2 @@ + +
    Clarification required
    [Not supported by viewer]
    Ready for delivery
    [Not supported by viewer]
    Open
    [Not supported by viewer]
    Transaction fulfill
    [Not supported by viewer]
    Transaction authorized
    [Not supported by viewer]
    Transaction failed
    [Not supported by viewer]
    Canceled / Rejected
    [Not supported by viewer]
    Depending on configuration
    [Not supported by viewer]
    Transaction decline / void
    [Not supported by viewer]
    Order is
    removed
    [Not supported by viewer]
    1
    [Not supported by viewer]
    4
    [Not supported by viewer]
    5
    [Not supported by viewer]
    2
    [Not supported by viewer]
    3
    [Not supported by viewer]
    \ No newline at end of file diff --git a/docs/fr/resource/state_graph_payment_state.svg b/docs/fr/resource/state_graph_payment_state.svg new file mode 100644 index 0000000..d09a614 --- /dev/null +++ b/docs/fr/resource/state_graph_payment_state.svg @@ -0,0 +1,3 @@ + + +
    In Progress
    In Progress
    Paid
    Paid
    Open
    Open
    Transaction complete / fulfill
    Transaction com...
    Transaction authorized
    Transaction a...
    Transaction failed
    Transaction fai...
    Canceled
    Canceled
    Transaction decline / void
    Transaction de...
    Failed
    Failed
    1
    1
    4
    4
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/fr/resource/token.png b/docs/fr/resource/token.png new file mode 100644 index 0000000..15be72e Binary files /dev/null and b/docs/fr/resource/token.png differ diff --git a/docs/fr/resource/user.png b/docs/fr/resource/user.png new file mode 100644 index 0000000..5673a04 Binary files /dev/null and b/docs/fr/resource/user.png differ diff --git a/docs/fr/resource/void-transaction.png b/docs/fr/resource/void-transaction.png new file mode 100644 index 0000000..8037d28 Binary files /dev/null and b/docs/fr/resource/void-transaction.png differ diff --git a/docs/fr/resource/webhook-listeners.png b/docs/fr/resource/webhook-listeners.png new file mode 100644 index 0000000..7b7f2b4 Binary files /dev/null and b/docs/fr/resource/webhook-listeners.png differ diff --git a/docs/fr/resource/webhooks.png b/docs/fr/resource/webhooks.png new file mode 100644 index 0000000..27a58e1 Binary files /dev/null and b/docs/fr/resource/webhooks.png differ diff --git a/docs/it/documentation.html b/docs/it/documentation.html index 1d134c8..f89f2ec 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
  • @@ -50,7 +50,7 @@
    -

    Versione di Shopware: 6.5.x o 6.6.x (vedere la tabella di compatibilità).

    +

    Versione di Shopware: 6.5.x, 6.6.x o 6.7.x (vedere la tabella di compatibilità).

    PHP: Versione minima richiesta dalla vostra installazione di Shopware (ad es. 7.4+).

    @@ -71,22 +71,28 @@ -

    Shopware Version

    -

    Plugin Version

    -

    PHP Version

    -

    Support Until

    +

    Versione Shopware

    +

    Versione Plugin

    +

    Versione PHP

    +

    Supporto fino a

    + + +

    6.7.x

    +

    7.x.x

    +

    PHP 8.2 e 8.3

    +

    In corso

    6.6.x

    6.x.x

    -

    PHP 8.2 and 8.3

    -

    Ongoing

    +

    PHP 8.2 e 8.3

    +

    Dicembre 2025

    -

    6.5.x - Deprecated

    +

    6.5.x – Deprecato

    5.x.x

    -

    PHP 8.2 and 8.3

    -

    October 2024

    +

    PHP 8.2 e 8.3

    +

    Ottobre 2024

    @@ -712,10 +718,19 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
    +
    +
    +

    + 8.7Pagamenti ricorrenti

    +
    +
    +
    +

    Shopware fornisce il pacchetto "Shopware Commercial" con funzionalità aggiuntive, tra cui gli abbonamenti. Questo plugin supporta l’esecuzione di pagamenti adatti per gli abbonamenti. Finché il connettore del metodo di pagamento supporta la tokenizzazione, può essere utilizzato per gli abbonamenti. Il pagamento ricorrente è completamente gestito dal plugin Shopware Commercial. Si prega di fare riferimento alla loro documentazione per maggiori informazioni.

    +

    - 8.7Key Features

    + 8.8Key Features
    @@ -732,12 +747,15 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
  • Automatic Updates: I metodi di pagamento si sincronizzano dinamicamente tramite l’API VR Payment.

  • +
  • +

    Pagamenti ricorrenti: Effettua pagamenti ricorrenti con Abbonamenti (Shopware Commercial) e VRPayment.

    +
  • - 8.8Risoluzione dei Problemi

    + 8.9Risoluzione dei Problemi
    @@ -768,7 +786,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.

    - 8.9FAQs

    + 8.10FAQs
    @@ -965,18 +983,23 @@ La tokenizzazione non è disponibile per i checkout degli ospiti. Tokenization diff --git a/docs/it/resource/api-key.png b/docs/it/resource/api-key.png new file mode 100644 index 0000000..c74fe13 Binary files /dev/null and b/docs/it/resource/api-key.png differ diff --git a/docs/it/resource/application-users.png b/docs/it/resource/application-users.png new file mode 100644 index 0000000..51a97b9 Binary files /dev/null and b/docs/it/resource/application-users.png differ diff --git a/docs/it/resource/assign-role.png b/docs/it/resource/assign-role.png new file mode 100644 index 0000000..616a1dd Binary files /dev/null and b/docs/it/resource/assign-role.png differ diff --git a/docs/it/resource/bogus-processor.png b/docs/it/resource/bogus-processor.png new file mode 100644 index 0000000..db79bb1 Binary files /dev/null and b/docs/it/resource/bogus-processor.png differ diff --git a/docs/it/resource/capture-transaction.png b/docs/it/resource/capture-transaction.png new file mode 100644 index 0000000..5fb2044 Binary files /dev/null and b/docs/it/resource/capture-transaction.png differ diff --git a/docs/it/resource/cc-disable.png b/docs/it/resource/cc-disable.png new file mode 100644 index 0000000..88048c8 Binary files /dev/null and b/docs/it/resource/cc-disable.png differ diff --git a/docs/it/resource/cc-enable.png b/docs/it/resource/cc-enable.png new file mode 100644 index 0000000..9b7e655 Binary files /dev/null and b/docs/it/resource/cc-enable.png differ diff --git a/docs/it/resource/connectors.png b/docs/it/resource/connectors.png new file mode 100644 index 0000000..056a892 Binary files /dev/null and b/docs/it/resource/connectors.png differ diff --git a/docs/it/resource/loading-roles.png b/docs/it/resource/loading-roles.png new file mode 100644 index 0000000..5d0d501 Binary files /dev/null and b/docs/it/resource/loading-roles.png differ diff --git a/docs/it/resource/name-processor.png b/docs/it/resource/name-processor.png new file mode 100644 index 0000000..d028107 Binary files /dev/null and b/docs/it/resource/name-processor.png differ diff --git a/docs/it/resource/order-confirmation-email.png b/docs/it/resource/order-confirmation-email.png new file mode 100644 index 0000000..b7e8d57 Binary files /dev/null and b/docs/it/resource/order-confirmation-email.png differ diff --git a/docs/it/resource/payment-method-configuration.png b/docs/it/resource/payment-method-configuration.png new file mode 100644 index 0000000..c84e6c0 Binary files /dev/null and b/docs/it/resource/payment-method-configuration.png differ diff --git a/docs/it/resource/payment-methods.png b/docs/it/resource/payment-methods.png new file mode 100644 index 0000000..4bbea90 Binary files /dev/null and b/docs/it/resource/payment-methods.png differ diff --git a/docs/it/resource/payment-settings.png b/docs/it/resource/payment-settings.png new file mode 100644 index 0000000..bd758a5 Binary files /dev/null and b/docs/it/resource/payment-settings.png differ diff --git a/docs/it/resource/plugin-configuration.png b/docs/it/resource/plugin-configuration.png new file mode 100644 index 0000000..1fa6bd4 Binary files /dev/null and b/docs/it/resource/plugin-configuration.png differ diff --git a/docs/it/resource/plugin-installation.png b/docs/it/resource/plugin-installation.png new file mode 100644 index 0000000..5b32274 Binary files /dev/null and b/docs/it/resource/plugin-installation.png differ diff --git a/docs/it/resource/refund-transaction.png b/docs/it/resource/refund-transaction.png new file mode 100644 index 0000000..a03d38c Binary files /dev/null and b/docs/it/resource/refund-transaction.png differ diff --git a/docs/it/resource/roles.png b/docs/it/resource/roles.png new file mode 100644 index 0000000..6dd3548 Binary files /dev/null and b/docs/it/resource/roles.png differ diff --git a/docs/it/resource/save-role.png b/docs/it/resource/save-role.png new file mode 100644 index 0000000..b5d30cb Binary files /dev/null and b/docs/it/resource/save-role.png differ diff --git a/docs/it/resource/shopware_6_stage_graph_delivery.svg b/docs/it/resource/shopware_6_stage_graph_delivery.svg new file mode 100644 index 0000000..03e5a1d --- /dev/null +++ b/docs/it/resource/shopware_6_stage_graph_delivery.svg @@ -0,0 +1,3 @@ + + +
    Hold
    Hold
    Open
    Open
    Open
    Open
    Transaction fullfil 
    Transaction ful...
    Transaction confirm
    Transaction c...
    Canceled
    Canceled
    Transaction decline / fail / void
    Transaction de...
    1
    1
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/it/resource/shopware_6_stage_graph_order.svg b/docs/it/resource/shopware_6_stage_graph_order.svg new file mode 100644 index 0000000..89a9ea7 --- /dev/null +++ b/docs/it/resource/shopware_6_stage_graph_order.svg @@ -0,0 +1,3 @@ + + +
    In Progress
    In Progress
    Paid
    Paid
    Open
    Open
    Transaction Invoice paid / not applicable
    Transaction Inv...
    Transaction authorized
    Transaction a...
    Transaction failed
    Transaction fai...
    Canceled
    Canceled
    Transaction decline / void
    Transaction de...
    Failed
    Failed
    1
    1
    4
    4
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/it/resource/state_graph_order.svg b/docs/it/resource/state_graph_order.svg new file mode 100644 index 0000000..46dbc35 --- /dev/null +++ b/docs/it/resource/state_graph_order.svg @@ -0,0 +1,2 @@ + +
    Clarification required
    [Not supported by viewer]
    Ready for delivery
    [Not supported by viewer]
    Open
    [Not supported by viewer]
    Transaction fulfill
    [Not supported by viewer]
    Transaction authorized
    [Not supported by viewer]
    Transaction failed
    [Not supported by viewer]
    Canceled / Rejected
    [Not supported by viewer]
    Depending on configuration
    [Not supported by viewer]
    Transaction decline / void
    [Not supported by viewer]
    Order is
    removed
    [Not supported by viewer]
    1
    [Not supported by viewer]
    4
    [Not supported by viewer]
    5
    [Not supported by viewer]
    2
    [Not supported by viewer]
    3
    [Not supported by viewer]
    \ No newline at end of file diff --git a/docs/it/resource/state_graph_payment_state.svg b/docs/it/resource/state_graph_payment_state.svg new file mode 100644 index 0000000..d09a614 --- /dev/null +++ b/docs/it/resource/state_graph_payment_state.svg @@ -0,0 +1,3 @@ + + +
    In Progress
    In Progress
    Paid
    Paid
    Open
    Open
    Transaction complete / fulfill
    Transaction com...
    Transaction authorized
    Transaction a...
    Transaction failed
    Transaction fai...
    Canceled
    Canceled
    Transaction decline / void
    Transaction de...
    Failed
    Failed
    1
    1
    4
    4
    2
    2
    3
    3
    Viewer does not support full SVG 1.1
    \ No newline at end of file diff --git a/docs/it/resource/token.png b/docs/it/resource/token.png new file mode 100644 index 0000000..15be72e Binary files /dev/null and b/docs/it/resource/token.png differ diff --git a/docs/it/resource/user.png b/docs/it/resource/user.png new file mode 100644 index 0000000..5673a04 Binary files /dev/null and b/docs/it/resource/user.png differ diff --git a/docs/it/resource/void-transaction.png b/docs/it/resource/void-transaction.png new file mode 100644 index 0000000..8037d28 Binary files /dev/null and b/docs/it/resource/void-transaction.png differ diff --git a/docs/it/resource/webhook-listeners.png b/docs/it/resource/webhook-listeners.png new file mode 100644 index 0000000..7b7f2b4 Binary files /dev/null and b/docs/it/resource/webhook-listeners.png differ diff --git a/docs/it/resource/webhooks.png b/docs/it/resource/webhooks.png new file mode 100644 index 0000000..27a58e1 Binary files /dev/null and b/docs/it/resource/webhooks.png differ diff --git a/src/Core/Api/PaymentMethodConfiguration/Service/PaymentMethodConfigurationService.php b/src/Core/Api/PaymentMethodConfiguration/Service/PaymentMethodConfigurationService.php index 508f807..60ec19b 100644 --- a/src/Core/Api/PaymentMethodConfiguration/Service/PaymentMethodConfigurationService.php +++ b/src/Core/Api/PaymentMethodConfiguration/Service/PaymentMethodConfigurationService.php @@ -499,6 +499,7 @@ class PaymentMethodConfigurationService { 'afterOrderEnabled' => true, 'active' => true, 'translations' => $this->getPaymentMethodConfigurationTranslation($paymentMethodConfiguration, $context), + 'technicalName' => $paymentMethodConfiguration->getName(), ]; $data['mediaId'] = $this->upsertMedia($id, $paymentMethodConfiguration, $context); diff --git a/src/Core/Api/Refund/Controller/RefundController.php b/src/Core/Api/Refund/Controller/RefundController.php index 0133c85..b6b8661 100644 --- a/src/Core/Api/Refund/Controller/RefundController.php +++ b/src/Core/Api/Refund/Controller/RefundController.php @@ -115,7 +115,11 @@ class RefundController extends AbstractController $apiClient = $settings->getApiClient(); $transaction = $apiClient->getTransactionService()->read($settings->getSpaceId(), $transactionId); - $this->refundService->createRefundByAmount($transaction, $refundableAmount, $context); + $refund = $this->refundService->createRefundByAmount($transaction, $refundableAmount, $context); + + if ($refund === null) { + return new Response('refundExceedsAmount', Response::HTTP_BAD_REQUEST); + } return new Response(null, Response::HTTP_NO_CONTENT); } diff --git a/src/Core/Api/Transaction/Service/TransactionService.php b/src/Core/Api/Transaction/Service/TransactionService.php index 64f4754..f8ea0dd 100644 --- a/src/Core/Api/Transaction/Service/TransactionService.php +++ b/src/Core/Api/Transaction/Service/TransactionService.php @@ -8,7 +8,7 @@ use Shopware\Core\{ Checkout\Cart\CartException, Checkout\Cart\LineItem\LineItem, Checkout\Order\OrderEntity, - Checkout\Payment\Cart\AsyncPaymentTransactionStruct, + Checkout\Payment\Cart\PaymentTransactionStruct, Framework\Context, Framework\DataAbstractionLayer\Search\Criteria, Framework\DataAbstractionLayer\Search\Filter\EqualsFilter, @@ -16,22 +16,23 @@ use Shopware\Core\{ }; use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use VRPayment\Sdk\{ - Model\AddressCreate, - Model\ChargeAttempt, - Model\CreationEntityState, - Model\CriteriaOperator, - Model\EntityQuery, - Model\EntityQueryFilter, - Model\EntityQueryFilterType, - Model\Gender, - Model\LineItemAttributeCreate, - Model\LineItemCreate, - Model\LineItemType, - Model\Transaction, - Model\TransactionCreate, - Model\TransactionPending, - Model\TransactionState, +use VRPayment\Sdk\Model\{ + AddressCreate, + ChargeAttempt, + CreationEntityState, + CriteriaOperator, + EntityQuery, + EntityQueryFilter, + EntityQueryFilterType, + Gender, + LineItemAttributeCreate, + LineItemCreate, + LineItemType, + TokenizationMode, + Transaction, + TransactionCreate, + TransactionPending, + TransactionState, }; use VRPaymentPayment\Core\{ Api\OrderDeliveryState\Handler\OrderDeliveryStateHandler, @@ -115,7 +116,7 @@ class TransactionService * * A redirect to the url will be performed * - * @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction + * @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction * @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext * * @return string @@ -124,10 +125,14 @@ class TransactionService * @throws \VRPayment\Sdk\VersioningException */ public function create( - AsyncPaymentTransactionStruct $transaction, - SalesChannelContext $salesChannelContext + PaymentTransactionStruct $transaction, + SalesChannelContext $salesChannelContext ): string { + $criteria = new Criteria([$transaction->getOrderTransactionId()]); + $criteria->addAssociation('order'); + $orderTransaction = $this->container->get('order_transaction.repository')->search($criteria, $salesChannelContext->getContext())->first(); + $salesChannelId = $salesChannelContext->getSalesChannel()->getId(); $settings = $this->settingsService->getSettings($salesChannelId); $apiClient = $settings->getApiClient(); @@ -165,7 +170,7 @@ class TransactionService $redirectUrl = $this->container->get('router')->generate( 'frontend.vrpayment.checkout.pay', - ['orderId' => $transaction->getOrder()->getId(),], + ['orderId' => $orderTransaction->getOrder()->getId(),], UrlGeneratorInterface::ABSOLUTE_URL ); @@ -177,8 +182,8 @@ class TransactionService $this->upsert( $createdTransaction, $salesChannelContext->getContext(), - $transaction->getOrderTransaction()->getPaymentMethodId(), - $transaction->getOrder()->getSalesChannelId() + $orderTransaction->getPaymentMethodId(), + $orderTransaction->getOrder()->getSalesChannelId() ); $_SESSION['transactionId'] = null; $_SESSION['arrayOfPossibleMethods'] = null; @@ -186,26 +191,45 @@ class TransactionService $_SESSION['currencyCheck'] = null; - $this->holdDelivery($transaction->getOrder()->getId(), $salesChannelContext->getContext()); + $this->holdDelivery($orderTransaction->getOrder()->getId(), $salesChannelContext->getContext()); return $redirectUrl; } /** - * @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction + * Creates the transaction in the portal using the SDK. + * + * @return void + */ + public function createRecurringTransaction(TransactionCreate $sdkTransactionCreate, string $spaceId = ""): Transaction { + $settings = $this->settingsService->getSettings(); + if (empty($spaceId)) { + $spaceId = $settings->getSpaceId(); + } + + $sdkTransaction = $settings->getApiClient()->getTransactionService()->create($spaceId, $sdkTransactionCreate); + if ($sdkTransaction->valid()) { + return $settings->getApiClient()->getTransactionService()->processWithoutUserInteraction($spaceId, $sdkTransaction->getId()); + } + + throw new \Exception("The transacion is not valid and could not be created."); + } + + /** + * @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction * @param \Shopware\Core\Framework\Context $context * @param int $vrpaymentTransactionId * @param int $spaceId */ protected function addVRPaymentTransactionId( - AsyncPaymentTransactionStruct $transaction, + PaymentTransactionStruct $transaction, Context $context, int $vrpaymentTransactionId, int $spaceId ): void { $data = [ - 'id' => $transaction->getOrderTransaction()->getId(), + 'id' => $transaction->getOrderTransactionId(), 'customFields' => [ TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TRANSACTION_ID => $vrpaymentTransactionId, TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_SPACE_ID => $spaceId, @@ -343,7 +367,7 @@ class TransactionService * * @return \Shopware\Core\Checkout\Order\OrderEntity */ - private function getOrderEntity(string $orderId, Context $context): OrderEntity + protected function getOrderEntity(string $orderId, Context $context): OrderEntity { try { $criteria = (new Criteria([$orderId]))->addAssociations(['deliveries']); @@ -387,7 +411,7 @@ class TransactionService * @throws \VRPayment\Sdk\Http\ConnectionException * @throws \VRPayment\Sdk\VersioningException */ - public function read(int $transactionId, string $salesChannelId): Transaction + public function read(int $transactionId, string $salesChannelId = ""): Transaction { $settings = $this->settingsService->getSettings($salesChannelId); return $settings->getApiClient()->getTransactionService()->read($settings->getSpaceId(), $transactionId); @@ -594,7 +618,8 @@ class TransactionService ->setCustomerEmailAddress($customer->getEmail()) ->setCustomerId($customerId) ->setSuccessUrl($homeUrl . '?success') - ->setFailedUrl($homeUrl . '?fail'); + ->setFailedUrl($homeUrl . '?fail') + ->setTokenizationMode(TokenizationMode::FORCE_CREATION); $transactionService = $settings->getApiClient()->getTransactionService(); $transaction = $transactionService->create($settings->getSpaceId(), $transactionPayload); diff --git a/src/Core/Api/WebHooks/Strategy/WebHookTransactionStrategy.php b/src/Core/Api/WebHooks/Strategy/WebHookTransactionStrategy.php index a100f45..f0b75f7 100644 --- a/src/Core/Api/WebHooks/Strategy/WebHookTransactionStrategy.php +++ b/src/Core/Api/WebHooks/Strategy/WebHookTransactionStrategy.php @@ -9,12 +9,13 @@ use Shopware\Core\{ Checkout\Cart\CartException, Framework\Context, System\StateMachine\Exception\IllegalTransitionException}; -use VRPayment\Sdk\{ - Model\RefundState, - Model\Transaction, - Model\TransactionInvoiceState, - Model\TransactionState, - Model\TransactionInvoice,}; +use VRPayment\Sdk\Model\{ + RefundState, + Transaction, + TransactionInvoiceState, + TransactionState, + TransactionInvoice, + Token}; use VRPaymentPayment\Core\{ Api\WebHooks\Service\WebHooksService, Api\WebHooks\Struct\WebHookRequest, @@ -51,7 +52,7 @@ class WebHookTransactionStrategy extends WebHookStrategyBase implements WebhookS * @throws \VRPayment\Sdk\Http\ConnectionException ConnectionException. * @throws \VRPayment\Sdk\VersioningException VersioningException. */ - public function getTransaction(WebHookRequest $request) { + public function getTransaction(WebHookRequest $request): Transaction { return $this->settings->getApiClient() ->getTransactionService() ->read($request->getSpaceId(), $request->getEntityId()); @@ -60,7 +61,7 @@ class WebHookTransactionStrategy extends WebHookStrategyBase implements WebhookS /** * @inheritDoc */ - public function getOrderIdByTransaction($transaction): string + public function getOrderIdByTransaction(Transaction $transaction): string { /** @var \VRPayment\Sdk\Model\Transaction $transaction */ return $transaction->getMetaData()[TransactionPayload::VRPAYMENT_METADATA_ORDER_ID]; @@ -96,7 +97,7 @@ class WebHookTransactionStrategy extends WebHookStrategyBase implements WebhookS */ public function process(WebHookRequest $request): Response { - return $this->updateTransaction($request, $this->getContext()); + return $this->processTransaction($request, $this->getContext()); } /** @@ -107,16 +108,17 @@ class WebHookTransactionStrategy extends WebHookStrategyBase implements WebhookS * @param Context $context The operational context providing settings and environment for transaction processing. * @return Response Returns a JSON response indicating the result of the transaction update operation. */ - private function updateTransaction(WebHookRequest $request, Context $context): Response + private function processTransaction(WebHookRequest $request, Context $context): Response { $status = Response::HTTP_UNPROCESSABLE_ENTITY; try { /** @var \Shopware\Core\Checkout\Order\OrderEntity $order */ $transaction = $this->getTransaction($request); - $orderId = $transaction->getMetaData()[TransactionPayload::VRPAYMENT_METADATA_ORDER_ID]; - if(!empty($orderId) && !$transaction->getParent()) { - $this->executeLocked($orderId, $context, function () use ($orderId, $transaction, $context, $request) { + $token = $transaction->getToken(); + $orderId = $transaction->getMetaData()[TransactionPayload::VRPAYMENT_METADATA_ORDER_ID]; + if (!empty($orderId) && !$transaction->getParent()) { + $this->executeLocked($orderId, $context, function () use ($orderId, $transaction, $context, $request, $token) { $this->transactionService->upsert($transaction, $context); $orderTransactionId = $transaction->getMetaData()[TransactionPayload::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID]; $orderTransaction = $this->getOrderTransaction($orderId, $context); @@ -143,6 +145,16 @@ class WebHookTransactionStrategy extends WebHookStrategyBase implements WebhookS $this->unholdDelivery($orderId, $context); break; case TransactionState::AUTHORIZED: + if ($token instanceof Token) { + // Update orderTransaction with the authorized token: + $data = [ + 'id' => $orderTransactionId, + 'customFields' => [ + TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TOKEN => $token->getId(), + ], + ]; + $this->container->get('order_transaction.repository')->update([$data], $context); + } $this->orderTransactionStateHandler->process($orderTransactionId, $context); $this->sendEmail($transaction, $context, $orderId); break; diff --git a/src/Core/Api/WebHooks/Strategy/WebhookStrategyActionsInterface.php b/src/Core/Api/WebHooks/Strategy/WebhookStrategyActionsInterface.php index a2e25de..250db67 100644 --- a/src/Core/Api/WebHooks/Strategy/WebhookStrategyActionsInterface.php +++ b/src/Core/Api/WebHooks/Strategy/WebhookStrategyActionsInterface.php @@ -57,5 +57,5 @@ interface WebhookStrategyActionsInterface { * @param Transaction|TransactionInvoiceState|Refund|mixed $transaction The transaction object from which the order ID should be extracted. * @return string The order ID as a string. */ - public function getOrderIdByTransaction($transaction): string; + public function getOrderIdByTransaction(Transaction $transaction): string; } diff --git a/src/Core/Checkout/Cart/CustomCartPersister.php b/src/Core/Checkout/Cart/CustomCartPersister.php new file mode 100644 index 0000000..584dd1e --- /dev/null +++ b/src/Core/Checkout/Cart/CustomCartPersister.php @@ -0,0 +1,59 @@ +inner = $inner; + } + + public function delete(string $token, SalesChannelContext $context): void + { + if (!$context->getContext()->hasState('do-cart-delete') && $this->isWhiteLabelPayment($context)) { + return; + } + + $this->inner->delete($token, $context); + } + + public function load(string $token, SalesChannelContext $context): Cart + { + return $this->inner->load($token, $context); + } + + public function save(Cart $cart, SalesChannelContext $context): void + { + $this->inner->save($cart, $context); + } + + public function replace(string $oldToken, string $newToken, SalesChannelContext $context): void + { + $this->inner->replace($oldToken, $newToken, $context); + } + + public function getDecorated(): AbstractCartPersister + { + return $this->inner; + } + + private function isWhiteLabelPayment(SalesChannelContext $context): bool + { + $paymentMethod = $context->getPaymentMethod(); + + if (!$paymentMethod instanceof PaymentMethodEntity) { + return false; + } + + return $paymentMethod->getHandlerIdentifier() === VRPaymentPaymentHandler::class; + } +} diff --git a/src/Core/Checkout/PaymentHandler/VRPaymentPaymentHandler.php b/src/Core/Checkout/PaymentHandler/VRPaymentPaymentHandler.php index 669ad23..fd8c9bb 100644 --- a/src/Core/Checkout/PaymentHandler/VRPaymentPaymentHandler.php +++ b/src/Core/Checkout/PaymentHandler/VRPaymentPaymentHandler.php @@ -4,22 +4,42 @@ namespace VRPaymentPayment\Core\Checkout\PaymentHandler; use Psr\Log\LoggerInterface; use Shopware\Core\{ + Checkout\Order\OrderEntity, + Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity, Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler, - Checkout\Payment\Cart\AsyncPaymentTransactionStruct, - Checkout\Payment\Cart\PaymentHandler\AsynchronousPaymentHandlerInterface, - Checkout\Payment\Exception\AsyncPaymentFinalizeException, - Checkout\Payment\Exception\AsyncPaymentProcessException, + Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates, + Checkout\Payment\Cart\PaymentTransactionStruct, + Checkout\Payment\Cart\PaymentHandler\AbstractPaymentHandler, + Checkout\Payment\Cart\PaymentHandler\PaymentHandlerType, Checkout\Payment\PaymentException, Checkout\Payment\Exception\CustomerCanceledAsyncPaymentException, + Framework\App\AppException, + Framework\Api\Context\SalesChannelApiSource, + Framework\Context, + Framework\DataAbstractionLayer\EntityRepository, + Framework\DataAbstractionLayer\Search\Criteria, + Framework\DataAbstractionLayer\Search\Filter\EqualsFilter, + Framework\DataAbstractionLayer\Search\Sorting\FieldSorting, + Framework\Struct\Struct, Framework\Validation\DataBag\RequestDataBag, - System\SalesChannel\SalesChannelContext + System\StateMachine\Aggregation\StateMachineState\StateMachineStateEntity, + System\SalesChannel\Context\SalesChannelContextService, + System\SalesChannel\Context\SalesChannelContextServiceParameters }; +use Shopware\Core\Framework\Util\Random; +use VRPaymentPayment\Core\Checkout\Cart\CustomCartPersister; +use Shopware\Core\Checkout\Cart\Cart; +use Shopware\Core\Checkout\Cart\CartPersister; +use Shopware\Core\System\SalesChannel\SalesChannelContext; + use Symfony\Component\{ HttpFoundation\RedirectResponse, HttpFoundation\Request }; use VRPayment\Sdk\Model\TransactionState; -use VRPaymentPayment\Core\Api\Transaction\Service\TransactionService; +use VRPaymentPayment\Core\Api\Transaction\Service\TransactionService as PluginTransactionService; +use VRPaymentPayment\Core\Util\Payload\TransactionPayload; + /** @@ -27,13 +47,18 @@ use VRPaymentPayment\Core\Api\Transaction\Service\TransactionService; * * @package VRPaymentPayment\Core\Checkout\PaymentHandler */ -class VRPaymentPaymentHandler implements AsynchronousPaymentHandlerInterface +class VRPaymentPaymentHandler extends AbstractPaymentHandler { /** - * @var \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService + * @var CustomCartPersister */ - protected $transactionService; + private CustomCartPersister $cartPersister; + + /** + * @var \VRPaymentPayment\Core\Api\Transaction\Service\PluginTransactionService + */ + protected $pluginTransactionService; /** * @var \Psr\Log\LoggerInterface @@ -44,22 +69,32 @@ class VRPaymentPaymentHandler implements AsynchronousPaymentHandlerInterface */ private $orderTransactionStateHandler; - /** - * VRPaymentPaymentHandler constructor. - * - * @param \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService $transactionService - * @param \Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler $orderTransactionStateHandler - */ - public function __construct(TransactionService $transactionService, OrderTransactionStateHandler $orderTransactionStateHandler) - { - $this->transactionService = $transactionService; - $this->orderTransactionStateHandler = $orderTransactionStateHandler; - } + protected SalesChannelContextService $salesChannelContextService; + + protected EntityRepository $orderTransactionRepository; + + protected ?EntityRepository $subscriptionRepository; + /** + * VRPaymentPaymentHandler constructor. + */ + public function __construct( + CustomCartPersister $cartPersister, + PluginTransactionService $pluginTransactionService, + OrderTransactionStateHandler $orderTransactionStateHandler, + SalesChannelContextService $salesChannelContextService, + EntityRepository $orderTransactionRepository, + ?EntityRepository $subscriptionRepository, + ) { + $this->cartPersister = $cartPersister; + $this->pluginTransactionService = $pluginTransactionService; + $this->orderTransactionStateHandler = $orderTransactionStateHandler; + $this->salesChannelContextService = $salesChannelContextService; + $this->orderTransactionRepository = $orderTransactionRepository; + $this->subscriptionRepository = $subscriptionRepository; + } /** * @param \Psr\Log\LoggerInterface $logger - * @internal - * @required * */ public function setLogger(LoggerInterface $logger): void @@ -73,78 +108,352 @@ class VRPaymentPaymentHandler implements AsynchronousPaymentHandlerInterface * * A redirect to the url will be performed * - * @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction - * @param \Shopware\Core\Framework\Validation\DataBag\RequestDataBag $dataBag - * @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext + * @param \Symfony\Component\HttpFoundation\Request + * @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction + * @param \Shopware\Core\Framework\Context $context + * @param \Shopware\Core\Framework\Struct\Struct $validateStruct * @return \Symfony\Component\HttpFoundation\RedirectResponse */ public function pay( - AsyncPaymentTransactionStruct $transaction, - RequestDataBag $dataBag, - SalesChannelContext $salesChannelContext + Request $request, + PaymentTransactionStruct $transaction, + Context $context, + ?Struct $validateStruct ): RedirectResponse { try { + $orderTransactionId = $transaction->getOrderTransactionId(); + $orderTransaction = $this->orderTransactionRepository->search( + (new Criteria([$orderTransactionId])) + ->addAssociation('order'), $context + )->getEntities()->first(); + + $contextSource = $context->getSource(); + if ($contextSource instanceof SalesChannelApiSource) { + $salesChannelContextId = $contextSource->getSalesChannelId(); + } + + $parameters = new SalesChannelContextServiceParameters($salesChannelContextId, $request->getSession()->get("sw-context-token", Random::getAlphanumericString(32)), originalContext: $context); + $salesChannelContext = $this->salesChannelContextService->get($parameters); $redirectUrl = $transaction->getReturnUrl(); - if ($transaction->getOrder()->getAmountTotal() > 0) { - $transactionId = $_SESSION['transactionId'] ?? null; + + if ($orderTransaction->getOrder()->getAmountTotal() > 0) { + $transactionId = $request->getSession()->get('transactionId'); if ($transactionId === null) { - $this->transactionService->createPendingTransaction($salesChannelContext); + $this->pluginTransactionService->createPendingTransaction($salesChannelContext); } - $redirectUrl = $this->transactionService->create($transaction, $salesChannelContext); + $redirectUrl = $this->pluginTransactionService->create($transaction, $salesChannelContext); } return new RedirectResponse($redirectUrl); - - } catch (\Exception $e) { - unset($_SESSION['transactionId']); + } catch (\Throwable $e) { + $request->getSession()->remove('transactionId'); $errorMessage = 'An error occurred during the communication with external payment gateway : ' . $e->getMessage(); $this->logger->critical($errorMessage); - throw new \Exception($transaction->getOrderTransaction()->getId() . ': ' . $errorMessage); + throw PaymentException::customerCanceled($transaction->getOrderTransaction()->getId(), $errorMessage); } } /** * The finalize function will be called when the user is redirected back to shop from the payment gateway. * - * Throw a @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction * @param \Symfony\Component\HttpFoundation\Request $request - * @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext + * @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction + * @param \Shopware\Core\Framework\Context $context * @throws \VRPayment\Sdk\ApiException * @throws \VRPayment\Sdk\Http\ConnectionException * @throws \VRPayment\Sdk\VersioningException - * @see AsyncPaymentFinalizeException exception if an error ocurres while calling an external payment API - * Throw a @see CustomerCanceledAsyncPaymentException exception if the customer canceled the payment process on - * payment provider page - * + * @throws \Exception when the payment was canceled by the customer */ public function finalize( - AsyncPaymentTransactionStruct $transaction, - Request $request, - SalesChannelContext $salesChannelContext + Request $request, + PaymentTransactionStruct $transaction, + Context $context ): void { - if ($transaction->getOrder()->getAmountTotal() > 0) { - $transactionEntity = $this->transactionService->getByOrderId( - $transaction->getOrder()->getId(), - $salesChannelContext->getContext() + $orderTransactionId = $transaction->getOrderTransactionId(); + $orderTransaction = $this->orderTransactionRepository->search( + (new Criteria([$orderTransactionId])) + ->addAssociation('order'), $context + )->getEntities()->first(); + + if ($orderTransaction->getOrder()->getAmountTotal() > 0) { + $transactionEntity = $this->pluginTransactionService->getByOrderId( + $orderTransaction->getOrder()->getId(), + $context ); - $vRPaymentTransaction = $this->transactionService->read( + $vRPaymentTransaction = $this->pluginTransactionService->read( $transactionEntity->getTransactionId(), - $salesChannelContext->getSalesChannel()->getId() + $transactionEntity->getSalesChannelId() ); if (in_array($vRPaymentTransaction->getState(), [TransactionState::FAILED])) { $errorMessage = strtr('Customer canceled payment for :orderId on SalesChannel :salesChannelName', [ - ':orderId' => $transaction->getOrder()->getId(), - ':salesChannelName' => $salesChannelContext->getSalesChannel()->getName(), + ':orderId' => $orderTransaction->getOrder()->getId(), + ':salesChannelName' => $transactionEntity->getSalesChannelId(), ]); - unset($_SESSION['transactionId']); + $request->getSession()->remove('transactionId'); $this->logger->info($errorMessage); throw PaymentException::customerCanceled($transaction->getOrderTransaction()->getId(), $errorMessage); } } else { - $this->orderTransactionStateHandler->paid($transaction->getOrderTransaction()->getId(), $salesChannelContext->getContext()); + $this->orderTransactionStateHandler->paid($orderTransaction->getId(), $context); + } + + $token = $request->getSession()->get('sw-context-token'); + if ($token) { + $salesChannelId = $transactionEntity->getSalesChannelId(); + $parameters = new SalesChannelContextServiceParameters($salesChannelId, $token, originalContext: $context); + $salesChannelContext = $this->salesChannelContextService->get($parameters); + + $salesChannelContext->getContext()->addState('do-cart-delete'); + $this->logger->info('Clearing cart with token: ' . $token); + $this->cartPersister->delete($salesChannelContext->getToken(), $salesChannelContext); } } + + /** + * {@inheritDoc} + */ + public function supports( + PaymentHandlerType $type, + string $paymentMethodId, + Context $context + ): bool { + // Both PaymentHandlerType::RECURRING and PaymentHandlerType::REFUND are supported + //TODO: check that the payment method really supports recurring. + // In order to do that, we need to get this information in when synching the payment methods. + // The payment methods in the portal are managed by their Connectors. The Connectors need + // to support the recurrin and the refunding. These values are 1453357059666L and 1453351315899L for + // tokenization and refunding respectively. + return true; + } + + public function recurring( + PaymentTransactionStruct $transaction, + Context $context + ): void { + if ($this->subscriptionRepository === null || !class_exists(\Shopware\Commercial\Subscription\Entity\Subscription\SubscriptionEntity::class)) { + throw PaymentException::paymentTypeUnsupported( + $transaction->getOrderTransactionId(), + 'Shopware Commercial plugin with Subscription feature is not installed or active. Recurring payments cannot be processed.' + ); + } + + if ($transaction->isRecurring() === false) { + //TODO: Provide payment-method-id instead of order-transaction-id + throw PaymentException::paymentTypeUnsupported($transaction->getOrderTransaction()->getId(), PaymentHandlerType::RECURRING); + } + + $recurringData = $transaction->getRecurring(); + $newTransactionId = $transaction->getOrderTransactionId(); + + if ($recurringData === null) { + throw PaymentException::recurringInterrupted($newTransactionId, 'Recurring payment data is missing from the transaction struct.'); + } + + try { + // Get information about the subscription + $subscriptionId = $recurringData->getSubscriptionId(); + $criteria = new Criteria([$subscriptionId]); + $criteria->addAssociation('orders.transactions.stateMachineState'); + + /** @var SubscriptionEntity|null $subscription */ + $subscription = $this->subscriptionRepository->search($criteria, $context)->get($subscriptionId); + + if ($subscription === null) { + throw PaymentException::recurringInterrupted($newTransactionId, sprintf('Subscription with ID "%s" could not be found.', $subscriptionId)); + } + + // Find the original order and transaction + $orders = $subscription->getOrders(); + if ($orders === null || $orders->count() === 0) { + throw PaymentException::recurringInterrupted($newTransactionId, 'No orders found associated with the subscription.'); + } + + $orders->sort(fn (OrderEntity $a, OrderEntity $b) => $a->getCreatedAt() <=> $b->getCreatedAt()); + /** @var OrderEntity|null $originalOrder */ + $originalOrder = $orders->first(); + + $originalTransactions = $originalOrder->getTransactions(); + + if ($originalTransactions === null) { + throw PaymentException::recurringInterrupted($newTransactionId, 'No transactions found on the original order.'); + } + + /** @var OrderTransactionEntity|null $originalTransaction */ + $originalTransaction = $originalTransactions->filter( + fn (OrderTransactionEntity $t) => $t->getStateMachineState()?->getTechnicalName() === OrderTransactionStates::STATE_PAID + )->first(); + + if ($originalTransaction === null) { + throw PaymentException::recurringInterrupted($newTransactionId, 'A successful, paid transaction could not be found on the original order to retrieve payment details.'); + } + + $newOrderTransaction = $this->orderTransactionRepository->search( + (new Criteria([$newTransactionId])) + ->addAssociation('order'), $context + )->getEntities()->first(); + $orderNumber = $newOrderTransaction->getOrder()->getOrderNumber(); + + // Access the custom fields for getting the original transaction details + $customFields = $originalTransaction->getCustomFields(); + // The tokenReference is not really needed because it's also stored in the original transaction + $tokenReference = $customFields[TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TOKEN] ?? null; + $spaceId = (string) $customFields[TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_SPACE_ID] ?? null; + $sdkTransactionId = $customFields[TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TRANSACTION_ID] ?? null; + + if ($sdkTransactionId === null || $spaceId === null) { + throw PaymentException::recurringInterrupted($newTransactionId, 'Required original transaction ID and spaceId is missing from order transaction custom fields.'); + } + + /** @var \VRPayment\Sdk\Model\Transaction $originalSdkTransaction */ + $originalSdkTransaction = $this->pluginTransactionService->read($sdkTransactionId, ""); + + //TODO: Consider moving this logic to its own function for improved readability + $sdkTransactionCreate = new \VRPayment\Sdk\Model\TransactionCreate; + + // Build the new transaction based on the original transaction + $sdkTransactionCreate->setCurrency($originalSdkTransaction->getCurrency()); + $sdkTransactionCreate->setBillingAddress($this->addressCreateFromSdk($originalSdkTransaction->getBillingAddress())); + $sdkTransactionCreate->setShippingAddress($this->addressCreateFromSdk($originalSdkTransaction->getShippingAddress())); + $sdkTransactionCreate->setShippingMethod($originalSdkTransaction->getShippingMethod()); + $sdkTransactionCreate->setCustomerEmailAddress($originalSdkTransaction->getCustomerEmailAddress()); + $sdkTransactionCreate->setCustomerId($originalSdkTransaction->getCustomerId()); + $sdkTransactionCreate->setLanguage($originalSdkTransaction->getLanguage()); + // Get the merchant reference from the new Order, not the original one + $sdkTransactionCreate->setMerchantReference($orderNumber); + $sdkTransactionCreate->setInvoiceMerchantReference($originalSdkTransaction->getInvoiceMerchantReference()); + + $lineItems = $originalSdkTransaction->getLineItems(); + $lineItemsCreate = []; + foreach ($lineItems as $lineItem) { + $lineItemsCreate[] = $this->lineItemCreateFromSdk($lineItem); + } + if (count($lineItemsCreate) > 0) { + $sdkTransactionCreate->setLineItems($lineItemsCreate); + } + + $sdkTransactionCreate->setSuccessUrl($originalSdkTransaction->getSuccessUrl()); + $sdkTransactionCreate->setToken($originalSdkTransaction->getToken()); + $sdkTransactionCreate->setTokenizationMode($originalSdkTransaction->getTokenizationMode()); + $sdkTransactionCreate->setMetaData($originalSdkTransaction->getMetaData()); + + // Create the new recurring transaction + $newSdkTransaction = $this->pluginTransactionService->createRecurringTransaction($sdkTransactionCreate, $spaceId); + + // Set the new state for the new order transaction + if (in_array($newSdkTransaction->getState(), [TransactionState::AUTHORIZED, TransactionState::COMPLETED, TransactionState::CONFIRMED, TransactionState::FULFILL])) { + $this->orderTransactionStateHandler->paid($newTransactionId, $context); + } elseif (in_array($newSdkTransaction->getState(), [TransactionState::DECLINE, TransactionState::FAILED, TransactionState::VOIDED])) { + $this->orderTransactionStateHandler->fail($newTransactionId, $context); + } elseif (in_array($newSdkTransaction->getState(), [TransactionState::PENDING, TransactionState::PROCESSING])) { + $this->orderTransactionStateHandler->process($newTransactionId, $context); + } else { + $this->orderTransactionStateHandler->reopen($newTransactionId, $context); + } + + $data = [ + 'id' => $newTransactionId, + 'customFields' => [ + TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TRANSACTION_ID => $newSdkTransaction->getId(), + TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_SPACE_ID => $spaceId, + TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TOKEN => $tokenReference, + ], + ]; + + // Update the new order transaction with the new transaction details + $this->orderTransactionRepository->update([$data], $context); + $this->pluginTransactionService->upsert($newSdkTransaction, $context); + } + catch (\Throwable $e) { + $errorMessage = 'An error occurred during the communication with external payment gateway : ' . $e->getMessage(); + $this->logger->critical($errorMessage); + throw PaymentException::recurringInterrupted($transaction->getOrderTransactionId(), $errorMessage); + } + } + + /** + * Creates a new AddressCreate instance from the given SDK Address model. + * + * @param \VRPayment\Sdk\Model\Address $address The address model from the SDK. + * @return \VRPayment\Sdk\Model\AddressCreate The newly created AddressCreate instance. + */ + private function addressCreateFromSdk(\VRPayment\Sdk\Model\Address $address): \VRPayment\Sdk\Model\AddressCreate { + $addressCreate = new \VRPayment\Sdk\Model\AddressCreate; + + $addressCreate->setCity($address->getCity()); + $addressCreate->setCommercialRegisterNumber($address->getCommercialRegisterNumber()); + $addressCreate->setCountry($address->getCountry()); + $addressCreate->setDateOfBirth($address->getDateOfBirth()); + $addressCreate->setDependentLocality($address->getDependentLocality()); + $addressCreate->setEmailAddress($address->getEmailAddress()); + $addressCreate->setFamilyName($address->getFamilyName()); + $addressCreate->setGender($address->getGender()); + $addressCreate->setGivenName($address->getGivenName()); + $addressCreate->setMobilePhoneNumber($address->getMobilePhoneNumber()); + $addressCreate->setOrganizationName($address->getOrganizationName()); + $addressCreate->setPhoneNumber($address->getPhoneNumber()); + $addressCreate->setPostalState($address->getPostalState()); + $addressCreate->setPostcode($address->getPostcode()); + $addressCreate->setSalesTaxNumber($address->getSalesTaxNumber()); + $addressCreate->setSalutation($address->getSalutation()); + $addressCreate->setSocialSecurityNumber($address->getSocialSecurityNumber()); + $addressCreate->setSortingCode($address->getSortingCode()); + $addressCreate->setStreet($address->getStreet()); + + return $addressCreate; + } + + /** + * Creates a LineItemCreate object from a given SDK LineItem. + * + * This method takes a \VRPayment\Sdk\Model\LineItem instance and transforms it into a + * \VRPayment\Sdk\Model\LineItemCreate object, which can be used for further processing + * or integration with the VRPayment payment SDK. + * + * @param \VRPayment\Sdk\Model\LineItem $lineItem The line item from the SDK to convert. + * @return \VRPayment\Sdk\Model\LineItemCreate The created LineItemCreate object. + */ + private function lineItemCreateFromSdk(\VRPayment\Sdk\Model\LineItem $lineItem): \VRPayment\Sdk\Model\LineItemCreate + { + $lineItemCreate = new \VRPayment\Sdk\Model\LineItemCreate(); + + $lineItemCreate->setAmountIncludingTax($lineItem->getAmountIncludingTax()); + + $attributes = $lineItem->getAttributes(); + $attributesCreate = []; + foreach ($attributes as $id => $attribute) { + $attributeCreate = new \VRPayment\Sdk\Model\LineItemAttributeCreate(); + $attributeCreate->setLabel($attribute->getLabel()); + $attributeCreate->setValue($attribute->getValue()); + $attributesCreate[$id] = $attributeCreate; + } + if (count($attributesCreate) > 0) { + $lineItemCreate->setAttributes($attributesCreate); + } + + $lineItemCreate->setDiscountIncludingTax($lineItem->getDiscountIncludingTax()); + $lineItemCreate->setName($lineItem->getName()); + $lineItemCreate->setQuantity($lineItem->getQuantity()); + $lineItemCreate->setShippingRequired($lineItem->getShippingRequired()); + $lineItemCreate->setSku($lineItem->getSku()); + + $taxes = $lineItem->getTaxes(); + $taxesCreate = []; + foreach ($taxes as $tax) { + $taxCreate = new \VRPayment\Sdk\Model\TaxCreate(); + $taxCreate->setRate($tax->getRate()); + $taxCreate->setTitle($tax->getTitle()); + $taxesCreate[] = $taxCreate; + } + if (count($taxesCreate) > 0) { + $lineItemCreate->setTaxes($taxesCreate); + } + + $lineItemCreate->setType($lineItem->getType()); + $lineItemCreate->setUniqueId($lineItem->getUniqueId()); + + return $lineItemCreate; + } } diff --git a/src/Core/Checkout/Subscription/Command/GenerateSubscriptionOrderCommand.php b/src/Core/Checkout/Subscription/Command/GenerateSubscriptionOrderCommand.php new file mode 100644 index 0000000..8719a5b --- /dev/null +++ b/src/Core/Checkout/Subscription/Command/GenerateSubscriptionOrderCommand.php @@ -0,0 +1,116 @@ +addArgument('subscriptionIdentifier', InputArgument::REQUIRED, 'The ID or Number of the subscription to process.'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new ShopwareStyle($input, $output); + + if ($this->subscriptionRepository === null || !class_exists(\Shopware\Commercial\Subscription\Entity\Subscription\SubscriptionEntity::class)) { + $io->error('Subscription functionality is not available in this Shopware instance. Please ensure the Subscription plugin is installed and enabled.'); + return self::FAILURE; + } + + $identifier = $input->getArgument('subscriptionIdentifier'); + + if (!is_string($identifier)) { + $io->error('Invalid Subscription ID provided.'); + return self::FAILURE; + } + $subscriptionId = $this->findSubscriptionId($identifier, $io); + + if ($subscriptionId === null) { + // Error message is already printed in findSubscriptionId + return self::FAILURE; + } + + $io->text(sprintf('Forcing next schedule for subscription ID: %s', $subscriptionId)); + $this->forceNextSchedule($subscriptionId); + + $io->title('Subscription Order Generation'); + $io->text(sprintf('Dispatching GenerateSubscriptionOrder message for subscription ID: %s', $subscriptionId)); + + $this->bus->dispatch(new GenerateSubscriptionOrder($subscriptionId)); + + $io->success('Message dispatched successfully!'); + $io->note('Ensure a message consumer is running to process the queue: "bin/console messenger:consume async"'); + + return self::SUCCESS; + } + + /** + * Set the next schedule date to the current time, so it will be processed immediately. + * + * @param string $subscriptionId + * @return void + */ + private function forceNextSchedule(string $subscriptionId): void + { + $context = Context::createDefaultContext(); + $this->subscriptionRepository->update([ + [ + 'id' => $subscriptionId, + 'nextSchedule' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT), + ] + ], $context); + } + + private function findSubscriptionId(string $identifier, ShopwareStyle $io): ?string + { + $context = Context::createDefaultContext(); + if (Uuid::isValid($identifier)) { + // Check if a subscription with this ID actually exists + $result = $this->subscriptionRepository->searchIds(new Criteria([$identifier]), $context); + if ($result->firstId()) { + return $identifier; + } + $io->error(sprintf('No subscription found with ID "%s".', $identifier)); + return null; + } + + // If not a UUID, assume it's a subscription number + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('subscriptionNumber', $identifier)); + $result = $this->subscriptionRepository->searchIds($criteria, $context); + + if ($result->firstId() === null) { + $io->error(sprintf('No subscription found with number "%s".', $identifier)); + return null; + } + + return $result->firstId(); + } +} diff --git a/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php b/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php index 9baf214..9109457 100644 --- a/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php +++ b/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php @@ -100,6 +100,7 @@ class CheckoutSubscriber implements EventSubscriberInterface { return [ CheckoutConfirmPageLoadedEvent::class => ['onConfirmPageLoaded', 1], + "subscription." . CheckoutConfirmPageLoadedEvent::class => ['onConfirmPageLoaded', 1], MailBeforeValidateEvent::class => ['onMailBeforeValidate', 1], ]; } diff --git a/src/Core/Util/Analytics/Analytics.php b/src/Core/Util/Analytics/Analytics.php index cf2fd15..2a02274 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 => '6.1.15', + self::PLUGIN_SYSTEM_VERSION => '7.1.0', ]; } diff --git a/src/Core/Util/Payload/TransactionPayload.php b/src/Core/Util/Payload/TransactionPayload.php index 8f9bc59..30368e8 100644 --- a/src/Core/Util/Payload/TransactionPayload.php +++ b/src/Core/Util/Payload/TransactionPayload.php @@ -8,10 +8,14 @@ use Shopware\Core\{Checkout\Cart\Tax\Struct\CalculatedTaxCollection, Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity, Checkout\Customer\CustomerEntity, Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity, - Checkout\Payment\Cart\AsyncPaymentTransactionStruct, + Checkout\Order\OrderEntity, + Checkout\Payment\Cart\PaymentTransactionStruct, Framework\DataAbstractionLayer\Search\Criteria, System\SalesChannel\SalesChannelContext }; +use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; + use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Contracts\Translation\TranslatorInterface; use VRPayment\Sdk\{Model\AddressCreate, @@ -36,6 +40,10 @@ use VRPaymentPayment\Core\{Api\PaymentMethodConfiguration\Entity\PaymentMethodCo Util\Payload\CustomProducts\CustomProductsLineItemTypes }; +use Shopware\Core\System\SystemConfig\SystemConfigService; +use Shopware\Core\Framework\Context; +use Shopware\Core\System\Tax\TaxEntity; + /** * Class TransactionPayload * @@ -48,6 +56,7 @@ class TransactionPayload extends AbstractPayload public const ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_SPACE_ID = 'vrpayment_space_id'; public const ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TRANSACTION_ID = 'vrpayment_transaction_id'; + public const ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TOKEN = 'vrpayment_token'; public const VRPAYMENT_METADATA_SALES_CHANNEL_ID = 'salesChannelId'; public const VRPAYMENT_METADATA_ORDER_ID = 'orderId'; @@ -61,7 +70,7 @@ class TransactionPayload extends AbstractPayload protected $salesChannelContext; /** - * @var \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct + * @var \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct */ protected $transaction; @@ -85,6 +94,10 @@ class TransactionPayload extends AbstractPayload */ protected $translator; + protected EntityRepository $orderTransactionRepository; + + protected OrderEntity $order; + /** * TransactionPayload constructor. * @@ -92,14 +105,14 @@ class TransactionPayload extends AbstractPayload * @param \VRPaymentPayment\Core\Util\LocaleCodeProvider $localeCodeProvider * @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext * @param \VRPaymentPayment\Core\Settings\Struct\Settings $settings - * @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction + * @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction */ public function __construct( ContainerInterface $container, LocaleCodeProvider $localeCodeProvider, SalesChannelContext $salesChannelContext, Settings $settings, - AsyncPaymentTransactionStruct $transaction + PaymentTransactionStruct $transaction ) { $this->localeCodeProvider = $localeCodeProvider; @@ -108,6 +121,23 @@ class TransactionPayload extends AbstractPayload $this->transaction = $transaction; $this->container = $container; $this->translator = $this->container->get('translator'); + $this->orderTransactionRepository = $this->container->get('order_transaction.repository'); + + $criteria = (new Criteria()); + $criteria->addFilter(new EqualsFilter('id', $this->transaction->getOrderTransactionId())); + + $orders = $this->orderTransactionRepository->search($criteria, $this->salesChannelContext->getContext())->getEntities(); + $orderId = $orders->first()->getOrderId(); + + $criteria = new Criteria([$orderId]); + $criteria + ->addAssociation('lineItems') + ->addAssociation('orderCustomer') + ->addAssociation('transactions') + ->addAssociation('currency') + ; + + $this->order = $this->container->get('order.repository')->search($criteria, $this->salesChannelContext->getContext())->getEntities()->first(); } /** @@ -118,13 +148,21 @@ class TransactionPayload extends AbstractPayload */ public function get(int $version): TransactionPending { - $customer = $this->salesChannelContext->getCustomer(); + $customerId = $this->order->getOrderCustomer()->getCustomerId(); + $criteria = new Criteria([$customerId]); + $criteria->addAssociation('activeBillingAddress') + ->addAssociation('activeShippingAddress') + ->addAssociation('activeShippingAddress') + ->addAssociation('defaultBillingAddress') + ->addAssociation('defaultShippingAddress') + ->addAssociation('salutation'); + $customer = $this->container->get('customer.repository')->search($criteria, $this->salesChannelContext->getContext())->getEntities()->first(); $lineItems = $this->getLineItems(); + $billingAddress = $this->getAddressPayload($customer, $customer->getActiveBillingAddress()); $shippingAddress = $this->getAddressPayload($customer, $customer->getActiveShippingAddress(), false); - $customerId = null; $customerName = null; if ($customer->getGuest() === false) { @@ -137,14 +175,14 @@ class TransactionPayload extends AbstractPayload } $transactionData = [ - 'currency' => $this->salesChannelContext->getCurrency()->getIsoCode(), - 'customer_email_address' => $billingAddress->getEmailAddress(), + 'currency' => $this->order->getCurrency()->getIsoCode(), + 'customer_email_address' => $customer->getEmail(), 'customer_id' => $customerId, 'language' => $this->localeCodeProvider->getLocaleCodeFromContext($this->salesChannelContext->getContext()) ?? null, - 'merchant_reference' => $this->fixLength($this->transaction->getOrder()->getOrderNumber(), 100), + 'merchant_reference' => $this->fixLength($this->order->getOrderNumber(), 100), 'meta_data' => [ - self::VRPAYMENT_METADATA_ORDER_ID => $this->transaction->getOrder()->getId(), - self::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID => $this->transaction->getOrderTransaction()->getId(), + self::VRPAYMENT_METADATA_ORDER_ID => $this->order->getId(), + self::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID => $this->order->getTransactions()->first()->getId(), self::VRPAYMENT_METADATA_SALES_CHANNEL_ID => $this->salesChannelContext->getSalesChannel()->getId(), self::VRPAYMENT_METADATA_CUSTOMER_NAME => $customerName, ], @@ -161,8 +199,8 @@ class TransactionPayload extends AbstractPayload $transactionData['meta_data']['additionalAddress2'] = $additionalAddress2; } - if (!empty($this->transaction->getOrder()->getCustomerComment())) { - $transactionData['meta_data']['customer_comment'] = $this->transaction->getOrder()->getCustomerComment(); + if (!empty($this->order->getCustomerComment())) { + $transactionData['meta_data']['customer_comment'] = $this->order->getCustomerComment(); } $vatIds = $customer->getVatIds(); @@ -198,7 +236,7 @@ class TransactionPayload extends AbstractPayload $transactionPayload->setAllowedPaymentMethodConfigurations([$paymentConfiguration->getPaymentMethodConfigurationId()]); $successUrl = $this->transaction->getReturnUrl() . '&status=paid'; - $failedUrl = $this->getFailUrl($this->transaction->getOrder()->getId()) . '&status=fail'; + $failedUrl = $this->getFailUrl($this->order->getId()) . '&status=fail'; $transactionPayload->setSuccessUrl($successUrl) ->setFailedUrl($failedUrl); @@ -219,7 +257,7 @@ class TransactionPayload extends AbstractPayload protected function getLineItems(): array { $lineItems = []; - $items = $this->transaction->getOrder()->getLineItems(); + $items = $this->order->getLineItems() ?? []; foreach ($items as $shopLineItem) { if ($this->shouldSkipLineItem($shopLineItem)) { @@ -307,36 +345,99 @@ class TransactionPayload extends AbstractPayload protected function addDiscountLineItem($discount, array &$lineItems): void { $calculatedPrice = $discount->getPrice(); - $calculatedTaxesCollection = $calculatedPrice->getCalculatedTaxes(); + $discountName = $discount->getLabel() ?? 'Unnamed'; + $definition = $discount->getPriceDefinition(); - foreach ($calculatedTaxesCollection as $calculatedTax) { - $rate = $calculatedTax->getTaxRate(); - $lineItem = new LineItemCreate(); - $amount = $this->calculateDiscountAmount($calculatedTax); + if ($this->order->getTaxStatus() === 'net' || $definition instanceof \Shopware\Core\Checkout\Cart\Price\Struct\AbsolutePriceDefinition) { + $calculatedTaxesCollection = $calculatedPrice->getCalculatedTaxes(); + foreach ($calculatedTaxesCollection as $calculatedTax) { + $rate = $calculatedTax->getTaxRate(); + $amount = $this->calculateDiscountAmount($calculatedTax); - $discountName = $discount->getLabel(); - $lineItem->setAmountIncludingTax($amount) - ->setName(sprintf('DISCOUNT: %s (%s%% tax)', $discount->getLabel(), $rate)) - ->setQuantity(1) - ->setShippingRequired(false) - ->setSku('sku-discount-' . $rate . '-' . $discountName, 200) - ->setType(LineItemType::DISCOUNT) - ->setUniqueId('coupon-sku-discount-' . $rate . '-' . $rate . '-' . $discountName); + $lineItems[] = $this->createDiscountLineItem($discountName, $amount, $rate); + } + } else { + $taxRules = $calculatedPrice->getTaxRules(); - $taxRate = new TaxCreate(['title' => 'Discount Tax: ' . $rate, 'rate' => $rate]); - $lineItem->setTaxes([$taxRate]); - - $lineItems[] = $lineItem; + if ($taxRules && $taxRules->count() > 0) { + foreach ($taxRules as $taxRule) { + $rate = $taxRule->getTaxRate(); + $amount = $calculatedPrice->getTotalPrice(); + $lineItems[] = $this->createDiscountLineItem($discountName, $amount, $rate); + } + } else { + $rate = $this->getDefaultTaxRate(); + $amount = $calculatedPrice->getTotalPrice(); + $lineItems[] = $this->createDiscountLineItem($discountName, $amount, $rate); + } } } + /** + * @param string $discountName + * @param float $amount + * @param float $rate + * @return LineItemCreate + */ + private function createDiscountLineItem(string $discountName, float $amount, float $rate): LineItemCreate + { + $lineItem = new LineItemCreate(); + + $discountSkuName = 'sku-discount-' . $rate . '-' . $discountName; + $discountTitle = sprintf('DISCOUNT: %s (%s%% tax)', $discountName, $rate); + if ($this->order->getTaxStatus() === 'tax-free') { + $discountSkuName = 'sku-discount-' . $discountName; + $discountTitle = sprintf('DISCOUNT: %s', $discountName); + } + + $lineItem->setAmountIncludingTax($amount) + ->setName($discountTitle) + ->setQuantity(1) + ->setShippingRequired(false) + ->setSku($discountSkuName, 200) + ->setType(LineItemType::DISCOUNT) + ->setUniqueId('coupon-' . $discountSkuName); + + $taxRate = new TaxCreate([ + 'title' => 'Discount Tax: ' . $rate, + 'rate' => $rate, + ]); + + if ($this->order->getTaxStatus() !== 'tax-free') { + $lineItem->setTaxes([$taxRate]); + } + + return $lineItem; + } + + /** + * @return float + */ + private function getDefaultTaxRate(): float + { + /** @var SystemConfigService $systemConfigService */ + $systemConfigService = $this->container->get(SystemConfigService::class); + $taxId = $systemConfigService->get('core.tax.defaultTaxRate'); + + if (!$taxId || !is_string($taxId)) { + return 21.0; + } + + $criteria = new Criteria([$taxId]); + /** @var TaxRepository $taxRepository */ + $taxRepository = $this->container->get('tax.repository'); + $tax = $taxRepository->search($criteria, Context::createDefaultContext())->get($taxId); + + return $tax instanceof TaxEntity ? $tax->getTaxRate() : 21.0; + } + /** * Calculate discount amount including tax if necessary. */ protected function calculateDiscountAmount($calculatedTax): float { $amount = self::round($calculatedTax->getPrice()); - if ($this->transaction->getOrder()->getTaxStatus() === 'net') { + if ($this->order->getTaxStatus() === 'net') { $amount = self::round($amount + $calculatedTax->getTax()); } return $amount; @@ -357,9 +458,7 @@ class TransactionPayload extends AbstractPayload */ protected function addOptionalLineItems(array &$lineItems): void { - $shippingCosts = $this->transaction->getOrder()->getShippingCosts(); - - if ($shippingCosts && $this->transaction->getOrder()->getShippingTotal() > 0) { + if ($this->order->getShippingCosts() && $this->order->getShippingTotal() > 0) { if ($shippingLineItem = $this->getShippingLineItem()) { $lineItems[] = $shippingLineItem; } @@ -381,7 +480,7 @@ class TransactionPayload extends AbstractPayload protected function getCustomProductOptionLabel(string $lineItemParentId): string { $label = ''; - foreach ($this->transaction->getOrder()->getLineItems() as $shopLineItem) { + foreach ($this->order->getLineItems() as $shopLineItem) { if ($shopLineItem->getParentId() === $lineItemParentId && $shopLineItem->getType() === CustomProductsLineItemTypes::LINE_ITEM_TYPE_PRODUCT) { $label = $shopLineItem->getLabel(); break; @@ -406,10 +505,11 @@ class TransactionPayload extends AbstractPayload $sku = $payLoad['productNumber']; } $sku = $this->fixLength($sku, 200); + $amount = $shopLineItem->getTotalPrice() ? self::round($shopLineItem->getTotalPrice()) : 0; //include Tax Excluded for Net Tax display customer group - if ($this->transaction->getOrder()->getTaxStatus() === 'net') { + if ($this->order->getTaxStatus() === 'net') { $amount = self::round($amount + $shopLineItem->getPrice()->getCalculatedTaxes()->getAmount()); } @@ -445,7 +545,9 @@ class TransactionPayload extends AbstractPayload } if (!empty($taxes)) { - $lineItem->setTaxes($taxes); + if ($this->order->getTaxStatus() !== 'tax-free') { + $lineItem->setTaxes($taxes); + } } if ($shopLineItem->getTotalPrice() >= 0) { @@ -521,31 +623,34 @@ class TransactionPayload extends AbstractPayload { try { - $amount = $this->transaction->getOrder()->getShippingTotal(); + $amount = $this->order->getShippingTotal(); $amount = self::round($amount); if ($amount > 0) { $shippingName = $this->salesChannelContext->getShippingMethod()->getName() ?? $this->translator->trans('vrpayment.payload.shipping.name'); $taxes = $this->getTaxes( - $this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes(), + $this->order->getShippingCosts()->getCalculatedTaxes(), $shippingName ); - if ($this->transaction->getOrder()->getTaxStatus() === 'net') { - $amount = self::round($amount + $this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes()->getAmount()); + if ($this->order->getTaxStatus() === 'net') { + $amount = self::round($amount + $this->order->getShippingCosts()->getCalculatedTaxes()->getAmount()); } $lineItem = (new LineItemCreate()) ->setAmountIncludingTax($amount) ->setName($this->fixLength($shippingName . ' ' . $this->translator->trans('vrpayment.payload.shipping.lineItem'), 150)) - ->setQuantity($this->transaction->getOrder()->getShippingCosts()->getQuantity() ?? 1) - ->setTaxes($taxes) + ->setQuantity($this->order->getShippingCosts()->getQuantity() ?? 1) ->setSku($this->fixLength($shippingName . '-Shipping', 200)) /** @noinspection PhpParamsInspection */ ->setType(LineItemType::SHIPPING) ->setUniqueId($this->fixLength($shippingName . '-Shipping', 200)); + if ($this->order->getTaxStatus() !== 'tax-free') { + $lineItem->setTaxes($taxes); + } + if (!$lineItem->valid()) { $this->logger->critical('Shipping LineItem payload invalid:', $lineItem->listInvalidProperties()); throw new InvalidPayloadException('Shipping LineItem payload invalid:' . json_encode($lineItem->listInvalidProperties())); @@ -566,15 +671,15 @@ class TransactionPayload extends AbstractPayload protected function getMultipleShippingLineItems(): array { try { - if ($this->transaction->getOrder()->getShippingTotal() > 0) { + if ($this->order->getShippingTotal() > 0) { $lineItems = []; $shippingName = $this->salesChannelContext->getShippingMethod()->getName() ?? $this->translator->trans('vrpayment.payload.shipping.name'); $isFirst = true; - foreach ($this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes() as $taxItem) { + foreach ($this->order->getShippingCosts()->getCalculatedTaxes() as $taxItem) { $amount = self::round($taxItem->getPrice()); - if ($this->transaction->getOrder()->getTaxStatus() === 'net') { + if ($this->order->getTaxStatus() === 'net') { $amount = self::round($amount + $taxItem->getTax()); } $taxRate = $taxItem->getTaxRate(); @@ -586,12 +691,15 @@ class TransactionPayload extends AbstractPayload $lineItem = (new LineItemCreate()) ->setAmountIncludingTax($amount) ->setName($this->fixLength($name . ' ' . $this->translator->trans('vrpayment.payload.shipping.lineItem'), 150)) - ->setQuantity($this->transaction->getOrder()->getShippingCosts()->getQuantity() ?? 1) - ->setTaxes([$tax]) + ->setQuantity($this->order->getShippingCosts()->getQuantity() ?? 1) ->setSku($this->fixLength($name . '-Shipping', 200)) ->setType($isFirst ? LineItemType::SHIPPING : LineItemType::FEE) // First item as SHIPPING, rest as FEE ->setUniqueId($this->fixLength($name . '-Shipping', 200)); + if ($this->order->getTaxStatus() !== 'tax-free') { + $lineItem->setTaxes([$tax]); + } + if (!$lineItem->valid()) { $this->logger->critical('Shipping LineItem payload invalid:', $lineItem->listInvalidProperties()); throw new InvalidPayloadException('Shipping LineItem payload invalid:' . json_encode($lineItem->listInvalidProperties())); @@ -625,9 +733,8 @@ class TransactionPayload extends AbstractPayload $lineItemPriceTotal = array_sum(array_map(static fn(LineItemCreate $li) => $li->getAmountIncludingTax(), $lineItems)); $this->logger->debug("LineItem price total before adjustment: $lineItemPriceTotal"); - // Get shipping total including taxes from the order - $shippingCosts = $this->transaction->getOrder()->getShippingCosts(); + $shippingCosts = $this->order->getShippingCosts(); $shippingTotal = $shippingCosts ? self::round($shippingCosts->getTotalPrice()) : 0.0; // Add shipping to the line items total if it's not already included @@ -636,13 +743,13 @@ class TransactionPayload extends AbstractPayload $lineItemPriceTotal += $shippingTotal; } - $adjustmentPrice = self::round($this->transaction->getOrder()->getAmountTotal() - $lineItemPriceTotal); + $adjustmentPrice = self::round($this->order->getAmountTotal() - $lineItemPriceTotal); if (abs($adjustmentPrice) != 0) { if ($this->settings->isLineItemConsistencyEnabled()) { $error = strtr('LineItems total :lineItemTotal does not add up to order total :orderTotal', [ ':lineItemTotal' => $lineItemPriceTotal, - ':orderTotal' => $this->transaction->getOrder()->getAmountTotal(), + ':orderTotal' => $this->order->getAmountTotal(), ]); $this->logger->critical($error); throw new \Exception($error); diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-completion/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-completion/index.html.twig index 506861f..ec0cc3b 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-completion/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-completion/index.html.twig @@ -4,21 +4,21 @@ @modal-close="$emit('modal-close')"> {% block vrpayment_order_action_completion_amount %} - - + v-model:checked="isCompletion"> + {% endblock %} {% block vrpayment_order_action_completion_confirm_button %} {% endblock %} - + {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.html.twig index 3f00152..6f86754 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.html.twig @@ -4,23 +4,23 @@ @modal-close="$emit('modal-close')"> {% block vrpayment_order_action_refund_amount_by_amount %} - - + {% endblock %} {% block vrpayment_order_action_refund_confirm_button_by_amount %} {% endblock %} - + {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.js b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.js index 2a0e0ad..f11d712 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.js +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.js @@ -70,9 +70,18 @@ Component.register('vrpayment-order-action-refund-by-amount', { }); }).catch((errorResponse) => { try { + var errorTitle; + var errorMessage; + if (errorResponse.response.data == 'refundExceedsAmount') { + errorTitle = this.$tc('vrpayment-order.refundAction.refundExceedsTotalError.title'); + errorMessage = this.$tc('vrpayment-order.refundAction.refundExceedsTotalError.messageRefundAmountExceedsAvailableBalance'); + } else { + errorTitle = errorResponse.response.data.errors[0].title; + errorMessage = errorResponse.response.data.errors[0].detail; + } this.createNotificationError({ - title: errorResponse.response.data.errors[0].title, - message: errorResponse.response.data.errors[0].detail, + title: errorTitle, + message: errorMessage, autoClose: false }); } catch (e) { diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.html.twig index c3aa0cc..37a7e2b 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.html.twig @@ -4,13 +4,13 @@ @modal-close="$emit('modal-close')"> {% block vrpayment_order_action_refund_amount_partial %} - - +
    {{ $tc('vrpayment-order.refundAction.maxAvailableAmountToRefund') }}: @@ -20,12 +20,12 @@ {% block vrpayment_order_action_refund_confirm_button_partial %} {% endblock %} - + {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.js b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.js index b9274e8..d581002 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.js +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.js @@ -47,7 +47,9 @@ Component.register('vrpayment-order-action-refund-partial', { createdComponent() { this.isLoading = false; this.currency = this.transactionData.transactions[0].currency; - this.refundAmount = this.$parent.$parent.itemRefundableAmount; + if (!this.refundAmount) { + this.refundAmount = this.$parent.$parent.itemRefundableAmount; + } }, createPartialRefund(itemUniqueId) { diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-selected/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-selected/index.html.twig index b1cf34d..a2bfbb1 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-selected/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-selected/index.html.twig @@ -5,12 +5,12 @@ {% block vrpayment_order_action_refund_confirm_button_selected %} {% endblock %} - + {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.html.twig index d25ef15..2e3e421 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.html.twig @@ -5,12 +5,12 @@ {% block vrpayment_order_action_refund_amount %} - - +
    {{ $tc('vrpayment-order.refundAction.maxAvailableItemsToRefund') }}: @@ -20,12 +20,12 @@ {% block vrpayment_order_action_refund_confirm_button %} {% endblock %} - + {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-void/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-void/index.html.twig index 98c67c1..62abf11 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-void/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-void/index.html.twig @@ -4,21 +4,22 @@ @modal-close="$emit('modal-close')"> {% block vrpayment_order_action_void_amount %} - - + v-model:checked="isVoid"> + {% endblock %} {% block vrpayment_order_action_void_confirm_button %} {% endblock %} - + {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-order/extension/sw-order/sw-order.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/extension/sw-order/sw-order.html.twig index 27d4108..aeac916 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/extension/sw-order/sw-order.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/extension/sw-order/sw-order.html.twig @@ -1,6 +1,7 @@ {% block sw_order_detail_content_tabs_general %} {% parent %} +{# sw-tabs-item will dissappear. See: https://github.com/shopware/shopware/blob/trunk/UPGRADE-6.7.md#sw-tabs-is-removed #} diff --git a/src/Resources/app/administration/src/module/vrpayment-order/extension/sw-order/sw-order.scss b/src/Resources/app/administration/src/module/vrpayment-order/extension/sw-order/sw-order.scss index ff18ca8..f7ab85e 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/extension/sw-order/sw-order.scss +++ b/src/Resources/app/administration/src/module/vrpayment-order/extension/sw-order/sw-order.scss @@ -3,7 +3,7 @@ margin-top: 40px; } - .sw-order-detail-base .sw-card-view__content { + .sw-order-detail-base .mt-card-view__content { overflow-x: visible; overflow-y: visible; } diff --git a/src/Resources/app/administration/src/module/vrpayment-order/page/vrpayment-order-detail/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/page/vrpayment-order-detail/index.html.twig index 5d68090..30d37cc 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/page/vrpayment-order-detail/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/page/vrpayment-order-detail/index.html.twig @@ -1,61 +1,61 @@ {% block vrpayment_order_detail %}
    - + - + {% block vrpayment_order_transaction_history_card %} - + - + {% endblock %} {% block vrpayment_order_transaction_line_items_card %} - + - + {% endblock %} {% block vrpayment_order_transaction_refunds_card %} - + - + {% endblock %} {% block vrpayment_order_actions_modal_refund_partial %} {% endblock %}
    - +
    {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-order/snippet/de-DE.json b/src/Resources/app/administration/src/module/vrpayment-order/snippet/de-DE.json index ecd1e48..d712fb1 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/snippet/de-DE.json +++ b/src/Resources/app/administration/src/module/vrpayment-order/snippet/de-DE.json @@ -77,7 +77,11 @@ "successMessage": "Ihre Rückerstattung war erfolgreich", "successTitle": "Erfolg", "maxAvailableItemsToRefund": "Maximal Verfügbare Artikel zum Erstatten", - "maxAvailableAmountToRefund": "Maximal verfügbarer Erstattungsbetrag" + "maxAvailableAmountToRefund": "Maximal verfügbarer Erstattungsbetrag", + "refundExceedsTotalError": { + "title": "Fehler beim Erstellen der Rückerstattung.", + "messageRefundAmountExceedsAvailableBalance": "Der Rückerstattungsbetrag übersteigt das verfügbare Guthaben." + } }, "transactionHistory": { "cardTitle": "Einzelheiten", diff --git a/src/Resources/app/administration/src/module/vrpayment-order/snippet/en-GB.json b/src/Resources/app/administration/src/module/vrpayment-order/snippet/en-GB.json index 8f3f943..370354c 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/snippet/en-GB.json +++ b/src/Resources/app/administration/src/module/vrpayment-order/snippet/en-GB.json @@ -78,7 +78,11 @@ "successMessage": "Your refund was successful.", "successTitle": "Success", "maxAvailableItemsToRefund": "Maximum available items to refund", - "maxAvailableAmountToRefund": "Maximum available amount to refund" + "maxAvailableAmountToRefund": "Maximum available amount to refund", + "refundExceedsTotalError": { + "title": "Error while creating the refund.", + "messageRefundAmountExceedsAvailableBalance": "Refund amount exceeds available balance." + } }, "transactionHistory": { "cardTitle": "Details", diff --git a/src/Resources/app/administration/src/module/vrpayment-order/snippet/fr-FR.json b/src/Resources/app/administration/src/module/vrpayment-order/snippet/fr-FR.json index 97688e3..b4e9f00 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/snippet/fr-FR.json +++ b/src/Resources/app/administration/src/module/vrpayment-order/snippet/fr-FR.json @@ -77,7 +77,11 @@ "successMessage": "Votre remboursement a été effectué avec succès.", "successTitle": "Succès", "maxAvailableItemsToRefund": "Nombre maximum d'articles disponibles pour le remboursement", - "maxAvailableAmountToRefund": "Montant maximal disponible pour le remboursement" + "maxAvailableAmountToRefund": "Montant maximal disponible pour le remboursement", + "refundExceedsTotalError": { + "title": "Erreur lors de la création du remboursement.", + "messageRefundAmountExceedsAvailableBalance": "Le montant du remboursement dépasse le solde disponible." + } }, "transactionHistory": { "cardTitle": "Détails", diff --git a/src/Resources/app/administration/src/module/vrpayment-order/snippet/it-IT.json b/src/Resources/app/administration/src/module/vrpayment-order/snippet/it-IT.json index 12d174b..12a9ac8 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/snippet/it-IT.json +++ b/src/Resources/app/administration/src/module/vrpayment-order/snippet/it-IT.json @@ -77,7 +77,11 @@ "successMessage": "Il tuo rimborso è andato a buon fine.", "successTitle": "Successo", "maxAvailableItemsToRefund": "Numero massimo di articoli disponibili da rimborsare", - "maxAvailableAmountToRefund": "Importo massimo disponibile per il rimborso" + "maxAvailableAmountToRefund": "Importo massimo disponibile per il rimborso", + "refundExceedsTotalError": { + "title": "Errore durante la creazione del rimborso.", + "messageRefundAmountExceedsAvailableBalance": "LL'importo del rimborso supera il saldo disponibile." + } }, "transactionHistory": { "cardTitle": "Dettagli", diff --git a/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-advanced-options/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-advanced-options/index.html.twig index 024b3ff..68ca180 100644 --- a/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-advanced-options/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-advanced-options/index.html.twig @@ -1,4 +1,4 @@ -
    @@ -7,16 +7,16 @@ :inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_STOREFRONT_WEBHOOKS_UPDATE_ENABLED]" :customInheritationCheckFunction="checkBoolFieldInheritance"> @@ -25,19 +25,19 @@ :inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_STOREFRONT_PAYMENTS_UPDATE_ENABLED]" :customInheritationCheckFunction="checkBoolFieldInheritance">
    -
    + 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 90f9b5e..117ac2d 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 @@ -1,6 +1,6 @@ {% block vrpayment_settings_content_card_channel_config_credentials %} - @@ -17,17 +17,17 @@ :inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_SPACE_ID]" :customInheritationCheckFunction="checkNumberFieldInheritance"> {% endblock %} @@ -38,17 +38,17 @@ :inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_USER_ID]" :customInheritationCheckFunction="checkNumberFieldInheritance"> {% endblock %} @@ -59,7 +59,7 @@ :inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_APPLICATION_KEY]" :customInheritationCheckFunction="checkTextFieldInheritance"> {% endblock %}
    {% endblock %} + {% verbatim %} - {{ $tc('vrpayment-settings.settingForm.credentials.button.label') }} - + + {% endverbatim %} {% endblock %} - + {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-options/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-options/index.html.twig index 0760ce1..252b010 100644 --- a/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-options/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-options/index.html.twig @@ -1,5 +1,5 @@ {% block vrpayment_settings_content_card_channel_config_options %} - {% block vrpayment_settings_content_card_channel_config_credentials_card_container %} @@ -14,15 +14,15 @@ :inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_SPACE_VIEW_ID]" :customInheritationCheckFunction="checkNumberFieldInheritance"> {% endblock %} @@ -55,16 +55,16 @@ :inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_LINE_ITEM_CONSISTENCY_ENABLED]" :customInheritationCheckFunction="checkBoolFieldInheritance"> {% endblock %} @@ -75,16 +75,16 @@ :inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_EMAIL_ENABLED]" :customInheritationCheckFunction="checkBoolFieldInheritance"> {% endblock %} @@ -92,6 +92,6 @@ {% endblock %} {% endblock %} - + {% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-settings-icon/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-settings-icon/index.html.twig index ad1f95e..3fad643 100644 --- a/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-settings-icon/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-settings/component/sw-vrpayment-settings-icon/index.html.twig @@ -1,5 +1,5 @@ {% block vrpayment_settings_icon %} - +
    @@ -7,19 +7,19 @@ :inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_STOREFRONT_INVOICE_DOWNLOAD_ENABLED]" :customInheritationCheckFunction="checkBoolFieldInheritance">
    - + 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 0fee779..377d7a2 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 @@ -5,7 +5,7 @@ @@ -14,7 +14,7 @@ {% block vrpayment_settings_actions %} {% endblock %} @@ -31,7 +31,7 @@ {% endblock %} @@ -134,12 +135,12 @@ {% endblock %} {% block vrpayment_settings_content_card_loading %} - + {% endblock %} - + {% endblock %} {% endblock %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/Resources/app/administration/src/module/vrpayment-settings/page/vrpayment-settings/index.js b/src/Resources/app/administration/src/module/vrpayment-settings/page/vrpayment-settings/index.js index 05b1c95..56add61 100644 --- a/src/Resources/app/administration/src/module/vrpayment-settings/page/vrpayment-settings/index.js +++ b/src/Resources/app/administration/src/module/vrpayment-settings/page/vrpayment-settings/index.js @@ -65,18 +65,6 @@ Component.register('vrpayment-settings', { }; }, - created() { - // Registers a listener for the 'check-api-connection-event'. - // Triggered when this event is emitted. - this.$on('check-api-connection-event', this.onCheckApiConnection); - }, - - beforeDestroy() { - // Removes the listener for the 'check-api-connection-event' - // before the component is destroyed to prevent memory leaks. - this.$off('check-api-connection-event', this.onCheckApiConnection); - }, - watch: { config: { handler(configData) { diff --git a/src/Resources/config/services/core/checkout.xml b/src/Resources/config/services/core/checkout.xml index e980a67..ee1861e 100644 --- a/src/Resources/config/services/core/checkout.xml +++ b/src/Resources/config/services/core/checkout.xml @@ -5,13 +5,31 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + + + + + + + + + + + - + + + + + diff --git a/src/Resources/config/services/core/storefront/checkout.xml b/src/Resources/config/services/core/storefront/checkout.xml index f022b03..427f4d5 100644 --- a/src/Resources/config/services/core/storefront/checkout.xml +++ b/src/Resources/config/services/core/storefront/checkout.xml @@ -19,9 +19,10 @@ - + + diff --git a/src/Resources/public/storefront/js/app.js b/src/Resources/public/storefront/js/app.js index fc1c90c..773dfe8 100644 --- a/src/Resources/public/storefront/js/app.js +++ b/src/Resources/public/storefront/js/app.js @@ -29,7 +29,7 @@ payment_method_handler_status: 'input[name="vrpayment_payment_handler_validation_status"]', payment_form_id: 'confirmOrderForm', button_cancel_id: 'vrpaymentOrderCancel', - button_home_override: 'vrpaymentHomeLink', + // button_home_override: 'vrpaymentHomeLink', loader_id: 'vrpaymentLoader', checkout_url: null, checkout_url_id: 'checkoutUrl', @@ -46,7 +46,7 @@ this.cart_recreate_url = document.getElementById(this.cart_recreate_url_id).value; document.getElementById(this.button_cancel_id).addEventListener('click', this.recreateCart, false); - document.getElementById(this.button_home_override).addEventListener('click', this.recreateCart, false); + // document.getElementById(this.button_home_override).addEventListener('click', this.recreateCart, false); document.getElementById(this.payment_form_id).addEventListener('submit', this.submitPayment, false); VRPaymentCheckout.getIframe(); diff --git a/src/Resources/views/storefront/page/checkout/order/vrpayment.html.twig b/src/Resources/views/storefront/page/checkout/order/vrpayment.html.twig index 5e6c15b..9aa434c 100644 --- a/src/Resources/views/storefront/page/checkout/order/vrpayment.html.twig +++ b/src/Resources/views/storefront/page/checkout/order/vrpayment.html.twig @@ -1,15 +1,11 @@ {% sw_extends '@Storefront/storefront/page/checkout/_page.html.twig' %} -{% block base_header %} - {% sw_include '@VRPaymentPayment/storefront/page/checkout/order/vrpayment_header.html.twig' %} -{% endblock %} - -{% block base_navigation %}{% endblock %} {% block base_body_classes %}vrpayment-payment is-act-confirmpage{% endblock %} {% block page_checkout_main_content %} - {% block page_checkout_pay %} - {% block page_checkout_confirm_header %} +
    + {% block page_checkout_pay %} + {% block page_checkout_confirm_header %}

    {{ "vrpayment.payHeader"|trans|sw_sanitize }}

    @@ -144,10 +140,6 @@
    {% endblock %} -{% block base_footer %} - {% sw_include '@Storefront/storefront/layout/footer/footer-minimal.html.twig' %} -{% endblock %} - {% block base_body_script %} {{ parent() }} {% if page.extensions.vRPaymentData %} diff --git a/src/Resources/views/storefront/page/checkout/order/vrpayment_header.html.twig b/src/Resources/views/storefront/page/checkout/order/vrpayment_header.html.twig deleted file mode 100644 index 4d958c1..0000000 --- a/src/Resources/views/storefront/page/checkout/order/vrpayment_header.html.twig +++ /dev/null @@ -1,53 +0,0 @@ -{% sw_extends '@Storefront/storefront/layout/header/header-minimal.html.twig' %} - -{% block layout_header_minimal_logo %} - -{% endblock %} - -{% block layout_header_minimal_button %} -
    - -
    -{% endblock %} \ No newline at end of file diff --git a/src/VRPaymentPayment.php b/src/VRPaymentPayment.php index e305188..a6650cb 100644 --- a/src/VRPaymentPayment.php +++ b/src/VRPaymentPayment.php @@ -3,6 +3,7 @@ namespace VRPaymentPayment; use Shopware\Core\{ + Framework\Feature, Framework\Plugin, Framework\Plugin\Context\ActivateContext, Framework\Plugin\Context\DeactivateContext, @@ -21,6 +22,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; use Symfony\Component\DependencyInjection\Loader\GlobFileLoader; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; // expect the vendor folder on Shopware store releases if (file_exists(dirname(__DIR__) . '/vendor/autoload.php')) { @@ -82,19 +84,21 @@ class VRPaymentPayment extends Plugin { { parent::build($container); - $locator = new FileLocator('Resources/config'); + $confDir = \rtrim($this->getPath(), '/') . '/Resources/config'; + $locator = new FileLocator($confDir); $resolver = new LoaderResolver([ - new YamlFileLoader($container, $locator), - new GlobFileLoader($container, $locator), - new DirectoryLoader($container, $locator), + new YamlFileLoader($container, $locator), + new XmlFileLoader($container, $locator), + new GlobFileLoader($container, $locator), + new DirectoryLoader($container, $locator), ]); $configLoader = new DelegatingLoader($resolver); - $confDir = \rtrim($this->getPath(), '/') . '/Resources/config'; - $configLoader->load($confDir . '/{packages}/*.yaml', 'glob'); + + $configLoader->load('services/core/checkout.xml'); } public function enrichPrivileges(): array