Compare commits

..

5 Commits

Author SHA1 Message Date
andrewrowanwallee e732454683 Release 6.2.1 2026-02-12 13:13:32 +01:00
andrewrowanwallee 57246e23ce Release 6.2.0 2026-01-15 09:20:03 +01:00
andrewrowanwallee 68592a9409 Release 6.1.17 2025-11-03 13:29:47 +01:00
andrewrowanwallee 1393f4ff7c Release 6.1.16 2025-10-01 10:15:25 +02:00
andrewrowanwallee d714cf2f84 release 6.1.15 2025-09-17 12:11:32 +02:00
73 changed files with 2296 additions and 1233 deletions
+15 -9
View File
@@ -1,14 +1,20 @@
# 7.0.1
## Feature
- Add plugin version metric
# 6.2.1
- Fixed issue with multiple discount codes
## Bugfix
- Fixed error message when refund amount exceeds total
- Fixed bug where only 25 sales channels showed in the dropdown
- Removed erroneous logs
# 6.2.0
- Renamed database table to avoid a naming conflict with legacy plugins
- Fixed issue with refunds failing for payments using Invoice
# 7.0.0
- Compatibility with Shopware 6.7.0
# 6.1.17
- Sales channels now support different spaces
- Upgraded SDK to include latest fallback CA Bundle
- Fixed error screen when returning from portal on failed payment
# 6.1.16
- Fixed issue with pending orders remaining open
# 6.1.15
- Fixed issue with shipping costs not being processed correctly
# 6.1.14
- Disable Recreate Cart for Headless Storefront Order
+16 -7
View File
@@ -1,11 +1,20 @@
# 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
# 6.2.1
- Problem mit mehreren Rabattcodes behoben
# 7.0.0
- Kompatibilität mit Shopware 6.7.0
# 6.2.0
- Datenbanktabelle umbenannt, um Namenskonflikte mit älteren Plugins zu vermeiden.
- Problem mit fehlgeschlagenen Rückerstattungen bei Zahlungen mit Rechnungen behoben.
# 6.1.17
- Vertriebskanäle unterstützen jetzt verschiedene Bereiche
- SDK aktualisiert und enthält nun das neueste CA-Fallback-Bundle
- Fehlerbildschirm beim Zurückkehren vom Portal nach fehlgeschlagener Zahlung behoben
# 6.1.16
- Problem behoben, bei dem die Versandkosten nicht korrekt verarbeitet wurden
# 6.1.15
- Problem behoben, bei dem ausstehende Bestellungen offen blieben
# 6.1.14
Warenkorb neu erstellen für Headless Storefront Order deaktivieren
+1 -1
View File
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2025 VR Payment GmbH
Copyright 2026 VR Payment GmbH
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+26 -11
View File
@@ -3,20 +3,20 @@
VR Payment Integration for Shopware 6
=============================
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).
## **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.
## Requirements
- Shopware 6.7.x, 6.6.x or 6.5.x. See table below.
- PHP minimum version supported by the each shop version.
- **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/).
## Documentation
- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.0.1/docs/en/documentation.html)
- Für die deutsche Dokumentation klicken Sie [hier](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.0.1/docs/de/documentation.html)
- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.0.1/docs/fr/documentation.html)
- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.0.1/docs/it/documentation.html)
- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.2.1/docs/en/documentation.html)
- Für die deutsche Dokumentation klicken Sie [hier](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.2.1/docs/de/documentation.html)
- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.2.1/docs/fr/documentation.html)
- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.2.1/docs/it/documentation.html)
## Installation
@@ -42,6 +42,22 @@ bin/console plugin:refresh
bin/console plugin:install --activate --clearCache VRPaymentPayment
```
## Update
### Via Administration
1. Go to Shopware Admin > Extensions > My extensions.
2. Find VRPaymentPayment.
3. Click Update.
### Via CLI
1. Deploy the new plugin files (replace the folder in custom/plugins/VRPaymentPayment or upload/install a new ZIP).
2. Run:
```bash
bin/console plugin:refresh
bin/console plugin:update --clearCache VRPaymentPayment
bin/console cache:clear
```
## Configuration
### API Credentials
@@ -66,8 +82,7 @@ Configure supported methods (e.g., credit cards, Apple Pay) via the [VR Payment
___________________________________________________________________________________
| Shopware 6 version | Plugin major version | Supported until |
|-------------------------------|------------------------|------------------------|
| Shopware 6.7.x | 7.x | Further notice |
| Shopware 6.6.x | 6.x | December 2025 |
| Shopware 6.6.x | 6.x | Further notice |
| Shopware 6.5.x | 5.x | October 2024 |
-----------------------------------------------------------------------------------
+4 -4
View File
@@ -53,11 +53,11 @@
"ext-json": "*",
"ext-mbstring": "*",
"php": ">=8.2",
"shopware/core": "~6.7.0",
"shopware/administration": "~6.7.0",
"shopware/storefront":"~6.7.0",
"shopware/core": "~6.6.0",
"shopware/administration": "~6.6.0",
"shopware/storefront":"~6.6.0",
"vrpayment/sdk": "^4.0.0"
},
"type": "shopware-platform-plugin",
"version": "7.0.1"
"version": "6.2.1"
}
+115 -49
View File
@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="keywords" value="VR Payment, Shopware, Shopware Plugin, Payment, Payment Integration, Documentation"><meta name="description" value="The documentation for the Shopware 6 plugin that enables processing payments with VR Payment.">
<link rel="canonical" href="https://plugin-documentation.wallee.com/wallee-payment/shopware-6/master/VRPaymentPayment/docs/de/documentation.html" />
<link rel="canonical" href="@WalleeCanonicalPath(https://plugin-documentation.wallee.com/wallee-payment, VRPaymentPayment/docs/de/documentation.html)" />
<title>VR Payment Zahlungs-Plugin für Shopware 6</title>
<link href="assets/monokai-sublime.css" rel="stylesheet" />
<link href="assets/base.css" rel="stylesheet" />
@@ -23,7 +23,7 @@
</a>
</li>
<li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.0.1/">
<a href="@WalleeReleasePath()">
Source
</a>
</li>
@@ -178,14 +178,63 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment</code></
</ol>
</div> </div>
</div> </div>
</div> <div class="chapter" id="_update">
<div class="chapter-title">
<h1>
<span class="title-number">5</span>Update </h1>
</div>
<div class="chapter-body">
<div class="section" id="_via_administration">
<div class="section-title">
<h2>
<span class="title-number">5.1</span>Via Administration </h2>
</div>
<div class="section-body">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Gehe zu Shopware Admin &gt; Erweiterungen &gt; Meine Erweiterungen.</p>
</li>
<li>
<p>Suche nach VRPaymentPayment.</p>
</li>
<li>
<p>Klicke auf Aktualisieren.</p>
</li>
</ol>
</div> </div>
</div> <div class="section" id="_via_cli">
<div class="section-title">
<h2>
<span class="title-number">5.2</span>Via CLI </h2>
</div>
<div class="section-body">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Stelle die neuen Plugin-Dateien bereit (ersetze den Ordner <code>custom/plugins/VRPaymentPayment</code> oder lade ein neues ZIP hoch/installiere es).</p>
</li>
<li>
<p>Führe aus:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">bin/console plugin:refresh
bin/console plugin:update --clearCache VRPaymentPayment
bin/console cache:clear</code></pre>
</div>
</div>
</li>
</ol>
</div> </div>
</div> </div>
</div> <div class="chapter" id="portal-startup-guide">
<div class="chapter-title">
<h1>
<span class="title-number">5</span>Portal-Startanleitung </h1>
<span class="title-number">6</span>Portal-Startanleitung </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
<p>Gehen Sie zu <a href="https://gateway.vr-payment.de/user/login/user/login">VR Payment</a> und erstellen Sie ein Konto, falls Sie noch keines haben.</p>
<p>Gehen Sie zu <a href="https://gateway.vr-payment.de/user/login">VR Payment</a> und erstellen Sie ein Konto, falls Sie noch keines haben.</p>
</div><div class="admonitionblock tip">
<table>
<tr>
@@ -200,7 +249,7 @@ Wählen Sie das passende Abo aus es sollte E-Commerce-Transaktionen unterst
</div> <div class="section" id="_erstellen_sie_den_api_schlüssel">
<div class="section-title">
<h2>
<span class="title-number">5.1</span>Erstellen Sie den API-Schlüssel: </h2>
<span class="title-number">6.1</span>Erstellen Sie den API-Schlüssel: </h2>
</div>
<div class="section-body">
<div class="olist arabic">
@@ -286,7 +335,7 @@ Bitte beachten Sie, dass das Laden der Rollen einige Sekunden dauern kann.
</div> <div class="section" id="_zahlungsmethoden_einrichten">
<div class="section-title">
<h2>
<span class="title-number">5.2</span>Zahlungsmethoden einrichten </h2>
<span class="title-number">6.2</span>Zahlungsmethoden einrichten </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -348,7 +397,7 @@ Bitte beachten Sie, dass die Konnektoren doppelt erscheinen, da einer für Zahlu
</div> <div class="chapter" id="_shop_startanleitung">
<div class="chapter-title">
<h1>
<span class="title-number">6</span>Shop-Startanleitung </h1>
<span class="title-number">7</span>Shop-Startanleitung </h1>
</div>
<div class="chapter-body">
<div class="olist arabic">
@@ -487,7 +536,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi
</div> <div class="chapter" id="_transaktionszustandsdiagramm">
<div class="chapter-title">
<h1>
<span class="title-number">7</span>Transaktionszustandsdiagramm </h1>
<span class="title-number">8</span>Transaktionszustandsdiagramm </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -497,7 +546,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi
</div> <div class="section" id="_zustandsabbildung_von_shopware_bestellungen">
<div class="section-title">
<h2>
<span class="title-number">7.1</span>Zustandsabbildung von Shopware-Bestellungen </h2>
<span class="title-number">8.1</span>Zustandsabbildung von Shopware-Bestellungen </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -505,7 +554,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi
</div> <div class="section" id="_allgemeine_anmerkungen_zu_bestellstatus">
<div class="section-title">
<h3>
<span class="title-number">7.1.1</span>Allgemeine Anmerkungen zu Bestellstatus </h3>
<span class="title-number">8.1.1</span>Allgemeine Anmerkungen zu Bestellstatus </h3>
</div>
<div class="section-body">
<div class="paragraph">
@@ -515,7 +564,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi
</div> <div class="section" id="_zustandsabbildung_des_shopware_zahlungsstatus">
<div class="section-title">
<h2>
<span class="title-number">7.2</span>Zustandsabbildung des Shopware-Zahlungsstatus </h2>
<span class="title-number">8.2</span>Zustandsabbildung des Shopware-Zahlungsstatus </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -542,7 +591,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi
</div> <div class="section" id="_allgemeine_anmerkungen_zu_zahlungsstatus">
<div class="section-title">
<h3>
<span class="title-number">7.2.1</span>Allgemeine Anmerkungen zu Zahlungsstatus </h3>
<span class="title-number">8.2.1</span>Allgemeine Anmerkungen zu Zahlungsstatus </h3>
</div>
<div class="section-body">
<div class="paragraph">
@@ -552,7 +601,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi
</div> <div class="section" id="_zustandsabbildung_des_shopware_lieferstatus">
<div class="section-title">
<h2>
<span class="title-number">7.3</span>Zustandsabbildung des Shopware-Lieferstatus </h2>
<span class="title-number">8.3</span>Zustandsabbildung des Shopware-Lieferstatus </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -578,7 +627,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi
</div> <div class="chapter" id="_transaktionsverwaltung">
<div class="chapter-title">
<h1>
<span class="title-number">8</span>Transaktionsverwaltung </h1>
<span class="title-number">9</span>Transaktionsverwaltung </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -586,7 +635,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi
</div> <div class="section" id="_bestellung_abschließen_erfassen">
<div class="section-title">
<h2>
<span class="title-number">8.1</span>Bestellung abschließen (erfassen) </h2>
<span class="title-number">9.1</span>Bestellung abschließen (erfassen) </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -614,7 +663,7 @@ Wenn der Abschluss in VR Payment ausstehend ist, bleibt die Bestellung im Status
</div> <div class="section" id="_transaktion_stornieren">
<div class="section-title">
<h2>
<span class="title-number">8.2</span>Transaktion stornieren </h2>
<span class="title-number">9.2</span>Transaktion stornieren </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -638,7 +687,7 @@ Sie können nur Transaktionen stornieren, die noch nicht abgeschlossen sind.
</div> <div class="section" id="_rückerstattung_einer_transaktion">
<div class="section-title">
<h2>
<span class="title-number">8.3</span>Rückerstattung einer Transaktion </h2>
<span class="title-number">9.3</span>Rückerstattung einer Transaktion </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -664,7 +713,7 @@ Es kann einige Zeit dauern, bis Sie die Rückerstattung in Shopware sehen. Rück
</div> <div class="section" id="_bestellungen_auf_on_hold">
<div class="section-title">
<h2>
<span class="title-number">8.4</span>Bestellungen auf On Hold </h2>
<span class="title-number">9.4</span>Bestellungen auf On Hold </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -686,7 +735,7 @@ Es kann einige Zeit dauern, bis Sie die Rückerstattung in Shopware sehen. Rück
</div> <div class="section" id="_einschränkungen_der_synchronisierung_zwischen_whitelabelname_und_shopware">
<div class="section-title">
<h2>
<span class="title-number">8.5</span>Einschränkungen der Synchronisierung zwischen VR Payment und Shopware </h2>
<span class="title-number">9.5</span>Einschränkungen der Synchronisierung zwischen VR Payment und Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -697,7 +746,7 @@ Es kann einige Zeit dauern, bis Sie die Rückerstattung in Shopware sehen. Rück
</div> <div class="section" id="_tokenisierung">
<div class="section-title">
<h2>
<span class="title-number">8.6</span>Tokenisierung </h2>
<span class="title-number">9.6</span>Tokenisierung </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -717,7 +766,7 @@ Die Tokenisierung ist für Gast-Checkouts nicht verfügbar
</div> <div class="section" id="_hauptfunktionen">
<div class="section-title">
<h2>
<span class="title-number">8.7</span>Hauptfunktionen </h2>
<span class="title-number">9.7</span>Hauptfunktionen </h2>
</div>
<div class="section-body">
<div class="ulist">
@@ -739,7 +788,7 @@ Die Tokenisierung ist für Gast-Checkouts nicht verfügbar
</div> <div class="section" id="_fehlerbehebung">
<div class="section-title">
<h2>
<span class="title-number">8.8</span>Fehlerbehebung </h2>
<span class="title-number">9.8</span>Fehlerbehebung </h2>
</div>
<div class="section-body">
<div class="ulist">
@@ -771,7 +820,7 @@ tail -f var/log/whitelabelname_payment*.log</code></pre>
</div> <div class="section" id="_faqs">
<div class="section-title">
<h2>
<span class="title-number">8.9</span>FAQs </h2>
<span class="title-number">9.9</span>FAQs </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -800,7 +849,7 @@ A: Ja, das Plugin unterstützt Wallets wie Apple Pay.</p>
</div> <div class="chapter" id="_änderungsprotokoll">
<div class="chapter-title">
<h1>
<span class="title-number">9</span>Änderungsprotokoll </h1>
<span class="title-number">10</span>Änderungsprotokoll </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -809,7 +858,7 @@ A: Ja, das Plugin unterstützt Wallets wie Apple Pay.</p>
</div> <div class="chapter" id="_mitwirken">
<div class="chapter-title">
<h1>
<span class="title-number">10</span>Mitwirken </h1>
<span class="title-number">11</span>Mitwirken </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -820,7 +869,7 @@ A: Ja, das Plugin unterstützt Wallets wie Apple Pay.</p>
</div> <div class="chapter" id="_support">
<div class="chapter-title">
<h1>
<span class="title-number">11</span>Support </h1>
<span class="title-number">12</span>Support </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -871,128 +920,145 @@ A: Ja, das Plugin unterstützt Wallets wie Apple Pay.</p>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
<a href="#_update">
<span class="item-number">5</span>
<span class="item-title">Update</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_via_administration">
<span class="item-number">5.1</span>
<span class="item-title">Via Administration</span>
</a>
</li> <li class="nav-level-2">
<a href="#_via_cli">
<span class="item-number">5.2</span>
<span class="item-title">Via CLI</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
<span class="item-number">6</span>
<span class="item-title">Portal-Startanleitung</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_erstellen_sie_den_api_schlüssel">
<span class="item-number">5.1</span>
<span class="item-number">6.1</span>
<span class="item-title">Erstellen Sie den API-Schlüssel:</span>
</a>
</li> <li class="nav-level-2">
<a href="#_zahlungsmethoden_einrichten">
<span class="item-number">5.2</span>
<span class="item-number">6.2</span>
<span class="item-title">Zahlungsmethoden einrichten</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_shop_startanleitung">
<span class="item-number">6</span>
<span class="item-number">7</span>
<span class="item-title">Shop-Startanleitung</span>
</a>
</li> <li class="nav-level-1">
<a href="#_transaktionszustandsdiagramm">
<span class="item-number">7</span>
<span class="item-number">8</span>
<span class="item-title">Transaktionszustandsdiagramm</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_zustandsabbildung_von_shopware_bestellungen">
<span class="item-number">7.1</span>
<span class="item-number">8.1</span>
<span class="item-title">Zustandsabbildung von Shopware-Bestellungen</span>
</a>
<ul class="nav">
<li class="nav-level-3">
<a href="#_allgemeine_anmerkungen_zu_bestellstatus">
<span class="item-number">7.1.1</span>
<span class="item-number">8.1.1</span>
<span class="item-title">Allgemeine Anmerkungen zu Bestellstatus</span>
</a>
</li> </ul>
</li> <li class="nav-level-2">
<a href="#_zustandsabbildung_des_shopware_zahlungsstatus">
<span class="item-number">7.2</span>
<span class="item-number">8.2</span>
<span class="item-title">Zustandsabbildung des Shopware-Zahlungsstatus</span>
</a>
<ul class="nav">
<li class="nav-level-3">
<a href="#_allgemeine_anmerkungen_zu_zahlungsstatus">
<span class="item-number">7.2.1</span>
<span class="item-number">8.2.1</span>
<span class="item-title">Allgemeine Anmerkungen zu Zahlungsstatus</span>
</a>
</li> </ul>
</li> <li class="nav-level-2">
<a href="#_zustandsabbildung_des_shopware_lieferstatus">
<span class="item-number">7.3</span>
<span class="item-number">8.3</span>
<span class="item-title">Zustandsabbildung des Shopware-Lieferstatus</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_transaktionsverwaltung">
<span class="item-number">8</span>
<span class="item-number">9</span>
<span class="item-title">Transaktionsverwaltung</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_bestellung_abschließen_erfassen">
<span class="item-number">8.1</span>
<span class="item-number">9.1</span>
<span class="item-title">Bestellung abschließen (erfassen)</span>
</a>
</li> <li class="nav-level-2">
<a href="#_transaktion_stornieren">
<span class="item-number">8.2</span>
<span class="item-number">9.2</span>
<span class="item-title">Transaktion stornieren</span>
</a>
</li> <li class="nav-level-2">
<a href="#_rückerstattung_einer_transaktion">
<span class="item-number">8.3</span>
<span class="item-number">9.3</span>
<span class="item-title">Rückerstattung einer Transaktion</span>
</a>
</li> <li class="nav-level-2">
<a href="#_bestellungen_auf_on_hold">
<span class="item-number">8.4</span>
<span class="item-number">9.4</span>
<span class="item-title">Bestellungen auf On Hold</span>
</a>
</li> <li class="nav-level-2">
<a href="#_einschränkungen_der_synchronisierung_zwischen_whitelabelname_und_shopware">
<span class="item-number">8.5</span>
<span class="item-number">9.5</span>
<span class="item-title">Einschränkungen der Synchronisierung zwischen VR Payment und Shopware</span>
</a>
</li> <li class="nav-level-2">
<a href="#_tokenisierung">
<span class="item-number">8.6</span>
<span class="item-number">9.6</span>
<span class="item-title">Tokenisierung</span>
</a>
</li> <li class="nav-level-2">
<a href="#_hauptfunktionen">
<span class="item-number">8.7</span>
<span class="item-number">9.7</span>
<span class="item-title">Hauptfunktionen</span>
</a>
</li> <li class="nav-level-2">
<a href="#_fehlerbehebung">
<span class="item-number">8.8</span>
<span class="item-number">9.8</span>
<span class="item-title">Fehlerbehebung</span>
</a>
</li> <li class="nav-level-2">
<a href="#_faqs">
<span class="item-number">8.9</span>
<span class="item-number">9.9</span>
<span class="item-title">FAQs</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_änderungsprotokoll">
<span class="item-number">9</span>
<span class="item-number">10</span>
<span class="item-title">Änderungsprotokoll</span>
</a>
</li> <li class="nav-level-1">
<a href="#_mitwirken">
<span class="item-number">10</span>
<span class="item-number">11</span>
<span class="item-title">Mitwirken</span>
</a>
</li> <li class="nav-level-1">
<a href="#_support">
<span class="item-number">11</span>
<span class="item-number">12</span>
<span class="item-title">Support</span>
</a>
</li> </ul>
+115 -49
View File
@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="keywords" value="VR Payment, Shopware, Shopware Plugin, Payment, Payment Integration, Documentation"><meta name="description" value="The documentation for the Shopware 6 plugin that enables processing payments with VR Payment.">
<link rel="canonical" href="https://plugin-documentation.wallee.com/wallee-payment/shopware-6/master/VRPaymentPayment/docs/en/documentation.html" />
<link rel="canonical" href="@WalleeCanonicalPath(https://plugin-documentation.wallee.com/wallee-payment, VRPaymentPayment/docs/en/documentation.html)" />
<title>VR Payment Shopware 6 Documentation</title>
<link href="assets/monokai-sublime.css" rel="stylesheet" />
<link href="assets/base.css" rel="stylesheet" />
@@ -23,7 +23,7 @@
</a>
</li>
<li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.0.1/">
<a href="@WalleeReleasePath()">
Source
</a>
</li>
@@ -172,14 +172,63 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment</code></
</ol>
</div> </div>
</div> </div>
</div> <div class="chapter" id="_update">
<div class="chapter-title">
<h1>
<span class="title-number">5</span>Update </h1>
</div>
<div class="chapter-body">
<div class="section" id="_via_administration">
<div class="section-title">
<h2>
<span class="title-number">5.1</span>Via Administration </h2>
</div>
<div class="section-body">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Go to Shopware Admin &gt; Extensions &gt; My extensions.</p>
</li>
<li>
<p>Find VRPaymentPayment.</p>
</li>
<li>
<p>Click Update.</p>
</li>
</ol>
</div> </div>
</div> <div class="section" id="_via_cli">
<div class="section-title">
<h2>
<span class="title-number">5.2</span>Via CLI </h2>
</div>
<div class="section-body">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Deploy the new plugin files (replace the folder in <code>custom/plugins/VRPaymentPayment</code> or upload/install a new ZIP).</p>
</li>
<li>
<p>Run:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">bin/console plugin:refresh
bin/console plugin:update --clearCache VRPaymentPayment
bin/console cache:clear</code></pre>
</div>
</div>
</li>
</ol>
</div> </div>
</div> </div>
</div> <div class="chapter" id="portal-startup-guide">
<div class="chapter-title">
<h1>
<span class="title-number">5</span>Portal Startup Guide </h1>
<span class="title-number">6</span>Portal Startup Guide </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
<p>Go to <a href="https://gateway.vr-payment.de/user/login/user/login">VR Payment</a> and create an Account if you do not already have one.</p>
<p>Go to <a href="https://gateway.vr-payment.de/user/login">VR Payment</a> and create an Account if you do not already have one.</p>
</div><div class="admonitionblock tip">
<table>
<tr>
@@ -194,7 +243,7 @@ Please select the proper subscription plan - it should support ecommerce transac
</div> <div class="section" id="_create_the_api_key">
<div class="section-title">
<h2>
<span class="title-number">5.1</span>Create the API key: </h2>
<span class="title-number">6.1</span>Create the API key: </h2>
</div>
<div class="section-body">
<div class="olist arabic">
@@ -280,7 +329,7 @@ Please note that Roles might be loading for few seconds
</div> <div class="section" id="_setup_payment_methods">
<div class="section-title">
<h2>
<span class="title-number">5.2</span>Setup Payment Methods </h2>
<span class="title-number">6.2</span>Setup Payment Methods </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -342,7 +391,7 @@ Please note that the connectors seems duplicated but it because one is for Physi
</div> <div class="chapter" id="_shop_startup_guide">
<div class="chapter-title">
<h1>
<span class="title-number">6</span>Shop Startup Guide </h1>
<span class="title-number">7</span>Shop Startup Guide </h1>
</div>
<div class="chapter-body">
<div class="olist arabic">
@@ -481,7 +530,7 @@ Please note that if you do not use the Space View Id; this option should stay em
</div> <div class="chapter" id="_transaction_state_graph">
<div class="chapter-title">
<h1>
<span class="title-number">7</span>Transaction State graph </h1>
<span class="title-number">8</span>Transaction State graph </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -493,7 +542,7 @@ can be found in the <a href="https://gateway.vr-payment.de/en-us/doc/payment/tra
</div> <div class="section" id="_state_mapping_of_shopware_orders">
<div class="section-title">
<h2>
<span class="title-number">7.1</span>State mapping of Shopware orders </h2>
<span class="title-number">8.1</span>State mapping of Shopware orders </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -501,7 +550,7 @@ can be found in the <a href="https://gateway.vr-payment.de/en-us/doc/payment/tra
</div> <div class="section" id="_general_remarks_regarding_order_statuses">
<div class="section-title">
<h3>
<span class="title-number">7.1.1</span>General remarks regarding order statuses </h3>
<span class="title-number">8.1.1</span>General remarks regarding order statuses </h3>
</div>
<div class="section-body">
<div class="paragraph">
@@ -511,7 +560,7 @@ can be found in the <a href="https://gateway.vr-payment.de/en-us/doc/payment/tra
</div> <div class="section" id="_state_mapping_of_shopware_payment_status">
<div class="section-title">
<h2>
<span class="title-number">7.2</span>State mapping of Shopware payment status </h2>
<span class="title-number">8.2</span>State mapping of Shopware payment status </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -538,7 +587,7 @@ can be found in the <a href="https://gateway.vr-payment.de/en-us/doc/payment/tra
</div> <div class="section" id="_general_remarks_regarding_payment_statuses">
<div class="section-title">
<h3>
<span class="title-number">7.2.1</span>General remarks regarding payment statuses </h3>
<span class="title-number">8.2.1</span>General remarks regarding payment statuses </h3>
</div>
<div class="section-body">
<div class="paragraph">
@@ -548,7 +597,7 @@ can be found in the <a href="https://gateway.vr-payment.de/en-us/doc/payment/tra
</div> <div class="section" id="_state_mapping_of_shopware_delivery_status">
<div class="section-title">
<h2>
<span class="title-number">7.3</span>State mapping of Shopware delivery status </h2>
<span class="title-number">8.3</span>State mapping of Shopware delivery status </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -574,7 +623,7 @@ can be found in the <a href="https://gateway.vr-payment.de/en-us/doc/payment/tra
</div> <div class="chapter" id="_transaction_management">
<div class="chapter-title">
<h1>
<span class="title-number">8</span>Transaction management </h1>
<span class="title-number">9</span>Transaction management </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -584,7 +633,7 @@ Shopware. However, there are some limitations (see below).</p>
</div> <div class="section" id="_complete_capture_an_order">
<div class="section-title">
<h2>
<span class="title-number">8.1</span>Complete (capture) an order </h2>
<span class="title-number">9.1</span>Complete (capture) an order </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -618,7 +667,7 @@ the fulfill state is reached. Initially the transaction will be in the <code>Aut
</div> <div class="section" id="_void_a_transaction">
<div class="section-title">
<h2>
<span class="title-number">8.2</span>Void a transaction </h2>
<span class="title-number">9.2</span>Void a transaction </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -642,7 +691,7 @@ You can only void transactions that are not yet completed.
</div> <div class="section" id="_refund_of_a_transaction">
<div class="section-title">
<h2>
<span class="title-number">8.3</span>Refund of a transaction </h2>
<span class="title-number">9.3</span>Refund of a transaction </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -669,7 +718,7 @@ It can take some time until you see the refund in Shopware. Refunds will only be
</div> <div class="section" id="_on_hold_orders">
<div class="section-title">
<h2>
<span class="title-number">8.4</span>On hold orders </h2>
<span class="title-number">9.4</span>On hold orders </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -693,7 +742,7 @@ within the defined time frame, VR Payment will generate a manual task which you
</div> <div class="section" id="_limitations_of_the_synchronization_between_whitelabelname_and_shopware">
<div class="section-title">
<h2>
<span class="title-number">8.5</span>Limitations of the synchronization between VR Payment and Shopware </h2>
<span class="title-number">9.5</span>Limitations of the synchronization between VR Payment and Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -709,7 +758,7 @@ your Shopware backend.</p>
</div> <div class="section" id="_tokenization">
<div class="section-title">
<h2>
<span class="title-number">8.6</span>Tokenization </h2>
<span class="title-number">9.6</span>Tokenization </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -730,7 +779,7 @@ Tokenization is not available for guest checkouts.
</div> <div class="section" id="_key_features">
<div class="section-title">
<h2>
<span class="title-number">8.7</span>Key Features </h2>
<span class="title-number">9.7</span>Key Features </h2>
</div>
<div class="section-body">
<div class="ulist">
@@ -752,7 +801,7 @@ Tokenization is not available for guest checkouts.
</div> <div class="section" id="_troubleshooting">
<div class="section-title">
<h2>
<span class="title-number">8.8</span>Troubleshooting </h2>
<span class="title-number">9.8</span>Troubleshooting </h2>
</div>
<div class="section-body">
<div class="ulist">
@@ -783,7 +832,7 @@ Tokenization is not available for guest checkouts.
</div> <div class="section" id="_faqs">
<div class="section-title">
<h2>
<span class="title-number">8.9</span>FAQs </h2>
<span class="title-number">9.9</span>FAQs </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -815,7 +864,7 @@ Tokenization is not available for guest checkouts.
</div> <div class="chapter" id="_changelog">
<div class="chapter-title">
<h1>
<span class="title-number">9</span>Changelog </h1>
<span class="title-number">10</span>Changelog </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -824,7 +873,7 @@ Tokenization is not available for guest checkouts.
</div> <div class="chapter" id="_contributing">
<div class="chapter-title">
<h1>
<span class="title-number">10</span>Contributing </h1>
<span class="title-number">11</span>Contributing </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -835,7 +884,7 @@ Tokenization is not available for guest checkouts.
</div> <div class="chapter" id="_support">
<div class="chapter-title">
<h1>
<span class="title-number">11</span>Support </h1>
<span class="title-number">12</span>Support </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -886,128 +935,145 @@ Tokenization is not available for guest checkouts.
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
<a href="#_update">
<span class="item-number">5</span>
<span class="item-title">Update</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_via_administration">
<span class="item-number">5.1</span>
<span class="item-title">Via Administration</span>
</a>
</li> <li class="nav-level-2">
<a href="#_via_cli">
<span class="item-number">5.2</span>
<span class="item-title">Via CLI</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
<span class="item-number">6</span>
<span class="item-title">Portal Startup Guide</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_create_the_api_key">
<span class="item-number">5.1</span>
<span class="item-number">6.1</span>
<span class="item-title">Create the API key:</span>
</a>
</li> <li class="nav-level-2">
<a href="#_setup_payment_methods">
<span class="item-number">5.2</span>
<span class="item-number">6.2</span>
<span class="item-title">Setup Payment Methods</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_shop_startup_guide">
<span class="item-number">6</span>
<span class="item-number">7</span>
<span class="item-title">Shop Startup Guide</span>
</a>
</li> <li class="nav-level-1">
<a href="#_transaction_state_graph">
<span class="item-number">7</span>
<span class="item-number">8</span>
<span class="item-title">Transaction State graph</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_state_mapping_of_shopware_orders">
<span class="item-number">7.1</span>
<span class="item-number">8.1</span>
<span class="item-title">State mapping of Shopware orders</span>
</a>
<ul class="nav">
<li class="nav-level-3">
<a href="#_general_remarks_regarding_order_statuses">
<span class="item-number">7.1.1</span>
<span class="item-number">8.1.1</span>
<span class="item-title">General remarks regarding order statuses</span>
</a>
</li> </ul>
</li> <li class="nav-level-2">
<a href="#_state_mapping_of_shopware_payment_status">
<span class="item-number">7.2</span>
<span class="item-number">8.2</span>
<span class="item-title">State mapping of Shopware payment status</span>
</a>
<ul class="nav">
<li class="nav-level-3">
<a href="#_general_remarks_regarding_payment_statuses">
<span class="item-number">7.2.1</span>
<span class="item-number">8.2.1</span>
<span class="item-title">General remarks regarding payment statuses</span>
</a>
</li> </ul>
</li> <li class="nav-level-2">
<a href="#_state_mapping_of_shopware_delivery_status">
<span class="item-number">7.3</span>
<span class="item-number">8.3</span>
<span class="item-title">State mapping of Shopware delivery status</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_transaction_management">
<span class="item-number">8</span>
<span class="item-number">9</span>
<span class="item-title">Transaction management</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_complete_capture_an_order">
<span class="item-number">8.1</span>
<span class="item-number">9.1</span>
<span class="item-title">Complete (capture) an order</span>
</a>
</li> <li class="nav-level-2">
<a href="#_void_a_transaction">
<span class="item-number">8.2</span>
<span class="item-number">9.2</span>
<span class="item-title">Void a transaction</span>
</a>
</li> <li class="nav-level-2">
<a href="#_refund_of_a_transaction">
<span class="item-number">8.3</span>
<span class="item-number">9.3</span>
<span class="item-title">Refund of a transaction</span>
</a>
</li> <li class="nav-level-2">
<a href="#_on_hold_orders">
<span class="item-number">8.4</span>
<span class="item-number">9.4</span>
<span class="item-title">On hold orders</span>
</a>
</li> <li class="nav-level-2">
<a href="#_limitations_of_the_synchronization_between_whitelabelname_and_shopware">
<span class="item-number">8.5</span>
<span class="item-number">9.5</span>
<span class="item-title">Limitations of the synchronization between VR Payment and Shopware</span>
</a>
</li> <li class="nav-level-2">
<a href="#_tokenization">
<span class="item-number">8.6</span>
<span class="item-number">9.6</span>
<span class="item-title">Tokenization</span>
</a>
</li> <li class="nav-level-2">
<a href="#_key_features">
<span class="item-number">8.7</span>
<span class="item-number">9.7</span>
<span class="item-title">Key Features</span>
</a>
</li> <li class="nav-level-2">
<a href="#_troubleshooting">
<span class="item-number">8.8</span>
<span class="item-number">9.8</span>
<span class="item-title">Troubleshooting</span>
</a>
</li> <li class="nav-level-2">
<a href="#_faqs">
<span class="item-number">8.9</span>
<span class="item-number">9.9</span>
<span class="item-title">FAQs</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_changelog">
<span class="item-number">9</span>
<span class="item-number">10</span>
<span class="item-title">Changelog</span>
</a>
</li> <li class="nav-level-1">
<a href="#_contributing">
<span class="item-number">10</span>
<span class="item-number">11</span>
<span class="item-title">Contributing</span>
</a>
</li> <li class="nav-level-1">
<a href="#_support">
<span class="item-number">11</span>
<span class="item-number">12</span>
<span class="item-title">Support</span>
</a>
</li> </ul>
+115 -49
View File
@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="keywords" value="VR Payment, Shopware, Shopware Plugin, Payment, Payment Integration, Documentation"><meta name="description" value="The documentation for the Shopware 6 plugin that enables processing payments with VR Payment.">
<link rel="canonical" href="https://plugin-documentation.wallee.com/wallee-payment/shopware-6/master/VRPaymentPayment/docs/fr/documentation.html" />
<link rel="canonical" href="@WalleeCanonicalPath(https://plugin-documentation.wallee.com/wallee-payment, VRPaymentPayment/docs/fr/documentation.html)" />
<title>Wallee Payment Plugin pour Shopware 6</title>
<link href="assets/monokai-sublime.css" rel="stylesheet" />
<link href="assets/base.css" rel="stylesheet" />
@@ -23,7 +23,7 @@
</a>
</li>
<li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.0.1/">
<a href="@WalleeReleasePath()">
Source
</a>
</li>
@@ -165,14 +165,63 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment</code></
</div>
</div> </div>
</div> </div>
</div> <div class="chapter" id="_mise_à_jour">
<div class="chapter-title">
<h1>
<span class="title-number">5</span>Mise à jour </h1>
</div>
<div class="chapter-body">
<div class="section" id="_via_l_administration">
<div class="section-title">
<h2>
<span class="title-number">5.1</span>Via ladministration </h2>
</div>
<div class="section-body">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Allez dans Shopware Admin &gt; Extensions &gt; Mes extensions.</p>
</li>
<li>
<p>Recherchez VRPaymentPayment.</p>
</li>
<li>
<p>Cliquez sur Mettre à jour.</p>
</li>
</ol>
</div> </div>
</div> <div class="section" id="_via_la_cli">
<div class="section-title">
<h2>
<span class="title-number">5.2</span>Via la CLI </h2>
</div>
<div class="section-body">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Déployez les nouveaux fichiers du plugin (remplacez le dossier <code>custom/plugins/VRPaymentPayment</code> ou téléversez/installez un nouveau ZIP).</p>
</li>
<li>
<p>Exécutez :</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">bin/console plugin:refresh
bin/console plugin:update --clearCache VRPaymentPayment
bin/console cache:clear</code></pre>
</div>
</div>
</li>
</ol>
</div> </div>
</div> </div>
</div> <div class="chapter" id="portal-startup-guide">
<div class="chapter-title">
<h1>
<span class="title-number">5</span>Guide de démarrage pour le Portail </h1>
<span class="title-number">6</span>Guide de démarrage pour le Portail </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
<p>Allez sur <a href="https://gateway.vr-payment.de/user/login/user/login">VR Payment</a> et créez un Compte si vous nen avez pas déjà un</p>
<p>Allez sur hhttps://gateway.vr-payment.de/user/login[VR Payment] et créez un Compte si vous nen avez pas déjà un</p>
</div><div class="admonitionblock tip">
<table>
<tr>
@@ -187,7 +236,7 @@ Veuillez sélectionner le plan d&#8217;abonnement approprié - il doit prendre e
</div> <div class="section" id="_créez_la_clé_api">
<div class="section-title">
<h2>
<span class="title-number">5.1</span>Créez la clé API: </h2>
<span class="title-number">6.1</span>Créez la clé API: </h2>
</div>
<div class="section-body">
<div class="olist arabic">
@@ -273,7 +322,7 @@ Veuillez noter que le chargement des rôles peut durer quelques secondes.
</div> <div class="section" id="_configurer_les_modes_de_paiement">
<div class="section-title">
<h2>
<span class="title-number">5.2</span>Configurer les modes de paiement </h2>
<span class="title-number">6.2</span>Configurer les modes de paiement </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -335,7 +384,7 @@ Veuillez noter que les connecteurs semblent faire double emploi, mais c&#8217;es
</div> <div class="chapter" id="_guide_de_démarrage_pour_shopware">
<div class="chapter-title">
<h1>
<span class="title-number">6</span>Guide de démarrage pour Shopware </h1>
<span class="title-number">7</span>Guide de démarrage pour Shopware </h1>
</div>
<div class="chapter-body">
<div class="olist arabic">
@@ -474,7 +523,7 @@ Veuillez noter que si vous n&#8217;utilisez pas Space View Id, cette option doit
</div> <div class="chapter" id="_différents_etats_pour_une_transaction">
<div class="chapter-title">
<h1>
<span class="title-number">7</span>Différents Etats pour une Transaction </h1>
<span class="title-number">8</span>Différents Etats pour une Transaction </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -484,7 +533,7 @@ Veuillez noter que si vous n&#8217;utilisez pas Space View Id, cette option doit
</div> <div class="section" id="_cartographie_des_différents_états_d_une_commande_de_shopware">
<div class="section-title">
<h2>
<span class="title-number">7.1</span>Cartographie des différents états dune commande de Shopware </h2>
<span class="title-number">8.1</span>Cartographie des différents états dune commande de Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -492,7 +541,7 @@ Veuillez noter que si vous n&#8217;utilisez pas Space View Id, cette option doit
</div> <div class="section" id="_remarque_générales_concernant_les_status_des_commandes">
<div class="section-title">
<h3>
<span class="title-number">7.1.1</span>Remarque générales concernant les status des commandes </h3>
<span class="title-number">8.1.1</span>Remarque générales concernant les status des commandes </h3>
</div>
<div class="section-body">
<div class="paragraph">
@@ -502,7 +551,7 @@ Veuillez noter que si vous n&#8217;utilisez pas Space View Id, cette option doit
</div> <div class="section" id="_cartographie_des_différents_états_du_paiement_de_shopware">
<div class="section-title">
<h2>
<span class="title-number">7.2</span>Cartographie des différents états du paiement de Shopware </h2>
<span class="title-number">8.2</span>Cartographie des différents états du paiement de Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -529,7 +578,7 @@ Veuillez noter que si vous n&#8217;utilisez pas Space View Id, cette option doit
</div> <div class="section" id="_remarques_générales_concernant_les_différents_status_pour_les_paiements">
<div class="section-title">
<h3>
<span class="title-number">7.2.1</span>Remarques générales concernant les différents status pour les paiements </h3>
<span class="title-number">8.2.1</span>Remarques générales concernant les différents status pour les paiements </h3>
</div>
<div class="section-body">
<div class="paragraph">
@@ -539,7 +588,7 @@ Veuillez noter que si vous n&#8217;utilisez pas Space View Id, cette option doit
</div> <div class="section" id="_carthographie_des_différents_états_de_livraison_chez_shopware">
<div class="section-title">
<h2>
<span class="title-number">7.3</span>Carthographie des différents états de livraison chez Shopware </h2>
<span class="title-number">8.3</span>Carthographie des différents états de livraison chez Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -565,7 +614,7 @@ Veuillez noter que si vous n&#8217;utilisez pas Space View Id, cette option doit
</div> <div class="chapter" id="_gestion_des_transactions">
<div class="chapter-title">
<h1>
<span class="title-number">8</span>Gestion des Transactions </h1>
<span class="title-number">9</span>Gestion des Transactions </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -573,7 +622,7 @@ Veuillez noter que si vous n&#8217;utilisez pas Space View Id, cette option doit
</div> <div class="section" id="_complete_capture_an_order">
<div class="section-title">
<h2>
<span class="title-number">8.1</span>Complete (capture) an order </h2>
<span class="title-number">9.1</span>Complete (capture) an order </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -605,7 +654,7 @@ Lorsque le paiement est en attente dans wallee, la commande reste en attente.
</div> <div class="section" id="_annuler_une_transaction">
<div class="section-title">
<h2>
<span class="title-number">8.2</span>Annuler une transaction </h2>
<span class="title-number">9.2</span>Annuler une transaction </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -629,7 +678,7 @@ Vous ne pouvez annuler que les transactions qui ne sont pas encore complétée..
</div> <div class="section" id="_remboursement_d_une_transaction">
<div class="section-title">
<h2>
<span class="title-number">8.3</span>Remboursement d&#8217;une transaction </h2>
<span class="title-number">9.3</span>Remboursement d&#8217;une transaction </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -655,7 +704,7 @@ Il peut s&#8217;écouler un certain temps avant que vous ne voyiez le remboursem
</div> <div class="section" id="_commandes_en_attente">
<div class="section-title">
<h2>
<span class="title-number">8.4</span>Commandes en attente </h2>
<span class="title-number">9.4</span>Commandes en attente </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -677,7 +726,7 @@ Il peut s&#8217;écouler un certain temps avant que vous ne voyiez le remboursem
</div> <div class="section" id="_limites_de_la_synchronisation_entre_wallee_et_shopware">
<div class="section-title">
<h2>
<span class="title-number">8.5</span>Limites de la synchronisation entre wallee et Shopware </h2>
<span class="title-number">9.5</span>Limites de la synchronisation entre wallee et Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -688,7 +737,7 @@ Il peut s&#8217;écouler un certain temps avant que vous ne voyiez le remboursem
</div> <div class="section" id="_tokenisation">
<div class="section-title">
<h2>
<span class="title-number">8.6</span>Tokenisation </h2>
<span class="title-number">9.6</span>Tokenisation </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -708,7 +757,7 @@ La tokenisation n&#8217;est pas disponible pour les paiements par les invités.
</div> <div class="section" id="_caractéristiques_pricinpales">
<div class="section-title">
<h2>
<span class="title-number">8.7</span>Caractéristiques Pricinpales </h2>
<span class="title-number">9.7</span>Caractéristiques Pricinpales </h2>
</div>
<div class="section-body">
<div class="ulist">
@@ -730,7 +779,7 @@ La tokenisation n&#8217;est pas disponible pour les paiements par les invités.
</div> <div class="section" id="_troubleshooting">
<div class="section-title">
<h2>
<span class="title-number">8.8</span>Troubleshooting </h2>
<span class="title-number">9.8</span>Troubleshooting </h2>
</div>
<div class="section-body">
<div class="ulist">
@@ -761,7 +810,7 @@ La tokenisation n&#8217;est pas disponible pour les paiements par les invités.
</div> <div class="section" id="_faqs">
<div class="section-title">
<h2>
<span class="title-number">8.9</span>FAQs </h2>
<span class="title-number">9.9</span>FAQs </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -789,7 +838,7 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.</p>
</div> <div class="chapter" id="_changelog">
<div class="chapter-title">
<h1>
<span class="title-number">9</span>Changelog </h1>
<span class="title-number">10</span>Changelog </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -798,7 +847,7 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.</p>
</div> <div class="chapter" id="_contribuer">
<div class="chapter-title">
<h1>
<span class="title-number">10</span>Contribuer </h1>
<span class="title-number">11</span>Contribuer </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -809,7 +858,7 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.</p>
</div> <div class="chapter" id="_support">
<div class="chapter-title">
<h1>
<span class="title-number">11</span>Support </h1>
<span class="title-number">12</span>Support </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -860,128 +909,145 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.</p>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
<a href="#_mise_à_jour">
<span class="item-number">5</span>
<span class="item-title">Mise à jour</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_via_l_administration">
<span class="item-number">5.1</span>
<span class="item-title">Via ladministration</span>
</a>
</li> <li class="nav-level-2">
<a href="#_via_la_cli">
<span class="item-number">5.2</span>
<span class="item-title">Via la CLI</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
<span class="item-number">6</span>
<span class="item-title">Guide de démarrage pour le Portail</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_créez_la_clé_api">
<span class="item-number">5.1</span>
<span class="item-number">6.1</span>
<span class="item-title">Créez la clé API:</span>
</a>
</li> <li class="nav-level-2">
<a href="#_configurer_les_modes_de_paiement">
<span class="item-number">5.2</span>
<span class="item-number">6.2</span>
<span class="item-title">Configurer les modes de paiement</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_guide_de_démarrage_pour_shopware">
<span class="item-number">6</span>
<span class="item-number">7</span>
<span class="item-title">Guide de démarrage pour Shopware</span>
</a>
</li> <li class="nav-level-1">
<a href="#_différents_etats_pour_une_transaction">
<span class="item-number">7</span>
<span class="item-number">8</span>
<span class="item-title">Différents Etats pour une Transaction</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_cartographie_des_différents_états_d_une_commande_de_shopware">
<span class="item-number">7.1</span>
<span class="item-number">8.1</span>
<span class="item-title">Cartographie des différents états dune commande de Shopware</span>
</a>
<ul class="nav">
<li class="nav-level-3">
<a href="#_remarque_générales_concernant_les_status_des_commandes">
<span class="item-number">7.1.1</span>
<span class="item-number">8.1.1</span>
<span class="item-title">Remarque générales concernant les status des commandes</span>
</a>
</li> </ul>
</li> <li class="nav-level-2">
<a href="#_cartographie_des_différents_états_du_paiement_de_shopware">
<span class="item-number">7.2</span>
<span class="item-number">8.2</span>
<span class="item-title">Cartographie des différents états du paiement de Shopware</span>
</a>
<ul class="nav">
<li class="nav-level-3">
<a href="#_remarques_générales_concernant_les_différents_status_pour_les_paiements">
<span class="item-number">7.2.1</span>
<span class="item-number">8.2.1</span>
<span class="item-title">Remarques générales concernant les différents status pour les paiements</span>
</a>
</li> </ul>
</li> <li class="nav-level-2">
<a href="#_carthographie_des_différents_états_de_livraison_chez_shopware">
<span class="item-number">7.3</span>
<span class="item-number">8.3</span>
<span class="item-title">Carthographie des différents états de livraison chez Shopware</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_gestion_des_transactions">
<span class="item-number">8</span>
<span class="item-number">9</span>
<span class="item-title">Gestion des Transactions</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_complete_capture_an_order">
<span class="item-number">8.1</span>
<span class="item-number">9.1</span>
<span class="item-title">Complete (capture) an order</span>
</a>
</li> <li class="nav-level-2">
<a href="#_annuler_une_transaction">
<span class="item-number">8.2</span>
<span class="item-number">9.2</span>
<span class="item-title">Annuler une transaction</span>
</a>
</li> <li class="nav-level-2">
<a href="#_remboursement_d_une_transaction">
<span class="item-number">8.3</span>
<span class="item-number">9.3</span>
<span class="item-title">Remboursement d&amp;#8217;une transaction</span>
</a>
</li> <li class="nav-level-2">
<a href="#_commandes_en_attente">
<span class="item-number">8.4</span>
<span class="item-number">9.4</span>
<span class="item-title">Commandes en attente</span>
</a>
</li> <li class="nav-level-2">
<a href="#_limites_de_la_synchronisation_entre_wallee_et_shopware">
<span class="item-number">8.5</span>
<span class="item-number">9.5</span>
<span class="item-title">Limites de la synchronisation entre wallee et Shopware</span>
</a>
</li> <li class="nav-level-2">
<a href="#_tokenisation">
<span class="item-number">8.6</span>
<span class="item-number">9.6</span>
<span class="item-title">Tokenisation</span>
</a>
</li> <li class="nav-level-2">
<a href="#_caractéristiques_pricinpales">
<span class="item-number">8.7</span>
<span class="item-number">9.7</span>
<span class="item-title">Caractéristiques Pricinpales</span>
</a>
</li> <li class="nav-level-2">
<a href="#_troubleshooting">
<span class="item-number">8.8</span>
<span class="item-number">9.8</span>
<span class="item-title">Troubleshooting</span>
</a>
</li> <li class="nav-level-2">
<a href="#_faqs">
<span class="item-number">8.9</span>
<span class="item-number">9.9</span>
<span class="item-title">FAQs</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_changelog">
<span class="item-number">9</span>
<span class="item-number">10</span>
<span class="item-title">Changelog</span>
</a>
</li> <li class="nav-level-1">
<a href="#_contribuer">
<span class="item-number">10</span>
<span class="item-number">11</span>
<span class="item-title">Contribuer</span>
</a>
</li> <li class="nav-level-1">
<a href="#_support">
<span class="item-number">11</span>
<span class="item-number">12</span>
<span class="item-title">Support</span>
</a>
</li> </ul>
+115 -49
View File
@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="keywords" value="VR Payment, Shopware, Shopware Plugin, Payment, Payment Integration, Documentation"><meta name="description" value="The documentation for the Shopware 6 plugin that enables processing payments with VR Payment.">
<link rel="canonical" href="https://plugin-documentation.wallee.com/wallee-payment/shopware-6/master/VRPaymentPayment/docs/it/documentation.html" />
<link rel="canonical" href="@WalleeCanonicalPath(https://plugin-documentation.wallee.com/wallee-payment, VRPaymentPayment/docs/it/documentation.html)" />
<title>VR Payment Shopware 6 Documentation</title>
<link href="assets/monokai-sublime.css" rel="stylesheet" />
<link href="assets/base.css" rel="stylesheet" />
@@ -23,7 +23,7 @@
</a>
</li>
<li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.0.1/">
<a href="@WalleeReleasePath()">
Source
</a>
</li>
@@ -172,14 +172,63 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment</code></
</ol>
</div> </div>
</div> </div>
</div> <div class="chapter" id="_aggiornamento">
<div class="chapter-title">
<h1>
<span class="title-number">5</span>Aggiornamento </h1>
</div>
<div class="chapter-body">
<div class="section" id="_tramite_amministrazione">
<div class="section-title">
<h2>
<span class="title-number">5.1</span>Tramite Amministrazione </h2>
</div>
<div class="section-body">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Vai su Shopware Admin &gt; Estensioni &gt; Le mie estensioni.</p>
</li>
<li>
<p>Trova VRPaymentPayment.</p>
</li>
<li>
<p>Clicca su Aggiorna.</p>
</li>
</ol>
</div> </div>
</div> <div class="section" id="_tramite_cli">
<div class="section-title">
<h2>
<span class="title-number">5.2</span>Tramite CLI </h2>
</div>
<div class="section-body">
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Distribuisci i nuovi file del plugin (sostituisci la cartella <code>custom/plugins/VRPaymentPayment</code> oppure carica/installa un nuovo ZIP).</p>
</li>
<li>
<p>Esegui:</p>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">bin/console plugin:refresh
bin/console plugin:update --clearCache VRPaymentPayment
bin/console cache:clear</code></pre>
</div>
</div>
</li>
</ol>
</div> </div>
</div> </div>
</div> <div class="chapter" id="portal-startup-guide">
<div class="chapter-title">
<h1>
<span class="title-number">5</span>Guida Rapida al Portale </h1>
<span class="title-number">6</span>Guida Rapida al Portale </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
<p>Andate su <a href="https://gateway.vr-payment.de/user/login/user/login">VR Payment</a> e create un account se non ne avete già uno.</p>
<p>Andate su <a href="https://gateway.vr-payment.de/user/login">VR Payment</a> e create un account se non ne avete già uno.</p>
</div><div class="admonitionblock tip">
<table>
<tr>
@@ -194,7 +243,7 @@ Selezionate il piano di abbonamento appropriato: dovrebbe supportare le transazi
</div> <div class="section" id="_create_la_chiave_api">
<div class="section-title">
<h2>
<span class="title-number">5.1</span>Create la chiave API: </h2>
<span class="title-number">6.1</span>Create la chiave API: </h2>
</div>
<div class="section-body">
<div class="olist arabic">
@@ -280,7 +329,7 @@ Si prega di notare che il caricamento dei ruoli potrebbe richiedere alcuni secon
</div> <div class="section" id="_configurate_i_metodi_di_pagamento">
<div class="section-title">
<h2>
<span class="title-number">5.2</span>Configurate i Metodi di Pagamento </h2>
<span class="title-number">6.2</span>Configurate i Metodi di Pagamento </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -342,7 +391,7 @@ Si prega di notare che i connettori sembrano duplicati, ma è perché uno è per
</div> <div class="chapter" id="_guida_rapida_al_shop">
<div class="chapter-title">
<h1>
<span class="title-number">6</span>Guida Rapida al Shop </h1>
<span class="title-number">7</span>Guida Rapida al Shop </h1>
</div>
<div class="chapter-body">
<div class="olist arabic">
@@ -481,7 +530,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb
</div> <div class="chapter" id="_grafico_dello_stato_della_transazione">
<div class="chapter-title">
<h1>
<span class="title-number">7</span>Grafico dello Stato della Transazione </h1>
<span class="title-number">8</span>Grafico dello Stato della Transazione </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -491,7 +540,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb
</div> <div class="section" id="_mappatura_degli_stati_degli_ordini_di_shopware">
<div class="section-title">
<h2>
<span class="title-number">7.1</span>Mappatura degli Stati degli Ordini di Shopware </h2>
<span class="title-number">8.1</span>Mappatura degli Stati degli Ordini di Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -499,7 +548,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb
</div> <div class="section" id="_osservazioni_generali_riguardo_agli_stati_degli_ordini">
<div class="section-title">
<h3>
<span class="title-number">7.1.1</span>Osservazioni Generali Riguardo agli Stati degli Ordini </h3>
<span class="title-number">8.1.1</span>Osservazioni Generali Riguardo agli Stati degli Ordini </h3>
</div>
<div class="section-body">
<div class="paragraph">
@@ -509,7 +558,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb
</div> <div class="section" id="_mappatura_dello_stato_di_pagamento_di_shopware">
<div class="section-title">
<h2>
<span class="title-number">7.2</span>Mappatura dello Stato di Pagamento di Shopware </h2>
<span class="title-number">8.2</span>Mappatura dello Stato di Pagamento di Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -536,7 +585,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb
</div> <div class="section" id="_osservazioni_generali_riguardo_agli_stati_di_pagamento">
<div class="section-title">
<h3>
<span class="title-number">7.2.1</span>Osservazioni Generali Riguardo agli Stati di Pagamento </h3>
<span class="title-number">8.2.1</span>Osservazioni Generali Riguardo agli Stati di Pagamento </h3>
</div>
<div class="section-body">
<div class="paragraph">
@@ -546,7 +595,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb
</div> <div class="section" id="_mappatura_dello_stato_di_spedizione_di_shopware">
<div class="section-title">
<h2>
<span class="title-number">7.3</span>Mappatura dello Stato di Spedizione di Shopware </h2>
<span class="title-number">8.3</span>Mappatura dello Stato di Spedizione di Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -572,7 +621,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb
</div> <div class="chapter" id="_gestione_delle_transazioni">
<div class="chapter-title">
<h1>
<span class="title-number">8</span>Gestione delle Transazioni </h1>
<span class="title-number">9</span>Gestione delle Transazioni </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -580,7 +629,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb
</div> <div class="section" id="_completare_acquisire_un_ordine">
<div class="section-title">
<h2>
<span class="title-number">8.1</span>Completare (Acquisire) un Ordine </h2>
<span class="title-number">9.1</span>Completare (Acquisire) un Ordine </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -612,7 +661,7 @@ Quando il completamento è in sospeso in Wallee, l&#8217;ordine rimarrà nello s
</div> <div class="section" id="_annullare_una_transazione">
<div class="section-title">
<h2>
<span class="title-number">8.2</span>Annullare una transazione </h2>
<span class="title-number">9.2</span>Annullare una transazione </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -636,7 +685,7 @@ Puoi annullare solo le transazioni che non sono ancora state completate
</div> <div class="section" id="_rimborso_di_una_transazione">
<div class="section-title">
<h2>
<span class="title-number">8.3</span>Rimborso di una Transazione </h2>
<span class="title-number">9.3</span>Rimborso di una Transazione </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -662,7 +711,7 @@ Potrebbe volerci un po' di tempo prima che vediate il rimborso in Shopware. I ri
</div> <div class="section" id="_ordini_in_attesa">
<div class="section-title">
<h2>
<span class="title-number">8.4</span>Ordini in Attesa </h2>
<span class="title-number">9.4</span>Ordini in Attesa </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -684,7 +733,7 @@ Potrebbe volerci un po' di tempo prima che vediate il rimborso in Shopware. I ri
</div> <div class="section" id="_limitazioni_della_sincronizzazione_tra_wallee_e_shopware">
<div class="section-title">
<h2>
<span class="title-number">8.5</span>Limitazioni della Sincronizzazione tra Wallee e Shopware </h2>
<span class="title-number">9.5</span>Limitazioni della Sincronizzazione tra Wallee e Shopware </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -695,7 +744,7 @@ Potrebbe volerci un po' di tempo prima che vediate il rimborso in Shopware. I ri
</div> <div class="section" id="_tokenization">
<div class="section-title">
<h2>
<span class="title-number">8.6</span>Tokenization </h2>
<span class="title-number">9.6</span>Tokenization </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -715,7 +764,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
</div> <div class="section" id="_key_features">
<div class="section-title">
<h2>
<span class="title-number">8.7</span>Key Features </h2>
<span class="title-number">9.7</span>Key Features </h2>
</div>
<div class="section-body">
<div class="ulist">
@@ -737,7 +786,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
</div> <div class="section" id="_risoluzione_dei_problemi">
<div class="section-title">
<h2>
<span class="title-number">8.8</span>Risoluzione dei Problemi </h2>
<span class="title-number">9.8</span>Risoluzione dei Problemi </h2>
</div>
<div class="section-body">
<div class="ulist">
@@ -768,7 +817,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
</div> <div class="section" id="_faqs">
<div class="section-title">
<h2>
<span class="title-number">8.9</span>FAQs </h2>
<span class="title-number">9.9</span>FAQs </h2>
</div>
<div class="section-body">
<div class="paragraph">
@@ -800,7 +849,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
</div> <div class="chapter" id="_changelog">
<div class="chapter-title">
<h1>
<span class="title-number">9</span>Changelog </h1>
<span class="title-number">10</span>Changelog </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -809,7 +858,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
</div> <div class="chapter" id="_contribuzione">
<div class="chapter-title">
<h1>
<span class="title-number">10</span>Contribuzione </h1>
<span class="title-number">11</span>Contribuzione </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -820,7 +869,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
</div> <div class="chapter" id="_support">
<div class="chapter-title">
<h1>
<span class="title-number">11</span>Support </h1>
<span class="title-number">12</span>Support </h1>
</div>
<div class="chapter-body">
<div class="paragraph">
@@ -871,128 +920,145 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
<a href="#_aggiornamento">
<span class="item-number">5</span>
<span class="item-title">Aggiornamento</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_tramite_amministrazione">
<span class="item-number">5.1</span>
<span class="item-title">Tramite Amministrazione</span>
</a>
</li> <li class="nav-level-2">
<a href="#_tramite_cli">
<span class="item-number">5.2</span>
<span class="item-title">Tramite CLI</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
<span class="item-number">6</span>
<span class="item-title">Guida Rapida al Portale</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_create_la_chiave_api">
<span class="item-number">5.1</span>
<span class="item-number">6.1</span>
<span class="item-title">Create la chiave API:</span>
</a>
</li> <li class="nav-level-2">
<a href="#_configurate_i_metodi_di_pagamento">
<span class="item-number">5.2</span>
<span class="item-number">6.2</span>
<span class="item-title">Configurate i Metodi di Pagamento</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_guida_rapida_al_shop">
<span class="item-number">6</span>
<span class="item-number">7</span>
<span class="item-title">Guida Rapida al Shop</span>
</a>
</li> <li class="nav-level-1">
<a href="#_grafico_dello_stato_della_transazione">
<span class="item-number">7</span>
<span class="item-number">8</span>
<span class="item-title">Grafico dello Stato della Transazione</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_mappatura_degli_stati_degli_ordini_di_shopware">
<span class="item-number">7.1</span>
<span class="item-number">8.1</span>
<span class="item-title">Mappatura degli Stati degli Ordini di Shopware</span>
</a>
<ul class="nav">
<li class="nav-level-3">
<a href="#_osservazioni_generali_riguardo_agli_stati_degli_ordini">
<span class="item-number">7.1.1</span>
<span class="item-number">8.1.1</span>
<span class="item-title">Osservazioni Generali Riguardo agli Stati degli Ordini</span>
</a>
</li> </ul>
</li> <li class="nav-level-2">
<a href="#_mappatura_dello_stato_di_pagamento_di_shopware">
<span class="item-number">7.2</span>
<span class="item-number">8.2</span>
<span class="item-title">Mappatura dello Stato di Pagamento di Shopware</span>
</a>
<ul class="nav">
<li class="nav-level-3">
<a href="#_osservazioni_generali_riguardo_agli_stati_di_pagamento">
<span class="item-number">7.2.1</span>
<span class="item-number">8.2.1</span>
<span class="item-title">Osservazioni Generali Riguardo agli Stati di Pagamento</span>
</a>
</li> </ul>
</li> <li class="nav-level-2">
<a href="#_mappatura_dello_stato_di_spedizione_di_shopware">
<span class="item-number">7.3</span>
<span class="item-number">8.3</span>
<span class="item-title">Mappatura dello Stato di Spedizione di Shopware</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_gestione_delle_transazioni">
<span class="item-number">8</span>
<span class="item-number">9</span>
<span class="item-title">Gestione delle Transazioni</span>
</a>
<ul class="nav">
<li class="nav-level-2">
<a href="#_completare_acquisire_un_ordine">
<span class="item-number">8.1</span>
<span class="item-number">9.1</span>
<span class="item-title">Completare (Acquisire) un Ordine</span>
</a>
</li> <li class="nav-level-2">
<a href="#_annullare_una_transazione">
<span class="item-number">8.2</span>
<span class="item-number">9.2</span>
<span class="item-title">Annullare una transazione</span>
</a>
</li> <li class="nav-level-2">
<a href="#_rimborso_di_una_transazione">
<span class="item-number">8.3</span>
<span class="item-number">9.3</span>
<span class="item-title">Rimborso di una Transazione</span>
</a>
</li> <li class="nav-level-2">
<a href="#_ordini_in_attesa">
<span class="item-number">8.4</span>
<span class="item-number">9.4</span>
<span class="item-title">Ordini in Attesa</span>
</a>
</li> <li class="nav-level-2">
<a href="#_limitazioni_della_sincronizzazione_tra_wallee_e_shopware">
<span class="item-number">8.5</span>
<span class="item-number">9.5</span>
<span class="item-title">Limitazioni della Sincronizzazione tra Wallee e Shopware</span>
</a>
</li> <li class="nav-level-2">
<a href="#_tokenization">
<span class="item-number">8.6</span>
<span class="item-number">9.6</span>
<span class="item-title">Tokenization</span>
</a>
</li> <li class="nav-level-2">
<a href="#_key_features">
<span class="item-number">8.7</span>
<span class="item-number">9.7</span>
<span class="item-title">Key Features</span>
</a>
</li> <li class="nav-level-2">
<a href="#_risoluzione_dei_problemi">
<span class="item-number">8.8</span>
<span class="item-number">9.8</span>
<span class="item-title">Risoluzione dei Problemi</span>
</a>
</li> <li class="nav-level-2">
<a href="#_faqs">
<span class="item-number">8.9</span>
<span class="item-number">9.9</span>
<span class="item-title">FAQs</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#_changelog">
<span class="item-number">9</span>
<span class="item-number">10</span>
<span class="item-title">Changelog</span>
</a>
</li> <li class="nav-level-1">
<a href="#_contribuzione">
<span class="item-number">10</span>
<span class="item-number">11</span>
<span class="item-title">Contribuzione</span>
</a>
</li> <li class="nav-level-1">
<a href="#_support">
<span class="item-number">11</span>
<span class="item-number">12</span>
<span class="item-title">Support</span>
</a>
</li> </ul>
BIN
View File
Binary file not shown.
@@ -251,9 +251,9 @@ class PaymentMethodConfigurationService {
{
$data = [];
$paymentMethodData = [];
$salesChannelPaymentMethodData = [];
$criteria = (new Criteria())->addFilter(new EqualsFilter('state', 'ACTIVE'));
$criteria = (new Criteria())->addFilter(new EqualsFilter('state', 'ACTIVE'))
->addFilter(new EqualsFilter('spaceId', $this->getSpaceId()));
/**
* @var $vRPaymentPMConfigurationRepository
@@ -276,7 +276,7 @@ class PaymentMethodConfigurationService {
];
$paymentMethodData[] = [
'id' => $paymentMethodConfigurationEntity->getId(),
'id' => $paymentMethodConfigurationEntity->getPaymentMethodId(),
'active' => false,
];
}
@@ -349,35 +349,68 @@ class PaymentMethodConfigurationService {
*/
foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) {
$paymentMethodConfigurationEntity = $this->getPaymentMethodConfigurationEntity(
$entity = $this->getPaymentMethodConfigurationEntity(
$paymentMethodConfiguration->getSpaceId(),
$paymentMethodConfiguration->getId(),
$context
);
$id = is_null($paymentMethodConfigurationEntity) ? Uuid::randomHex() : $paymentMethodConfigurationEntity->getId();
$configId = $entity ? $entity->getId() : Uuid::randomHex();
$technicalName = $paymentMethodConfiguration->getName();
$paymentMethodId = $this->getOrCreatePaymentMethodId(
$technicalName,
VRPaymentPaymentHandler::class,
$context
);
$data = [
'id' => $id,
'id' => $configId,
'paymentMethodConfigurationId' => $paymentMethodConfiguration->getId(),
'paymentMethodId' => $id,
'paymentMethodId' => $paymentMethodId,
'data' => json_decode(strval($paymentMethodConfiguration), true),
'sortOrder' => $paymentMethodConfiguration->getSortOrder(),
'spaceId' => $paymentMethodConfiguration->getSpaceId(),
'state' => CreationEntityState::ACTIVE,
];
$this->upsertPaymentMethod($id, $paymentMethodConfiguration, $context);
try {
$this->container->get(PaymentMethodConfigurationEntityDefinition::ENTITY_NAME . '.repository')->upsert([$data], $context);
$this->upsertPaymentMethod($paymentMethodId, $paymentMethodConfiguration, $context);
$this->container
->get(PaymentMethodConfigurationEntityDefinition::ENTITY_NAME . '.repository')
->upsert([$data], $context);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [$e->getTraceAsString()]);
}
}
}
private function getOrCreatePaymentMethodId(string $technicalName, string $handlerIdentifier, Context $context): string
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('technicalName', $technicalName));
$criteria->setLimit(1);
$existing = $this->paymentMethodRepository->search($criteria, $context)->first();
if ($existing !== null) {
return $existing->getId();
}
$paymentMethodId = Uuid::randomHex();
$this->paymentMethodRepository->upsert([[
'id' => $paymentMethodId,
'handlerIdentifier' => $handlerIdentifier,
'technicalName' => $technicalName,
'name' => $technicalName,
'active' => false,
]], $context);
return $paymentMethodId;
}
/**
* Fetch active merchant payment methods from VRPayment API
*
@@ -482,8 +515,7 @@ class PaymentMethodConfigurationService {
string $id,
PaymentMethodConfiguration $paymentMethodConfiguration,
Context $context
): void
{
): void {
/** @var PluginIdProvider $pluginIdProvider */
$pluginIdProvider = $this->container->get(PluginIdProvider::class);
$pluginId = $pluginIdProvider->getPluginIdByBaseClass(
@@ -502,16 +534,16 @@ class PaymentMethodConfigurationService {
'technicalName' => $paymentMethodConfiguration->getName(),
];
$data['mediaId'] = $this->upsertMedia($id, $paymentMethodConfiguration, $context);
$data = array_filter($data);
$mediaId = $this->upsertMedia($id, $paymentMethodConfiguration, $context);
if ($mediaId) {
$data['mediaId'] = $mediaId;
}
try {
$this->paymentMethodRepository->upsert([$data], $context);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [$e->getTraceAsString()]);
}
}
/**
@@ -613,46 +645,58 @@ class PaymentMethodConfigurationService {
*
* @return string|null
*/
/**
* Upload or update Payment Method icons
*/
protected function upsertMedia(string $id, PaymentMethodConfiguration $paymentMethodConfiguration, Context $context): ?string
{
try {
$existingRecord = $this->getMediaDefaultFolderForPaymentMethod($paymentMethodConfiguration, $context);
$folderKey = 'payment_method_' . $paymentMethodConfiguration->getId();
if ($existingRecord->count() > 0) {
$id = $existingRecord->first()->getId();
// Check existing default folder
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('entity', $folderKey));
$existingFolder = $this->mediaDefaultFolderRepository->search($criteria, $context);
$folderId = $id;
if ($existingFolder->count() > 0) {
$folderId = $existingFolder->first()->getId();
}
// Ensure default folder
$this->mediaDefaultFolderRepository->upsert([
[
'id' => $id,
'id' => $folderId,
'associationFields' => [],
'entity' => 'payment_method_' . $paymentMethodConfiguration->getId(),
'entity' => $folderKey,
],
], $context);
// Ensure media folder
$this->mediaFolderRepository->upsert([
[
'id' => $id,
'defaultFolderId' => $id,
'id' => $folderId,
'defaultFolderId' => $folderId,
'name' => $paymentMethodConfiguration->getName(),
'useParentConfiguration' => false,
'configuration' => [],
],
], $context);
/**
* @var \Shopware\Core\Content\Media\MediaDefinition
*/
// Media insert/update
$mediaDefinition = $this->container->get(MediaDefinition::class);
$this->mediaSerializer->setRegistry($this->serializerRegistry);
$data = [
'id' => $id,
'title' => $paymentMethodConfiguration->getName(),
'url' => $paymentMethodConfiguration->getResolvedImageUrl(),
'mediaFolderId' => $id,
'mediaFolderId' => $folderId,
];
$data = $this->mediaSerializer->deserialize(new Config([], [], []), $mediaDefinition, $data);
$this->mediaRepository->upsert([$data], $context);
return $id;
} catch (\Exception $e) {
$this->logger->critical($e->getMessage(), [$e->getTraceAsString()]);
@@ -13,7 +13,9 @@ use Symfony\Component\{
};
use VRPaymentPayment\Core\{
Api\Refund\Service\RefundService,
Settings\Service\SettingsService
Api\Transaction\Service\TransactionService,
Settings\Service\SettingsService,
Util\Exception\RefundNotSupportedException
};
/**
@@ -41,16 +43,23 @@ class RefundController extends AbstractController
*/
protected $logger;
/**
* @var \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService
*/
protected $transactionService;
/**
* RefundController constructor.
*
* @param \VRPaymentPayment\Core\Api\Refund\Service\RefundService $refundService
* @param \VRPaymentPayment\Core\Settings\Service\SettingsService $settingsService
* @param \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService $transactionService
*/
public function __construct(RefundService $refundService, SettingsService $settingsService)
public function __construct(RefundService $refundService, SettingsService $settingsService, TransactionService $transactionService)
{
$this->settingsService = $settingsService;
$this->refundService = $refundService;
$this->transactionService = $transactionService;
}
/**
@@ -82,11 +91,28 @@ class RefundController extends AbstractController
$quantity = (int)$request->request->get('quantity');
$lineItemId = $request->request->get('lineItemId');
if ($quantity === null || $quantity <= 0) {
return new Response('refundQuantityZero', Response::HTTP_BAD_REQUEST);
}
$settings = $this->settingsService->getSettings($salesChannelId);
$apiClient = $settings->getApiClient();
$transaction = $apiClient->getTransactionService()->read($settings->getSpaceId(), $transactionId);
$maxQuantity = $this->refundService->getMaxRefundableQuantity($transaction, $context, $lineItemId);
if ($quantity > $maxQuantity) {
return new Response('refundExceedsQuantity', Response::HTTP_BAD_REQUEST);
}
try {
$refund = $this->refundService->create($transaction, $context, $lineItemId, $quantity);
} catch (RefundNotSupportedException $exception) {
$this->logger->info('Payment method does not support online refunds for transaction: ' . $transactionId);
return new Response('methodDoesNotSupportRefund', Response::HTTP_BAD_REQUEST);
}
if ($refund === null) {
return new Response('Refund was not created. Please check the refund amound or if the item was not refunded before', Response::HTTP_BAD_REQUEST);
}
@@ -111,14 +137,32 @@ class RefundController extends AbstractController
$transactionId = $request->request->get('transactionId');
$refundableAmount = $request->request->get('refundableAmount');
if ($refundableAmount === null || $refundableAmount <= 0.0) {
return new Response('refundAmountZero', Response::HTTP_BAD_REQUEST);
}
$settings = $this->settingsService->getSettings($salesChannelId);
$apiClient = $settings->getApiClient();
$transaction = $apiClient->getTransactionService()->read($settings->getSpaceId(), $transactionId);
$completed = (float) $transaction->getCompletedAmount();
$refunded = (float) $transaction->getRefundedAmount();
$maxRefund = round($completed - $refunded, 2);
if ($refundableAmount > $maxRefund) {
return new Response('refundExceedsAmount', Response::HTTP_BAD_REQUEST);
}
try {
$refund = $this->refundService->createRefundByAmount($transaction, $refundableAmount, $context);
} catch (RefundNotSupportedException $exception) {
$this->logger->info('Payment method does not support online refunds for transaction: ' . $transactionId);
return new Response('methodDoesNotSupportRefund', Response::HTTP_BAD_REQUEST);
}
if ($refund === null) {
return new Response('refundExceedsAmount', Response::HTTP_BAD_REQUEST);
return new Response(null, Response::HTTP_BAD_REQUEST);
}
return new Response(null, Response::HTTP_NO_CONTENT);
@@ -146,7 +190,13 @@ class RefundController extends AbstractController
$apiClient = $settings->getApiClient();
$transaction = $apiClient->getTransactionService()->read($settings->getSpaceId(), $transactionId);
$this->refundService->createPartialRefund($transaction, $context, $lineItemId, $refundableAmount);
try {
$refund = $this->refundService->createPartialRefund($transaction, $context, $lineItemId, $refundableAmount);
} catch (RefundNotSupportedException $exception) {
$this->logger->info('Payment method does not support online refunds for transaction: ' . $transactionId);
return new Response('methodDoesNotSupportRefund', Response::HTTP_BAD_REQUEST);
}
return new Response(null, Response::HTTP_NO_CONTENT);
}
+89 -2
View File
@@ -12,14 +12,20 @@ use Shopware\Core\{
};
use VRPayment\Sdk\{
Model\Refund,
Model\Transaction
Model\Transaction,
Model\CriteriaOperator,
Model\EntityQueryFilter,
Model\EntityQueryFilterType,
Model\EntityQuery,
ApiException
};
use VRPaymentPayment\Core\{
Api\Refund\Entity\RefundEntity,
Api\Transaction\Entity\TransactionEntity,
Api\Transaction\Entity\TransactionEntityDefinition,
Settings\Service\SettingsService,
Util\Payload\RefundPayload
Util\Payload\RefundPayload,
Util\Exception\RefundNotSupportedException
};
/**
@@ -99,6 +105,12 @@ class RefundService
$this->upsert($refund, $context);
return $refund;
}
} catch (ApiException $exception) {
$message = $exception->getMessage();
$this->logger->critical($message);
if ($exception->getCode() === 442 && str_contains($message, 'does not support online refunds')) {
throw new RefundNotSupportedException($message, 0, $exception);
}
} catch (\Exception $exception) {
$this->logger->critical($exception->getMessage());
}
@@ -134,6 +146,12 @@ class RefundService
$this->upsert($refund, $context);
return $refund;
}
} catch (ApiException $exception) {
$message = $exception->getMessage();
$this->logger->critical($message);
if ($exception->getCode() === 442 && str_contains($message, 'does not support online refunds')) {
throw new RefundNotSupportedException($message, 0, $exception);
}
} catch (\Exception $exception) {
$this->logger->critical($exception->getMessage());
}
@@ -170,6 +188,12 @@ class RefundService
$this->upsert($refund, $context);
return $refund;
}
} catch (ApiException $exception) {
$message = $exception->getMessage();
$this->logger->critical($message);
if ($exception->getCode() === 442 && str_contains($message, 'does not support online refunds')) {
throw new RefundNotSupportedException($message, 0, $exception);
}
} catch (\Exception $exception) {
$this->logger->critical($exception->getMessage());
}
@@ -241,4 +265,67 @@ class RefundService
->first();
}
/**
* Get total refunded quantity for transaction's line item by lineItemId.
*
* @param \VRPayment\Sdk\Model\Transaction $transaction
* @param \Shopware\Core\Framework\Context $context
* @param string $lineItemId
*
* @return int
*/
public function getRefundedQuantity(Transaction $transaction, Context $context, string $lineItemId): int {
$transactionEntity = $this->getTransactionEntityByTransactionId($transaction->getId(), $context);
$settings = $this->settingsService->getSettings($transactionEntity->getSalesChannel()->getId());
$apiClient = $settings->getApiClient();
$entityQueryFilter = (new EntityQueryFilter())
->setType(EntityQueryFilterType::LEAF)
->setOperator(CriteriaOperator::EQUALS)
->setFieldName('transaction.id')
->setValue($transaction->getId());
$query = (new EntityQuery())->setFilter($entityQueryFilter);
$refunds = $apiClient->getRefundService()->search($settings->getSpaceId(), $query);
$refundedQuantity = 0;
foreach ($refunds as $refund) {
foreach ($refund->getReductions() as $reduction) {
if ($reduction->getLineItemUniqueId() === $lineItemId) {
$refundedQuantity += (int) $reduction->getQuantityReduction();
}
}
}
return $refundedQuantity;
}
/**
* Get maximum quantity of available items to refund for line item.
*
* @param \VRPayment\Sdk\Model\Transaction $transaction
* @param \Shopware\Core\Framework\Context $context
* @param string $lineItemId
*
* @return int
*/
public function getMaxRefundableQuantity(Transaction $transaction, Context $context, string $lineItemId): int {
$originalQuantity = 0;
foreach ($transaction->getLineItems() as $lineItem) {
if ($lineItem->getUniqueId() === $lineItemId) {
$originalQuantity = (int) $lineItem->getQuantity();
break;
}
}
$refundedQuantity = $this->getRefundedQuantity($transaction, $context, $lineItemId);
$maxQuantity = $originalQuantity - $refundedQuantity;
return $maxQuantity;
}
}
@@ -32,7 +32,7 @@ use VRPaymentPayment\Core\Api\Refund\Entity\RefundEntityDefinition;
*/
class TransactionEntityDefinition extends EntityDefinition {
public const ENTITY_NAME = 'vrpayment_transaction';
public const ENTITY_NAME = 'vrpayment_transaction_data';
/**
* @return string
@@ -8,13 +8,14 @@ use Shopware\Core\{
Checkout\Cart\CartException,
Checkout\Cart\LineItem\LineItem,
Checkout\Order\OrderEntity,
Checkout\Payment\Cart\PaymentTransactionStruct,
Checkout\Payment\Cart\AsyncPaymentTransactionStruct,
Framework\Context,
Framework\DataAbstractionLayer\Search\Criteria,
Framework\DataAbstractionLayer\Search\Filter\EqualsFilter,
System\SalesChannel\SalesChannelContext
};
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use VRPayment\Sdk\{
Model\AddressCreate,
@@ -46,6 +47,9 @@ use VRPaymentPayment\Core\{
Util\Payload\TransactionPayload
};
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
use Shopware\Core\Framework\Struct\ArrayEntity;
/**
* Class TransactionService
*
@@ -115,7 +119,7 @@ class TransactionService
*
* A redirect to the url will be performed
*
* @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction
* @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
* @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext
*
* @return string
@@ -124,14 +128,10 @@ class TransactionService
* @throws \VRPayment\Sdk\VersioningException
*/
public function create(
PaymentTransactionStruct $transaction,
AsyncPaymentTransactionStruct $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();
@@ -169,7 +169,7 @@ class TransactionService
$redirectUrl = $this->container->get('router')->generate(
'frontend.vrpayment.checkout.pay',
['orderId' => $orderTransaction->getOrder()->getId(),],
['orderId' => $transaction->getOrder()->getId(),],
UrlGeneratorInterface::ABSOLUTE_URL
);
@@ -181,35 +181,44 @@ class TransactionService
$this->upsert(
$createdTransaction,
$salesChannelContext->getContext(),
$orderTransaction->getPaymentMethodId(),
$orderTransaction->getOrder()->getSalesChannelId()
$transaction->getOrderTransaction()->getPaymentMethodId(),
$transaction->getOrder()->getSalesChannelId()
);
$salesChannelContext->getContext()->addExtension(
'checkoutState',
new ArrayEntity([
'transactionId' => null,
'addressHash' => null,
'currency' => null,
])
);
$salesChannelContext->getContext()->addExtension(
'possibleMethods',
new ArrayEntity(['ids' => []])
);
$_SESSION['transactionId'] = null;
$_SESSION['arrayOfPossibleMethods'] = null;
$_SESSION['addressCheck'] = null;
$_SESSION['currencyCheck'] = null;
$this->holdDelivery($orderTransaction->getOrder()->getId(), $salesChannelContext->getContext());
$this->holdDelivery($transaction->getOrder()->getId(), $salesChannelContext->getContext());
return $redirectUrl;
}
/**
* @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction
* @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
* @param \Shopware\Core\Framework\Context $context
* @param int $vrpaymentTransactionId
* @param int $spaceId
*/
protected function addVRPaymentTransactionId(
PaymentTransactionStruct $transaction,
AsyncPaymentTransactionStruct $transaction,
Context $context,
int $vrpaymentTransactionId,
int $spaceId
): void
{
$data = [
'id' => $transaction->getOrderTransactionId(),
'id' => $transaction->getOrderTransaction()->getId(),
'customFields' => [
TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TRANSACTION_ID => $vrpaymentTransactionId,
TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_SPACE_ID => $spaceId,
@@ -347,7 +356,7 @@ class TransactionService
*
* @return \Shopware\Core\Checkout\Order\OrderEntity
*/
protected function getOrderEntity(string $orderId, Context $context): OrderEntity
private function getOrderEntity(string $orderId, Context $context): OrderEntity
{
try {
$criteria = (new Criteria([$orderId]))->addAssociations(['deliveries']);
@@ -482,14 +491,18 @@ class TransactionService
/**
* @param SalesChannelContext $salesChannelContext
* @param CheckoutConfirmPageLoadedEvent|null $event
* @param $event
* @return int
*/
public function createPendingTransaction(SalesChannelContext $salesChannelContext, ?CheckoutConfirmPageLoadedEvent $event = null): int
public function createPendingTransaction(SalesChannelContext $salesChannelContext, $event = null): int
{
$expiredTransaction = true;
$transactionId = $_SESSION['transactionId'] ?? null;
$settings = $this->settingsService->getValidSettings($salesChannelContext->getSalesChannel()->getId());
if (!$settings) {
throw new \Exception('Space settings not configured');
}
if ($transactionId) {
$transactionService = $settings->getApiClient()->getTransactionService();
@@ -498,6 +511,7 @@ class TransactionService
TransactionState::DECLINE,
TransactionState::FAILED,
TransactionState::VOIDED,
null
];
if (!in_array($pendingTransaction->getState(), $failedStates)) {
$expiredTransaction = false;
@@ -571,6 +585,7 @@ class TransactionService
$lineItems = [];
if ($event) {
if ($event instanceof CheckoutConfirmPageLoadedEvent) {
$cartLineItems = $event->getPage()->getCart()->getLineItems()->getElements();
foreach ($cartLineItems as $cartLineItem) {
if ($cartLineItem->getType() === CustomProductsLineItemTypes::LINE_ITEM_TYPE_CUSTOMIZED_PRODUCTS) {
@@ -578,6 +593,12 @@ class TransactionService
}
$lineItems[] = $this->createTempLineItem($cartLineItem);
}
} elseif ($event instanceof AccountEditOrderPageLoadedEvent) {
$order = $event->getPage()->getOrder();
foreach ($order->getLineItems() as $orderLineItem) {
$lineItems[] = $this->createTempLineItem($orderLineItem);
}
}
}
$customerId = "";
@@ -735,14 +756,26 @@ class TransactionService
* @param LineItem $productData
* @return LineItemCreate
*/
private function createTempLineItem(LineItem $productData): LineItemCreate
private function createTempLineItem($productData): LineItemCreate
{
$lineItem = new LineItemCreate();
if ($productData instanceof LineItem) {
$lineItem->setName($productData->getLabel());
$lineItem->setUniqueId($productData->getId());
$lineItem->setSku($productData->getId());
$lineItem->setSku($productData->getReferencedId() ?? $productData->getId());
$lineItem->setQuantity($productData->getQuantity());
$lineItem->setAmountIncludingTax($productData->getPrice()->getUnitPrice());
} elseif ($productData instanceof OrderLineItemEntity) {
$lineItem->setName($productData->getLabel());
$lineItem->setUniqueId($productData->getId());
$lineItem->setSku($productData->getProductId() ?? $productData->getIdentifier() ?? $productData->getId());
$lineItem->setQuantity($productData->getQuantity());
$lineItem->setAmountIncludingTax($productData->getUnitPrice());
} else {
throw new \InvalidArgumentException('Unsupported line item type: ' . get_class($productData));
}
$lineItem->setType(LineItemType::PRODUCT);
return $lineItem;
@@ -226,6 +226,14 @@ class WebHookController extends AbstractController {
$this->settings = $this->settingsService->getSettings($salesChannelId);
$signature = $request->server->get('HTTP_X_SIGNATURE');
$requestJson = json_decode($request->getContent(), true);
if ($requestJson['eventId'] == null && $requestJson['entityId'] == null && $requestJson['listenerEntityId'] == null && $requestJson['listenerEntityId'] == null && $requestJson['listenerEntityTechnicalName'] == null && $requestJson['spaceId'] == null) {
throw new \InvalidArgumentException('Empty webhook');
}
if (!$this->settings->getSpaceId() || !$this->settings->getUserId() || !$this->settings->getApplicationKey()) {
throw new \InvalidArgumentException('Not correct webhook configuration for salesChannelId: ' . $salesChannelId . ' Debug: ' . var_dump($requestJson));
}
$apiClient = $this->settings->getApiClient();
$callBackData->assign($requestJson);
@@ -1,59 +0,0 @@
<?php declare(strict_types=1);
namespace VRPaymentPayment\Core\Checkout\Cart;
use Shopware\Core\Checkout\Cart\AbstractCartPersister;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use VRPaymentPayment\Core\Checkout\PaymentHandler\VRPaymentPaymentHandler;
class CustomCartPersister extends AbstractCartPersister
{
private AbstractCartPersister $inner;
public function __construct(AbstractCartPersister $inner)
{
$this->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;
}
}
@@ -4,30 +4,16 @@ namespace VRPaymentPayment\Core\Checkout\PaymentHandler;
use Psr\Log\LoggerInterface;
use Shopware\Core\{
Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity,
Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler,
Checkout\Payment\Cart\PaymentTransactionStruct,
Checkout\Payment\Cart\PaymentHandler\AbstractPaymentHandler,
Checkout\Payment\Cart\PaymentHandler\PaymentHandlerType,
Checkout\Payment\Cart\AsyncPaymentTransactionStruct,
Checkout\Payment\Cart\PaymentHandler\AsynchronousPaymentHandlerInterface,
Checkout\Payment\Exception\AsyncPaymentFinalizeException,
Checkout\Payment\Exception\AsyncPaymentProcessException,
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\Sorting\FieldSorting,
Framework\Struct\Struct,
Framework\Validation\DataBag\RequestDataBag,
System\SalesChannel\Context\SalesChannelContextService,
System\SalesChannel\Context\SalesChannelContextServiceParameters
System\SalesChannel\SalesChannelContext
};
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
@@ -41,14 +27,9 @@ use VRPaymentPayment\Core\Api\Transaction\Service\TransactionService;
*
* @package VRPaymentPayment\Core\Checkout\PaymentHandler
*/
class VRPaymentPaymentHandler extends AbstractPaymentHandler
class VRPaymentPaymentHandler implements AsynchronousPaymentHandlerInterface
{
/**
* @var CustomCartPersister
*/
private CustomCartPersister $cartPersister;
/**
* @var \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService
*/
@@ -63,34 +44,22 @@ class VRPaymentPaymentHandler extends AbstractPaymentHandler
*/
private $orderTransactionStateHandler;
protected SalesChannelContextService $salesChannelContextService;
protected EntityRepository $orderTransactionRepository;
/**
* VRPaymentPaymentHandler constructor.
*
* @param \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService $transactionService
* @param \Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler $orderTransactionStateHandler
* @param SalesChannelContextService $salesChannelContextService
* @param EntityRepository $orderTransactionRepository
*/
public function __construct(
CustomCartPersister $cartPersister,
TransactionService $transactionService,
OrderTransactionStateHandler $orderTransactionStateHandler,
SalesChannelContextService $salesChannelContextService,
EntityRepository $orderTransactionRepository
) {
$this->cartPersister = $cartPersister;
public function __construct(TransactionService $transactionService, OrderTransactionStateHandler $orderTransactionStateHandler)
{
$this->transactionService = $transactionService;
$this->orderTransactionStateHandler = $orderTransactionStateHandler;
$this->salesChannelContextService = $salesChannelContextService;
$this->orderTransactionRepository = $orderTransactionRepository;
}
/**
* @param \Psr\Log\LoggerInterface $logger
* @internal
* @required
*
*/
public function setLogger(LoggerInterface $logger): void
@@ -104,123 +73,78 @@ class VRPaymentPaymentHandler extends AbstractPaymentHandler
*
* A redirect to the url will be performed
*
* @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
* @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
* @param \Shopware\Core\Framework\Validation\DataBag\RequestDataBag $dataBag
* @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function pay(
Request $request,
PaymentTransactionStruct $transaction,
Context $context,
?Struct $validateStruct
AsyncPaymentTransactionStruct $transaction,
RequestDataBag $dataBag,
SalesChannelContext $salesChannelContext
): 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 ($orderTransaction->getOrder()->getAmountTotal() > 0) {
if ($transaction->getOrder()->getAmountTotal() > 0) {
$transactionId = $_SESSION['transactionId'] ?? null;
if ($transactionId === null) {
$this->transactionService->createPendingTransaction($transaction, $salesChannelContext);
$this->transactionService->createPendingTransaction($salesChannelContext);
}
$redirectUrl = $this->transactionService->create($transaction, $salesChannelContext);
}
return new RedirectResponse($redirectUrl);
} catch (\Throwable $e) {
} catch (\Exception $e) {
unset($_SESSION['transactionId']);
$errorMessage = 'An error occurred during the communication with external payment gateway : ' . $e->getMessage();
$this->logger->critical($errorMessage);
throw PaymentException::customerCanceled($transaction->getOrderTransaction()->getId(), $errorMessage);
throw new \Exception($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\Checkout\Payment\Cart\PaymentTransactionStruct $transaction
* @param \Shopware\Core\Framework\Context $context
* @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext
* @throws \VRPayment\Sdk\ApiException
* @throws \VRPayment\Sdk\Http\ConnectionException
* @throws \VRPayment\Sdk\VersioningException
* @throws \Exception when the payment was canceled by the customer
* @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
*
*/
public function finalize(
AsyncPaymentTransactionStruct $transaction,
Request $request,
PaymentTransactionStruct $transaction,
Context $context
SalesChannelContext $salesChannelContext
): void
{
$orderTransactionId = $transaction->getOrderTransactionId();
$orderTransaction = $this->orderTransactionRepository->search(
(new Criteria([$orderTransactionId]))
->addAssociation('order'), $context
)->getEntities()->first();
if ($orderTransaction->getOrder()->getAmountTotal() > 0) {
if ($transaction->getOrder()->getAmountTotal() > 0) {
$transactionEntity = $this->transactionService->getByOrderId(
$orderTransaction->getOrder()->getId(),
$context
$transaction->getOrder()->getId(),
$salesChannelContext->getContext()
);
$vRPaymentTransaction = $this->transactionService->read(
$transactionEntity->getTransactionId(),
$transactionEntity->getSalesChannelId()
$salesChannelContext->getSalesChannel()->getId()
);
if (in_array($vRPaymentTransaction->getState(), [TransactionState::FAILED])) {
$errorMessage = strtr('Customer canceled payment for :orderId on SalesChannel :salesChannelName', [
':orderId' => $orderTransaction->getOrder()->getId(),
':salesChannelName' => $transactionEntity->getSalesChannelId(),
':orderId' => $transaction->getOrder()->getId(),
':salesChannelName' => $salesChannelContext->getSalesChannel()->getName(),
]);
unset($_SESSION['transactionId']);
$this->logger->info($errorMessage);
throw PaymentException::customerCanceled($transaction->getOrderTransaction()->getId(), $errorMessage);
}
} else {
$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);
$this->orderTransactionStateHandler->paid($transaction->getOrderTransaction()->getId(), $salesChannelContext->getContext());
}
}
/**
* {@inheritDoc}
*/
public function supports(
PaymentHandlerType $type,
string $paymentMethodId,
Context $context
): bool {
if ($type === PaymentHandlerType::RECURRING) {
return false;
}
return true;
}
}
@@ -2,15 +2,21 @@
namespace VRPaymentPayment\Core\Storefront\Checkout\Controller;
use Psr\Log\LoggerInterface;
use Psr\{
Log\LoggerInterface,
Cache\CacheItemPoolInterface
};
use Shopware\Core\{
Checkout\Payment\PaymentException,
Checkout\Cart\Cart,
Checkout\Cart\CartException,
Checkout\Cart\LineItemFactoryRegistry,
Checkout\Cart\SalesChannel\CartService,
Checkout\Order\Aggregate\OrderLineItem\OrderLineItemCollection,
Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity,
Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler,
Checkout\Order\OrderEntity,
Checkout\Order\OrderDefinition,
Checkout\Order\SalesChannel\AbstractOrderRoute,
Framework\Context,
Framework\DataAbstractionLayer\Search\Criteria,
@@ -21,7 +27,9 @@ use Shopware\Core\{
Framework\Uuid\Uuid,
Framework\Uuid\Exception\InvalidUuidException,
Framework\Validation\DataBag\RequestDataBag,
System\SalesChannel\SalesChannelContext
System\SalesChannel\SalesChannelContext,
System\StateMachine\StateMachineRegistry,
System\StateMachine\Transition,
};
use Shopware\Storefront\{
Controller\StorefrontController,
@@ -31,9 +39,13 @@ use Shopware\Storefront\{
use Symfony\Component\{
HttpFoundation\Request,
HttpFoundation\Response,
HttpFoundation\RedirectResponse,
Routing\Attribute\Route,
Routing\Generator\UrlGeneratorInterface
Routing\Generator\UrlGeneratorInterface,
Cache\Adapter\FilesystemAdapter,
DependencyInjection\ParameterBag\ParameterBagInterface
};
use Symfony\Contracts\Cache\ItemInterface;
use VRPayment\Sdk\{
Model\Transaction,
Model\TransactionState
@@ -43,10 +55,10 @@ use VRPaymentPayment\Core\{
Settings\Options\Integration,
Settings\Service\SettingsService,
Storefront\Checkout\Struct\CheckoutPageData,
Util\Payload\CustomProducts\CustomProductsLineItemTypes
Util\Payload\CustomProducts\CustomProductsLineItemTypes,
Util\Payload\TransactionPayload
};
/**
* Class CheckoutController
*
@@ -57,6 +69,18 @@ use VRPaymentPayment\Core\{
#[Route(defaults: ['_routeScope' => ['storefront']])]
class CheckoutController extends StorefrontController {
public const ORDER_STATE_CANCEL = 'cancel';
/**
* @var \Shopware\Core\System\StateMachine\StateMachineRegistry
*/
private $stateMachineRegistry;
/**
* @var \Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler
*/
protected $orderTransactionStateHandler;
/**
* @var \Shopware\Storefront\Page\GenericPageLoader
*/
@@ -97,6 +121,11 @@ class CheckoutController extends StorefrontController {
*/
private $orderRoute;
/**
* @var \Psr\Cache\CacheItemPoolInterface
*/
private CacheItemPoolInterface $cache;
/**
* PaymentController constructor.
*
@@ -106,6 +135,9 @@ class CheckoutController extends StorefrontController {
* @param \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService $transactionService
* @param \Shopware\Storefront\Page\GenericPageLoaderInterface $genericLoader
* @param \Shopware\Core\Checkout\Order\SalesChannel\AbstractOrderRoute $orderRoute
* @param \Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler $orderTransactionStateHandler
* @param \Shopware\Core\System\StateMachine\StateMachineRegistry $stateMachineRegistry
* @param Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface $params
*/
public function __construct(
LineItemFactoryRegistry $lineItemFactoryRegistry,
@@ -113,7 +145,10 @@ class CheckoutController extends StorefrontController {
SettingsService $settingsService,
TransactionService $transactionService,
GenericPageLoaderInterface $genericLoader,
AbstractOrderRoute $orderRoute
AbstractOrderRoute $orderRoute,
OrderTransactionStateHandler $orderTransactionStateHandler,
StateMachineRegistry $stateMachineRegistry,
ParameterBagInterface $params
)
{
$this->cartService = $cartService;
@@ -122,6 +157,9 @@ class CheckoutController extends StorefrontController {
$this->transactionService = $transactionService;
$this->lineItemFactoryRegistry = $lineItemFactoryRegistry;
$this->orderRoute = $orderRoute;
$this->orderTransactionStateHandler = $orderTransactionStateHandler;
$this->stateMachineRegistry = $stateMachineRegistry;
$this->cache = new FilesystemAdapter('vrpayment', 0, rtrim($params->get('kernel.cache_dir'), '/') . '/vrpayment-cache');
}
/**
@@ -363,6 +401,32 @@ class CheckoutController extends StorefrontController {
if($orderEntity->getSalesChannelId() !== $salesChannelContext->getSalesChannelId()) {
$this->settings = $this->settingsService->getSettings($orderEntity->getSalesChannelId());
$trans = $this->getTransaction($orderId, $salesChannelContext->getContext());
// Adoption in case of duplicate requests
// Get order specific value from cache
$cacheKey = 'vrpayment_recreate_order_' . $orderId;
$isFound = $this->cache->get($cacheKey, function (ItemInterface $item) {
$item->expiresAfter(10);
return false;
});
// If value is found in cache - send user directly to successful checkout confirmation page for unpaid transactions
if ($isFound === true && in_array($trans->getState(), [TransactionState::FAILED])) {
$unpaidUrl = $this->getUnpaidUrlFromToken($trans->getSuccessUrl())
?? $this->buildUnpaidUrl($orderEntity->getSalesChannelId(), $salesChannelContext, $orderId);
if ($unpaidUrl) {
return new RedirectResponse(
$unpaidUrl . (parse_url($unpaidUrl, \PHP_URL_QUERY) ? '&' : '?') . 'error-code=' . PaymentException::PAYMENT_CUSTOMER_CANCELED_EXTERNAL
);
}
}
// Cache order specific value for some time on first request
$this->cache->delete($cacheKey);
$this->cache->get($cacheKey, function (ItemInterface $item) {
$item->expiresAfter(10);
return true;
});
return $this->redirect($trans->getSuccessUrl());
}
// End Adoption for Headless Storefronts
@@ -380,6 +444,7 @@ class CheckoutController extends StorefrontController {
}
$transaction = $this->getTransaction($orderId, $salesChannelContext->getContext());
$orderTransactionId = $transaction->getMetaData()[TransactionPayload::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID];
if (!empty($transaction->getUserFailureMessage())) {
$this->addFlash('danger', $transaction->getUserFailureMessage());
}
@@ -414,6 +479,18 @@ class CheckoutController extends StorefrontController {
}
// Close the old, existing order to prevent confusion for the customer
$this->orderTransactionStateHandler->cancel($orderTransactionId, $salesChannelContext->getContext());
$this->stateMachineRegistry->transition(
new Transition(
OrderDefinition::ENTITY_NAME,
$orderId,
self::ORDER_STATE_CANCEL,
'stateId'
),
$salesChannelContext->getContext()
);
} catch (\Exception $exception) {
$this->addFlash('danger', $this->trans('error.addToCartError'));
$this->logger->critical($exception->getMessage());
@@ -423,6 +500,74 @@ class CheckoutController extends StorefrontController {
return $this->redirectToRoute('frontend.checkout.confirm.page');
}
/**
* Tries to return successful checkout confirmation url for unpaid transactions.
*
* It achieves that by getting payment token from successUrl, parsing and decoding
* it, and finally reading the claims.
*
* @param string $successUrl
*
* @return string|null
*/
private function getUnpaidUrlFromToken(string $successUrl): ?string {
$query = [];
parse_str((string) parse_url($successUrl, PHP_URL_QUERY), $query);
$jwt = $query['_sw_payment_token'] ?? null;
if (!$jwt) {
return null;
}
$data = explode('.', $jwt, 3);
if (count($data) !== 3) {
return null;
}
[, $c, ] = $data;
try {
$urlSafeData = strtr($c, '-_', '+/');
$paddedData = str_pad($urlSafeData, \strlen($urlSafeData) % 4, '=');
$decoded = base64_decode($paddedData, true);
if (!$decoded) {
return null;
}
$claims = json_decode(json: $decoded, associative: true, flags: JSON_THROW_ON_ERROR);
$unpaidUrl = $claims['eul'] ?? null;
return $unpaidUrl;
} catch (\Throwable $e) {
$this->logger->warning("CheckoutController::getUnpaidUrlFromToken - JWT parse failed: {errorMessage}", [
'errorMessage' => $e->getMessage(),
]);
return null;
}
}
/**
* Tries to return successful checkout confirmation url for unpaid transactions.
*
* It achieves that by fetching headless storefront's base url,
* and building custom url.
*
* @param string $salesChannelId
* @param SalesChannelContext $salesChannelContext
* @param string $orderId
*
* @return string|null
*/
private function buildUnpaidUrl(string $salesChannelId, SalesChannelContext $salesChannelContext, string $orderId): ?string {
$salesChannelDomainRepo = $this->container->get('sales_channel_domain.repository');
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('salesChannelId', $salesChannelId))->setLimit(10);
$domain = $salesChannelDomainRepo->search($criteria, $salesChannelContext->getContext())->first();
if(!$domain) {
return null;
}
$baseUrl = rtrim($domain->getUrl(), '/');
return sprintf('%s/checkout/success/%s/unpaid', $baseUrl, $orderId);
}
/**
* @param OrderLineItemCollection $orderItems
*
@@ -7,11 +7,18 @@ use Shopware\Core\{Checkout\Order\Aggregate\OrderTransaction\OrderTransactionCol
Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates,
Checkout\Order\OrderEntity,
Content\MailTemplate\Service\Event\MailBeforeValidateEvent};
use Shopware\Core\Checkout\Payment\PaymentMethodCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent;
use Shopware\Storefront\Page\Account\PaymentMethod\AccountPaymentMethodPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use VRPaymentPayment\Core\{Api\Transaction\Service\OrderMailService,
Api\Transaction\Service\TransactionService,
use VRPaymentPayment\Core\{Api\Transaction\Service\TransactionService,
Checkout\PaymentHandler\VRPaymentPaymentHandler,
Settings\Service\SettingsService,
Settings\Struct\Settings,
@@ -31,6 +38,8 @@ use VRPaymentPayment\Sdk\{Model\AddressCreate,
Model\Transaction,
Model\TransactionCreate,
Model\TransactionPending};
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
/**
* Class CheckoutSubscriber
@@ -65,6 +74,9 @@ class CheckoutSubscriber implements EventSubscriberInterface
*/
private $paymentMethodUtil;
/** @var EntityRepository */
private EntityRepository $paymentMethodRepository;
/**
* CheckoutSubscriber constructor.
*
@@ -73,12 +85,13 @@ class CheckoutSubscriber implements EventSubscriberInterface
* @param \VRPaymentPayment\Core\Settings\Service\SettingsService $settingsService
* @param \VRPaymentPayment\Core\Util\PaymentMethodUtil $paymentMethodUtil
*/
public function __construct(PaymentMethodConfigurationService $paymentMethodConfigurationService, TransactionService $transactionService, SettingsService $settingsService, PaymentMethodUtil $paymentMethodUtil)
public function __construct(PaymentMethodConfigurationService $paymentMethodConfigurationService, TransactionService $transactionService, SettingsService $settingsService, PaymentMethodUtil $paymentMethodUtil, EntityRepository $paymentMethodRepository)
{
$this->paymentMethodConfigurationService = $paymentMethodConfigurationService;
$this->transactionService = $transactionService;
$this->settingsService = $settingsService;
$this->paymentMethodUtil = $paymentMethodUtil;
$this->paymentMethodRepository = $paymentMethodRepository;
}
/**
@@ -99,7 +112,9 @@ class CheckoutSubscriber implements EventSubscriberInterface
public static function getSubscribedEvents(): array
{
return [
CheckoutConfirmPageLoadedEvent::class => ['onConfirmPageLoaded', 1],
CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmLoaded',
AccountEditOrderPageLoadedEvent::class => 'onAccountOrderEditLoaded',
AccountPaymentMethodPageLoadedEvent::class => 'onAccountPaymentMethodLoaded',
MailBeforeValidateEvent::class => ['onMailBeforeValidate', 1],
];
}
@@ -153,9 +168,10 @@ class CheckoutSubscriber implements EventSubscriberInterface
}
/**
* @param \Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent $event
* @param CheckoutConfirmPageLoadedEvent $event
* @return void
*/
public function onConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void
public function onCheckoutConfirmLoaded(CheckoutConfirmPageLoadedEvent $event): void
{
try {
$salesChannelContext = $event->getSalesChannelContext();
@@ -168,7 +184,7 @@ class CheckoutSubscriber implements EventSubscriberInterface
$createdTransactionId = $this->transactionService->createPendingTransaction($salesChannelContext, $event);
$this->updateTempTransactionIfNeeded($salesChannelContext, $createdTransactionId);
$this->getAvailablePaymentMethods($settings, $createdTransactionId);
$this->getAvailablePaymentMethods($settings, $createdTransactionId, $salesChannelContext);
$this->setPossiblePaymentMethods($settings->getSpaceId(), $event);
} catch (\Exception $e) {
$this->logger->error($e->getMessage());
@@ -176,10 +192,74 @@ class CheckoutSubscriber implements EventSubscriberInterface
}
}
/**
* @param AccountEditOrderPageLoadedEvent $event
* @return void
*/
public function onAccountOrderEditLoaded(AccountEditOrderPageLoadedEvent $event): void
{
try {
$this->handlePaymentMethodFiltering($event);
} catch (\Throwable $e) {
$this->logger->error($e->getMessage());
$this->removeVRPaymentPaymentMethodFromConfirmPage($event);
}
}
/**
* @param AccountPaymentMethodPageLoadedEvent $event
* @return void
*/
public function onAccountPaymentMethodLoaded(AccountPaymentMethodPageLoadedEvent $event): void
{
try {
$this->handlePaymentMethodFiltering($event);
} catch (\Throwable $e) {
$this->logger->error($e->getMessage());
$this->removeVRPaymentPaymentMethodFromConfirmPage($event);
}
}
/**
* @param \Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent $event
*/
private function removeVRPaymentPaymentMethodFromConfirmPage(CheckoutConfirmPageLoadedEvent $event): void
public function onConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void
{
try {
$this->handlePaymentMethodFiltering($event);
} catch (\Throwable $e) {
$this->logger->error($e->getMessage());
$this->removeVRPaymentPaymentMethodFromConfirmPage($event);
}
}
/**
* @param $event
* @return void
*/
private function handlePaymentMethodFiltering($event): void
{
$salesChannelContext = $event->getSalesChannelContext();
$settings = $this->settingsService->getValidSettings($salesChannelContext->getSalesChannel()->getId());
if (is_null($settings)) {
$this->logger->notice('Removing payment methods because settings are invalid');
$this->removeVRPaymentPaymentMethodFromConfirmPage($event);
return;
}
$createdTransactionId = $this->transactionService->createPendingTransaction($salesChannelContext, $event);
$this->updateTempTransactionIfNeeded($salesChannelContext, $createdTransactionId);
$this->getAvailablePaymentMethods($settings, $createdTransactionId, $salesChannelContext);
$this->setPossiblePaymentMethods($settings->getSpaceId(), $event);
}
/**
* @param $event
* @return void
*/
private function removeVRPaymentPaymentMethodFromConfirmPage($event): void
{
$paymentMethodCollection = $event->getPage()->getPaymentMethods();
$paymentMethodIds = $this->paymentMethodUtil->getVRPaymentPaymentMethodIds($event->getContext());
@@ -193,7 +273,7 @@ class CheckoutSubscriber implements EventSubscriberInterface
* @param int $createdTransactionId
* @return void
*/
private function getAvailablePaymentMethods(Settings $settings, int $createdTransactionId): void
private function getAvailablePaymentMethods(Settings $settings, int $createdTransactionId, SalesChannelContext $salesChannelContext): void
{
$transactionService = $settings->getApiClient()->getTransactionService();
$possiblePaymentMethods = $transactionService->fetchPaymentMethods(
@@ -203,9 +283,13 @@ class CheckoutSubscriber implements EventSubscriberInterface
);
$arrayOfPossibleMethods = [];
foreach ($possiblePaymentMethods as $possiblePaymentMethod) {
$arrayOfPossibleMethods[] = $possiblePaymentMethod->getid();
$arrayOfPossibleMethods[] = $possiblePaymentMethod->getId();
}
$_SESSION['arrayOfPossibleMethods'] = $arrayOfPossibleMethods;
$salesChannelContext->getContext()->addExtension(
'possibleMethods',
new ArrayEntity(['ids' => $arrayOfPossibleMethods])
);
}
/**
@@ -213,26 +297,57 @@ class CheckoutSubscriber implements EventSubscriberInterface
* @param CheckoutConfirmPageLoadedEvent $event
* @return void
*/
private function setPossiblePaymentMethods(int $spaceId, CheckoutConfirmPageLoadedEvent $event): void
private function setPossiblePaymentMethods(int $spaceId, $event): void
{
$localPaymentMethods = [];
$paymentMethodConfigurations = $this->paymentMethodConfigurationService->getAllPaymentMethodConfigurations($spaceId, $event->getSalesChannelContext()->getContext());
foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) {
$localPaymentMethods[$paymentMethodConfiguration->getId()] = $paymentMethodConfiguration->getPaymentMethodConfigurationId();
$paymentIds = [];
$paymentMethodCollection = $event->getPage()->getPaymentMethods();
foreach ($paymentMethodCollection as $paymentMethodCollectionItem) {
$isVRPaymentPM = VRPaymentPaymentHandler::class === $paymentMethodCollectionItem->getHandlerIdentifier();
if (!$isVRPaymentPM) {
$paymentIds[] = $paymentMethodCollectionItem->getId();
}
}
$paymentMethodCollection = $event->getPage()->getPaymentMethods();
foreach ($paymentMethodCollection as $paymentMethodCollectionItem) {
$isVRPaymentPM = VRPaymentPaymentHandler::class == $paymentMethodCollectionItem->getHandlerIdentifier();
if (!$isVRPaymentPM) {
$allowedWLMethods = [];
$paymentMethodConfigurations = $this->paymentMethodConfigurationService
->getAllPaymentMethodConfigurations($spaceId, $event->getSalesChannelContext()->getContext());
foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) {
if ($paymentMethodConfiguration->getPaymentMethod() === null) {
continue;
}
$paymentMethodConfigurationId = $localPaymentMethods[$paymentMethodCollectionItem->getId()];
if (!\in_array($paymentMethodConfigurationId, $_SESSION['arrayOfPossibleMethods'])) {
$paymentMethodCollection->remove($paymentMethodCollectionItem->getId());
$pmId = $paymentMethodConfiguration->getPaymentMethod()->getId();
$pmConfigId = $paymentMethodConfiguration->getPaymentMethodConfigurationId();
$allowedIds = $this->getAllowedPaymentMethodIds($event->getSalesChannelContext());
if ($paymentMethodConfiguration->getSpaceId() === $spaceId
&& \in_array($pmConfigId, $allowedIds, true)) {
$allowedWLMethods[] = $pmId;
}
}
$allPaymentIds = array_unique(array_merge($paymentIds, $allowedWLMethods));
$collection = new PaymentMethodCollection();
if (!empty($allPaymentIds)) {
$criteria = new Criteria($allPaymentIds);
$criteria->addFilter(new EqualsFilter('active', true));
$criteria->addFilter(
new EqualsFilter('salesChannels.id', $event->getSalesChannelContext()->getSalesChannelId())
);
$criteria->addSorting(new FieldSorting('position', FieldSorting::ASCENDING));
$criteria->addAssociation('media');
$result = $this->paymentMethodRepository->search($criteria, $event->getContext());
foreach ($result->getEntities() as $method) {
if (!$collection->has($method->getId())) {
$collection->add($method);
}
}
}
$event->getPage()->setPaymentMethods($collection);
}
/**
@@ -242,19 +357,43 @@ class CheckoutSubscriber implements EventSubscriberInterface
*/
private function updateTempTransactionIfNeeded(SalesChannelContext $salesChannelContext, int $createdTransactionId): void
{
$addressCheck = $_SESSION['addressCheck'] ?? null;
$currencyCheck = $_SESSION['currencyCheck'] ?? null;
$ctx = $salesChannelContext->getContext();
/** @var ArrayEntity|null $ext */
$ext = $ctx->getExtension('checkoutState');
$oldAddressHash = $ext instanceof ArrayEntity ? $ext->get('addressHash') : null;
$oldCurrency = $ext instanceof ArrayEntity ? $ext->get('currency') : null;
$customer = $salesChannelContext->getCustomer();
$addressHash = md5(json_encode((array) $customer));
$currency = $salesChannelContext->getCurrency()->getIsoCode();
if (($addressCheck && $currencyCheck) && $addressCheck !== $addressHash || $currencyCheck !== $currency) {
$needsUpdate = ($oldAddressHash !== $addressHash) || ($oldCurrency !== $currency);
if ($needsUpdate) {
if ($createdTransactionId) {
$this->transactionService->updateTempTransaction($salesChannelContext, $createdTransactionId);
}
$_SESSION['arrayOfPossibleMethods'] = null;
$_SESSION['addressCheck'] = $addressHash;
$_SESSION['currencyCheck'] = $currency;
$ctx->addExtension('possibleMethods', new ArrayEntity(['ids' => []]));
$ctx->addExtension(
'checkoutState',
new ArrayEntity([
'addressHash' => $addressHash,
'currency' => $currency,
])
);
}
}
/**
* @param SalesChannelContext $salesChannelContext
* @return array
*/
private function getAllowedPaymentMethodIds(SalesChannelContext $salesChannelContext): array
{
$ext = $salesChannelContext->getContext()->getExtension('possibleMethods');
return $ext instanceof ArrayEntity ? ($ext->get('ids') ?? []) : [];
}
}
+58 -5
View File
@@ -3,6 +3,7 @@
namespace VRPaymentPayment\Core\Util\Analytics;
use VRPayment\Sdk\ApiClient;
use Shopware\Core\Kernel;
/**
* Class Analytics
@@ -19,26 +20,78 @@ class Analytics {
/**
* @return array
*/
public static function getDefaultData()
public static function getDefaultData(): array
{
$shopwareVersion = self::getShopwareVersion();
return [
self::SHOP_SYSTEM => 'shopware',
self::SHOP_SYSTEM_VERSION => '6',
self::SHOP_SYSTEM_AND_VERSION => 'shopware-6',
self::PLUGIN_SYSTEM_VERSION => '7.0.1',
self::SHOP_SYSTEM_VERSION => $shopwareVersion,
self::SHOP_SYSTEM_AND_VERSION => 'shopware-' . $shopwareVersion,
self::PLUGIN_SYSTEM_VERSION => '6.2.1',
];
}
/**
* @param \VRPayment\Sdk\ApiClient $apiClient
*/
public static function addHeaders(ApiClient &$apiClient)
public static function addHeaders(ApiClient &$apiClient): void
{
$data = self::getDefaultData();
foreach ($data as $key => $value) {
$apiClient->addDefaultHeader($key, $value);
}
}
/**
* Reads Shopware version and caches it for performance.
*
* @return string
*/
public static function getShopwareVersion(): string
{
static $cachedVersion = null;
if ($cachedVersion !== null) {
return $cachedVersion;
}
$basePath = dirname(__DIR__, 7);
$installedFile = $basePath . '/vendor/composer/installed.php';
if (is_file($installedFile)) {
$installed = include $installedFile;
$packages = [];
if (isset($installed['versions'])) {
$packages = $installed['versions'];
} elseif (is_array($installed)) {
foreach ($installed as $section) {
if (isset($section['versions'])) {
$packages = $section['versions'];
break;
}
}
}
if (isset($packages['shopware/core']['pretty_version'])) {
return $cachedVersion = ltrim($packages['shopware/core']['pretty_version'], 'v');
}
}
$lockFile = $basePath . '/composer.lock';
if (is_file($lockFile)) {
$data = json_decode((string) file_get_contents($lockFile), true);
if (!empty($data['packages'])) {
foreach ($data['packages'] as $package) {
if (($package['name'] ?? '') === 'shopware/core') {
return $cachedVersion = ltrim($package['version'], 'v');
}
}
}
}
return $cachedVersion = Kernel::SHOPWARE_FALLBACK_VERSION;
}
}
@@ -0,0 +1,8 @@
<?php declare(strict_types=1);
namespace VRPaymentPayment\Core\Util\Exception;
class RefundNotSupportedException extends \LogicException{
}
+83 -170
View File
@@ -8,14 +8,11 @@ use Shopware\Core\{Checkout\Cart\Tax\Struct\CalculatedTaxCollection,
Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity,
Checkout\Customer\CustomerEntity,
Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity,
Checkout\Order\OrderEntity,
Checkout\Payment\Cart\PaymentTransactionStruct,
Checkout\Payment\Cart\AsyncPaymentTransactionStruct,
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,
@@ -40,10 +37,6 @@ 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
*
@@ -69,7 +62,7 @@ class TransactionPayload extends AbstractPayload
protected $salesChannelContext;
/**
* @var \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct
* @var \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct
*/
protected $transaction;
@@ -93,10 +86,6 @@ class TransactionPayload extends AbstractPayload
*/
protected $translator;
protected EntityRepository $orderTransactionRepository;
protected OrderEntity $order;
/**
* TransactionPayload constructor.
*
@@ -104,14 +93,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\PaymentTransactionStruct $transaction
* @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
*/
public function __construct(
ContainerInterface $container,
LocaleCodeProvider $localeCodeProvider,
SalesChannelContext $salesChannelContext,
Settings $settings,
PaymentTransactionStruct $transaction
AsyncPaymentTransactionStruct $transaction
)
{
$this->localeCodeProvider = $localeCodeProvider;
@@ -120,23 +109,6 @@ 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();
}
/**
@@ -147,21 +119,13 @@ class TransactionPayload extends AbstractPayload
*/
public function get(int $version): TransactionPending
{
$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();
$customer = $this->salesChannelContext->getCustomer();
$lineItems = $this->getLineItems();
$billingAddress = $this->getAddressPayload($customer, $customer->getActiveBillingAddress());
$shippingAddress = $this->getAddressPayload($customer, $customer->getActiveShippingAddress(), false);
$customerId = null;
$customerName = null;
if ($customer->getGuest() === false) {
@@ -174,14 +138,14 @@ class TransactionPayload extends AbstractPayload
}
$transactionData = [
'currency' => $this->order->getCurrency()->getIsoCode(),
'customer_email_address' => $customer->getEmail(),
'currency' => $this->salesChannelContext->getCurrency()->getIsoCode(),
'customer_email_address' => $billingAddress->getEmailAddress(),
'customer_id' => $customerId,
'language' => $this->localeCodeProvider->getLocaleCodeFromContext($this->salesChannelContext->getContext()) ?? null,
'merchant_reference' => $this->fixLength($this->order->getOrderNumber(), 100),
'merchant_reference' => $this->fixLength($this->transaction->getOrder()->getOrderNumber(), 100),
'meta_data' => [
self::VRPAYMENT_METADATA_ORDER_ID => $this->order->getId(),
self::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID => $this->order->getTransactions()->first()->getId(),
self::VRPAYMENT_METADATA_ORDER_ID => $this->transaction->getOrder()->getId(),
self::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID => $this->transaction->getOrderTransaction()->getId(),
self::VRPAYMENT_METADATA_SALES_CHANNEL_ID => $this->salesChannelContext->getSalesChannel()->getId(),
self::VRPAYMENT_METADATA_CUSTOMER_NAME => $customerName,
],
@@ -198,8 +162,8 @@ class TransactionPayload extends AbstractPayload
$transactionData['meta_data']['additionalAddress2'] = $additionalAddress2;
}
if (!empty($this->order->getCustomerComment())) {
$transactionData['meta_data']['customer_comment'] = $this->order->getCustomerComment();
if (!empty($this->transaction->getOrder()->getCustomerComment())) {
$transactionData['meta_data']['customer_comment'] = $this->transaction->getOrder()->getCustomerComment();
}
$vatIds = $customer->getVatIds();
@@ -230,12 +194,18 @@ class TransactionPayload extends AbstractPayload
->setShippingAddress($shippingAddress)
->setShippingMethod($transactionData['shipping_method']);
$paymentConfiguration = $this->getPaymentConfiguration($this->salesChannelContext->getPaymentMethod()->getId());
$transactionPayload->setAllowedPaymentMethodConfigurations([$paymentConfiguration->getPaymentMethodConfigurationId()]);
$paymentConfiguration = $this->getPaymentConfiguration(
$this->salesChannelContext->getPaymentMethod()->getId(),
$this->settings->getSpaceId()
);
if ($paymentConfiguration) {
$transactionPayload->setAllowedPaymentMethodConfigurations([
$paymentConfiguration->getPaymentMethodConfigurationId()
]);
}
$successUrl = $this->transaction->getReturnUrl() . '&status=paid';
$failedUrl = $this->getFailUrl($this->order->getId()) . '&status=fail';
$failedUrl = $this->getFailUrl($this->transaction->getOrder()->getId()) . '&status=fail';
$transactionPayload->setSuccessUrl($successUrl)
->setFailedUrl($failedUrl);
@@ -247,6 +217,23 @@ class TransactionPayload extends AbstractPayload
return $transactionPayload;
}
/**
* @param string $paymentMethodId
* @param int $spaceId
* @return PaymentMethodConfigurationEntity|null
*/
protected function getPaymentConfiguration(string $paymentMethodId, int $spaceId): ?PaymentMethodConfigurationEntity
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('paymentMethodId', $paymentMethodId));
$criteria->addFilter(new EqualsFilter('spaceId', $spaceId));
return $this->container->get('vrpayment_payment_method_configuration.repository')
->search($criteria, $this->salesChannelContext->getContext())
->first();
}
/**
* Get transaction line items
*
@@ -256,7 +243,7 @@ class TransactionPayload extends AbstractPayload
protected function getLineItems(): array
{
$lineItems = [];
$items = $this->order->getLineItems() ?? [];
$items = $this->transaction->getOrder()->getLineItems();
foreach ($items as $shopLineItem) {
if ($this->shouldSkipLineItem($shopLineItem)) {
@@ -344,90 +331,27 @@ class TransactionPayload extends AbstractPayload
protected function addDiscountLineItem($discount, array &$lineItems): void
{
$calculatedPrice = $discount->getPrice();
$discountName = $discount->getLabel() ?? 'Unnamed';
$definition = $discount->getPriceDefinition();
if ($this->order->getTaxStatus() === 'net' || $definition instanceof \Shopware\Core\Checkout\Cart\Price\Struct\AbsolutePriceDefinition) {
$calculatedTaxesCollection = $calculatedPrice->getCalculatedTaxes();
foreach ($calculatedTaxesCollection as $calculatedTax) {
$rate = $calculatedTax->getTaxRate();
$lineItem = new LineItemCreate();
$amount = $this->calculateDiscountAmount($calculatedTax);
$lineItems[] = $this->createDiscountLineItem($discountName, $amount, $rate);
}
} else {
$taxRules = $calculatedPrice->getTaxRules();
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);
}
$discountName = $discount->getLabel();
$lineItem->setAmountIncludingTax($amount)
->setName($discountTitle)
->setName(sprintf('DISCOUNT: %s (%s%% tax)', $discount->getLabel(), $rate))
->setQuantity(1)
->setShippingRequired(false)
->setSku($discountSkuName, 200)
->setSku('sku-discount-' . $rate . '-' . $discountName, 200)
->setType(LineItemType::DISCOUNT)
->setUniqueId('coupon-' . $discountSkuName);
->setUniqueId('coupon-sku-discount-' . $rate . '-' . $rate . '-' . $discountName . '-' . $discount->getId());
$taxRate = new TaxCreate([
'title' => 'Discount Tax: ' . $rate,
'rate' => $rate,
]);
if ($this->order->getTaxStatus() !== 'tax-free') {
$taxRate = new TaxCreate(['title' => 'Discount Tax: ' . $rate, 'rate' => $rate]);
$lineItem->setTaxes([$taxRate]);
$lineItems[] = $lineItem;
}
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;
}
/**
@@ -436,7 +360,7 @@ class TransactionPayload extends AbstractPayload
protected function calculateDiscountAmount($calculatedTax): float
{
$amount = self::round($calculatedTax->getPrice());
if ($this->order->getTaxStatus() === 'net') {
if ($this->transaction->getOrder()->getTaxStatus() === 'net') {
$amount = self::round($amount + $calculatedTax->getTax());
}
return $amount;
@@ -457,7 +381,9 @@ class TransactionPayload extends AbstractPayload
*/
protected function addOptionalLineItems(array &$lineItems): void
{
if (count($this->order->getShippingCosts()->getCalculatedTaxes()) === 1) {
$shippingCosts = $this->transaction->getOrder()->getShippingCosts();
if ($shippingCosts && $this->transaction->getOrder()->getShippingTotal() > 0) {
if ($shippingLineItem = $this->getShippingLineItem()) {
$lineItems[] = $shippingLineItem;
}
@@ -479,7 +405,7 @@ class TransactionPayload extends AbstractPayload
protected function getCustomProductOptionLabel(string $lineItemParentId): string
{
$label = '';
foreach ($this->order->getLineItems() as $shopLineItem) {
foreach ($this->transaction->getOrder()->getLineItems() as $shopLineItem) {
if ($shopLineItem->getParentId() === $lineItemParentId && $shopLineItem->getType() === CustomProductsLineItemTypes::LINE_ITEM_TYPE_PRODUCT) {
$label = $shopLineItem->getLabel();
break;
@@ -504,11 +430,10 @@ 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->order->getTaxStatus() === 'net') {
if ($this->transaction->getOrder()->getTaxStatus() === 'net') {
$amount = self::round($amount + $shopLineItem->getPrice()->getCalculatedTaxes()->getAmount());
}
@@ -544,10 +469,8 @@ class TransactionPayload extends AbstractPayload
}
if (!empty($taxes)) {
if ($this->order->getTaxStatus() !== 'tax-free') {
$lineItem->setTaxes($taxes);
}
}
if ($shopLineItem->getTotalPrice() >= 0) {
$lineItem->setType(LineItemType::PRODUCT);
@@ -622,34 +545,31 @@ class TransactionPayload extends AbstractPayload
{
try {
$amount = $this->order->getShippingTotal();
$amount = $this->transaction->getOrder()->getShippingTotal();
$amount = self::round($amount);
if ($amount > 0) {
$shippingName = $this->salesChannelContext->getShippingMethod()->getName() ?? $this->translator->trans('vrpayment.payload.shipping.name');
$taxes = $this->getTaxes(
$this->order->getShippingCosts()->getCalculatedTaxes(),
$this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes(),
$shippingName
);
if ($this->order->getTaxStatus() === 'net') {
$amount = self::round($amount + $this->order->getShippingCosts()->getCalculatedTaxes()->getAmount());
if ($this->transaction->getOrder()->getTaxStatus() === 'net') {
$amount = self::round($amount + $this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes()->getAmount());
}
$lineItem = (new LineItemCreate())
->setAmountIncludingTax($amount)
->setName($this->fixLength($shippingName . ' ' . $this->translator->trans('vrpayment.payload.shipping.lineItem'), 150))
->setQuantity($this->order->getShippingCosts()->getQuantity() ?? 1)
->setQuantity($this->transaction->getOrder()->getShippingCosts()->getQuantity() ?? 1)
->setTaxes($taxes)
->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()));
@@ -670,15 +590,15 @@ class TransactionPayload extends AbstractPayload
protected function getMultipleShippingLineItems(): array
{
try {
if ($this->order->getShippingTotal() > 0) {
if ($this->transaction->getOrder()->getShippingTotal() > 0) {
$lineItems = [];
$shippingName = $this->salesChannelContext->getShippingMethod()->getName() ?? $this->translator->trans('vrpayment.payload.shipping.name');
$isFirst = true;
foreach ($this->order->getShippingCosts()->getCalculatedTaxes() as $taxItem) {
foreach ($this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes() as $taxItem) {
$amount = self::round($taxItem->getPrice());
if ($this->order->getTaxStatus() === 'net') {
if ($this->transaction->getOrder()->getTaxStatus() === 'net') {
$amount = self::round($amount + $taxItem->getTax());
}
$taxRate = $taxItem->getTaxRate();
@@ -690,15 +610,12 @@ class TransactionPayload extends AbstractPayload
$lineItem = (new LineItemCreate())
->setAmountIncludingTax($amount)
->setName($this->fixLength($name . ' ' . $this->translator->trans('vrpayment.payload.shipping.lineItem'), 150))
->setQuantity($this->order->getShippingCosts()->getQuantity() ?? 1)
->setQuantity($this->transaction->getOrder()->getShippingCosts()->getQuantity() ?? 1)
->setTaxes([$tax])
->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()));
@@ -728,18 +645,28 @@ class TransactionPayload extends AbstractPayload
{
$lineItem = null;
$lineItemPriceTotal = array_sum(array_map(static function (LineItemCreate $lineItem) {
return $lineItem->getAmountIncludingTax();
}, $lineItems));
// Calculate total of all current line items
$lineItemPriceTotal = array_sum(array_map(static fn(LineItemCreate $li) => $li->getAmountIncludingTax(), $lineItems));
$adjustmentPrice = $this->order->getAmountTotal() - $lineItemPriceTotal;
$adjustmentPrice = self::round($adjustmentPrice);
$this->logger->debug("LineItem price total before adjustment: $lineItemPriceTotal");
// Get shipping total including taxes from the order
$shippingCosts = $this->transaction->getOrder()->getShippingCosts();
$shippingTotal = $shippingCosts ? self::round($shippingCosts->getTotalPrice()) : 0.0;
// Add shipping to the line items total if it's not already included
$hasShippingLineItem = array_filter($lineItems, static fn(LineItemCreate $li) => $li->getType() === LineItemType::SHIPPING);
if (!$hasShippingLineItem && $shippingTotal > 0) {
$lineItemPriceTotal += $shippingTotal;
}
$adjustmentPrice = self::round($this->transaction->getOrder()->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->order->getAmountTotal(),
':orderTotal' => $this->transaction->getOrder()->getAmountTotal(),
]);
$this->logger->critical($error);
throw new \Exception($error);
@@ -889,20 +816,6 @@ class TransactionPayload extends AbstractPayload
return $addressPayload;
}
/**
* @param string $id
*
* @return \VRPaymentPayment\Core\Api\PaymentMethodConfiguration\Entity\PaymentMethodConfigurationEntity
*/
protected function getPaymentConfiguration(string $id): PaymentMethodConfigurationEntity
{
$criteria = (new Criteria([$id]));
return $this->container->get('vrpayment_payment_method_configuration.repository')
->search($criteria, $this->salesChannelContext->getContext())
->getEntities()->first();
}
/**
* Get failure URL
*
@@ -31,7 +31,7 @@ class Migration1590156974TransactionEntity extends MigrationStep {
public function update(Connection $connection): void
{
$connection->executeStatement('
CREATE TABLE IF NOT EXISTS `vrpayment_transaction` (
CREATE TABLE IF NOT EXISTS `vrpayment_transaction_tmp` (
`id` BINARY(16) NOT NULL,
`data` JSON NOT NULL,
`payment_method_id` BINARY(16) NOT NULL,
@@ -42,7 +42,7 @@ class Migration1590646356RefundEntity extends MigrationStep {
PRIMARY KEY (`id`),
UNIQUE KEY `refund_id_UNIQUE` (`refund_id`),
KEY `fk.vrp_refund.transaction_id` (`transaction_id`),
CONSTRAINT `fk.vrp_refund.transaction_id` FOREIGN KEY (`transaction_id`) REFERENCES `vrpayment_transaction` (`transaction_id`) ON DELETE CASCADE
CONSTRAINT `fk.vrp_refund.transaction_id` FOREIGN KEY (`transaction_id`) REFERENCES `vrpayment_transaction_tmp` (`transaction_id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
');
}
@@ -30,7 +30,7 @@ class Migration1590646356TransactionEntity extends MigrationStep {
public function update(Connection $connection): void
{
try {
$connection->executeStatement('ALTER TABLE `vrpayment_transaction` ADD COLUMN `confirmation_email_sent` TINYINT(1) NOT NULL DEFAULT 0 AFTER `id`;');
$connection->executeStatement('ALTER TABLE `vrpayment_transaction_tmp` ADD COLUMN `confirmation_email_sent` TINYINT(1) NOT NULL DEFAULT 0 AFTER `id`;');
}catch (\Exception $exception){
// column probably exists
}
@@ -33,19 +33,19 @@ class Migration1605701048TransactionEntity extends MigrationStep
try {
$connection->executeStatement('
ALTER TABLE `vrpayment_transaction`
ALTER TABLE `vrpayment_transaction_tmp`
ADD `order_version_id` binary(16) NOT NULL AFTER `transaction_id`;
');
$connection->executeStatement('
UPDATE `vrpayment_transaction` t1
UPDATE `vrpayment_transaction_tmp` t1
INNER JOIN `order` t2
ON t1.order_id = t2.id
SET t1.order_version_id = t2.version_id;
');
$connection->executeStatement('
ALTER TABLE `vrpayment_transaction`
ALTER TABLE `vrpayment_transaction_tmp`
DROP FOREIGN KEY `fk.vrp_transaction.order_id`,
DROP FOREIGN KEY `fk.vrp_transaction.order_transaction_id`,
DROP FOREIGN KEY `fk.vrp_transaction.payment_method_id`,
@@ -53,7 +53,7 @@ class Migration1605701048TransactionEntity extends MigrationStep
');
$connection->executeStatement('
ALTER TABLE `vrpayment_transaction`
ALTER TABLE `vrpayment_transaction_tmp`
ADD CONSTRAINT `fk.vrp_transaction_order_id` FOREIGN KEY (`order_id`, `order_version_id`)
REFERENCES `order` (`id`, `version_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `fk.vrp_transaction_payment_method_id` FOREIGN KEY (`payment_method_id`)
@@ -30,7 +30,7 @@ class Migration1684240994TransactionEntity extends MigrationStep {
public function update(Connection $connection): void
{
try {
$connection->executeStatement('ALTER TABLE `vrpayment_transaction` ADD COLUMN `erp_merchant_id` VARCHAR(255) DEFAULT NULL AFTER `confirmation_email_sent`;');
$connection->executeStatement('ALTER TABLE `vrpayment_transaction_tmp` ADD COLUMN `erp_merchant_id` VARCHAR(255) DEFAULT NULL AFTER `confirmation_email_sent`;');
}catch (\Exception $exception){
// column probably exists
}
@@ -0,0 +1,324 @@
<?php declare(strict_types=1);
namespace VRPaymentPayment\Migration;
use Doctrine\DBAL\Connection;
use Shopware\Core\Framework\Migration\MigrationStep;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
/**
* Class Migration1766067106TransactionEntity
*
* @package VRPaymentPayment\Migration
*/
class Migration1766067106TransactionEntity extends MigrationStep
{
/**
* get creation timestamp
*
* @return int
*/
public function getCreationTimestamp(): int
{
return 1766067106;
}
/**
* update non-destructive changes
*
* @param \Doctrine\DBAL\Connection $connection
*/
public function update(Connection $connection): void
{
$oldTableName = 'vrpayment_transaction';
$tempTableName = 'vrpayment_transaction_tmp';
$realTableName = 'vrpayment_transaction_data';
$logger = new Logger('vrpayment_migration');
$logger->pushHandler(new StreamHandler(dirname(__DIR__, 5) . '/var/log/vrpayment-migration.log'));
$logger->info(
'Migration start', [
'old_table_exists' => $this->tableExists($connection, $oldTableName),
'temp_table_exists' => $this->tableExists($connection, $tempTableName),
'real_table_exists' => $this->tableExists($connection, $realTableName),
]
);
if ($this->tableExists($connection, $tempTableName)) {
// If _temp table exists, it means that this is a fresh installation.
$logger->info('Fresh installation detected.');
$connection->executeStatement(
sprintf('RENAME TABLE `%s` TO `%s`', $tempTableName, $realTableName)
);
$logger->info('Fresh installation finished.');
} else {
// If _temp does not exist, it means that this could be a version upgrade.
$logger->info('Possible plugin upgrade detected.');
if ($this->tableExists($connection, $oldTableName) && !$this->isOldPluginTable($connection, $oldTableName)) {
$logger->info('Old vrpayment_transaction table detected.');
// If vrpayment_transaction already exists and does not belong to old plugin,
// it means that this is indeed a version update.
$this->syncTransactionTable($connection, $oldTableName);
$logger->info('Old vrpayment_transaction table sync finished.');
$this->syncRefundTable($connection, $oldTableName);
$logger->info('Old vrpayment_refund table sync finished.');
$connection->executeStatement(
sprintf('RENAME TABLE `%s` TO `%s`', $oldTableName, $realTableName)
);
$logger->info('Old vrpayment_transaction table renaming completed.');
}
$logger->info('Possible plugin upgrade finished.');
// If vrpayment_transaction exists and it does belong to old plugin,
// it means we must run it in parallel.
}
$logger->info('Migration finished.');
return;
}
/**
* Check if table exists.
*
* @param \Doctrine\DBAL\Connection $connection
* @param string $table
*
* @return bool
*/
public function tableExists(Connection $connection, string $table): bool {
$result = $connection->fetchOne('SHOW TABLES LIKE :table', ['table' => $table]);
return $result !== false && $result !== null;
}
/**
* Check if table belongs to old plugin.
*
* @param \Doctrine\DBAL\Connection $connection
* @param string $table
*
* @return bool
*/
public function isOldPluginTable(Connection $connection, string $table): bool {
$oldTableExclusiveColumns = [
'finalized_at' => 'datetime',
'refunded_at' => 'datetime',
'initial_transaction_mode' => 'varchar',
'manual_capture' => 'tinyint',
'partial_refunded_at' => 'datetime',
'refunded_amount' => 'double',
'amount_to_refund' => 'double',
];
$resultColumns = $connection->fetchAllAssociative(
'SELECT LOWER(COLUMN_NAME) AS column_name, LOWER(DATA_TYPE) AS data_type
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = :table',
['table' => $table]
);
$dbColumns = [];
foreach($resultColumns as $column) {
$dbColumns[$column['column_name']] = $column['data_type'];
}
$oldPluginTable = true;
foreach($oldTableExclusiveColumns as $columnName => $columnType) {
if(!isset($dbColumns[$columnName])) {
$oldPluginTable = false;
break;
}
if ($dbColumns[$columnName] !== $columnType) {
$oldPluginTable = false;
break;
}
}
return $oldPluginTable;
}
/**
* Synchronizes the transaction table with the current/latest version.
*
* @param \Doctrine\DBAL\Connection $connection
* @param string $table
*/
private function syncTransactionTable(Connection $connection, string $table): void {
$this->addColumnIfMissing($connection, $table, 'confirmation_email_sent', "TINYINT(1) NOT NULL DEFAULT 0 AFTER `id`");
$this->addColumnIfMissing($connection, $table, 'erp_merchant_id', "VARCHAR(255) DEFAULT NULL AFTER `confirmation_email_sent`");
$this->addColumnIfMissing($connection, $table, 'data', "LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`data`)) AFTER `erp_merchant_id`");
$this->addColumnIfMissing($connection, $table, 'payment_method_id', "BINARY(16) NOT NULL");
$this->addColumnIfMissing($connection, $table, 'order_id', "BINARY(16) NOT NULL");
$this->addColumnIfMissing($connection, $table, 'order_transaction_id', "BINARY(16) NOT NULL");
$this->addColumnIfMissing($connection, $table, 'space_id', "INT(10) UNSIGNED NOT NULL");
$this->addColumnIfMissing($connection, $table, 'state', "VARCHAR(255) NOT NULL");
$this->addColumnIfMissing($connection, $table, 'sales_channel_id', "BINARY(16) NOT NULL");
$this->addColumnIfMissing($connection, $table, 'transaction_id', "INT(10) UNSIGNED NOT NULL");
$this->addColumnIfMissing($connection, $table, 'order_version_id', "BINARY(16) NOT NULL AFTER `transaction_id`");
$this->addColumnIfMissing($connection, $table, 'created_at', "DATETIME(3) NOT NULL");
$this->addColumnIfMissing($connection, $table, 'updated_at', "DATETIME(3) DEFAULT NULL");
$this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction.order_id', "KEY `fk.vrp_transaction.order_id` (`order_id`)");
$this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction.order_transaction_id', "KEY `fk.vrp_transaction.order_transaction_id` (`order_transaction_id`)");
$this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction.payment_method_id', "KEY `fk.vrp_transaction.payment_method_id` (`payment_method_id`)");
$this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction.sales_channel_id', "KEY `fk.vrp_transaction.sales_channel_id` (`sales_channel_id`)");
$this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction', "KEY `fk.vrp_transaction` (`order_id`,`order_version_id`)");
$this->ensureForeignKey(
$connection,
$table,
'fk.vrp_transaction_order_id',
['order_id', 'order_version_id'],
'order',
['id', 'version_id'],
'CASCADE',
'CASCADE'
);
$this->ensureForeignKey(
$connection,
$table,
'fk.vrp_transaction_payment_method_id',
['payment_method_id'],
'payment_method',
['id'],
'RESTRICT',
'CASCADE'
);
$this->ensureForeignKey(
$connection,
$table,
'fk.vrp_transaction_sales_channel_id',
['sales_channel_id'],
'sales_channel',
['id'],
'RESTRICT',
'CASCADE'
);
}
/**
* Synchronizes the parts of the refund table related to transactions with the current/latest version.
*
* @param \Doctrine\DBAL\Connection $connection
* @param string $table
*/
private function syncRefundTable(Connection $connection, string $table): void {
$refundTable = 'vrpayment_refund';
$this->ensureIndexBySql($connection, $refundTable, 'fk.vrp_refund.transaction_id', "KEY `fk.vrp_refund.transaction_id` (`transaction_id`)");
$this->ensureForeignKey(
$connection,
$refundTable,
'fk.vrp_refund.transaction_id',
['transaction_id'],
$table,
['transaction_id'],
'CASCADE',
null
);
}
/**
* Adds column to the table if it's missing.
*
* @param \Doctrine\DBAL\Connection $connection
* @param string $table
* @param string $column
* @param string $sqlFragment
*/
private function addColumnIfMissing(Connection $connection, string $table, string $column, string $sqlFragment): void {
if ($this->columnExists($connection, $table, $column)) {
return;
}
$connection->executeStatement(
sprintf("ALTER TABLE `%s` ADD COLUMN `%s` %s", $table, $column, $sqlFragment)
);
}
/**
* Adds index to the table if it's missing.
*
* @param \Doctrine\DBAL\Connection $connection
* @param string $table
* @param string $indexName
* @param string $sqlFragment
*/
private function ensureIndexBySql(Connection $connection, string $table, string $indexName, string $sqlFragment): void {
if ($this->indexExists($connection, $table, $indexName)) {
return;
}
$connection->executeStatement(
sprintf("ALTER TABLE `%s` ADD %s", $table, $sqlFragment)
);
}
/**
* Adds foreign key constraint to the table if it's missing.
*
* @param \Doctrine\DBAL\Connection $connection
* @param string $table
* @param string $constraintName
* @param string $columns
* @param string $refTable
* @param string $refColumns
* @param string|null $onDelete
* @param string|null $onUpdate
*/
private function ensureForeignKey(
Connection $connection,
string $table,
string $constraintName,
array $columns,
string $refTable,
array $refColumns,
?string $onDelete,
?string $onUpdate
): void {
if ($this->foreignKeyExists($connection, $table, $constraintName)) {
return;
}
$columnsList = '`' . implode('`,`', $columns) . '`';
$refColumnsList = '`' . implode('`,`', $refColumns) . '`';
$connection->executeStatement(
sprintf(
"ALTER TABLE `%s`
ADD CONSTRAINT `%s` FOREIGN KEY (%s)
REFERENCES `%s` (%s)%s%s",
$table,
$constraintName,
$columnsList,
$refTable,
$refColumnsList,
$onDelete ? " ON DELETE {$onDelete}" : "",
$onUpdate ? " ON UPDATE {$onUpdate}" : ""
)
);
}
/**
* Check if foreign key constraint exists.
*
* @param \Doctrine\DBAL\Connection $connection
* @param string $table
* @param string $constraintName
*
* @return bool
*/
private function foreignKeyExists(Connection $connection, string $table, $constraintName): bool {
$result = $connection->fetchOne(
"SELECT 1 FROM information_schema.referential_constraints
WHERE constraint_schema = DATABASE()
AND table_name = ?
AND constraint_name = ?
LIMIT 1",
[$table,$constraintName]
);
return $result !== false && $result !== null;
}
/**
* update destructive changes
*
* @param \Doctrine\DBAL\Connection $connection
*/
public function updateDestructive(Connection $connection): void
{
// implement update destructive
}
}
BIN
View File
Binary file not shown.
@@ -4,21 +4,21 @@
@modal-close="$emit('modal-close')">
{% block vrpayment_order_action_completion_amount %}
<mt-checkbox
<sw-checkbox-field
:label="$tc('vrpayment-order.captureAction.button.text')"
v-model:checked="isCompletion">
</mt-checkbox>
v-model:value="isCompletion">
</sw-checkbox-field>
{% endblock %}
{% block vrpayment_order_action_completion_confirm_button %}
<template #modal-footer>
<mt-button variant="primary"
<sw-button variant="primary"
@click="completion">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</mt-button>
</sw-button>
</template>
{% endblock %}
<mt-loader v-if="isLoading"></mt-loader>
<sw-loader v-if="isLoading"></sw-loader>
</sw-modal>
{% endblock %}
@@ -4,23 +4,23 @@
@modal-close="$emit('modal-close')">
{% block vrpayment_order_action_refund_amount_by_amount %}
<mt-number-field
<sw-number-field
:max="refundableAmount"
:min="0"
v-model="refundAmount"
v-model:value="refundAmount"
:label="$tc('vrpayment-order.refund.refundAmount.label')"
:suffix="currency">
</mt-number-field>
</sw-number-field>
{% endblock %}
{% block vrpayment_order_action_refund_confirm_button_by_amount %}
<template #modal-footer>
<mt-button variant="primary" @click="refundByAmount()">
<sw-button variant="primary" @click="refundByAmount()">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</mt-button>
</sw-button>
</template>
{% endblock %}
<mt-loader v-if="isLoading"></mt-loader>
<sw-loader v-if="isLoading"></sw-loader>
</sw-modal>
{% endblock %}
@@ -70,13 +70,19 @@ Component.register('vrpayment-order-action-refund-by-amount', {
});
}).catch((errorResponse) => {
try {
var errorTitle;
var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.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;
switch(errorResponse.response.data) {
case 'refundAmountZero':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messageRefundAmountIsZero');
break;
case 'refundExceedsAmount':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messageRefundAmountExceedsAvailableBalance');
break;
case 'methodDoesNotSupportRefund':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund');
break;
default:
errorMessage = errorResponse.response.data.errors[0].detail;
}
this.createNotificationError({
@@ -4,13 +4,13 @@
@modal-close="$emit('modal-close')">
{% block vrpayment_order_action_refund_amount_partial %}
<mt-number-field
<sw-number-field
:max="this.$parent.$parent.itemRefundableAmount"
:min="0.00"
v-model="refundAmount"
v-model:value="refundAmount"
:label="$tc('vrpayment-order.refund.refundAmount.label')"
:suffix="currency">
</mt-number-field>
</sw-number-field>
<div>
{{ $tc('vrpayment-order.refundAction.maxAvailableAmountToRefund') }}:
@@ -20,12 +20,12 @@
{% block vrpayment_order_action_refund_confirm_button_partial %}
<template #modal-footer>
<mt-button variant="primary" @click="createPartialRefund(this.$parent.$parent.currentLineItem)">
<sw-button variant="primary" @click="createPartialRefund(this.$parent.$parent.currentLineItem)">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</mt-button>
</sw-button>
</template>
{% endblock %}
<mt-loader v-if="isLoading"></mt-loader>
<sw-loader v-if="isLoading"></sw-loader>
</sw-modal>
{% endblock %}
@@ -47,9 +47,7 @@ Component.register('vrpayment-order-action-refund-partial', {
createdComponent() {
this.isLoading = false;
this.currency = this.transactionData.transactions[0].currency;
if (!this.refundAmount) {
this.refundAmount = this.$parent.$parent.itemRefundableAmount;
}
},
createPartialRefund(itemUniqueId) {
@@ -71,9 +69,18 @@ Component.register('vrpayment-order-action-refund-partial', {
});
}).catch((errorResponse) => {
try {
var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle')
var errorMessage;
switch(errorResponse.response.data) {
case 'methodDoesNotSupportRefund':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund');
break;
default:
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) {
@@ -5,12 +5,12 @@
{% block vrpayment_order_action_refund_confirm_button_selected %}
<template #modal-footer>
<mt-button variant="primary" @click="refundSelected()">
<sw-button variant="primary" @click="refundSelected()">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</mt-button>
</sw-button>
</template>
{% endblock %}
<mt-loader v-if="isLoading"></mt-loader>
<sw-loader v-if="isLoading"></sw-loader>
</sw-modal>
{% endblock %}
@@ -70,9 +70,18 @@ Component.register('vrpayment-order-action-refund-selected', {
});
}).catch((errorResponse) => {
try {
var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle')
var errorMessage;
switch(errorResponse.response.data) {
case 'methodDoesNotSupportRefund':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund');
break;
default:
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) {
@@ -5,12 +5,13 @@
{% block vrpayment_order_action_refund_amount %}
<mt-number-field
<sw-number-field
:max="this.$parent.$parent.itemRefundableQuantity"
:min="0"
v-model="refundQuantity"
v-model:value="refundQuantity"
number-type="int"
:label="$tc('vrpayment-order.refund.refundQuantity.label')">
</mt-number-field>
</sw-number-field>
<div>
{{ $tc('vrpayment-order.refundAction.maxAvailableItemsToRefund') }}:
@@ -20,12 +21,12 @@
{% block vrpayment_order_action_refund_confirm_button %}
<template #modal-footer>
<mt-button variant="primary" @click="refund()">
<sw-button variant="primary" @click="refund()">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</mt-button>
</sw-button>
</template>
{% endblock %}
<mt-loader v-if="isLoading"></mt-loader>
<sw-loader v-if="isLoading"></sw-loader>
</sw-modal>
{% endblock %}
@@ -68,9 +68,24 @@ Component.register('vrpayment-order-action-refund', {
});
}).catch((errorResponse) => {
try {
var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle')
var errorMessage;
switch(errorResponse.response.data) {
case 'refundQuantityZero':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messageRefundQuantityIsZero');
break;
case 'refundExceedsQuantity':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messageRefundQuantityExceedsAvailableBalance');
break;
case 'methodDoesNotSupportRefund':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund');
break;
default:
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) {
@@ -4,22 +4,21 @@
@modal-close="$emit('modal-close')">
{% block vrpayment_order_action_void_amount %}
{# Review if this v-model:checked="isVoid" needs to change to checked #}
<mt-checkbox
<sw-checkbox-field
:label="$tc('vrpayment-order.voidAction.confirm.message')"
v-model:checked="isVoid">
</mt-checkbox>
v-model:value="isVoid">
</sw-checkbox-field>
{% endblock %}
{% block vrpayment_order_action_void_confirm_button %}
<template #modal-footer>
<mt-button variant="primary"
<sw-button variant="primary"
@click="voidPayment">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</mt-button>
</sw-button>
</template>
{% endblock %}
<mt-loader v-if="isLoading"></mt-loader>
<sw-loader v-if="isLoading"></sw-loader>
</sw-modal>
{% endblock %}
@@ -1,7 +1,6 @@
{% 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 #}
<sw-tabs-item v-if="isVRPaymentPayment"
:route="{ name: 'vrpayment.order.detail', params: { id: $route.params.id } }"
:title="$tc('vrpayment-order.header')">
@@ -3,7 +3,7 @@
margin-top: 40px;
}
.sw-order-detail-base .mt-card-view__content {
.sw-order-detail-base .sw-card-view__content {
overflow-x: visible;
overflow-y: visible;
}
@@ -1,61 +1,61 @@
{% block vrpayment_order_detail %}
<div class="vrpayment-order-detail">
<div v-if="!isLoading">
<mt-card :title="$tc('vrpayment-order.paymentDetails.cardTitle')">
<sw-card :title="$tc('vrpayment-order.paymentDetails.cardTitle')">
<template #grid>
{% block vrpayment_order_actions_section %}
<mt-card-section secondary slim>
<sw-card-section secondary slim>
{% block vrpayment_order_transaction_refunds_action_button %}
<mt-button
<sw-button
variant="primary"
size="small"
:disabled="transaction.state != 'FULFILL' || refundableAmount <= 0"
@click="spawnModal('refundByAmount')">
{{ $tc('vrpayment-order.buttons.label.refund') }}
</mt-button>
</sw-button>
{% endblock %}
{% block vrpayment_order_transaction_completion_action_button %}
<mt-button
<sw-button
variant="primary"
size="small"
:disabled="transaction.state != 'AUTHORIZED' || isLoading"
@click="spawnModal('completion')">
{{ $tc('vrpayment-order.buttons.label.completion') }}
</mt-button>
</sw-button>
{% endblock %}
{% block vrpayment_order_transaction_void_action_button %}
<mt-button
<sw-button
variant="primary"
size="small"
:disabled="transaction.state != 'AUTHORIZED' || isLoading"
@click="spawnModal('void')">
{{ $tc('vrpayment-order.buttons.label.void') }}
</mt-button>
</sw-button>
{% endblock %}
{% block vrpayment_order_transaction_download_invoice_action_button %}
<mt-button
<sw-button
variant="primary"
size="small"
:disabled="transaction.state != 'FULFILL'"
@click="downloadInvoice()">
{{ $tc('vrpayment-order.buttons.label.download-invoice') }}
</mt-button>
</sw-button>
{% endblock %}
{% block vrpayment_order_transaction_download_packing_slip_action_button %}
<mt-button
<sw-button
variant="primary"
size="small"
:disabled="transaction.state != 'FULFILL'"
@click="downloadPackingSlip()">
{{ $tc('vrpayment-order.buttons.label.download-packing-slip') }}
</mt-button>
</sw-button>
{% endblock %}
</mt-card-section>
</sw-card-section>
{% endblock %}
</template>
</mt-card>
</sw-card>
{% block vrpayment_order_transaction_history_card %}
<mt-card :title="$tc('vrpayment-order.transactionHistory.cardTitle')">
<sw-card :title="$tc('vrpayment-order.transactionHistory.cardTitle')">
<template #grid>
{% block vrpayment_order_transaction_history_grid %}
@@ -78,10 +78,10 @@
{% endblock %}
</template>
</mt-card>
</sw-card>
{% endblock %}
{% block vrpayment_order_transaction_line_items_card %}
<mt-card :title="$tc('vrpayment-order.lineItem.cardTitle')">
<sw-card :title="$tc('vrpayment-order.lineItem.cardTitle')">
<template #grid>
{% block vrpayment_order_transaction_line_items_grid %}
@@ -98,7 +98,7 @@
<template #actions="{ item }">
<sw-context-menu-item
:disabled="transaction.state != 'FULFILL' || item.refundableQuantity != item.quantity || item.refundableAmount == 0 || item.itemRefundedAmount > 0 || item.itemRefundedQuantity > 0"
@click="lineItemRefund(item.uniqueId)">
@click="lineItemRefund(item.uniqueId, item.quantity)">
{{ $tc('vrpayment-order.buttons.label.refund-whole-line-item') }}
</sw-context-menu-item>
@@ -131,10 +131,10 @@
</sw-data-grid>
{% endblock %}
</template>
</mt-card>
</sw-card>
{% endblock %}
{% block vrpayment_order_transaction_refunds_card %}
<mt-card :title="$tc('vrpayment-order.refund.cardTitle')" v-if="transactionData.refunds.length > 0">
<sw-card :title="$tc('vrpayment-order.refund.cardTitle')" v-if="transactionData.refunds.length > 0">
<template #grid>
{% block vrpayment_order_transaction_refunds_grid %}
@@ -147,7 +147,7 @@
{% endblock %}
</template>
</mt-card>
</sw-card>
{% endblock %}
{% block vrpayment_order_actions_modal_refund_partial %}
<vrpayment-order-action-refund-partial
@@ -195,6 +195,6 @@
</vrpayment-order-action-void>
{% endblock %}
</div>
<mt-loader v-if="isLoading"></mt-loader>
<sw-loader v-if="isLoading"></sw-loader>
</div>
{% endblock %}
@@ -332,12 +332,12 @@ Component.register('vrpayment-order-detail', {
this.modalType = '';
},
lineItemRefund(lineItemId) {
lineItemRefund(lineItemId, itemQuantity) {
this.isLoading = true;
this.VRPaymentRefundService.createRefund(
this.transactionData.transactions[0].metaData.salesChannelId,
this.transactionData.transactions[0].id,
0,
itemQuantity,
lineItemId
).then(() => {
this.createNotificationSuccess({
@@ -351,9 +351,18 @@ Component.register('vrpayment-order-detail', {
});
}).catch((errorResponse) => {
try {
var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle')
var errorMessage;
switch(errorResponse.response.data) {
case 'methodDoesNotSupportRefund':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund');
break;
default:
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) {
@@ -385,7 +394,7 @@ Component.register('vrpayment-order-detail', {
// Force the DOM to update before proceeding with the asynchronous operations
this.$nextTick(() => {
const refundPromises = this.selectedItems.map((item) => {
return this.lineItemRefundBulk(item.uniqueId); // Simulated refund action with delay
return this.lineItemRefundBulk(item.uniqueId, item.quantity); // Simulated refund action with delay
});
// Wait for all refund promises to complete
@@ -410,7 +419,7 @@ Component.register('vrpayment-order-detail', {
});
}
},
lineItemRefundBulk(lineItemId) {
lineItemRefundBulk(lineItemId, itemQuantity) {
return new Promise((resolve, reject) => {
this.VRPaymentRefundService.createRefund(
this.transactionData.transactions[0].metaData.salesChannelId,
@@ -427,9 +436,18 @@ Component.register('vrpayment-order-detail', {
})
.catch((errorResponse) => {
try {
var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle')
var errorMessage;
switch(errorResponse.response.data) {
case 'methodDoesNotSupportRefund':
errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund');
break;
default:
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) {
@@ -78,9 +78,13 @@
"successTitle": "Erfolg",
"maxAvailableItemsToRefund": "Maximal Verfügbare Artikel zum Erstatten",
"maxAvailableAmountToRefund": "Maximal verfügbarer Erstattungsbetrag",
"refundExceedsTotalError": {
"title": "Fehler beim Erstellen der Rückerstattung.",
"messageRefundAmountExceedsAvailableBalance": "Der Rückerstattungsbetrag übersteigt das verfügbare Guthaben."
"refundCreateError": {
"errorTitle": "Fehler beim Erstellen der Rückerstattung.",
"messageRefundAmountExceedsAvailableBalance": "Der Rückerstattungsbetrag übersteigt das verfügbare Guthaben.",
"messageRefundAmountIsZero": "Der Rückerstattungsbetrag muss größer als 0 sein.",
"messageRefundQuantityExceedsAvailableBalance": "Rückerstattung nach Menge überschreitet die maximal verfügbare Anzahl an Artikeln zur Rückerstattung.",
"messageRefundQuantityIsZero": "Rückerstattung nach Menge muss größer als 0 sein.",
"messagePaymentMethodDoesNotSupportRefund": "Die Zahlungsmethode unterstützt keine Online-Rückerstattungen."
}
},
"transactionHistory": {
@@ -9,7 +9,6 @@
"void": "Cancel authorization",
"refund-whole-line-item": "Refund whole line item",
"refund-line-item-by-quantity": "Refund by quantity",
"refund-line-item-selected": "Rembourser sélectionnés",
"refund-line-item-selected": "Refund selected",
"refund-line-item-parial": "Partial refund"
}
@@ -79,9 +78,13 @@
"successTitle": "Success",
"maxAvailableItemsToRefund": "Maximum available items to refund",
"maxAvailableAmountToRefund": "Maximum available amount to refund",
"refundExceedsTotalError": {
"title": "Error while creating the refund.",
"messageRefundAmountExceedsAvailableBalance": "Refund amount exceeds available balance."
"refundCreateError": {
"errorTitle": "Error while creating the refund.",
"messageRefundAmountExceedsAvailableBalance": "Refund amount exceeds available balance.",
"messageRefundAmountIsZero": "Refund amount must be greater than 0.",
"messageRefundQuantityExceedsAvailableBalance": "Refund by quantity exceeds maximum available items to refund.",
"messageRefundQuantityIsZero": "Refund by quantity must be greater than 0.",
"messagePaymentMethodDoesNotSupportRefund": "Payment method does not support online refunds."
}
},
"transactionHistory": {
@@ -78,9 +78,13 @@
"successTitle": "Succès",
"maxAvailableItemsToRefund": "Nombre maximum d'articles disponibles 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."
"refundCreateError": {
"errorTitle": "Erreur lors de la création du remboursement.",
"messageRefundAmountExceedsAvailableBalance": "Le montant du remboursement dépasse le solde disponible.",
"messageRefundAmountIsZero": "Le montant du remboursement doit être supérieur à 0.",
"messageRefundQuantityExceedsAvailableBalance": "Le remboursement par quantité dépasse le nombre maximal darticles remboursables.",
"messageRefundQuantityIsZero": "Le remboursement par quantité doit être supérieur à 0.",
"messagePaymentMethodDoesNotSupportRefund": "Le mode de paiement ne prend pas en charge les remboursements en ligne."
}
},
"transactionHistory": {
@@ -78,9 +78,13 @@
"successTitle": "Successo",
"maxAvailableItemsToRefund": "Numero massimo di articoli disponibili da rimborsare",
"maxAvailableAmountToRefund": "Importo massimo disponibile per il rimborso",
"refundExceedsTotalError": {
"title": "Errore durante la creazione del rimborso.",
"messageRefundAmountExceedsAvailableBalance": "LL'importo del rimborso supera il saldo disponibile."
"refundCreateError": {
"errorTitle": "Errore durante la creazione del rimborso.",
"messageRefundAmountExceedsAvailableBalance": "LL'importo del rimborso supera il saldo disponibile.",
"messageRefundAmountIsZero": "L'importo del rimborso deve essere superiore a 0.",
"messageRefundQuantityExceedsAvailableBalance": "Il rimborso per quantità supera il numero massimo di articoli rimborsabili.",
"messageRefundQuantityIsZero": "Il rimborso per quantità deve essere maggiore di 0.",
"messagePaymentMethodDoesNotSupportRefund": "Il metodo di pagamento non supporta i rimborsi online."
}
},
"transactionHistory": {
@@ -1,4 +1,4 @@
<mt-card class="mt-card"
<sw-card class="sw-card"
:title="$tc('vrpayment-settings.settingForm.advancedOptions.cardTitle')">
<sw-container>
<div v-if="actualConfigData" class="vrpayment-settings-advanced-options-fields">
@@ -7,16 +7,16 @@
:inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_STOREFRONT_WEBHOOKS_UPDATE_ENABLED]"
:customInheritationCheckFunction="checkBoolFieldInheritance">
<template #content="props">
<mt-switch
<sw-switch-field
:name="CONFIG_STOREFRONT_WEBHOOKS_UPDATE_ENABLED"
bordered
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.advancedOptions.webhooksUpdateEnabled.label')"
:helpText="$tc('vrpayment-settings.settingForm.advancedOptions.webhooksUpdateEnabled.tooltipText')"
:disabled="props.isInherited"
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
</template>
</sw-inherit-wrapper>
@@ -25,19 +25,19 @@
:inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_STOREFRONT_PAYMENTS_UPDATE_ENABLED]"
:customInheritationCheckFunction="checkBoolFieldInheritance">
<template #content="props">
<mt-switch
<sw-switch-field
:name="CONFIG_STOREFRONT_PAYMENTS_UPDATE_ENABLED"
bordered
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.advancedOptions.paymentsUpdateEnabled.label')"
:helpText="$tc('vrpayment-settings.settingForm.advancedOptions.paymentsUpdateEnabled.tooltipText')"
:disabled="props.isInherited"
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
</template>
</sw-inherit-wrapper>
</div>
</sw-container>
</mt-card>
</sw-card>
@@ -1,6 +1,6 @@
{% block vrpayment_settings_content_card_channel_config_credentials %}
<mt-card
class="mt-card"
<sw-card
class="sw-card"
:title="$tc('vrpayment-settings.settingForm.credentials.cardTitle')"
v-if="actualConfigData"
>
@@ -14,20 +14,20 @@
{% block vrpayment_settings_content_card_channel_config_credentials_card_container_settings_space_id %}
<sw-inherit-wrapper
v-model:value="actualConfigData[CONFIG_SPACE_ID]"
:inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_SPACE_ID]"
:inheritedValue="getInheritedValue(CONFIG_SPACE_ID)"
:customInheritationCheckFunction="checkNumberFieldInheritance">
<template #content="props">
<mt-number-field
<sw-number-field
:name="CONFIG_SPACE_ID"
:required="true"
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.credentials.spaceId.label')"
:helpText="$tc('vrpayment-settings.settingForm.credentials.spaceId.tooltipText')"
:disabled="props.isInherited || !acl.can('vrpayment.editor')"
:model-value="props.currentValue"
:disabled="!acl.can('vrpayment.editor')"
:value="props.currentValue"
:error="spaceIdErrorState"
@update:model-value="props.updateCurrentValue">
</mt-number-field>
@update:value="props.updateCurrentValue">
</sw-number-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -35,20 +35,20 @@
{% block vrpayment_settings_content_card_channel_config_credentials_card_container_settings_user_id %}
<sw-inherit-wrapper
v-model:value="actualConfigData[CONFIG_USER_ID]"
:inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_USER_ID]"
:inheritedValue="getInheritedValue(CONFIG_USER_ID)"
:customInheritationCheckFunction="checkNumberFieldInheritance">
<template #content="props">
<mt-number-field
<sw-number-field
:name="CONFIG_USER_ID"
:required="true"
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.credentials.userId.label')"
:helpText="$tc('vrpayment-settings.settingForm.credentials.userId.tooltipText')"
:disabled="props.isInherited || !acl.can('vrpayment.editor')"
:model-value="props.currentValue"
:disabled="!acl.can('vrpayment.editor')"
:value="props.currentValue"
:error="userIdErrorState"
@update:model-value="props.updateCurrentValue">
</mt-number-field>
@update:value="props.updateCurrentValue">
</sw-number-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -56,40 +56,37 @@
{% block vrpayment_settings_content_card_channel_config_credentials_card_container_settings_application_key %}
<sw-inherit-wrapper
v-model:value="actualConfigData[CONFIG_APPLICATION_KEY]"
:inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_APPLICATION_KEY]"
:inheritedValue="getInheritedValue(CONFIG_APPLICATION_KEY)"
:customInheritationCheckFunction="checkTextFieldInheritance">
<template #content="props">
<mt-password-field
<sw-password-field
:name="CONFIG_APPLICATION_KEY"
:required="true"
:passwordToggleAble="true"
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.credentials.applicationKey.label')"
:helpText="$tc('vrpayment-settings.settingForm.credentials.applicationKey.tooltipText')"
:disabled="props.isInherited || !acl.can('vrpayment.editor')"
:model-value="props.currentValue"
:disabled="!acl.can('vrpayment.editor')"
:value="props.currentValue"
:error="applicationKeyErrorState"
@update:model-value="props.updateCurrentValue">
</mt-password-field>
@update:value="props.updateCurrentValue">
</sw-password-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
</div>
{% endblock %}
{% verbatim %}
<sw-container columns="1fr 1fr" gap="0px 30px">
<mt-button
variant="primary"
<sw-button-process
:isLoading="isTesting"
@click="emitCheckApiConnectionEvent">
{{ $tc('vrpayment-settings.settingForm.credentials.button.label') }}
</mt-button>
</sw-button-process>
</sw-container>
{% endverbatim %}
</sw-container>
{% endblock %}
</mt-card>
</sw-card>
{% endblock %}
@@ -6,7 +6,7 @@ import constants from '../../page/vrpayment-settings/configuration-constants'
const {Component, Mixin} = Shopware;
Component.register('sw-vrpayment-credentials', {
template: template,
template,
name: 'VRPaymentCredentials',
@@ -29,7 +29,9 @@ Component.register('sw-vrpayment-credentials', {
},
selectedSalesChannelId: {
required: true
type: [String, null],
required: false,
default: null
},
spaceIdFilled: {
type: Boolean,
@@ -68,22 +70,24 @@ Component.register('sw-vrpayment-credentials', {
};
},
computed: {
currentConfig() {
if (this.selectedSalesChannelId && this.allConfigs[this.selectedSalesChannelId]) {
return this.allConfigs[this.selectedSalesChannelId];
}
return this.allConfigs['null'] || {};
}
},
methods: {
checkTextFieldInheritance(value) {
if (typeof value !== 'string') {
return true;
}
return value.length <= 0;
return !value || value.length <= 0;
},
checkNumberFieldInheritance(value) {
if (typeof value !== 'number') {
return true;
}
return value.length <= 0;
return value == null || value === '';
},
checkBoolFieldInheritance(value) {
@@ -94,12 +98,16 @@ Component.register('sw-vrpayment-credentials', {
// Used to trigger API connection testing from this component.
emitCheckApiConnectionEvent() {
const apiConnectionParams = {
spaceId: this.actualConfigData[constants.CONFIG_SPACE_ID],
userId: this.actualConfigData[constants.CONFIG_USER_ID],
applicationKey: this.actualConfigData[constants.CONFIG_APPLICATION_KEY]
spaceId: this.currentConfig[constants.CONFIG_SPACE_ID],
userId: this.currentConfig[constants.CONFIG_USER_ID],
applicationKey: this.currentConfig[constants.CONFIG_APPLICATION_KEY]
};
this.$emit('check-api-connection-event', apiConnectionParams);
},
getInheritedValue(key) {
return this.allConfigs['null']?.[key] ?? null;
}
}
});
@@ -1,5 +1,5 @@
{% block vrpayment_settings_content_card_channel_config_options %}
<mt-card class="mt-card"
<sw-card class="sw-card"
:title="$tc('vrpayment-settings.settingForm.options.cardTitle')">
{% 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">
<template #content="props">
<mt-number-field
<sw-number-field
:name="CONFIG_SPACE_VIEW_ID"
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.options.spaceViewId.label')"
:helpText="$tc('vrpayment-settings.settingForm.options.spaceViewId.tooltipText')"
:disabled="props.isInherited"
:model-value="props.currentValue"
@update:model-value="props.updateCurrentValue">
</mt-number-field>
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-number-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -55,16 +55,16 @@
:inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_LINE_ITEM_CONSISTENCY_ENABLED]"
:customInheritationCheckFunction="checkBoolFieldInheritance">
<template #content="props">
<mt-switch
<sw-switch-field
:name="CONFIG_LINE_ITEM_CONSISTENCY_ENABLED"
bordered
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.options.lineItemConsistencyEnabled.label')"
:helpText="$tc('vrpayment-settings.settingForm.options.lineItemConsistencyEnabled.tooltipText')"
:disabled="props.isInherited"
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -75,16 +75,16 @@
:inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_EMAIL_ENABLED]"
:customInheritationCheckFunction="checkBoolFieldInheritance">
<template #content="props">
<mt-switch
<sw-switch-field
:name="CONFIG_EMAIL_ENABLED"
bordered
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.options.emailEnabled.label')"
:helpText="$tc('vrpayment-settings.settingForm.options.emailEnabled.tooltipText')"
:disabled="props.isInherited"
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -92,6 +92,6 @@
{% endblock %}
</sw-container>
{% endblock %}
</mt-card>
</sw-card>
{% endblock %}
@@ -1,5 +1,5 @@
{% block vrpayment_settings_icon %}
<span class="mt-icon icon--vrpayment-multicolor mt-icon--multicolor" style="width: 16px; height: 16px;">
<span class="sw-icon icon--vrpayment-multicolor sw-icon--multicolor">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" contentScriptType="text/ecmascript" y="0px" zoomAndPan="magnify" style="enable-background:new 0 0 632.126 170.079;" contentStyleType="text/css" viewBox="0 0 632.126 170.079" preserveAspectRatio="xMidYMid meet" xml:space="preserve" version="1.1">
<style type="text/css" xml:space="preserve">
.st0{fill:none;}
@@ -1,4 +1,4 @@
<mt-card class="mt-card"
<sw-card class="sw-card"
:title="$tc('vrpayment-settings.settingForm.storefrontOptions.cardTitle')">
<sw-container>
<div v-if="actualConfigData" class="vrpayment-settings-storefront-options-fields">
@@ -7,19 +7,19 @@
:inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_STOREFRONT_INVOICE_DOWNLOAD_ENABLED]"
:customInheritationCheckFunction="checkBoolFieldInheritance">
<template #content="props">
<mt-switch
<sw-switch-field
:name="CONFIG_STOREFRONT_INVOICE_DOWNLOAD_ENABLED"
bordered
:mapInheritance="props"
:label="$tc('vrpayment-settings.settingForm.storefrontOptions.invoiceDownloadEnabled.label')"
:helpText="$tc('vrpayment-settings.settingForm.storefrontOptions.invoiceDownloadEnabled.tooltipText')"
:disabled="props.isInherited"
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
</template>
</sw-inherit-wrapper>
</div>
</sw-container>
</mt-card>
</sw-card>
@@ -1,6 +1,6 @@
{% block vrpayment_settings %}
<sw-page class="vrpayment-settings">
<sw-page class="vrpayment-settings">
{% block vrpayment_settings_header %}
<template #smart-bar-header>
<h2>
@@ -45,15 +45,14 @@
<mt-card title="Sales Channel Switch">
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_title %}
<sw-entity-single-select
v-model:value="selectedSalesChannelId"
labelProperty="translated.name"
<sw-single-select
:value="selectedSalesChannelId"
:options="salesChannel.map(sc => ({ id: sc.id, name: sc.translated.name }))"
labelProperty="name"
valueProperty="id"
:mapInheritance="props"
:isLoading="isLoading"
entity="sales_channel"
@update:value="onInput">
</sw-entity-single-select>
@update:value="onInput"
/>
{% endblock %}
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer %}
<template #footer>
@@ -65,10 +65,22 @@ 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) {
const defaultConfig = this.$refs.configComponent.allConfigs.null;
const defaultConfig = (this.$refs.configComponent.allConfigs || {}).null || {};
const salesChannelId = this.$refs.configComponent.selectedSalesChannelId;
if (salesChannelId === null) {
File diff suppressed because one or more lines are too long
@@ -10,6 +10,7 @@
<service id="VRPaymentPayment\Core\Api\Refund\Controller\RefundController" public="true">
<argument type="service" id="VRPaymentPayment\Core\Api\Refund\Service\RefundService"/>
<argument type="service" id="VRPaymentPayment\Core\Settings\Service\SettingsService"/>
<argument type="service" id="VRPaymentPayment\Core\Api\Transaction\Service\TransactionService"/>
<call method="setLogger">
<argument type="service" id="monolog.logger.vrpayment_payment"/>
</call>
@@ -6,21 +6,12 @@
<services>
<service id="VRPaymentPayment\Core\Checkout\PaymentHandler\VRPaymentPaymentHandler">
<argument type="service" id="VRPaymentPayment\Core\Checkout\Cart\CustomCartPersister"/>
<argument type="service" id="VRPaymentPayment\Core\Api\Transaction\Service\TransactionService"/>
<argument type="service" id="Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler"/>
<argument type="service" id="Shopware\Core\System\SalesChannel\Context\SalesChannelContextService"/>
<argument type="service" id="order_transaction.repository"/>
<call method="setLogger">
<argument type="service" id="monolog.logger.vrpayment_payment"/>
</call>
<tag name="shopware.payment.method"/>
</service>
<service id="VRPaymentPayment\Core\Checkout\Cart\CustomCartPersister"
decorates="Shopware\Core\Checkout\Cart\CartPersister"
decoration-inner-name="VRPaymentPayment\Core\Checkout\Cart\CustomCartPersister.inner">
<argument type="service" id="VRPaymentPayment\Core\Checkout\Cart\CustomCartPersister.inner"/>
<tag name="shopware.payment.method.async"/>
</service>
</services>
@@ -13,16 +13,18 @@
<argument type="service" id="VRPaymentPayment\Core\Api\Transaction\Service\TransactionService"/>
<argument type="service" id="Shopware\Storefront\Page\GenericPageLoader"/>
<argument type="service" id="Shopware\Core\Checkout\Order\SalesChannel\OrderRoute"/>
<argument type="service" id="Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler"/>
<argument type="service" id="Shopware\Core\System\StateMachine\StateMachineRegistry"/>
<argument type="service" id="Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface"/>
<call method="setLogger">
<argument type="service" id="monolog.logger.vrpayment_payment"/>
</call>
<call method="setContainer">
<argument type="service" id="service_container"/>
</call>
<!-- Removed in 6.7 -->
<!-- <call method="setTwig">
<call method="setTwig">
<argument type="service" id="twig"/>
</call> -->
</call>
</service>
<!-- Subscribers -->
@@ -31,6 +33,7 @@
<argument id="VRPaymentPayment\Core\Api\Transaction\Service\TransactionService" type="service"/>
<argument id="VRPaymentPayment\Core\Settings\Service\SettingsService" type="service"/>
<argument id="VRPaymentPayment\Core\Util\PaymentMethodUtil" type="service"/>
<argument id="payment_method.repository" type="service"/>
<call method="setLogger">
<argument type="service" id="monolog.logger.vrpayment_payment"/>
</call>
BIN
View File
Binary file not shown.
Binary file not shown.
@@ -1,25 +0,0 @@
{
"base": "/bundles/vrpaymentpayment/administration/",
"entryPoints": {
"v-r-payment-payment": {
"css": [
"/bundles/vrpaymentpayment/administration/assets/v-r-payment-payment-D4AH6HY2.css"
],
"dynamic": [],
"js": [
"/bundles/vrpaymentpayment/administration/assets/v-r-payment-payment-C6eiDWfX.js"
],
"legacy": false,
"preload": []
}
},
"legacy": false,
"metadatas": {},
"version": [
"7.1.0",
7,
1,
0
],
"viteServer": null
}
@@ -1,11 +0,0 @@
{
"main.js": {
"file": "assets/v-r-payment-payment-C6eiDWfX.js",
"name": "v-r-payment-payment",
"src": "main.js",
"isEntry": true,
"css": [
"assets/v-r-payment-payment-D4AH6HY2.css"
]
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
.sw-order-detail .sw-tabs{margin-top:40px}.sw-order-detail .sw-order-detail-base .mt-card-view__content{overflow-x:visible;overflow-y:visible}.vrpayment-order-detail__data{display:grid}.vrpayment-order-detail__heading{padding-top:15px}
@@ -0,0 +1,2 @@
.sw-order-detail .sw-tabs{margin-top:40px}.sw-order-detail .sw-order-detail-base .sw-card-view__content{overflow-x:visible;overflow-y:visible}
.vrpayment-order-detail__data{display:grid}.vrpayment-order-detail__heading{padding-top:15px}
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -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();
@@ -1,9 +1,13 @@
{% 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 %}
<div id="vrpaymentOrderCancel"></div>
{% block page_checkout_pay %}
{% block page_checkout_confirm_header %}
<h1 class="confirm-main-header">
@@ -140,6 +144,10 @@
</div>
{% endblock %}
{% block base_footer %}
{% sw_include '@Storefront/storefront/layout/footer/footer-minimal.html.twig' %}
{% endblock %}
{% block base_body_script %}
{{ parent() }}
{% if page.extensions.vRPaymentData %}
@@ -0,0 +1,53 @@
{% sw_extends '@Storefront/storefront/layout/header/header-minimal.html.twig' %}
{% block layout_header_minimal_logo %}
<div class="col-6 col-md-4 header-minimal-logo">
{% block layout_header_logo_inner %}
<div class="header-logo-main">
{% block layout_header_logo_link %}
<a class="header-logo-main-link"
id="vrpaymentHomeLink"
href="{{ path('frontend.home.page') }}"
title="{{ "header.logoLink"|trans|striptags }}">
{% block layout_header_logo_image %}
<picture class="header-logo-picture">
{% block layout_header_logo_image_tablet %}
{% if theme_config('sw-logo-tablet') and theme_config('sw-logo-tablet') != theme_config('sw-logo-desktop') %}
<source srcset="{{ theme_config('sw-logo-tablet') |sw_encode_url }}"
media="(min-width: {{ theme_config('breakpoint.md') }}px) and (max-width: {{ theme_config('breakpoint.lg') - 1 }}px)">
{% endif %}
{% endblock %}
{% block layout_header_logo_image_mobile %}
{% if theme_config('sw-logo-mobile') and theme_config('sw-logo-mobile') != theme_config('sw-logo-desktop') %}
<source srcset="{{ theme_config('sw-logo-mobile') |sw_encode_url }}"
media="(max-width: {{ theme_config('breakpoint.md') - 1 }}px)">
{% endif %}
{% endblock %}
{% block layout_header_logo_image_default %}
{% if theme_config('sw-logo-desktop') %}
<img src="{{ theme_config('sw-logo-desktop') |sw_encode_url }}"
alt="{{ "header.logoLink"|trans|striptags }}"
class="img-fluid header-logo-main-img"/>
{% endif %}
{% endblock %}
</picture>
{% endblock %}
</a>
{% endblock %}
</div>
{% endblock %}
</div>
{% endblock %}
{% block layout_header_minimal_button %}
<div class="col-md-4 header-minimal-back-to-shop">
<button type="button"
id="vrpaymentOrderCancel"
class="btn btn-outline-primary header-minimal-back-to-shop-button"
title="{{ "checkout.finishButtonBackToShop"|trans|striptags }}">
{{ "checkout.finishButtonBackToShop"|trans|striptags }}
</button>
</div>
{% endblock %}
+3 -7
View File
@@ -3,7 +3,6 @@
namespace VRPaymentPayment;
use Shopware\Core\{
Framework\Feature,
Framework\Plugin,
Framework\Plugin\Context\ActivateContext,
Framework\Plugin\Context\DeactivateContext,
@@ -22,7 +21,6 @@ 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')) {
@@ -84,21 +82,19 @@ class VRPaymentPayment extends Plugin {
{
parent::build($container);
$confDir = \rtrim($this->getPath(), '/') . '/Resources/config';
$locator = new FileLocator($confDir);
$locator = new FileLocator('Resources/config');
$resolver = new LoaderResolver([
new YamlFileLoader($container, $locator),
new XmlFileLoader($container, $locator),
new GlobFileLoader($container, $locator),
new DirectoryLoader($container, $locator),
]);
$configLoader = new DelegatingLoader($resolver);
$configLoader->load($confDir . '/{packages}/*.yaml', 'glob');
$confDir = \rtrim($this->getPath(), '/') . '/Resources/config';
$configLoader->load('services/core/checkout.xml');
$configLoader->load($confDir . '/{packages}/*.yaml', 'glob');
}
public function enrichPrivileges(): array