Compare commits

...

4 Commits

Author SHA1 Message Date
andrewrowanwallee 55bdb5c640 Release 7.1.5 2025-11-11 13:52:29 +01:00
andrewrowanwallee d1a78fedcf Release 7.1.4 2025-10-30 16:49:17 +01:00
andrewrowanwallee d7ea44d506 Release 7.1.3 2025-10-27 12:47:17 +01:00
andrewrowanwallee fa480808b9 Release 7.1.2 2025-10-06 12:23:20 +02:00
39 changed files with 1004 additions and 438 deletions
+19
View File
@@ -1,3 +1,22 @@
# 7.1.5
- Improved analytics
- Improved error handling for refunding amount 0 and too many items
# 7.1.4
- Updated SDK to 4.8.1
# 7.1.3
- Fixed issue with radio button/switch settings not saving
- Fixed issue with error screen sporadically happening after failed payments
# 7.1.2
- Support the ability to have different spaces for differet sales channels
- Fixed issue where Twint would not appear sometimes
# 7.1.1
- Updated documentation
- Fixed issue with addresses not being correctly synced
# 7.1.0
## Feature
- Support subscription payment methods
+19
View File
@@ -1,3 +1,22 @@
# 7.1.5
- Verbesserte Analysefunktionen
- Verbesserte Fehlerbehandlung bei Rückerstattungen von 0 Beträgen und zu vielen Artikeln
# 7.1.4
- Aktualisiertes SDK - 4.8.1
# 7.1.3
Problem behoben, bei dem die Einstellungen von Optionsfeldern/Schaltern nicht gespeichert wurden.
Problem behoben, bei dem nach fehlgeschlagenen Zahlungen sporadisch ein Fehlerbildschirm angezeigt wurde.
# 7.1.2
- Unterstützung der Möglichkeit, unterschiedliche Bereiche für verschiedene Vertriebskanäle zu nutzen.
- Problem behoben, bei dem Twint manchmal nicht angezeigt wurde.
# 7.1.1
- Dokumentation aktualisiert
- Problem behoben, bei dem Adressen nicht korrekt synchronisiert wurden.
# 7.1.0
Unterstützung für Abonnement-Zahlungsmethoden
Support für Shopware 6.7.2.0
+13 -4
View File
@@ -13,10 +13,10 @@ Please note that this plugin is for versions 6.5, 6.6 or 6.7. For the 6.4 plugin
## Documentation
- For English documentation click [here](@WalleeDocPath(/docs/en/documentation.html))
- Für die deutsche Dokumentation klicken Sie [hier](@WalleeDocPath(/docs/de/documentation.html))
- Pour la documentation Française, cliquez [ici](@WalleeDocPath(/docs/fr/documentation.html))
- Per la documentazione in tedesco, clicca [qui](@WalleeDocPath(/docs/it/documentation.html))
- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.5/docs/en/documentation.html)
- Für die deutsche Dokumentation klicken Sie [hier](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.5/docs/de/documentation.html)
- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.5/docs/fr/documentation.html)
- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.1.5/docs/it/documentation.html)
## Installation
@@ -48,6 +48,15 @@ bin/console plugin:install --activate --clearCache VRPayment
1. Navigate to Shopware Admin > Settings > VRPayment.
2. Enter your Space ID, User ID, and API Key (obtained from the [VR Payment Portal](https://gateway.vr-payment.de/)).
### VRPayment does not appear in Settings
1. You should run the following commmand
```bash
Copy
bin/build-administration.sh
```
### Payment Methods
Configure supported methods (e.g., credit cards, Apple Pay) via the [VR Payment Portal](https://gateway.vr-payment.de/).
+1 -1
View File
@@ -59,5 +59,5 @@
"vrpayment/sdk": "^4.0.0"
},
"type": "shopware-platform-plugin",
"version": "7.1.1"
"version": "7.1.5"
}
+20 -2
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="@WalleeCanonicalPath(https://plugin-documentation.wallee.com/wallee-payment, VRPaymentPayment/docs/de/documentation.html)" />
<link rel="canonical" href="https://plugin-documentation.wallee.com/wallee-payment/shopware-6/master/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="@WalleeReleasePath()">
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.1.5/">
Source
</a>
</li>
@@ -183,6 +183,19 @@ php bin/console plugin:install --activate --clearCache VRPayment</code></pre>
</li>
</ol>
</div> </div>
</div> <div class="section" id="_vrpayment_erscheint_nicht_in_den_einstellungen">
<div class="section-title">
<h2>
<span class="title-number">4.4</span>VRPayment erscheint nicht in den Einstellungen </h2>
</div>
<div class="section-body">
<div class="paragraph">
<p>Folgender Befehl muss ausgeführt werden</p>
</div><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">bin/build-administration.sh</code></pre>
</div>
</div> </div>
</div> </div>
</div> <div class="chapter" id="portal-startup-guide">
<div class="chapter-title">
@@ -888,6 +901,11 @@ A: Ja, das Plugin unterstützt Wallets wie Apple Pay.</p>
<span class="item-number">4.3</span>
<span class="item-title">Via Composer (Recommended)</span>
</a>
</li> <li class="nav-level-2">
<a href="#_vrpayment_erscheint_nicht_in_den_einstellungen">
<span class="item-number">4.4</span>
<span class="item-title">VRPayment erscheint nicht in den Einstellungen</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
+20 -2
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="@WalleeCanonicalPath(https://plugin-documentation.wallee.com/wallee-payment, VRPaymentPayment/docs/en/documentation.html)" />
<link rel="canonical" href="https://plugin-documentation.wallee.com/wallee-payment/shopware-6/master/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="@WalleeReleasePath()">
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.1.5/">
Source
</a>
</li>
@@ -179,6 +179,19 @@ php bin/console plugin:install --activate --clearCache VRPayment</code></pre>
</li>
</ol>
</div> </div>
</div> <div class="section" id="_vrpayment_does_not_appear_in_settings">
<div class="section-title">
<h2>
<span class="title-number">4.4</span>VRPayment does not appear in Settings </h2>
</div>
<div class="section-body">
<div class="paragraph">
<p>You should run the following commmand</p>
</div><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">bin/build-administration.sh</code></pre>
</div>
</div> </div>
</div> </div>
</div> <div class="chapter" id="portal-startup-guide">
<div class="chapter-title">
@@ -905,6 +918,11 @@ tokenization, it can be used for subscriptions. The recurring payment is fully m
<span class="item-number">4.3</span>
<span class="item-title">Manual Installation</span>
</a>
</li> <li class="nav-level-2">
<a href="#_vrpayment_does_not_appear_in_settings">
<span class="item-number">4.4</span>
<span class="item-title">VRPayment does not appear in Settings</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
+20 -2
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="@WalleeCanonicalPath(https://plugin-documentation.wallee.com/wallee-payment, VRPaymentPayment/docs/fr/documentation.html)" />
<link rel="canonical" href="https://plugin-documentation.wallee.com/wallee-payment/shopware-6/master/VRPaymentPayment/docs/fr/documentation.html" />
<title>VR 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="@WalleeReleasePath()">
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.1.5/">
Source
</a>
</li>
@@ -170,6 +170,19 @@ php bin/console plugin:install --activate --clearCache VRPayment</code></pre>
php bin/console plugin:install --activate --clearCache VRPayment</code></pre>
</div>
</div> </div>
</div> <div class="section" id="_si_vrpayment_n_apparaît_pas_dans_les_paramètres">
<div class="section-title">
<h2>
<span class="title-number">4.4</span>Si VRPayment n&#8217;apparaît pas dans les paramètres </h2>
</div>
<div class="section-body">
<div class="paragraph">
<p>Vous devez exécuter la commande suivante</p>
</div><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">bin/build-administration.sh</code></pre>
</div>
</div> </div>
</div> </div>
</div> <div class="chapter" id="portal-startup-guide">
<div class="chapter-title">
@@ -876,6 +889,11 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.</p>
<span class="item-number">4.3</span>
<span class="item-title">Via Composer (Recommended)</span>
</a>
</li> <li class="nav-level-2">
<a href="#_si_vrpayment_n_apparaît_pas_dans_les_paramètres">
<span class="item-number">4.4</span>
<span class="item-title">Si VRPayment n&amp;#8217;apparaît pas dans les paramètres</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
+20 -2
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="@WalleeCanonicalPath(https://plugin-documentation.wallee.com/wallee-payment, VRPaymentPayment/docs/it/documentation.html)" />
<link rel="canonical" href="https://plugin-documentation.wallee.com/wallee-payment/shopware-6/master/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="@WalleeReleasePath()">
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.1.5/">
Source
</a>
</li>
@@ -177,6 +177,19 @@ php bin/console plugin:install --activate --clearCache VRPayment</code></pre>
</li>
</ol>
</div> </div>
</div> <div class="section" id="_vrpayment_non_appare_nelle_impostazioni">
<div class="section-title">
<h2>
<span class="title-number">4.4</span>VRPayment non appare nelle impostazioni </h2>
</div>
<div class="section-body">
<div class="paragraph">
<p>Dovrebbe eseguire il seguente comando</p>
</div><div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-bash" data-lang="bash">bin/build-administration.sh</code></pre>
</div>
</div> </div>
</div> </div>
</div> <div class="chapter" id="portal-startup-guide">
<div class="chapter-title">
@@ -887,6 +900,11 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.
<span class="item-number">4.3</span>
<span class="item-title">Installazione manuale</span>
</a>
</li> <li class="nav-level-2">
<a href="#_vrpayment_non_appare_nelle_impostazioni">
<span class="item-number">4.4</span>
<span class="item-title">VRPayment non appare nelle impostazioni</span>
</a>
</li> </ul>
</li> <li class="nav-level-1">
<a href="#portal-startup-guide">
@@ -251,9 +251,9 @@ class PaymentMethodConfigurationService {
{
$data = [];
$paymentMethodData = [];
$salesChannelPaymentMethodData = [];
$criteria = (new Criteria())->addFilter(new EqualsFilter('state', 'ACTIVE'));
$criteria = (new Criteria())->addFilter(new EqualsFilter('state', 'ACTIVE'))
->addFilter(new EqualsFilter('spaceId', $this->getSpaceId()));
/**
* @var $vRPaymentPMConfigurationRepository
@@ -344,40 +344,67 @@ class PaymentMethodConfigurationService {
$paymentMethodConfigurations = $this->getPaymentMethodConfigurations();
$this->logger->debug('Updating payment methods', $paymentMethodConfigurations);
/**
* @var $paymentMethodConfiguration \VRPayment\Sdk\Model\PaymentMethodConfiguration
*/
foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) {
$paymentMethodConfigurationEntity = $this->getPaymentMethodConfigurationEntity(
$paymentMethodConfiguration->getSpaceId(),
$paymentMethodConfiguration->getId(),
$context
$entity = $this->getPaymentMethodConfigurationEntity(
$paymentMethodConfiguration->getSpaceId(),
$paymentMethodConfiguration->getId(),
$context
);
$id = is_null($paymentMethodConfigurationEntity) ? Uuid::randomHex() : $paymentMethodConfigurationEntity->getId();
$configId = $entity ? $entity->getId() : Uuid::randomHex();
$technicalName = $paymentMethodConfiguration->getName();
$paymentMethodId = $this->getOrCreatePaymentMethodId(
$technicalName,
VRPaymentPaymentHandler::class,
$context
);
$data = [
'id' => $id,
'paymentMethodConfigurationId' => $paymentMethodConfiguration->getId(),
'paymentMethodId' => $id,
'data' => json_decode(strval($paymentMethodConfiguration), true),
'sortOrder' => $paymentMethodConfiguration->getSortOrder(),
'spaceId' => $paymentMethodConfiguration->getSpaceId(),
'state' => CreationEntityState::ACTIVE,
'id' => $configId,
'paymentMethodConfigurationId' => $paymentMethodConfiguration->getId(),
'paymentMethodId' => $paymentMethodId,
'data' => json_decode(strval($paymentMethodConfiguration), true),
'sortOrder' => $paymentMethodConfiguration->getSortOrder(),
'spaceId' => $paymentMethodConfiguration->getSpaceId(),
'state' => CreationEntityState::ACTIVE,
];
$this->upsertPaymentMethod($id, $paymentMethodConfiguration, $context);
try {
$this->container->get(PaymentMethodConfigurationEntityDefinition::ENTITY_NAME . '.repository')->upsert([$data], $context);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [$e->getTraceAsString()]);
}
try {
$this->upsertPaymentMethod($paymentMethodId, $paymentMethodConfiguration, $context);
$this->container
->get(PaymentMethodConfigurationEntityDefinition::ENTITY_NAME . '.repository')
->upsert([$data], $context);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [$e->getTraceAsString()]);
}
}
}
private function getOrCreatePaymentMethodId(string $technicalName, string $handlerIdentifier, Context $context): string
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('technicalName', $technicalName));
$criteria->setLimit(1);
$existing = $this->paymentMethodRepository->search($criteria, $context)->first();
if ($existing !== null) {
return $existing->getId();
}
$paymentMethodId = Uuid::randomHex();
$this->paymentMethodRepository->upsert([[
'id' => $paymentMethodId,
'handlerIdentifier' => $handlerIdentifier,
'technicalName' => $technicalName,
'name' => $technicalName,
'active' => false,
]], $context);
return $paymentMethodId;
}
/**
* Fetch active merchant payment methods from VRPayment API
*
@@ -467,53 +494,6 @@ class PaymentMethodConfigurationService {
return $configurations->getElements();
}
/**
* Update or insert Payment Method
*
* @param string $id
* @param \VRPayment\Sdk\Model\PaymentMethodConfiguration $paymentMethodConfiguration
* @param \Shopware\Core\Framework\Context $context
*
* @throws \VRPayment\Sdk\ApiException
* @throws \VRPayment\Sdk\Http\ConnectionException
* @throws \VRPayment\Sdk\VersioningException
*/
protected function upsertPaymentMethod(
string $id,
PaymentMethodConfiguration $paymentMethodConfiguration,
Context $context
): void
{
/** @var PluginIdProvider $pluginIdProvider */
$pluginIdProvider = $this->container->get(PluginIdProvider::class);
$pluginId = $pluginIdProvider->getPluginIdByBaseClass(
VRPaymentPayment::class,
$context
);
$data = [
'id' => $id,
'handlerIdentifier' => VRPaymentPaymentHandler::class,
'pluginId' => $pluginId,
'position' => $paymentMethodConfiguration->getSortOrder() - 100,
'afterOrderEnabled' => true,
'active' => true,
'translations' => $this->getPaymentMethodConfigurationTranslation($paymentMethodConfiguration, $context),
'technicalName' => $paymentMethodConfiguration->getName(),
];
$data['mediaId'] = $this->upsertMedia($id, $paymentMethodConfiguration, $context);
$data = array_filter($data);
try {
$this->paymentMethodRepository->upsert([$data], $context);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [$e->getTraceAsString()]);
}
}
/**
* @param \VRPayment\Sdk\Model\PaymentMethodConfiguration $paymentMethodConfiguration
* @param \Shopware\Core\Framework\Context $context
@@ -605,54 +585,102 @@ class PaymentMethodConfigurationService {
}
/**
* Upload Payment Method icons
*
* @param string $id
* @param \VRPayment\Sdk\Model\PaymentMethodConfiguration $paymentMethodConfiguration
* @param \Shopware\Core\Framework\Context $context
*
* @return string|null
* Update or insert Payment Method
*/
protected function upsertPaymentMethod(
string $id,
PaymentMethodConfiguration $paymentMethodConfiguration,
Context $context
): void {
/** @var PluginIdProvider $pluginIdProvider */
$pluginIdProvider = $this->container->get(PluginIdProvider::class);
$pluginId = $pluginIdProvider->getPluginIdByBaseClass(
VRPaymentPayment::class,
$context
);
$data = [
'id' => $id,
'handlerIdentifier' => VRPaymentPaymentHandler::class,
'pluginId' => $pluginId,
'position' => $paymentMethodConfiguration->getSortOrder() - 100,
'afterOrderEnabled' => true,
'active' => true,
'translations' => $this->getPaymentMethodConfigurationTranslation($paymentMethodConfiguration, $context),
'technicalName' => $paymentMethodConfiguration->getName(),
];
$mediaId = $this->upsertMedia($id, $paymentMethodConfiguration, $context);
if ($mediaId) {
$data['mediaId'] = $mediaId;
}
try {
$this->paymentMethodRepository->upsert([$data], $context);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [$e->getTraceAsString()]);
}
}
/**
* Upload or update Payment Method icons
*/
protected function upsertMedia(string $id, PaymentMethodConfiguration $paymentMethodConfiguration, Context $context): ?string
{
try {
$existingRecord = $this->getMediaDefaultFolderForPaymentMethod($paymentMethodConfiguration, $context);
$folderKey = 'payment_method_' . $paymentMethodConfiguration->getId();
if ($existingRecord->count() > 0) {
$id = $existingRecord->first()->getId();
// Check existing default folder
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('entity', $folderKey));
$existingFolder = $this->mediaDefaultFolderRepository->search($criteria, $context);
$folderId = $id;
if ($existingFolder->count() > 0) {
$folderId = $existingFolder->first()->getId();
}
// Ensure default folder
$this->mediaDefaultFolderRepository->upsert([
[
'id' => $id,
'associationFields' => [],
'entity' => 'payment_method_' . $paymentMethodConfiguration->getId(),
],
[
'id' => $folderId,
'associationFields' => [],
'entity' => $folderKey,
],
], $context);
// Ensure media folder
$this->mediaFolderRepository->upsert([
[
'id' => $id,
'defaultFolderId' => $id,
'name' => $paymentMethodConfiguration->getName(),
'useParentConfiguration' => false,
'configuration' => [],
],
[
'id' => $folderId,
'defaultFolderId' => $folderId,
'name' => $paymentMethodConfiguration->getName(),
'useParentConfiguration' => false,
'configuration' => [],
],
], $context);
/**
* @var \Shopware\Core\Content\Media\MediaDefinition
*/
// Media insert/update
// detect if collision, return existing id
$existingId = $this->checkMediaAlreadyExists($paymentMethodConfiguration->getResolvedImageUrl(), $context);
if ($existingId) {
return $existingId;
}
$mediaDefinition = $this->container->get(MediaDefinition::class);
$this->mediaSerializer->setRegistry($this->serializerRegistry);
$data = [
'id' => $id,
'title' => $paymentMethodConfiguration->getName(),
'url' => $paymentMethodConfiguration->getResolvedImageUrl(),
'mediaFolderId' => $id,
'id' => $id,
'title' => $paymentMethodConfiguration->getName(),
'url' => $paymentMethodConfiguration->getResolvedImageUrl(),
'mediaFolderId' => $folderId,
];
$data = $this->mediaSerializer->deserialize(new Config([], [], []), $mediaDefinition, $data);
$this->mediaRepository->upsert([$data], $context);
return $id;
} catch (\Exception $e) {
$this->logger->critical($e->getMessage(), [$e->getTraceAsString()]);
@@ -660,6 +688,22 @@ class PaymentMethodConfigurationService {
}
}
private function checkMediaAlreadyExists($paymentMethodUrl, $context) {
// detect if collision, return existing id
if (preg_match('#/([^/]+)\.[^/.]+$#', $paymentMethodUrl, $matches)) {
$filename = $matches[1];
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('fileName', $filename));
$existing = $this->mediaRepository->search($criteria, $context)->first();
if ($existing) {
return $existing->getId();
}
return false;
}
/**
* Retrieves media default folder for a given payment method configuration.
*
@@ -13,6 +13,7 @@ use Symfony\Component\{
};
use VRPaymentPayment\Core\{
Api\Refund\Service\RefundService,
Api\Transaction\Service\TransactionService,
Settings\Service\SettingsService
};
@@ -40,17 +41,24 @@ class RefundController extends AbstractController
* @var \Psr\Log\LoggerInterface
*/
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;
}
/**
@@ -81,12 +89,24 @@ class RefundController extends AbstractController
$transactionId = $request->request->get('transactionId');
$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);
}
$refund = $this->refundService->create($transaction, $context, $lineItemId, $quantity);
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);
}
@@ -110,17 +130,30 @@ class RefundController extends AbstractController
$salesChannelId = $request->request->get('salesChannelId');
$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);
$refund = $this->refundService->createRefundByAmount($transaction, $refundableAmount, $context);
$completed = (float) $transaction->getCompletedAmount();
$refunded = (float) $transaction->getRefundedAmount();
$maxRefund = round($completed - $refunded, 2);
if ($refund === null) {
return new Response('refundExceedsAmount', Response::HTTP_BAD_REQUEST);
if ($refundableAmount > $maxRefund) {
return new Response('refundExceedsAmount', Response::HTTP_BAD_REQUEST);
}
$refund = $this->refundService->createRefundByAmount($transaction, $refundableAmount, $context);
if ($refund === null) {
return new Response('refundExceedsAmount', Response::HTTP_BAD_REQUEST);
}
return new Response(null, Response::HTTP_NO_CONTENT);
}
+68 -1
View File
@@ -12,7 +12,11 @@ use Shopware\Core\{
};
use VRPayment\Sdk\{
Model\Refund,
Model\Transaction
Model\Transaction,
Model\CriteriaOperator,
Model\EntityQueryFilter,
Model\EntityQueryFilterType,
Model\EntityQuery,
};
use VRPaymentPayment\Core\{
Api\Refund\Entity\RefundEntity,
@@ -241,4 +245,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;
}
}
@@ -15,6 +15,7 @@ use Shopware\Core\{
System\SalesChannel\SalesChannelContext
};
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use VRPayment\Sdk\Model\{
AddressCreate,
@@ -44,8 +45,12 @@ use VRPaymentPayment\Core\{
Settings\Service\SettingsService,
Util\LocaleCodeProvider,
Util\Payload\CustomProducts\CustomProductsLineItemTypes,
Util\Payload\TransactionPayload
Util\Payload\TransactionPayload,
Util\Analytics\Analytics
};
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Commercial\Subscription\Framework\Struct\SubscriptionContextStruct;
/**
* Class TransactionService
@@ -185,10 +190,20 @@ class TransactionService
$orderTransaction->getPaymentMethodId(),
$orderTransaction->getOrder()->getSalesChannelId()
);
$_SESSION['transactionId'] = null;
$_SESSION['arrayOfPossibleMethods'] = null;
$_SESSION['addressCheck'] = null;
$_SESSION['currencyCheck'] = null;
$salesChannelContext->getContext()->addExtension(
'checkoutState',
new ArrayEntity([
'transactionId' => null,
'addressHash' => null,
'currency' => null,
])
);
$salesChannelContext->getContext()->addExtension(
'possibleMethods',
new ArrayEntity(['ids' => []])
);
$this->holdDelivery($orderTransaction->getOrder()->getId(), $salesChannelContext->getContext());
@@ -207,9 +222,14 @@ class TransactionService
$spaceId = $settings->getSpaceId();
}
$sdkTransaction = $settings->getApiClient()->getTransactionService()->create($spaceId, $sdkTransactionCreate);
$apiClient = $settings->getApiClient();
Analytics::addHeaders($apiClient, [
Analytics::SUBSCRIPTION_TRANSACTION => true
]);
$sdkTransaction = $apiClient->getTransactionService()->create($spaceId, $sdkTransactionCreate);
if ($sdkTransaction->valid()) {
return $settings->getApiClient()->getTransactionService()->processWithoutUserInteraction($spaceId, $sdkTransaction->getId());
return $apiClient->getTransactionService()->processWithoutUserInteraction($spaceId, $sdkTransaction->getId());
}
throw new \Exception("The transacion is not valid and could not be created.");
@@ -502,24 +522,22 @@ class TransactionService
/**
* @param SalesChannelContext $salesChannelContext
* @param CheckoutConfirmPageLoadedEvent|null $event
*
* @return int
*/
public function createPendingTransaction(SalesChannelContext $salesChannelContext, ?CheckoutConfirmPageLoadedEvent $event = null): int
public function createPendingTransaction(SalesChannelContext $salesChannelContext, $event = null): int
{
$expiredTransaction = true;
$transactionId = $_SESSION['transactionId'] ?? null;
$settings = $this->settingsService->getValidSettings($salesChannelContext->getSalesChannel()->getId());
if (!$settings) {
throw new \Exception('Space settings not configured');
}
if ($transactionId) {
$transactionService = $settings->getApiClient()->getTransactionService();
$pendingTransaction = $transactionService->read($settings->getSpaceId(), $transactionId);
$failedStates = [
TransactionState::DECLINE,
TransactionState::FAILED,
TransactionState::VOIDED,
];
if (!in_array($pendingTransaction->getState(), $failedStates)) {
if ($pendingTransaction->getState() === TransactionState::PENDING) {
$expiredTransaction = false;
}
}
@@ -530,12 +548,19 @@ class TransactionService
$customer = $salesChannelContext->getCustomer();
$lineItems = [];
if ($event) {
$cartLineItems = $event->getPage()->getCart()->getLineItems()->getElements();
foreach ($cartLineItems as $cartLineItem) {
if ($cartLineItem->getType() === CustomProductsLineItemTypes::LINE_ITEM_TYPE_CUSTOMIZED_PRODUCTS) {
continue;
if ($event instanceof CheckoutConfirmPageLoadedEvent) {
$cartLineItems = $event->getPage()->getCart()->getLineItems()->getElements();
foreach ($cartLineItems as $cartLineItem) {
if ($cartLineItem->getType() === CustomProductsLineItemTypes::LINE_ITEM_TYPE_CUSTOMIZED_PRODUCTS) {
continue;
}
$lineItems[] = $this->createTempLineItem($cartLineItem);
}
} elseif ($event instanceof AccountEditOrderPageLoadedEvent) {
$order = $event->getPage()->getOrder();
foreach ($order->getLineItems() as $orderLineItem) {
$lineItems[] = $this->createTempLineItem($orderLineItem);
}
$lineItems[] = $this->createTempLineItem($cartLineItem);
}
}
@@ -551,6 +576,10 @@ class TransactionService
$billingAddress = $this->buildAddress($salesChannelContext, $customer->getActiveBillingAddress());
$shippingAddress = $this->buildAddress($salesChannelContext, $customer->getActiveShippingAddress());
if (!$settings) {
throw new \Exception('Space settings not configured');
}
$transactionPayload = (new TransactionCreate())
->setBillingAddress($billingAddress)
->setShippingAddress($shippingAddress)
@@ -562,8 +591,11 @@ class TransactionService
->setCustomerEmailAddress($customer->getEmail())
->setCustomerId($customerId)
->setSuccessUrl($homeUrl . '?success')
->setFailedUrl($homeUrl . '?fail')
->setTokenizationMode(TokenizationMode::FORCE_CREATION);
->setFailedUrl($homeUrl . '?fail');
if($this->isSubscription($salesChannelContext)) {
$transactionPayload->setTokenizationMode(TokenizationMode::FORCE_CREATION);
}
$transactionService = $settings->getApiClient()->getTransactionService();
$transaction = $transactionService->create($settings->getSpaceId(), $transactionPayload);
@@ -685,22 +717,30 @@ class TransactionService
return $chargeAttempts ? $chargeAttempts[0] : null;
}
/**
* @param LineItem $productData
* @return LineItemCreate
*/
private function createTempLineItem(LineItem $productData): LineItemCreate
{
$lineItem = new LineItemCreate();
$lineItem->setName($productData->getLabel());
$lineItem->setUniqueId($productData->getId());
$lineItem->setSku($productData->getId());
$lineItem->setQuantity($productData->getQuantity());
$lineItem->setAmountIncludingTax($productData->getPrice()->getUnitPrice());
$lineItem->setType(LineItemType::PRODUCT);
private function createTempLineItem($productData): LineItemCreate
{
$lineItem = new LineItemCreate();
return $lineItem;
}
if ($productData instanceof LineItem) {
$lineItem->setName($productData->getLabel());
$lineItem->setUniqueId($productData->getId());
$lineItem->setSku($productData->getReferencedId() ?? $productData->getId());
$lineItem->setQuantity($productData->getQuantity());
$lineItem->setAmountIncludingTax($productData->getPrice()->getUnitPrice());
} elseif ($productData instanceof OrderLineItemEntity) {
$lineItem->setName($productData->getLabel());
$lineItem->setUniqueId($productData->getId());
$lineItem->setSku($productData->getProductId() ?? $productData->getIdentifier() ?? $productData->getId());
$lineItem->setQuantity($productData->getQuantity());
$lineItem->setAmountIncludingTax($productData->getUnitPrice());
} else {
throw new \InvalidArgumentException('Unsupported line item type: ' . get_class($productData));
}
$lineItem->setType(LineItemType::PRODUCT);
return $lineItem;
}
/**
* Build a VRPayment address from Shopware customer address.
@@ -749,4 +789,21 @@ class TransactionService
return $address;
}
/**
* Checks if it's subscription context.
*
* @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext
* @return bool
*/
private function isSubscription(SalesChannelContext $salesChannelContext): bool {
$extensionName = 'subscription';
if (class_exists(\Shopware\Commercial\Subscription\Framework\Struct\SubscriptionContextStruct::class)) {
$extensionName = SubscriptionContextStruct::SUBSCRIPTION_EXTENSION;
}
if ($salesChannelContext->hasExtension($extensionName)) {
return true;
}
return false;
}
}
@@ -224,8 +224,18 @@ class WebHookController extends AbstractController {
// Configuration
$salesChannelId = $salesChannelId == 'null' ? null : $salesChannelId;
$this->settings = $this->settingsService->getSettings($salesChannelId);
$signature = $request->server->get('HTTP_X_SIGNATURE');
$requestJson = json_decode($request->getContent(), true);
if ($requestJson['eventId'] == null && $requestJson['entityId'] == null && $requestJson['listenerEntityId'] == null && $requestJson['listenerEntityId'] == null && $requestJson['listenerEntityTechnicalName'] == null && $requestJson['spaceId'] == null) {
throw new \InvalidArgumentException('Empty webhook');
}
if (!$this->settings->getSpaceId() || !$this->settings->getUserId() || !$this->settings->getApplicationKey()) {
throw new \InvalidArgumentException('Not correct webhook configuration for salesChannelId: ' . $salesChannelId . ' Debug: ' . var_dump($requestJson));
}
$apiClient = $this->settings->getApiClient();
$callBackData->assign($requestJson);
@@ -133,7 +133,20 @@ class VRPaymentPaymentHandler extends AbstractPaymentHandler
$salesChannelContextId = $contextSource->getSalesChannelId();
}
$parameters = new SalesChannelContextServiceParameters($salesChannelContextId, $request->getSession()->get("sw-context-token", Random::getAlphanumericString(32)), originalContext: $context);
$orderCustomer = $orderTransaction->getOrder()?->getOrderCustomer();
if ($orderCustomer) {
$customerId = $orderCustomer->getCustomerId();
} else {
$customerId = null;
}
$parameters = new SalesChannelContextServiceParameters(
$salesChannelContextId,
$request->getSession()->get("sw-context-token", Random::getAlphanumericString(32)),
originalContext: $context,
customerId: $customerId
);
$salesChannelContext = $this->salesChannelContextService->get($parameters);
$redirectUrl = $transaction->getReturnUrl();
@@ -149,7 +162,7 @@ class VRPaymentPaymentHandler extends AbstractPaymentHandler
$request->getSession()->remove('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 PaymentException::customerCanceled($orderTransactionId, $errorMessage);
}
}
@@ -194,7 +207,7 @@ class VRPaymentPaymentHandler extends AbstractPaymentHandler
]);
$request->getSession()->remove('transactionId');
$this->logger->info($errorMessage);
throw PaymentException::customerCanceled($transaction->getOrderTransaction()->getId(), $errorMessage);
throw PaymentException::customerCanceled($orderTransactionId, $errorMessage);
}
} else {
$this->orderTransactionStateHandler->paid($orderTransaction->getId(), $context);
@@ -4,33 +4,41 @@ namespace VRPaymentPayment\Core\Storefront\Checkout\Subscriber;
use Psr\Log\LoggerInterface;
use Shopware\Core\{Checkout\Order\Aggregate\OrderTransaction\OrderTransactionCollection,
Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates,
Checkout\Order\OrderEntity,
Content\MailTemplate\Service\Event\MailBeforeValidateEvent};
Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates,
Checkout\Order\OrderEntity,
Content\MailTemplate\Service\Event\MailBeforeValidateEvent};
use Shopware\Core\Checkout\Payment\PaymentMethodCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent;
use Shopware\Storefront\Page\Account\PaymentMethod\AccountPaymentMethodPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use VRPaymentPayment\Core\{Api\Transaction\Service\OrderMailService,
Api\Transaction\Service\TransactionService,
Checkout\PaymentHandler\VRPaymentPaymentHandler,
Settings\Service\SettingsService,
Settings\Struct\Settings,
Util\PaymentMethodUtil};
use VRPaymentPayment\Core\{Api\Transaction\Service\TransactionService,
Checkout\PaymentHandler\VRPaymentPaymentHandler,
Settings\Service\SettingsService,
Settings\Struct\Settings,
Util\PaymentMethodUtil};
use VRPaymentPayment\Core\Api\PaymentMethodConfiguration\Service\PaymentMethodConfigurationService;
use VRPaymentPayment\Sdk\{Model\AddressCreate,
Model\ChargeAttempt,
Model\CreationEntityState,
Model\CriteriaOperator,
Model\EntityQuery,
Model\EntityQueryFilter,
Model\EntityQueryFilterType,
Model\LineItemAttributeCreate,
Model\LineItemCreate,
Model\LineItemType,
Model\TaxCreate,
Model\Transaction,
Model\TransactionCreate,
Model\TransactionPending};
Model\ChargeAttempt,
Model\CreationEntityState,
Model\CriteriaOperator,
Model\EntityQuery,
Model\EntityQueryFilter,
Model\EntityQueryFilterType,
Model\LineItemAttributeCreate,
Model\LineItemCreate,
Model\LineItemType,
Model\TaxCreate,
Model\Transaction,
Model\TransactionCreate,
Model\TransactionPending};
use Shopware\Core\Framework\Struct\ArrayEntity;
/**
* Class CheckoutSubscriber
@@ -65,6 +73,9 @@ class CheckoutSubscriber implements EventSubscriberInterface
*/
private $paymentMethodUtil;
/** @var EntityRepository */
private EntityRepository $paymentMethodRepository;
/**
* CheckoutSubscriber constructor.
*
@@ -72,13 +83,15 @@ class CheckoutSubscriber implements EventSubscriberInterface
* @param \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService $transactionService
* @param \VRPaymentPayment\Core\Settings\Service\SettingsService $settingsService
* @param \VRPaymentPayment\Core\Util\PaymentMethodUtil $paymentMethodUtil
* @param EntityRepository $paymentMethodRepository
*/
public function __construct(PaymentMethodConfigurationService $paymentMethodConfigurationService, TransactionService $transactionService, SettingsService $settingsService, PaymentMethodUtil $paymentMethodUtil)
public function __construct(PaymentMethodConfigurationService $paymentMethodConfigurationService, TransactionService $transactionService, SettingsService $settingsService, PaymentMethodUtil $paymentMethodUtil, EntityRepository $paymentMethodRepository)
{
$this->paymentMethodConfigurationService = $paymentMethodConfigurationService;
$this->transactionService = $transactionService;
$this->settingsService = $settingsService;
$this->paymentMethodUtil = $paymentMethodUtil;
$this->paymentMethodConfigurationService = $paymentMethodConfigurationService;
$this->transactionService = $transactionService;
$this->settingsService = $settingsService;
$this->paymentMethodUtil = $paymentMethodUtil;
$this->paymentMethodRepository = $paymentMethodRepository;
}
/**
@@ -99,7 +112,9 @@ class CheckoutSubscriber implements EventSubscriberInterface
public static function getSubscribedEvents(): array
{
return [
CheckoutConfirmPageLoadedEvent::class => ['onConfirmPageLoaded', 1],
CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmLoaded',
AccountEditOrderPageLoadedEvent::class => 'onAccountOrderEditLoaded',
AccountPaymentMethodPageLoadedEvent::class => 'onAccountPaymentMethodLoaded',
"subscription." . CheckoutConfirmPageLoadedEvent::class => ['onConfirmPageLoaded', 1],
MailBeforeValidateEvent::class => ['onMailBeforeValidate', 1],
];
@@ -154,9 +169,10 @@ class CheckoutSubscriber implements EventSubscriberInterface
}
/**
* @param \Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent $event
* @param CheckoutConfirmPageLoadedEvent $event
* @return void
*/
public function onConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void
public function onCheckoutConfirmLoaded(CheckoutConfirmPageLoadedEvent $event): void
{
try {
$salesChannelContext = $event->getSalesChannelContext();
@@ -169,7 +185,7 @@ class CheckoutSubscriber implements EventSubscriberInterface
$createdTransactionId = $this->transactionService->createPendingTransaction($salesChannelContext, $event);
$this->updateTempTransactionIfNeeded($salesChannelContext, $createdTransactionId);
$this->getAvailablePaymentMethods($settings, $createdTransactionId);
$this->getAvailablePaymentMethods($settings, $createdTransactionId, $salesChannelContext);
$this->setPossiblePaymentMethods($settings->getSpaceId(), $event);
} catch (\Exception $e) {
$this->logger->error($e->getMessage());
@@ -177,10 +193,74 @@ class CheckoutSubscriber implements EventSubscriberInterface
}
}
/**
* @param AccountEditOrderPageLoadedEvent $event
* @return void
*/
public function onAccountOrderEditLoaded(AccountEditOrderPageLoadedEvent $event): void
{
try {
$this->handlePaymentMethodFiltering($event);
} catch (\Throwable $e) {
$this->logger->error($e->getMessage());
$this->removeVRPaymentPaymentMethodFromConfirmPage($event);
}
}
/**
* @param AccountPaymentMethodPageLoadedEvent $event
* @return void
*/
public function onAccountPaymentMethodLoaded(AccountPaymentMethodPageLoadedEvent $event): void
{
try {
$this->handlePaymentMethodFiltering($event);
} catch (\Throwable $e) {
$this->logger->error($e->getMessage());
$this->removeVRPaymentPaymentMethodFromConfirmPage($event);
}
}
/**
* @param \Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent $event
*/
private function removeVRPaymentPaymentMethodFromConfirmPage(CheckoutConfirmPageLoadedEvent $event): void
public function onConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void
{
try {
$this->handlePaymentMethodFiltering($event);
} catch (\Throwable $e) {
$this->logger->error($e->getMessage());
$this->removeVRPaymentPaymentMethodFromConfirmPage($event);
}
}
/**
* @param $event
* @return void
*/
private function handlePaymentMethodFiltering($event): void
{
$salesChannelContext = $event->getSalesChannelContext();
$settings = $this->settingsService->getValidSettings($salesChannelContext->getSalesChannel()->getId());
if (is_null($settings)) {
$this->logger->notice('Removing payment methods because settings are invalid');
$this->removeVRPaymentPaymentMethodFromConfirmPage($event);
return;
}
$createdTransactionId = $this->transactionService->createPendingTransaction($salesChannelContext, $event);
$this->updateTempTransactionIfNeeded($salesChannelContext, $createdTransactionId);
$this->getAvailablePaymentMethods($settings, $createdTransactionId, $salesChannelContext);
$this->setPossiblePaymentMethods($settings->getSpaceId(), $event);
}
/**
* @param $event
* @return void
*/
private function removeVRPaymentPaymentMethodFromConfirmPage($event): void
{
$paymentMethodCollection = $event->getPage()->getPaymentMethods();
$paymentMethodIds = $this->paymentMethodUtil->getVRPaymentPaymentMethodIds($event->getContext());
@@ -194,7 +274,7 @@ class CheckoutSubscriber implements EventSubscriberInterface
* @param int $createdTransactionId
* @return void
*/
private function getAvailablePaymentMethods(Settings $settings, int $createdTransactionId): void
private function getAvailablePaymentMethods(Settings $settings, int $createdTransactionId, SalesChannelContext $salesChannelContext): void
{
$transactionService = $settings->getApiClient()->getTransactionService();
$possiblePaymentMethods = $transactionService->fetchPaymentMethods(
@@ -204,9 +284,13 @@ class CheckoutSubscriber implements EventSubscriberInterface
);
$arrayOfPossibleMethods = [];
foreach ($possiblePaymentMethods as $possiblePaymentMethod) {
$arrayOfPossibleMethods[] = $possiblePaymentMethod->getid();
$arrayOfPossibleMethods[] = $possiblePaymentMethod->getId();
}
$_SESSION['arrayOfPossibleMethods'] = $arrayOfPossibleMethods;
$salesChannelContext->getContext()->addExtension(
'possibleMethods',
new ArrayEntity(['ids' => $arrayOfPossibleMethods])
);
}
/**
@@ -214,48 +298,101 @@ class CheckoutSubscriber implements EventSubscriberInterface
* @param CheckoutConfirmPageLoadedEvent $event
* @return void
*/
private function setPossiblePaymentMethods(int $spaceId, CheckoutConfirmPageLoadedEvent $event): void
private function setPossiblePaymentMethods(int $spaceId, $event): void
{
$localPaymentMethods = [];
$paymentMethodConfigurations = $this->paymentMethodConfigurationService->getAllPaymentMethodConfigurations($spaceId, $event->getSalesChannelContext()->getContext());
foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) {
$localPaymentMethods[$paymentMethodConfiguration->getId()] = $paymentMethodConfiguration->getPaymentMethodConfigurationId();
$paymentIds = [];
$paymentMethodCollection = $event->getPage()->getPaymentMethods();
foreach ($paymentMethodCollection as $paymentMethodCollectionItem) {
$isVRPaymentPM = VRPaymentPaymentHandler::class === $paymentMethodCollectionItem->getHandlerIdentifier();
if (!$isVRPaymentPM) {
$paymentIds[] = $paymentMethodCollectionItem->getId();
}
}
$paymentMethodCollection = $event->getPage()->getPaymentMethods();
foreach ($paymentMethodCollection as $paymentMethodCollectionItem) {
$isVRPaymentPM = VRPaymentPaymentHandler::class == $paymentMethodCollectionItem->getHandlerIdentifier();
if (!$isVRPaymentPM) {
$allowedWLMethods = [];
$paymentMethodConfigurations = $this->paymentMethodConfigurationService
->getAllPaymentMethodConfigurations($spaceId, $event->getSalesChannelContext()->getContext());
foreach ($paymentMethodConfigurations as $paymentMethodConfiguration) {
if ($paymentMethodConfiguration->getPaymentMethod() === null) {
continue;
}
$paymentMethodConfigurationId = $localPaymentMethods[$paymentMethodCollectionItem->getId()];
if (!\in_array($paymentMethodConfigurationId, $_SESSION['arrayOfPossibleMethods'])) {
$paymentMethodCollection->remove($paymentMethodCollectionItem->getId());
$pmId = $paymentMethodConfiguration->getPaymentMethod()->getId();
$pmConfigId = $paymentMethodConfiguration->getPaymentMethodConfigurationId();
$allowedIds = $this->getAllowedPaymentMethodIds($event->getSalesChannelContext());
if ($paymentMethodConfiguration->getSpaceId() === $spaceId
&& \in_array($pmConfigId, $allowedIds, true)) {
$allowedWLMethods[] = $pmId;
}
}
}
/**
* @param SalesChannelContext $salesChannelContext
* @param int $createdTransactionId
* @return void
*/
private function updateTempTransactionIfNeeded(SalesChannelContext $salesChannelContext, int $createdTransactionId): void
{
$addressCheck = $_SESSION['addressCheck'] ?? null;
$currencyCheck = $_SESSION['currencyCheck'] ?? null;
$allPaymentIds = array_unique(array_merge($paymentIds, $allowedWLMethods));
$collection = new PaymentMethodCollection();
if (!empty($allPaymentIds)) {
$criteria = new Criteria($allPaymentIds);
$criteria->addFilter(new EqualsFilter('active', true));
$criteria->addFilter(
new EqualsFilter('salesChannels.id', $event->getSalesChannelContext()->getSalesChannelId())
);
$customer = $salesChannelContext->getCustomer();
$addressHash = md5(json_encode((array)$customer));
$currency = $salesChannelContext->getCurrency()->getIsoCode();
if (($addressCheck && $currencyCheck) && $addressCheck !== $addressHash || $currencyCheck !== $currency) {
if ($createdTransactionId) {
$this->transactionService->updateTempTransaction($salesChannelContext, $createdTransactionId);
$result = $this->paymentMethodRepository->search($criteria, $event->getContext());
foreach ($result->getEntities() as $method) {
if (!$collection->has($method->getId())) {
$collection->add($method);
}
}
$_SESSION['arrayOfPossibleMethods'] = null;
$_SESSION['addressCheck'] = $addressHash;
$_SESSION['currencyCheck'] = $currency;
}
$event->getPage()->setPaymentMethods($collection);
}
/**
* @param SalesChannelContext $salesChannelContext
* @param int $createdTransactionId
* @return void
*/
private function updateTempTransactionIfNeeded(SalesChannelContext $salesChannelContext, int $createdTransactionId): void
{
$ctx = $salesChannelContext->getContext();
/** @var ArrayEntity|null $ext */
$ext = $ctx->getExtension('checkoutState');
$oldAddressHash = $ext instanceof ArrayEntity ? $ext->get('addressHash') : null;
$oldCurrency = $ext instanceof ArrayEntity ? $ext->get('currency') : null;
$customer = $salesChannelContext->getCustomer();
$addressHash = md5(json_encode((array) $customer));
$currency = $salesChannelContext->getCurrency()->getIsoCode();
$needsUpdate = ($oldAddressHash !== $addressHash) || ($oldCurrency !== $currency);
if ($needsUpdate) {
if ($createdTransactionId) {
$this->transactionService->updateTempTransaction($salesChannelContext, $createdTransactionId);
}
$ctx->addExtension('possibleMethods', new ArrayEntity(['ids' => []]));
$ctx->addExtension(
'checkoutState',
new ArrayEntity([
'addressHash' => $addressHash,
'currency' => $currency,
])
);
}
}
/**
* @param SalesChannelContext $salesChannelContext
* @return array
*/
private function getAllowedPaymentMethodIds(SalesChannelContext $salesChannelContext): array
{
$ext = $salesChannelContext->getContext()->getExtension('possibleMethods');
return $ext instanceof ArrayEntity ? ($ext->get('ids') ?? []) : [];
}
}
+4 -2
View File
@@ -15,6 +15,7 @@ class Analytics {
public const SHOP_SYSTEM_VERSION = 'x-meta-shop-system-version';
public const SHOP_SYSTEM_AND_VERSION = 'x-meta-shop-system-and-version';
public const PLUGIN_SYSTEM_VERSION = 'x-meta-plugin-version';
public const SUBSCRIPTION_TRANSACTION = 'x-meta-subscription-transaction';
/**
* @return array
@@ -25,16 +26,17 @@ class Analytics {
self::SHOP_SYSTEM => 'shopware',
self::SHOP_SYSTEM_VERSION => '6',
self::SHOP_SYSTEM_AND_VERSION => 'shopware-6',
self::PLUGIN_SYSTEM_VERSION => '7.1.1',
self::PLUGIN_SYSTEM_VERSION => '7.1.5',
];
}
/**
* @param \VRPayment\Sdk\ApiClient $apiClient
*/
public static function addHeaders(ApiClient &$apiClient)
public static function addHeaders(ApiClient &$apiClient, array $additionalHeaders = [])
{
$data = self::getDefaultData();
$data = array_merge($data, $additionalHeaders);
foreach ($data as $key => $value) {
$apiClient->addDefaultHeader($key, $value);
}
+23 -14
View File
@@ -231,9 +231,16 @@ class TransactionPayload extends AbstractPayload
->setShippingAddress($shippingAddress)
->setShippingMethod($transactionData['shipping_method']);
$paymentConfiguration = $this->getPaymentConfiguration($this->salesChannelContext->getPaymentMethod()->getId());
$paymentConfiguration = $this->getPaymentConfiguration(
$this->salesChannelContext->getPaymentMethod()->getId(),
$this->settings->getSpaceId()
);
$transactionPayload->setAllowedPaymentMethodConfigurations([$paymentConfiguration->getPaymentMethodConfigurationId()]);
if ($paymentConfiguration) {
$transactionPayload->setAllowedPaymentMethodConfigurations([
$paymentConfiguration->getPaymentMethodConfigurationId()
]);
}
$successUrl = $this->transaction->getReturnUrl() . '&status=paid';
$failedUrl = $this->getFailUrl($this->order->getId()) . '&status=fail';
@@ -899,19 +906,21 @@ class TransactionPayload extends AbstractPayload
return $addressPayload;
}
/**
* @param string $id
*
* @return \VRPaymentPayment\Core\Api\PaymentMethodConfiguration\Entity\PaymentMethodConfigurationEntity
*/
protected function getPaymentConfiguration(string $id): PaymentMethodConfigurationEntity
{
$criteria = (new Criteria([$id]));
/**
* @param string $paymentMethodId
* @param int $spaceId
* @return PaymentMethodConfigurationEntity|null
*/
protected function getPaymentConfiguration(string $paymentMethodId, int $spaceId): ?PaymentMethodConfigurationEntity
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('paymentMethodId', $paymentMethodId));
$criteria->addFilter(new EqualsFilter('spaceId', $spaceId));
return $this->container->get('vrpayment_payment_method_configuration.repository')
->search($criteria, $this->salesChannelContext->getContext())
->getEntities()->first();
}
return $this->container->get('vrpayment_payment_method_configuration.repository')
->search($criteria, $this->salesChannelContext->getContext())
->first();
}
/**
* Get failure URL
@@ -70,14 +70,17 @@ 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;
errorMessage = errorResponse.response.data.errors[0].detail;
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;
default:
errorMessage = errorResponse.response.data.errors[0].detail;
}
this.createNotificationError({
title: errorTitle,
@@ -9,6 +9,7 @@
:max="this.$parent.$parent.itemRefundableQuantity"
:min="0"
v-model="refundQuantity"
number-type="int"
:label="$tc('vrpayment-order.refund.refundQuantity.label')">
</mt-number-field>
@@ -68,9 +68,21 @@ 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;
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,12 @@
"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."
}
},
"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,12 @@
"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."
}
},
"transactionHistory": {
@@ -78,9 +78,12 @@
"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."
}
},
"transactionHistory": {
@@ -78,9 +78,12 @@
"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."
}
},
"transactionHistory": {
@@ -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,16 +25,16 @@
: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>
@@ -14,8 +14,8 @@
{% 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]"
:customInheritationCheckFunction="checkNumberFieldInheritance">
:inheritedValue="getInheritedValue(CONFIG_SPACE_ID)"
@update:value="onSwitchInput">
<template #content="props">
<mt-number-field
:name="CONFIG_SPACE_ID"
@@ -23,7 +23,7 @@
: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')"
:disabled="!acl.can('vrpayment.editor')"
:model-value="props.currentValue"
:error="spaceIdErrorState"
@update:model-value="props.updateCurrentValue">
@@ -35,7 +35,7 @@
{% 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
@@ -44,7 +44,7 @@
: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')"
:disabled="!acl.can('vrpayment.editor')"
:model-value="props.currentValue"
:error="userIdErrorState"
@update:model-value="props.updateCurrentValue">
@@ -56,7 +56,7 @@
{% 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
@@ -66,7 +66,7 @@
: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')"
:disabled="!acl.can('vrpayment.editor')"
:model-value="props.currentValue"
:error="applicationKeyErrorState"
@update:model-value="props.updateCurrentValue">
@@ -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,38 +70,42 @@ 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) {
return !value || value.length <= 0;
},
checkTextFieldInheritance(value) {
if (typeof value !== 'string') {
return true;
}
checkNumberFieldInheritance(value) {
return value == null || value === '';
},
return value.length <= 0;
},
checkNumberFieldInheritance(value) {
if (typeof value !== 'number') {
return true;
}
return value.length <= 0;
},
checkBoolFieldInheritance(value) {
return typeof value !== 'boolean';
},
checkBoolFieldInheritance(value) {
return typeof value !== 'boolean';
},
// Emits the 'check-api-connection-event' with the current API connection parameters.
// 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;
}
}
});
@@ -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 %}
@@ -7,16 +7,16 @@
: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>
@@ -1,146 +1,145 @@
{% block vrpayment_settings %}
<sw-page class="vrpayment-settings">
<sw-page class="vrpayment-settings">
{% block vrpayment_settings_header %}
<template #smart-bar-header>
<h2>
{{ $tc('sw-settings.index.title') }}
<mt-icon name="small-arrow-medium-right" size="16px"></mt-icon>
{{ $tc('vrpayment-settings.header') }}
</h2>
</template>
{% endblock %}
{% block vrpayment_settings_header %}
<template #smart-bar-header>
<h2>
{{ $tc('sw-settings.index.title') }}
<mt-icon name="small-arrow-medium-right" size="16px"></mt-icon>
{{ $tc('vrpayment-settings.header') }}
</h2>
</template>
{% endblock %}
{% block vrpayment_settings_actions %}
<template #smart-bar-actions>
{% block vrpayment_settings_actions_save %}
<mt-button
v-model:value="isSaveSuccessful"
class="sw-settings-login-registration__save-action"
variant="primary"
:isLoading="isLoading"
:disabled="isLoading"
@click="onSave">
{{ $tc('vrpayment-settings.settingForm.save') }}
</mt-button>
{% endblock %}
</template>
{% endblock %}
{% block vrpayment_settings_actions %}
<template #smart-bar-actions>
{% block vrpayment_settings_actions_save %}
<mt-button
v-model:value="isSaveSuccessful"
class="sw-settings-login-registration__save-action"
variant="primary"
:isLoading="isLoading"
:disabled="isLoading"
@click="onSave">
{{ $tc('vrpayment-settings.settingForm.save') }}
</mt-button>
{% endblock %}
</template>
{% endblock %}
{% block vrpayment_settings_content %}
<template #content>
{% block vrpayment_settings_content %}
<template #content>
{% block vrpayment_settings_content_card %}
<mt-card-view>
{% block vrpayment_settings_content_card %}
<mt-card-view>
{% block vrpayment_settings_content_card_channel_config %}
<sw-sales-channel-config v-model:value="config"
ref="configComponent"
:domain="CONFIG_DOMAIN">
{% block vrpayment_settings_content_card_channel_config %}
<sw-sales-channel-config v-model:value="config"
ref="configComponent"
:domain="CONFIG_DOMAIN">
{% block vrpayment_settings_content_card_channel_config_sales_channel %}
<template #select="{ onInput, selectedSalesChannelId, salesChannel }">
{% block vrpayment_settings_content_card_channel_config_sales_channel %}
<template #select="{ onInput, selectedSalesChannelId, salesChannel }">
{% block vrpayment_settings_content_card_channel_config_sales_channel_card %}
<mt-card title="Sales Channel Switch">
{% block vrpayment_settings_content_card_channel_config_sales_channel_card %}
<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"
valueProperty="id"
:mapInheritance="props"
:isLoading="isLoading"
entity="sales_channel"
@update:value="onInput">
</sw-entity-single-select>
{% endblock %}
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer %}
<template #footer>
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_title %}
<sw-single-select
:value="selectedSalesChannelId"
:options="salesChannel.map(sc => ({ id: sc.id, name: sc.translated.name }))"
labelProperty="name"
valueProperty="id"
:isLoading="isLoading"
@update:value="onInput"
/>
{% endblock %}
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer %}
<template #footer>
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer_container %}
<sw-container columns="2fr 1fr" gap="0px 30px">
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer_container %}
<sw-container columns="2fr 1fr" gap="0px 30px">
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer_container_text %}
<p>{{ $tc('vrpayment-settings.salesChannelCard.button.description') }}</p>
{% endblock %}
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer_container_text %}
<p>{{ $tc('vrpayment-settings.salesChannelCard.button.description') }}</p>
{% endblock %}
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer_container_button %}
<sw-button
variant="primary"
v-model:value="isSetDefaultPaymentSuccessful"
:isLoading="isSettingDefaultPaymentMethods"
@click="onSetPaymentMethodDefault">
{{ $tc('vrpayment-settings.salesChannelCard.button.label') }}
</sw-button>
{% endblock %}
</sw-container>
{% endblock %}
</template>
{% endblock %}
</mt-card>
{% endblock %}
</template>
{% endblock %}
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer_container_button %}
<sw-button
variant="primary"
v-model:value="isSetDefaultPaymentSuccessful"
:isLoading="isSettingDefaultPaymentMethods"
@click="onSetPaymentMethodDefault">
{{ $tc('vrpayment-settings.salesChannelCard.button.label') }}
</sw-button>
{% endblock %}
</sw-container>
{% endblock %}
</template>
{% endblock %}
</mt-card>
{% endblock %}
</template>
{% endblock %}
{% block vrpayment_settings_content_card_channel_config_cards %}
<template #content="{ actualConfigData, allConfigs, selectedSalesChannelId }">
<div v-if="actualConfigData">
{% block vrpayment_settings_content_card_channel_config_cards %}
<template #content="{ actualConfigData, allConfigs, selectedSalesChannelId }">
<div v-if="actualConfigData">
<sw-vrpayment-credentials
:actualConfigData="actualConfigData"
:allConfigs="allConfigs"
:selectedSalesChannelId="selectedSalesChannelId"
:spaceIdErrorState="spaceIdErrorState"
:userIdErrorState="userIdErrorState"
:applicationKeyErrorState="applicationKeyErrorState"
:spaceIdFilled="spaceIdFilled"
:userIdFilled="userIdFilled"
:applicationKeyFilled="applicationKeyFilled"
:isLoading="isLoading"
:isTesting="isTesting"
@check-api-connection-event="onCheckApiConnection"
></sw-vrpayment-credentials>
<sw-vrpayment-credentials
:actualConfigData="actualConfigData"
:allConfigs="allConfigs"
:selectedSalesChannelId="selectedSalesChannelId"
:spaceIdErrorState="spaceIdErrorState"
:userIdErrorState="userIdErrorState"
:applicationKeyErrorState="applicationKeyErrorState"
:spaceIdFilled="spaceIdFilled"
:userIdFilled="userIdFilled"
:applicationKeyFilled="applicationKeyFilled"
:isLoading="isLoading"
:isTesting="isTesting"
@check-api-connection-event="onCheckApiConnection"
></sw-vrpayment-credentials>
<sw-vrpayment-options
:actualConfigData="actualConfigData"
:allConfigs="allConfigs"
:isLoading="isLoading"
:selectedSalesChannelId="selectedSalesChannelId"
>
</sw-vrpayment-options>
<sw-vrpayment-options
:actualConfigData="actualConfigData"
:allConfigs="allConfigs"
:isLoading="isLoading"
:selectedSalesChannelId="selectedSalesChannelId"
>
</sw-vrpayment-options>
<sw-vrpayment-storefront-options
:actualConfigData="actualConfigData"
:allConfigs="allConfigs"
:isLoading="isLoading"
:selectedSalesChannelId="selectedSalesChannelId"
>
</sw-vrpayment-storefront-options>
<sw-vrpayment-storefront-options
:actualConfigData="actualConfigData"
:allConfigs="allConfigs"
:isLoading="isLoading"
:selectedSalesChannelId="selectedSalesChannelId"
>
</sw-vrpayment-storefront-options>
<sw-vrpayment-advanced-options
:actualConfigData="actualConfigData"
:allConfigs="allConfigs"
:isLoading="isLoading"
:selectedSalesChannelId="selectedSalesChannelId"
>
</sw-vrpayment-advanced-options>
<sw-vrpayment-advanced-options
:actualConfigData="actualConfigData"
:allConfigs="allConfigs"
:isLoading="isLoading"
:selectedSalesChannelId="selectedSalesChannelId"
>
</sw-vrpayment-advanced-options>
</div>
</template>
{% endblock %}
</div>
</template>
{% endblock %}
</sw-sales-channel-config>
{% endblock %}
</sw-sales-channel-config>
{% endblock %}
{% block vrpayment_settings_content_card_loading %}
<mt-loader v-if="isLoading"></mt-loader>
{% endblock %}
</mt-card-view>
{% endblock %}
{% block vrpayment_settings_content_card_loading %}
<mt-loader v-if="isLoading"></mt-loader>
{% endblock %}
</mt-card-view>
{% endblock %}
</template>
{% endblock %}
</sw-page>
</template>
{% endblock %}
</sw-page>
{% endblock %}
@@ -68,7 +68,7 @@ Component.register('vrpayment-settings', {
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>
@@ -31,6 +31,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>
@@ -0,0 +1,25 @@
{
"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-Cp2eQSV_.js"
],
"legacy": false,
"preload": []
}
},
"legacy": false,
"metadatas": {},
"version": [
"7.1.0",
7,
1,
0
],
"viteServer": null
}
@@ -0,0 +1,11 @@
{
"main.js": {
"file": "assets/v-r-payment-payment-Cp2eQSV_.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
@@ -0,0 +1 @@
.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}