Compare commits

..

3 Commits

Author SHA1 Message Date
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
50 changed files with 1249 additions and 977 deletions
+10 -2
View File
@@ -1,5 +1,13 @@
# 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
+10 -2
View File
@@ -1,5 +1,13 @@
# 7.0.0
- Kompatibilität mit Shopware 6.7.0
# 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
+10 -10
View File
@@ -3,20 +3,21 @@
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://plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.0.0/docs/en/documentation.html)
- Für die deutsche Dokumentation klicken Sie [hier](https://plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.0.0/docs/de/documentation.html)
- Pour la documentation Française, cliquez [ici](https://plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.0.0/docs/fr/documentation.html)
- Per la documentazione in tedesco, clicca [qui](https://plugin-documentation.vr-payment.de/vr-payment/shopware-6/7.0.0/docs/it/documentation.html)
- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.17/docs/en/documentation.html)
- Für die deutsche Dokumentation klicken Sie [hier](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.17/docs/de/documentation.html)
- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.17/docs/fr/documentation.html)
- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.17/docs/it/documentation.html)
## Installation
@@ -66,8 +67,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.0"
"version": "6.1.17"
}
+3 -3
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.0/">
<a href="@WalleeReleasePath()">
Source
</a>
</li>
@@ -185,7 +185,7 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment</code></
</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>
+3 -3
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.0/">
<a href="@WalleeReleasePath()">
Source
</a>
</li>
@@ -179,7 +179,7 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment</code></
</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>
+3 -3
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.0/">
<a href="@WalleeReleasePath()">
Source
</a>
</li>
@@ -172,7 +172,7 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment</code></
</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>
+3 -3
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.0/">
<a href="@WalleeReleasePath()">
Source
</a>
</li>
@@ -179,7 +179,7 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment</code></
</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>
@@ -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()]);
@@ -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;
}
}
+32 -1
View File
@@ -29,6 +29,31 @@ class SettingsService {
public const CONFIG_STOREFRONT_WEBHOOKS_UPDATE_ENABLED = 'storefrontWebhooksUpdateEnabled';
public const CONFIG_STOREFRONT_PAYMENTS_UPDATE_ENABLED = 'storefrontPaymentsUpdateEnabled';
/**
* List of config properties whose values allowed to be empty without triggering a warning in logger.
*
* This list is derived from testing of all config properties. The plugin fails only when either spaceId, userId, applicationKey and/or integration is empty.
* On top of that, spaceId, userId, applicationKey are marked as "required" input fields in admin interface.
*
* It is worth considering updating this list whenever a new config is introduced in settings.
* If new config is optional, left empty by design and not required for transactions to work, this list should be updated to avoid false-positive warnings.
*
* @var array
*/
private const ALLOWED_EMPTY_CONFIGS = [
// Options
self::CONFIG_SPACE_VIEW_ID,
self::CONFIG_LINE_ITEM_CONSISTENCY_ENABLED,
self::CONFIG_EMAIL_ENABLED,
// Storefront Options
self::CONFIG_STOREFRONT_INVOICE_DOWNLOAD_ENABLED,
// Advanced Options
self::CONFIG_STOREFRONT_WEBHOOKS_UPDATE_ENABLED,
self::CONFIG_STOREFRONT_PAYMENTS_UPDATE_ENABLED
];
/**
* @var \Shopware\Core\System\SystemConfig\SystemConfigService
*/
@@ -132,7 +157,13 @@ class SettingsService {
if ($property === '') {
continue;
}
if (!is_numeric($value) && empty($value)) {
// Space view id is only numeric setting which can be 0. If it is, rest of the loop is skipped.
if ($property === self::CONFIG_SPACE_VIEW_ID && $value === 0) {
$propertyValuePairs[$property] = $value;
continue;
}
// Check if $value is empty and is not in the list of configs which are allowed to be empty
if (empty($value) && !in_array($property, self::ALLOWED_EMPTY_CONFIGS, true)) {
$this->logger->warning(strtr('Empty value :value for settings :property.', [':property' => $property, ':value' => $value]));
}
$propertyValuePairs[$property] = $value;
@@ -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,7 @@ use VRPaymentPayment\Sdk\{Model\AddressCreate,
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.
*
@@ -73,12 +84,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 +111,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 +167,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 +183,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 +191,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 +272,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 +282,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 +296,55 @@ 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())
);
$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 +354,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') ?? []) : [];
}
}
+59 -4
View File
@@ -3,6 +3,7 @@
namespace VRPaymentPayment\Core\Util\Analytics;
use VRPayment\Sdk\ApiClient;
use Shopware\Core\Kernel;
/**
* Class Analytics
@@ -14,29 +15,83 @@ class Analytics {
public const SHOP_SYSTEM = 'x-meta-shop-system';
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';
/**
* @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::SHOP_SYSTEM_VERSION => $shopwareVersion,
self::SHOP_SYSTEM_AND_VERSION => 'shopware-' . $shopwareVersion,
self::PLUGIN_SYSTEM_VERSION => '6.1.17',
];
}
/**
* @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;
}
}
+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);
$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
*
@@ -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 %}
@@ -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) {
@@ -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 %}
@@ -5,12 +5,12 @@
{% 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"
:label="$tc('vrpayment-order.refund.refundQuantity.label')">
</mt-number-field>
</sw-number-field>
<div>
{{ $tc('vrpayment-order.refundAction.maxAvailableItemsToRefund') }}:
@@ -20,12 +20,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 %}
@@ -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 %}
@@ -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 %}
@@ -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>
@@ -46,14 +46,13 @@
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_title %}
<sw-single-select
v-model:value="selectedSalesChannelId"
labelProperty="translated.name"
:value="selectedSalesChannelId"
:options="salesChannel.map(sc => ({ id: sc.id, name: sc.translated.name }))"
labelProperty="name"
valueProperty="id"
:mapInheritance="props"
:isLoading="isLoading"
:options="salesChannel"
@update:value="onInput">
</sw-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
@@ -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>
@@ -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-CRU13hxm.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-CRU13hxm.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