Release 7.0.0

This commit is contained in:
andrewrowanwallee
2025-06-24 11:48:03 +02:00
parent 2f9a30ebd3
commit 2f5789aea8
42 changed files with 571 additions and 318 deletions
+7
View File
@@ -1,3 +1,10 @@
# 7.0.0
- Compatibility with Shopware 6.7.0
# 6.1.14
- Disable Recreate Cart for Headless Storefront Order
- Added the correct Exception Type to the finalize method
# 6.1.13
- Updated English documentation
- Added French, German and Italian documentation
+7
View File
@@ -1,3 +1,10 @@
# 7.0.0
- Kompatibilität mit Shopware 6.7.0
# 6.1.14
Warenkorb neu erstellen für Headless Storefront Order deaktivieren
Der korrekte Ausnahmetyp wurde zur Finalisierungsmethode hinzugefügt
# 6.1.13
Englische Dokumentation aktualisiert
Französische, deutsche und italienische Dokumentation hinzugefügt
+10 -10
View File
@@ -3,21 +3,20 @@
VR Payment Integration for Shopware 6
=============================
## **Overview**
The VR Payment Payment Plugin integrates modern payment processing into Shopware 6, offering features like iFrame-based payments, refunds, captures, and PCI compliance. It supports seamless integration with the [VR Payment Portal](https://gateway.vr-payment.de/) for managing transactions and payment methods.
The VR Payment plugin wraps around the VR Payment API. This library facilitates your interaction with various services such as transactions.
Please note that this plugin is for versions 6.5, 6.6 or 6.7. For the 6.4 plugin please visit [our Shopware 6.4 plugin](https://github.com/vr-payment/shopware-6-4).
## Requirements
- **Shopware Version:** 6.5.x or 6.6.x (see [compatibility table](#compatibility)).
- **PHP:** Minimum version as required by your Shopware installation (e.g., 7.4+).
- **VR Payment Account:** Obtain `Space ID`, `User ID`, and `API Key` from the [VR Payment Dashboard](https://gateway.vr-payment.de/).
- Shopware 6.7.x, 6.6.x or 6.5.x. See table below.
- PHP minimum version supported by the each shop version.
## Documentation
- For English documentation click [here](https://plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.14/docs/en/documentation.html)
- Für die deutsche Dokumentation klicken Sie [hier](https://plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.14/docs/de/documentation.html)
- Pour la documentation Française, cliquez [ici](https://plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.14/docs/fr/documentation.html)
- Per la documentazione in tedesco, clicca [qui](https://plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.14/docs/it/documentation.html)
- 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)
## Installation
@@ -67,7 +66,8 @@ Configure supported methods (e.g., credit cards, Apple Pay) via the [VR Payment
___________________________________________________________________________________
| Shopware 6 version | Plugin major version | Supported until |
|-------------------------------|------------------------|------------------------|
| Shopware 6.6.x | 6.x | Further notice |
| Shopware 6.7.x | 7.x | Further notice |
| Shopware 6.6.x | 6.x | December 2025 |
| Shopware 6.5.x | 5.x | October 2024 |
-----------------------------------------------------------------------------------
+4 -4
View File
@@ -53,11 +53,11 @@
"ext-json": "*",
"ext-mbstring": "*",
"php": ">=8.2",
"shopware/core": "~6.6.0",
"shopware/administration": "~6.6.0",
"shopware/storefront":"~6.6.0",
"shopware/core": "~6.7.0",
"shopware/administration": "~6.7.0",
"shopware/storefront":"~6.7.0",
"vrpayment/sdk": "^4.0.0"
},
"type": "shopware-platform-plugin",
"version": "6.1.14"
"version": "7.0.0"
}
+1 -1
View File
@@ -23,7 +23,7 @@
</a>
</li>
<li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/6.1.14/">
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.0.0/">
Source
</a>
</li>
+1 -1
View File
@@ -23,7 +23,7 @@
</a>
</li>
<li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/6.1.14/">
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.0.0/">
Source
</a>
</li>
+1 -1
View File
@@ -23,7 +23,7 @@
</a>
</li>
<li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/6.1.14/">
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.0.0/">
Source
</a>
</li>
+1 -1
View File
@@ -23,7 +23,7 @@
</a>
</li>
<li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/6.1.14/">
<a href="https://github.com/vr-payment/shopware-6/releases/tag/7.0.0/">
Source
</a>
</li>
@@ -499,6 +499,7 @@ class PaymentMethodConfigurationService {
'afterOrderEnabled' => true,
'active' => true,
'translations' => $this->getPaymentMethodConfigurationTranslation($paymentMethodConfiguration, $context),
'technicalName' => $paymentMethodConfiguration->getName(),
];
$data['mediaId'] = $this->upsertMedia($id, $paymentMethodConfiguration, $context);
@@ -8,7 +8,7 @@ use Shopware\Core\{
Checkout\Cart\CartException,
Checkout\Cart\LineItem\LineItem,
Checkout\Order\OrderEntity,
Checkout\Payment\Cart\AsyncPaymentTransactionStruct,
Checkout\Payment\Cart\PaymentTransactionStruct,
Framework\Context,
Framework\DataAbstractionLayer\Search\Criteria,
Framework\DataAbstractionLayer\Search\Filter\EqualsFilter,
@@ -115,7 +115,7 @@ class TransactionService
*
* A redirect to the url will be performed
*
* @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
* @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction
* @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext
*
* @return string
@@ -124,10 +124,14 @@ class TransactionService
* @throws \VRPayment\Sdk\VersioningException
*/
public function create(
AsyncPaymentTransactionStruct $transaction,
PaymentTransactionStruct $transaction,
SalesChannelContext $salesChannelContext
): string
{
$criteria = new Criteria([$transaction->getOrderTransactionId()]);
$criteria->addAssociation('order');
$orderTransaction = $this->container->get('order_transaction.repository')->search($criteria, $salesChannelContext->getContext())->first();
$salesChannelId = $salesChannelContext->getSalesChannel()->getId();
$settings = $this->settingsService->getSettings($salesChannelId);
$apiClient = $settings->getApiClient();
@@ -165,7 +169,7 @@ class TransactionService
$redirectUrl = $this->container->get('router')->generate(
'frontend.vrpayment.checkout.pay',
['orderId' => $transaction->getOrder()->getId(),],
['orderId' => $orderTransaction->getOrder()->getId(),],
UrlGeneratorInterface::ABSOLUTE_URL
);
@@ -177,8 +181,8 @@ class TransactionService
$this->upsert(
$createdTransaction,
$salesChannelContext->getContext(),
$transaction->getOrderTransaction()->getPaymentMethodId(),
$transaction->getOrder()->getSalesChannelId()
$orderTransaction->getPaymentMethodId(),
$orderTransaction->getOrder()->getSalesChannelId()
);
$_SESSION['transactionId'] = null;
$_SESSION['arrayOfPossibleMethods'] = null;
@@ -186,26 +190,26 @@ class TransactionService
$_SESSION['currencyCheck'] = null;
$this->holdDelivery($transaction->getOrder()->getId(), $salesChannelContext->getContext());
$this->holdDelivery($orderTransaction->getOrder()->getId(), $salesChannelContext->getContext());
return $redirectUrl;
}
/**
* @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
* @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction
* @param \Shopware\Core\Framework\Context $context
* @param int $vrpaymentTransactionId
* @param int $spaceId
*/
protected function addVRPaymentTransactionId(
AsyncPaymentTransactionStruct $transaction,
PaymentTransactionStruct $transaction,
Context $context,
int $vrpaymentTransactionId,
int $spaceId
): void
{
$data = [
'id' => $transaction->getOrderTransaction()->getId(),
'id' => $transaction->getOrderTransactionId(),
'customFields' => [
TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_TRANSACTION_ID => $vrpaymentTransactionId,
TransactionPayload::ORDER_TRANSACTION_CUSTOM_FIELDS_VRPAYMENT_SPACE_ID => $spaceId,
@@ -343,7 +347,7 @@ class TransactionService
*
* @return \Shopware\Core\Checkout\Order\OrderEntity
*/
private function getOrderEntity(string $orderId, Context $context): OrderEntity
protected function getOrderEntity(string $orderId, Context $context): OrderEntity
{
try {
$criteria = (new Criteria([$orderId]))->addAssociations(['deliveries']);
@@ -0,0 +1,59 @@
<?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,16 +4,30 @@ 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\AsyncPaymentTransactionStruct,
Checkout\Payment\Cart\PaymentHandler\AsynchronousPaymentHandlerInterface,
Checkout\Payment\Exception\AsyncPaymentFinalizeException,
Checkout\Payment\Exception\AsyncPaymentProcessException,
Checkout\Payment\Cart\PaymentTransactionStruct,
Checkout\Payment\Cart\PaymentHandler\AbstractPaymentHandler,
Checkout\Payment\Cart\PaymentHandler\PaymentHandlerType,
Checkout\Payment\PaymentException,
Checkout\Payment\Exception\CustomerCanceledAsyncPaymentException,
Framework\App\AppException,
Framework\Api\Context\SalesChannelApiSource,
Framework\Context,
Framework\DataAbstractionLayer\EntityRepository,
Framework\DataAbstractionLayer\Search\Criteria,
Framework\DataAbstractionLayer\Search\Sorting\FieldSorting,
Framework\Struct\Struct,
Framework\Validation\DataBag\RequestDataBag,
System\SalesChannel\SalesChannelContext
System\SalesChannel\Context\SalesChannelContextService,
System\SalesChannel\Context\SalesChannelContextServiceParameters
};
use Shopware\Core\Framework\Util\Random;
use VRPaymentPayment\Core\Checkout\Cart\CustomCartPersister;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartPersister;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\{
HttpFoundation\RedirectResponse,
HttpFoundation\Request
@@ -27,9 +41,14 @@ use VRPaymentPayment\Core\Api\Transaction\Service\TransactionService;
*
* @package VRPaymentPayment\Core\Checkout\PaymentHandler
*/
class VRPaymentPaymentHandler implements AsynchronousPaymentHandlerInterface
class VRPaymentPaymentHandler extends AbstractPaymentHandler
{
/**
* @var CustomCartPersister
*/
private CustomCartPersister $cartPersister;
/**
* @var \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService
*/
@@ -44,22 +63,34 @@ class VRPaymentPaymentHandler implements AsynchronousPaymentHandlerInterface
*/
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(TransactionService $transactionService, OrderTransactionStateHandler $orderTransactionStateHandler)
{
public function __construct(
CustomCartPersister $cartPersister,
TransactionService $transactionService,
OrderTransactionStateHandler $orderTransactionStateHandler,
SalesChannelContextService $salesChannelContextService,
EntityRepository $orderTransactionRepository
) {
$this->cartPersister = $cartPersister;
$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
@@ -73,78 +104,123 @@ class VRPaymentPaymentHandler implements AsynchronousPaymentHandlerInterface
*
* A redirect to the url will be performed
*
* @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
* @param \Shopware\Core\Framework\Validation\DataBag\RequestDataBag $dataBag
* @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext
* @param \Symfony\Component\HttpFoundation\Request
* @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction
* @param \Shopware\Core\Framework\Context $context
* @param \Shopware\Core\Framework\Struct\Struct $validateStruct
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function pay(
AsyncPaymentTransactionStruct $transaction,
RequestDataBag $dataBag,
SalesChannelContext $salesChannelContext
Request $request,
PaymentTransactionStruct $transaction,
Context $context,
?Struct $validateStruct
): RedirectResponse
{
try {
$orderTransactionId = $transaction->getOrderTransactionId();
$orderTransaction = $this->orderTransactionRepository->search(
(new Criteria([$orderTransactionId]))
->addAssociation('order'), $context
)->getEntities()->first();
$contextSource = $context->getSource();
if ($contextSource instanceof SalesChannelApiSource) {
$salesChannelContextId = $contextSource->getSalesChannelId();
}
$parameters = new SalesChannelContextServiceParameters($salesChannelContextId, $request->getSession()->get("sw-context-token", Random::getAlphanumericString(32)), originalContext: $context);
$salesChannelContext = $this->salesChannelContextService->get($parameters);
$redirectUrl = $transaction->getReturnUrl();
if ($transaction->getOrder()->getAmountTotal() > 0) {
if ($orderTransaction->getOrder()->getAmountTotal() > 0) {
$transactionId = $_SESSION['transactionId'] ?? null;
if ($transactionId === null) {
$this->transactionService->createPendingTransaction($salesChannelContext);
$this->transactionService->createPendingTransaction($transaction, $salesChannelContext);
}
$redirectUrl = $this->transactionService->create($transaction, $salesChannelContext);
}
return new RedirectResponse($redirectUrl);
} catch (\Exception $e) {
} catch (\Throwable $e) {
unset($_SESSION['transactionId']);
$errorMessage = 'An error occurred during the communication with external payment gateway : ' . $e->getMessage();
$this->logger->critical($errorMessage);
throw new \Exception($transaction->getOrderTransaction()->getId() . ': ' . $errorMessage);
throw PaymentException::customerCanceled($transaction->getOrderTransaction()->getId(), $errorMessage);
}
}
/**
* The finalize function will be called when the user is redirected back to shop from the payment gateway.
*
* Throw a @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext
* @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction
* @param \Shopware\Core\Framework\Context $context
* @throws \VRPayment\Sdk\ApiException
* @throws \VRPayment\Sdk\Http\ConnectionException
* @throws \VRPayment\Sdk\VersioningException
* @see AsyncPaymentFinalizeException exception if an error ocurres while calling an external payment API
* Throw a @see CustomerCanceledAsyncPaymentException exception if the customer canceled the payment process on
* payment provider page
*
* @throws \Exception when the payment was canceled by the customer
*/
public function finalize(
AsyncPaymentTransactionStruct $transaction,
Request $request,
SalesChannelContext $salesChannelContext
PaymentTransactionStruct $transaction,
Context $context
): void
{
if ($transaction->getOrder()->getAmountTotal() > 0) {
$orderTransactionId = $transaction->getOrderTransactionId();
$orderTransaction = $this->orderTransactionRepository->search(
(new Criteria([$orderTransactionId]))
->addAssociation('order'), $context
)->getEntities()->first();
if ($orderTransaction->getOrder()->getAmountTotal() > 0) {
$transactionEntity = $this->transactionService->getByOrderId(
$transaction->getOrder()->getId(),
$salesChannelContext->getContext()
$orderTransaction->getOrder()->getId(),
$context
);
$vRPaymentTransaction = $this->transactionService->read(
$transactionEntity->getTransactionId(),
$salesChannelContext->getSalesChannel()->getId()
$transactionEntity->getSalesChannelId()
);
if (in_array($vRPaymentTransaction->getState(), [TransactionState::FAILED])) {
$errorMessage = strtr('Customer canceled payment for :orderId on SalesChannel :salesChannelName', [
':orderId' => $transaction->getOrder()->getId(),
':salesChannelName' => $salesChannelContext->getSalesChannel()->getName(),
':orderId' => $orderTransaction->getOrder()->getId(),
':salesChannelName' => $transactionEntity->getSalesChannelId(),
]);
unset($_SESSION['transactionId']);
$this->logger->info($errorMessage);
throw PaymentException::customerCanceled($transaction->getOrderTransaction()->getId(), $errorMessage);
}
} else {
$this->orderTransactionStateHandler->paid($transaction->getOrderTransaction()->getId(), $salesChannelContext->getContext());
$this->orderTransactionStateHandler->paid($orderTransaction->getId(), $context);
}
$token = $request->getSession()->get('sw-context-token');
if ($token) {
$salesChannelId = $transactionEntity->getSalesChannelId();
$parameters = new SalesChannelContextServiceParameters($salesChannelId, $token, originalContext: $context);
$salesChannelContext = $this->salesChannelContextService->get($parameters);
$salesChannelContext->getContext()->addState('do-cart-delete');
$this->logger->info('Clearing cart with token: ' . $token);
$this->cartPersister->delete($salesChannelContext->getToken(), $salesChannelContext);
}
}
/**
* {@inheritDoc}
*/
public function supports(
PaymentHandlerType $type,
string $paymentMethodId,
Context $context
): bool {
if ($type === PaymentHandlerType::RECURRING) {
return false;
}
return true;
}
}
+150 -41
View File
@@ -8,10 +8,14 @@ use Shopware\Core\{Checkout\Cart\Tax\Struct\CalculatedTaxCollection,
Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity,
Checkout\Customer\CustomerEntity,
Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity,
Checkout\Payment\Cart\AsyncPaymentTransactionStruct,
Checkout\Order\OrderEntity,
Checkout\Payment\Cart\PaymentTransactionStruct,
Framework\DataAbstractionLayer\Search\Criteria,
System\SalesChannel\SalesChannelContext
};
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use VRPayment\Sdk\{Model\AddressCreate,
@@ -36,6 +40,10 @@ use VRPaymentPayment\Core\{Api\PaymentMethodConfiguration\Entity\PaymentMethodCo
Util\Payload\CustomProducts\CustomProductsLineItemTypes
};
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Core\Framework\Context;
use Shopware\Core\System\Tax\TaxEntity;
/**
* Class TransactionPayload
*
@@ -61,7 +69,7 @@ class TransactionPayload extends AbstractPayload
protected $salesChannelContext;
/**
* @var \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct
* @var \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct
*/
protected $transaction;
@@ -85,6 +93,10 @@ class TransactionPayload extends AbstractPayload
*/
protected $translator;
protected EntityRepository $orderTransactionRepository;
protected OrderEntity $order;
/**
* TransactionPayload constructor.
*
@@ -92,14 +104,14 @@ class TransactionPayload extends AbstractPayload
* @param \VRPaymentPayment\Core\Util\LocaleCodeProvider $localeCodeProvider
* @param \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext
* @param \VRPaymentPayment\Core\Settings\Struct\Settings $settings
* @param \Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct $transaction
* @param \Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct $transaction
*/
public function __construct(
ContainerInterface $container,
LocaleCodeProvider $localeCodeProvider,
SalesChannelContext $salesChannelContext,
Settings $settings,
AsyncPaymentTransactionStruct $transaction
PaymentTransactionStruct $transaction
)
{
$this->localeCodeProvider = $localeCodeProvider;
@@ -108,6 +120,23 @@ class TransactionPayload extends AbstractPayload
$this->transaction = $transaction;
$this->container = $container;
$this->translator = $this->container->get('translator');
$this->orderTransactionRepository = $this->container->get('order_transaction.repository');
$criteria = (new Criteria());
$criteria->addFilter(new EqualsFilter('id', $this->transaction->getOrderTransactionId()));
$orders = $this->orderTransactionRepository->search($criteria, $this->salesChannelContext->getContext())->getEntities();
$orderId = $orders->first()->getOrderId();
$criteria = new Criteria([$orderId]);
$criteria
->addAssociation('lineItems')
->addAssociation('orderCustomer')
->addAssociation('transactions')
->addAssociation('currency')
;
$this->order = $this->container->get('order.repository')->search($criteria, $this->salesChannelContext->getContext())->getEntities()->first();
}
/**
@@ -118,13 +147,21 @@ class TransactionPayload extends AbstractPayload
*/
public function get(int $version): TransactionPending
{
$customer = $this->salesChannelContext->getCustomer();
$customerId = $this->order->getOrderCustomer()->getCustomerId();
$criteria = new Criteria([$customerId]);
$criteria->addAssociation('activeBillingAddress')
->addAssociation('activeShippingAddress')
->addAssociation('activeShippingAddress')
->addAssociation('defaultBillingAddress')
->addAssociation('defaultShippingAddress')
->addAssociation('salutation');
$customer = $this->container->get('customer.repository')->search($criteria, $this->salesChannelContext->getContext())->getEntities()->first();
$lineItems = $this->getLineItems();
$billingAddress = $this->getAddressPayload($customer, $customer->getActiveBillingAddress());
$shippingAddress = $this->getAddressPayload($customer, $customer->getActiveShippingAddress(), false);
$customerId = null;
$customerName = null;
if ($customer->getGuest() === false) {
@@ -137,14 +174,14 @@ class TransactionPayload extends AbstractPayload
}
$transactionData = [
'currency' => $this->salesChannelContext->getCurrency()->getIsoCode(),
'customer_email_address' => $billingAddress->getEmailAddress(),
'currency' => $this->order->getCurrency()->getIsoCode(),
'customer_email_address' => $customer->getEmail(),
'customer_id' => $customerId,
'language' => $this->localeCodeProvider->getLocaleCodeFromContext($this->salesChannelContext->getContext()) ?? null,
'merchant_reference' => $this->fixLength($this->transaction->getOrder()->getOrderNumber(), 100),
'merchant_reference' => $this->fixLength($this->order->getOrderNumber(), 100),
'meta_data' => [
self::VRPAYMENT_METADATA_ORDER_ID => $this->transaction->getOrder()->getId(),
self::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID => $this->transaction->getOrderTransaction()->getId(),
self::VRPAYMENT_METADATA_ORDER_ID => $this->order->getId(),
self::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID => $this->order->getTransactions()->first()->getId(),
self::VRPAYMENT_METADATA_SALES_CHANNEL_ID => $this->salesChannelContext->getSalesChannel()->getId(),
self::VRPAYMENT_METADATA_CUSTOMER_NAME => $customerName,
],
@@ -161,8 +198,8 @@ class TransactionPayload extends AbstractPayload
$transactionData['meta_data']['additionalAddress2'] = $additionalAddress2;
}
if (!empty($this->transaction->getOrder()->getCustomerComment())) {
$transactionData['meta_data']['customer_comment'] = $this->transaction->getOrder()->getCustomerComment();
if (!empty($this->order->getCustomerComment())) {
$transactionData['meta_data']['customer_comment'] = $this->order->getCustomerComment();
}
$vatIds = $customer->getVatIds();
@@ -198,7 +235,7 @@ class TransactionPayload extends AbstractPayload
$transactionPayload->setAllowedPaymentMethodConfigurations([$paymentConfiguration->getPaymentMethodConfigurationId()]);
$successUrl = $this->transaction->getReturnUrl() . '&status=paid';
$failedUrl = $this->getFailUrl($this->transaction->getOrder()->getId()) . '&status=fail';
$failedUrl = $this->getFailUrl($this->order->getId()) . '&status=fail';
$transactionPayload->setSuccessUrl($successUrl)
->setFailedUrl($failedUrl);
@@ -219,7 +256,7 @@ class TransactionPayload extends AbstractPayload
protected function getLineItems(): array
{
$lineItems = [];
$items = $this->transaction->getOrder()->getLineItems();
$items = $this->order->getLineItems() ?? [];
foreach ($items as $shopLineItem) {
if ($this->shouldSkipLineItem($shopLineItem)) {
@@ -307,27 +344,90 @@ class TransactionPayload extends AbstractPayload
protected function addDiscountLineItem($discount, array &$lineItems): void
{
$calculatedPrice = $discount->getPrice();
$calculatedTaxesCollection = $calculatedPrice->getCalculatedTaxes();
$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);
$discountName = $discount->getLabel();
$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);
}
$lineItem->setAmountIncludingTax($amount)
->setName(sprintf('DISCOUNT: %s (%s%% tax)', $discount->getLabel(), $rate))
->setName($discountTitle)
->setQuantity(1)
->setShippingRequired(false)
->setSku('sku-discount-' . $rate . '-' . $discountName, 200)
->setSku($discountSkuName, 200)
->setType(LineItemType::DISCOUNT)
->setUniqueId('coupon-sku-discount-' . $rate . '-' . $rate . '-' . $discountName);
->setUniqueId('coupon-' . $discountSkuName);
$taxRate = new TaxCreate(['title' => 'Discount Tax: ' . $rate, 'rate' => $rate]);
$taxRate = new TaxCreate([
'title' => 'Discount Tax: ' . $rate,
'rate' => $rate,
]);
if ($this->order->getTaxStatus() !== 'tax-free') {
$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;
}
/**
@@ -336,7 +436,7 @@ class TransactionPayload extends AbstractPayload
protected function calculateDiscountAmount($calculatedTax): float
{
$amount = self::round($calculatedTax->getPrice());
if ($this->transaction->getOrder()->getTaxStatus() === 'net') {
if ($this->order->getTaxStatus() === 'net') {
$amount = self::round($amount + $calculatedTax->getTax());
}
return $amount;
@@ -357,7 +457,7 @@ class TransactionPayload extends AbstractPayload
*/
protected function addOptionalLineItems(array &$lineItems): void
{
if (count($this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes()) === 1) {
if (count($this->order->getShippingCosts()->getCalculatedTaxes()) === 1) {
if ($shippingLineItem = $this->getShippingLineItem()) {
$lineItems[] = $shippingLineItem;
}
@@ -379,7 +479,7 @@ class TransactionPayload extends AbstractPayload
protected function getCustomProductOptionLabel(string $lineItemParentId): string
{
$label = '';
foreach ($this->transaction->getOrder()->getLineItems() as $shopLineItem) {
foreach ($this->order->getLineItems() as $shopLineItem) {
if ($shopLineItem->getParentId() === $lineItemParentId && $shopLineItem->getType() === CustomProductsLineItemTypes::LINE_ITEM_TYPE_PRODUCT) {
$label = $shopLineItem->getLabel();
break;
@@ -404,10 +504,11 @@ class TransactionPayload extends AbstractPayload
$sku = $payLoad['productNumber'];
}
$sku = $this->fixLength($sku, 200);
$amount = $shopLineItem->getTotalPrice() ? self::round($shopLineItem->getTotalPrice()) : 0;
//include Tax Excluded for Net Tax display customer group
if ($this->transaction->getOrder()->getTaxStatus() === 'net') {
if ($this->order->getTaxStatus() === 'net') {
$amount = self::round($amount + $shopLineItem->getPrice()->getCalculatedTaxes()->getAmount());
}
@@ -443,8 +544,10 @@ class TransactionPayload extends AbstractPayload
}
if (!empty($taxes)) {
if ($this->order->getTaxStatus() !== 'tax-free') {
$lineItem->setTaxes($taxes);
}
}
if ($shopLineItem->getTotalPrice() >= 0) {
$lineItem->setType(LineItemType::PRODUCT);
@@ -519,31 +622,34 @@ class TransactionPayload extends AbstractPayload
{
try {
$amount = $this->transaction->getOrder()->getShippingTotal();
$amount = $this->order->getShippingTotal();
$amount = self::round($amount);
if ($amount > 0) {
$shippingName = $this->salesChannelContext->getShippingMethod()->getName() ?? $this->translator->trans('vrpayment.payload.shipping.name');
$taxes = $this->getTaxes(
$this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes(),
$this->order->getShippingCosts()->getCalculatedTaxes(),
$shippingName
);
if ($this->transaction->getOrder()->getTaxStatus() === 'net') {
$amount = self::round($amount + $this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes()->getAmount());
if ($this->order->getTaxStatus() === 'net') {
$amount = self::round($amount + $this->order->getShippingCosts()->getCalculatedTaxes()->getAmount());
}
$lineItem = (new LineItemCreate())
->setAmountIncludingTax($amount)
->setName($this->fixLength($shippingName . ' ' . $this->translator->trans('vrpayment.payload.shipping.lineItem'), 150))
->setQuantity($this->transaction->getOrder()->getShippingCosts()->getQuantity() ?? 1)
->setTaxes($taxes)
->setQuantity($this->order->getShippingCosts()->getQuantity() ?? 1)
->setSku($this->fixLength($shippingName . '-Shipping', 200))
/** @noinspection PhpParamsInspection */
->setType(LineItemType::SHIPPING)
->setUniqueId($this->fixLength($shippingName . '-Shipping', 200));
if ($this->order->getTaxStatus() !== 'tax-free') {
$lineItem->setTaxes($taxes);
}
if (!$lineItem->valid()) {
$this->logger->critical('Shipping LineItem payload invalid:', $lineItem->listInvalidProperties());
throw new InvalidPayloadException('Shipping LineItem payload invalid:' . json_encode($lineItem->listInvalidProperties()));
@@ -564,15 +670,15 @@ class TransactionPayload extends AbstractPayload
protected function getMultipleShippingLineItems(): array
{
try {
if ($this->transaction->getOrder()->getShippingTotal() > 0) {
if ($this->order->getShippingTotal() > 0) {
$lineItems = [];
$shippingName = $this->salesChannelContext->getShippingMethod()->getName() ?? $this->translator->trans('vrpayment.payload.shipping.name');
$isFirst = true;
foreach ($this->transaction->getOrder()->getShippingCosts()->getCalculatedTaxes() as $taxItem) {
foreach ($this->order->getShippingCosts()->getCalculatedTaxes() as $taxItem) {
$amount = self::round($taxItem->getPrice());
if ($this->transaction->getOrder()->getTaxStatus() === 'net') {
if ($this->order->getTaxStatus() === 'net') {
$amount = self::round($amount + $taxItem->getTax());
}
$taxRate = $taxItem->getTaxRate();
@@ -584,12 +690,15 @@ class TransactionPayload extends AbstractPayload
$lineItem = (new LineItemCreate())
->setAmountIncludingTax($amount)
->setName($this->fixLength($name . ' ' . $this->translator->trans('vrpayment.payload.shipping.lineItem'), 150))
->setQuantity($this->transaction->getOrder()->getShippingCosts()->getQuantity() ?? 1)
->setTaxes([$tax])
->setQuantity($this->order->getShippingCosts()->getQuantity() ?? 1)
->setSku($this->fixLength($name . '-Shipping', 200))
->setType($isFirst ? LineItemType::SHIPPING : LineItemType::FEE) // First item as SHIPPING, rest as FEE
->setUniqueId($this->fixLength($name . '-Shipping', 200));
if ($this->order->getTaxStatus() !== 'tax-free') {
$lineItem->setTaxes([$tax]);
}
if (!$lineItem->valid()) {
$this->logger->critical('Shipping LineItem payload invalid:', $lineItem->listInvalidProperties());
throw new InvalidPayloadException('Shipping LineItem payload invalid:' . json_encode($lineItem->listInvalidProperties()));
@@ -623,14 +732,14 @@ class TransactionPayload extends AbstractPayload
return $lineItem->getAmountIncludingTax();
}, $lineItems));
$adjustmentPrice = $this->transaction->getOrder()->getAmountTotal() - $lineItemPriceTotal;
$adjustmentPrice = $this->order->getAmountTotal() - $lineItemPriceTotal;
$adjustmentPrice = self::round($adjustmentPrice);
if (abs($adjustmentPrice) != 0) {
if ($this->settings->isLineItemConsistencyEnabled()) {
$error = strtr('LineItems total :lineItemTotal does not add up to order total :orderTotal', [
':lineItemTotal' => $lineItemPriceTotal,
':orderTotal' => $this->transaction->getOrder()->getAmountTotal(),
':orderTotal' => $this->order->getAmountTotal(),
]);
$this->logger->critical($error);
throw new \Exception($error);
@@ -4,21 +4,21 @@
@modal-close="$emit('modal-close')">
{% block vrpayment_order_action_completion_amount %}
<sw-checkbox-field
<mt-checkbox
:label="$tc('vrpayment-order.captureAction.button.text')"
v-model:value="isCompletion">
</sw-checkbox-field>
v-model:checked="isCompletion">
</mt-checkbox>
{% endblock %}
{% block vrpayment_order_action_completion_confirm_button %}
<template #modal-footer>
<sw-button variant="primary"
<mt-button variant="primary"
@click="completion">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</sw-button>
</mt-button>
</template>
{% endblock %}
<sw-loader v-if="isLoading"></sw-loader>
<mt-loader v-if="isLoading"></mt-loader>
</sw-modal>
{% endblock %}
@@ -4,23 +4,23 @@
@modal-close="$emit('modal-close')">
{% block vrpayment_order_action_refund_amount_by_amount %}
<sw-number-field
<mt-number-field
:max="refundableAmount"
:min="0"
v-model:value="refundAmount"
v-model="refundAmount"
:label="$tc('vrpayment-order.refund.refundAmount.label')"
:suffix="currency">
</sw-number-field>
</mt-number-field>
{% endblock %}
{% block vrpayment_order_action_refund_confirm_button_by_amount %}
<template #modal-footer>
<sw-button variant="primary" @click="refundByAmount()">
<mt-button variant="primary" @click="refundByAmount()">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</sw-button>
</mt-button>
</template>
{% endblock %}
<sw-loader v-if="isLoading"></sw-loader>
<mt-loader v-if="isLoading"></mt-loader>
</sw-modal>
{% endblock %}
@@ -4,13 +4,13 @@
@modal-close="$emit('modal-close')">
{% block vrpayment_order_action_refund_amount_partial %}
<sw-number-field
<mt-number-field
:max="this.$parent.$parent.itemRefundableAmount"
:min="0.00"
v-model:value="refundAmount"
v-model="refundAmount"
:label="$tc('vrpayment-order.refund.refundAmount.label')"
:suffix="currency">
</sw-number-field>
</mt-number-field>
<div>
{{ $tc('vrpayment-order.refundAction.maxAvailableAmountToRefund') }}:
@@ -20,12 +20,12 @@
{% block vrpayment_order_action_refund_confirm_button_partial %}
<template #modal-footer>
<sw-button variant="primary" @click="createPartialRefund(this.$parent.$parent.currentLineItem)">
<mt-button variant="primary" @click="createPartialRefund(this.$parent.$parent.currentLineItem)">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</sw-button>
</mt-button>
</template>
{% endblock %}
<sw-loader v-if="isLoading"></sw-loader>
<mt-loader v-if="isLoading"></mt-loader>
</sw-modal>
{% endblock %}
@@ -47,7 +47,9 @@ 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>
<sw-button variant="primary" @click="refundSelected()">
<mt-button variant="primary" @click="refundSelected()">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</sw-button>
</mt-button>
</template>
{% endblock %}
<sw-loader v-if="isLoading"></sw-loader>
<mt-loader v-if="isLoading"></mt-loader>
</sw-modal>
{% endblock %}
@@ -5,12 +5,12 @@
{% block vrpayment_order_action_refund_amount %}
<sw-number-field
<mt-number-field
:max="this.$parent.$parent.itemRefundableQuantity"
:min="0"
v-model:value="refundQuantity"
v-model="refundQuantity"
:label="$tc('vrpayment-order.refund.refundQuantity.label')">
</sw-number-field>
</mt-number-field>
<div>
{{ $tc('vrpayment-order.refundAction.maxAvailableItemsToRefund') }}:
@@ -20,12 +20,12 @@
{% block vrpayment_order_action_refund_confirm_button %}
<template #modal-footer>
<sw-button variant="primary" @click="refund()">
<mt-button variant="primary" @click="refund()">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</sw-button>
</mt-button>
</template>
{% endblock %}
<sw-loader v-if="isLoading"></sw-loader>
<mt-loader v-if="isLoading"></mt-loader>
</sw-modal>
{% endblock %}
@@ -4,21 +4,22 @@
@modal-close="$emit('modal-close')">
{% block vrpayment_order_action_void_amount %}
<sw-checkbox-field
{# Review if this v-model:checked="isVoid" needs to change to checked #}
<mt-checkbox
:label="$tc('vrpayment-order.voidAction.confirm.message')"
v-model:value="isVoid">
</sw-checkbox-field>
v-model:checked="isVoid">
</mt-checkbox>
{% endblock %}
{% block vrpayment_order_action_void_confirm_button %}
<template #modal-footer>
<sw-button variant="primary"
<mt-button variant="primary"
@click="voidPayment">
{{ $tc('vrpayment-order.refundAction.confirmButton.text') }}
</sw-button>
</mt-button>
</template>
{% endblock %}
<sw-loader v-if="isLoading"></sw-loader>
<mt-loader v-if="isLoading"></mt-loader>
</sw-modal>
{% endblock %}
@@ -1,6 +1,7 @@
{% block sw_order_detail_content_tabs_general %}
{% parent %}
{# sw-tabs-item will dissappear. See: https://github.com/shopware/shopware/blob/trunk/UPGRADE-6.7.md#sw-tabs-is-removed #}
<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 .sw-card-view__content {
.sw-order-detail-base .mt-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">
<sw-card :title="$tc('vrpayment-order.paymentDetails.cardTitle')">
<mt-card :title="$tc('vrpayment-order.paymentDetails.cardTitle')">
<template #grid>
{% block vrpayment_order_actions_section %}
<sw-card-section secondary slim>
<mt-card-section secondary slim>
{% block vrpayment_order_transaction_refunds_action_button %}
<sw-button
<mt-button
variant="primary"
size="small"
:disabled="transaction.state != 'FULFILL' || refundableAmount <= 0"
@click="spawnModal('refundByAmount')">
{{ $tc('vrpayment-order.buttons.label.refund') }}
</sw-button>
</mt-button>
{% endblock %}
{% block vrpayment_order_transaction_completion_action_button %}
<sw-button
<mt-button
variant="primary"
size="small"
:disabled="transaction.state != 'AUTHORIZED' || isLoading"
@click="spawnModal('completion')">
{{ $tc('vrpayment-order.buttons.label.completion') }}
</sw-button>
</mt-button>
{% endblock %}
{% block vrpayment_order_transaction_void_action_button %}
<sw-button
<mt-button
variant="primary"
size="small"
:disabled="transaction.state != 'AUTHORIZED' || isLoading"
@click="spawnModal('void')">
{{ $tc('vrpayment-order.buttons.label.void') }}
</sw-button>
</mt-button>
{% endblock %}
{% block vrpayment_order_transaction_download_invoice_action_button %}
<sw-button
<mt-button
variant="primary"
size="small"
:disabled="transaction.state != 'FULFILL'"
@click="downloadInvoice()">
{{ $tc('vrpayment-order.buttons.label.download-invoice') }}
</sw-button>
</mt-button>
{% endblock %}
{% block vrpayment_order_transaction_download_packing_slip_action_button %}
<sw-button
<mt-button
variant="primary"
size="small"
:disabled="transaction.state != 'FULFILL'"
@click="downloadPackingSlip()">
{{ $tc('vrpayment-order.buttons.label.download-packing-slip') }}
</sw-button>
</mt-button>
{% endblock %}
</sw-card-section>
</mt-card-section>
{% endblock %}
</template>
</sw-card>
</mt-card>
{% block vrpayment_order_transaction_history_card %}
<sw-card :title="$tc('vrpayment-order.transactionHistory.cardTitle')">
<mt-card :title="$tc('vrpayment-order.transactionHistory.cardTitle')">
<template #grid>
{% block vrpayment_order_transaction_history_grid %}
@@ -78,10 +78,10 @@
{% endblock %}
</template>
</sw-card>
</mt-card>
{% endblock %}
{% block vrpayment_order_transaction_line_items_card %}
<sw-card :title="$tc('vrpayment-order.lineItem.cardTitle')">
<mt-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>
</sw-card>
</mt-card>
{% endblock %}
{% block vrpayment_order_transaction_refunds_card %}
<sw-card :title="$tc('vrpayment-order.refund.cardTitle')" v-if="transactionData.refunds.length > 0">
<mt-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>
</sw-card>
</mt-card>
{% endblock %}
{% block vrpayment_order_actions_modal_refund_partial %}
<vrpayment-order-action-refund-partial
@@ -195,6 +195,6 @@
</vrpayment-order-action-void>
{% endblock %}
</div>
<sw-loader v-if="isLoading"></sw-loader>
<mt-loader v-if="isLoading"></mt-loader>
</div>
{% endblock %}
@@ -1,4 +1,4 @@
<sw-card class="sw-card"
<mt-card class="mt-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">
<sw-switch-field
<mt-switch
: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"
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
</template>
</sw-inherit-wrapper>
@@ -25,19 +25,19 @@
:inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_STOREFRONT_PAYMENTS_UPDATE_ENABLED]"
:customInheritationCheckFunction="checkBoolFieldInheritance">
<template #content="props">
<sw-switch-field
<mt-switch
: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"
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
</template>
</sw-inherit-wrapper>
</div>
</sw-container>
</sw-card>
</mt-card>
@@ -1,6 +1,6 @@
{% block vrpayment_settings_content_card_channel_config_credentials %}
<sw-card
class="sw-card"
<mt-card
class="mt-card"
:title="$tc('vrpayment-settings.settingForm.credentials.cardTitle')"
v-if="actualConfigData"
>
@@ -17,17 +17,17 @@
:inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_SPACE_ID]"
:customInheritationCheckFunction="checkNumberFieldInheritance">
<template #content="props">
<sw-number-field
<mt-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')"
:value="props.currentValue"
:model-value="props.currentValue"
:error="spaceIdErrorState"
@update:value="props.updateCurrentValue">
</sw-number-field>
@update:model-value="props.updateCurrentValue">
</mt-number-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -38,17 +38,17 @@
:inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_USER_ID]"
:customInheritationCheckFunction="checkNumberFieldInheritance">
<template #content="props">
<sw-number-field
<mt-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')"
:value="props.currentValue"
:model-value="props.currentValue"
:error="userIdErrorState"
@update:value="props.updateCurrentValue">
</sw-number-field>
@update:model-value="props.updateCurrentValue">
</mt-number-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -59,7 +59,7 @@
:inheritedValue="selectedSalesChannelId === null ? null : allConfigs['null'][CONFIG_APPLICATION_KEY]"
:customInheritationCheckFunction="checkTextFieldInheritance">
<template #content="props">
<sw-password-field
<mt-password-field
:name="CONFIG_APPLICATION_KEY"
:required="true"
:passwordToggleAble="true"
@@ -67,26 +67,29 @@
:label="$tc('vrpayment-settings.settingForm.credentials.applicationKey.label')"
:helpText="$tc('vrpayment-settings.settingForm.credentials.applicationKey.tooltipText')"
:disabled="props.isInherited || !acl.can('vrpayment.editor')"
:value="props.currentValue"
:model-value="props.currentValue"
:error="applicationKeyErrorState"
@update:value="props.updateCurrentValue">
</sw-password-field>
@update:model-value="props.updateCurrentValue">
</mt-password-field>
</template>
</sw-inherit-wrapper>
{% endblock %}
</div>
{% endblock %}
{% verbatim %}
<sw-container columns="1fr 1fr" gap="0px 30px">
<sw-button-process
<mt-button
variant="primary"
:isLoading="isTesting"
@click="emitCheckApiConnectionEvent">
{{ $tc('vrpayment-settings.settingForm.credentials.button.label') }}
</sw-button-process>
</mt-button>
</sw-container>
{% endverbatim %}
</sw-container>
{% endblock %}
</sw-card>
</mt-card>
{% endblock %}
@@ -1,5 +1,5 @@
{% block vrpayment_settings_content_card_channel_config_options %}
<sw-card class="sw-card"
<mt-card class="mt-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">
<sw-number-field
<mt-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"
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-number-field>
:model-value="props.currentValue"
@update:model-value="props.updateCurrentValue">
</mt-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">
<sw-switch-field
<mt-switch
: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"
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -75,16 +75,16 @@
:inheritedValue="selectedSalesChannelId == null ? null : allConfigs['null'][CONFIG_EMAIL_ENABLED]"
:customInheritationCheckFunction="checkBoolFieldInheritance">
<template #content="props">
<sw-switch-field
<mt-switch
: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"
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
</template>
</sw-inherit-wrapper>
{% endblock %}
@@ -92,6 +92,6 @@
{% endblock %}
</sw-container>
{% endblock %}
</sw-card>
</mt-card>
{% endblock %}
@@ -1,5 +1,5 @@
{% block vrpayment_settings_icon %}
<span class="sw-icon icon--vrpayment-multicolor sw-icon--multicolor">
<span class="mt-icon icon--vrpayment-multicolor mt-icon--multicolor" style="width: 16px; height: 16px;">
<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 @@
<sw-card class="sw-card"
<mt-card class="mt-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">
<sw-switch-field
<mt-switch
: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"
:value="props.currentValue"
@update:value="props.updateCurrentValue">
</sw-switch-field>
:checked="props.currentValue"
@update:checked="props.updateCurrentValue">
</mt-switch>
</template>
</sw-inherit-wrapper>
</div>
</sw-container>
</sw-card>
</mt-card>
@@ -5,7 +5,7 @@
<template #smart-bar-header>
<h2>
{{ $tc('sw-settings.index.title') }}
<sw-icon name="small-arrow-medium-right" small></sw-icon>
<mt-icon name="small-arrow-medium-right" size="16px"></mt-icon>
{{ $tc('vrpayment-settings.header') }}
</h2>
</template>
@@ -14,7 +14,7 @@
{% block vrpayment_settings_actions %}
<template #smart-bar-actions>
{% block vrpayment_settings_actions_save %}
<sw-button-process
<mt-button
v-model:value="isSaveSuccessful"
class="sw-settings-login-registration__save-action"
variant="primary"
@@ -22,7 +22,7 @@
:disabled="isLoading"
@click="onSave">
{{ $tc('vrpayment-settings.settingForm.save') }}
</sw-button-process>
</mt-button>
{% endblock %}
</template>
{% endblock %}
@@ -31,7 +31,7 @@
<template #content>
{% block vrpayment_settings_content_card %}
<sw-card-view>
<mt-card-view>
{% block vrpayment_settings_content_card_channel_config %}
<sw-sales-channel-config v-model:value="config"
@@ -42,7 +42,7 @@
<template #select="{ onInput, selectedSalesChannelId, salesChannel }">
{% block vrpayment_settings_content_card_channel_config_sales_channel_card %}
<sw-card title="Sales Channel Switch">
<mt-card title="Sales Channel Switch">
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_title %}
<sw-single-select
@@ -66,18 +66,19 @@
{% endblock %}
{% block vrpayment_settings_content_card_channel_config_sales_channel_card_footer_container_button %}
<sw-button-process
<sw-button
variant="primary"
v-model:value="isSetDefaultPaymentSuccessful"
:isLoading="isSettingDefaultPaymentMethods"
@click="onSetPaymentMethodDefault">
{{ $tc('vrpayment-settings.salesChannelCard.button.label') }}
</sw-button-process>
</sw-button>
{% endblock %}
</sw-container>
{% endblock %}
</template>
{% endblock %}
</sw-card>
</mt-card>
{% endblock %}
</template>
{% endblock %}
@@ -134,9 +135,9 @@
{% endblock %}
{% block vrpayment_settings_content_card_loading %}
<sw-loader v-if="isLoading"></sw-loader>
<mt-loader v-if="isLoading"></mt-loader>
{% endblock %}
</sw-card-view>
</mt-card-view>
{% endblock %}
</template>
@@ -65,18 +65,6 @@ Component.register('vrpayment-settings', {
};
},
created() {
// Registers a listener for the 'check-api-connection-event'.
// Triggered when this event is emitted.
this.$on('check-api-connection-event', this.onCheckApiConnection);
},
beforeDestroy() {
// Removes the listener for the 'check-api-connection-event'
// before the component is destroyed to prevent memory leaks.
this.$off('check-api-connection-event', this.onCheckApiConnection);
},
watch: {
config: {
handler(configData) {
File diff suppressed because one or more lines are too long
@@ -6,12 +6,21 @@
<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.async"/>
<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"/>
</service>
</services>
@@ -19,9 +19,10 @@
<call method="setContainer">
<argument type="service" id="service_container"/>
</call>
<call method="setTwig">
<!-- Removed in 6.7 -->
<!-- <call method="setTwig">
<argument type="service" id="twig"/>
</call>
</call> -->
</service>
<!-- Subscribers -->
@@ -0,0 +1,25 @@
{
"base": "/bundles/vrpaymentpayment/administration/",
"entryPoints": {
"v-r-payment-payment": {
"css": [
"/bundles/vrpaymentpayment/administration/assets/v-r-payment-payment-D4AH6HY2.css"
],
"dynamic": [],
"js": [
"/bundles/vrpaymentpayment/administration/assets/v-r-payment-payment-CRU13hxm.js"
],
"legacy": false,
"preload": []
}
},
"legacy": false,
"metadatas": {},
"version": [
"7.1.0",
7,
1,
0
],
"viteServer": null
}
@@ -0,0 +1,11 @@
{
"main.js": {
"file": "assets/v-r-payment-payment-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
@@ -0,0 +1 @@
.sw-order-detail .sw-tabs{margin-top:40px}.sw-order-detail .sw-order-detail-base .mt-card-view__content{overflow-x:visible;overflow-y:visible}.vrpayment-order-detail__data{display:grid}.vrpayment-order-detail__heading{padding-top:15px}
+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,13 +1,9 @@
{% 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">
@@ -144,10 +140,6 @@
</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 %}
@@ -1,53 +0,0 @@
{% 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 %}
+7 -3
View File
@@ -3,6 +3,7 @@
namespace VRPaymentPayment;
use Shopware\Core\{
Framework\Feature,
Framework\Plugin,
Framework\Plugin\Context\ActivateContext,
Framework\Plugin\Context\DeactivateContext,
@@ -21,6 +22,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\DirectoryLoader;
use Symfony\Component\DependencyInjection\Loader\GlobFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
// expect the vendor folder on Shopware store releases
if (file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
@@ -82,19 +84,21 @@ class VRPaymentPayment extends Plugin {
{
parent::build($container);
$locator = new FileLocator('Resources/config');
$confDir = \rtrim($this->getPath(), '/') . '/Resources/config';
$locator = new FileLocator($confDir);
$resolver = new LoaderResolver([
new YamlFileLoader($container, $locator),
new XmlFileLoader($container, $locator),
new GlobFileLoader($container, $locator),
new DirectoryLoader($container, $locator),
]);
$configLoader = new DelegatingLoader($resolver);
$confDir = \rtrim($this->getPath(), '/') . '/Resources/config';
$configLoader->load($confDir . '/{packages}/*.yaml', 'glob');
$configLoader->load('services/core/checkout.xml');
}
public function enrichPrivileges(): array