Release 6.1.12

This commit is contained in:
andrewrowanwallee
2025-03-05 12:03:51 +01:00
parent 350057e327
commit 3f291ef7ea
13 changed files with 219 additions and 159 deletions
+7
View File
@@ -1,3 +1,10 @@
# 6.1.12
- Compatibility with 6.6.10.x
- Prevent duplicate transactions being created when the first times out
- Fix for error when changing space credentials
- Payment status now shows refunded/partially refunded
- Order delivery status now shows 'open' instead of 'hold'
# 6.1.11 # 6.1.11
- Implement payment page integration. - Implement payment page integration.
- Fixed bug with duplicate payment methods appearing - Fixed bug with duplicate payment methods appearing
+7
View File
@@ -1,3 +1,10 @@
# 6.1.12
- Kompatibilität mit 6.6.10.x
- Verhindern Sie, dass beim ersten Timeout doppelte Transaktionen erstellt werden
- Fehler beim Ändern der Space-Anmeldeinformationen behoben
- Der Zahlungsstatus zeigt jetzt „erstattet/teilweise erstattet“ an
- Der Lieferstatus der Bestellung wird jetzt „Offen“ statt „Halten“ angezeigt.
# 6.1.11 # 6.1.11
- Integration der Zahlungsseite implementieren. - Integration der Zahlungsseite implementieren.
- Fehler mit doppelten angezeigten Zahlungsmethoden behoben - Fehler mit doppelten angezeigten Zahlungsmethoden behoben
+1 -1
View File
@@ -73,7 +73,7 @@ tail -f var/log/vrpayment_payment*.log
## Documentation ## Documentation
[Documentation](https://gateway.vr-payment.de/doc/shopware-6/6.1.11/docs/en/documentation.html) [Documentation](https://gateway.vr-payment.de/doc/shopware-6/6.1.12/docs/en/documentation.html)
## License ## License
+61 -61
View File
@@ -1,63 +1,63 @@
{ {
"authors": [ "authors": [
{ {
"homepage": "https://www.vr-payment.de/", "homepage": "https://www.vr-payment.de/",
"name": "VRPay" "name": "VRPay"
} }
], ],
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"VRPaymentPayment\\": "src/" "VRPaymentPayment\\": "src/"
} }
}, },
"description": "VRPayment integration for Shopware 6", "description": "VRPayment integration for Shopware 6",
"extra": { "extra": {
"copyright": "(c) by VRPay", "copyright": "(c) by VRPay",
"description": { "description": {
"de-DE": "VRPayment integration f\u00fcr Shopware 6", "de-DE": "VRPayment integration für Shopware 6",
"en-GB": "VRPayment integration for Shopware 6", "en-GB": "VRPayment integration for Shopware 6",
"fr-FR": "Int\u00e9gration de VRPayment pour Shopware 6", "fr-FR": "Intégration de VRPayment pour Shopware 6",
"it-IT": "Integrazione VRPayment per Shopware" "it-IT": "Integrazione VRPayment per Shopware"
}, },
"label": { "label": {
"de-DE": "VRPayment Produkte f\u00fcr Shopware 6", "de-DE": "VRPayment Produkte für Shopware 6",
"en-GB": "VRPayment Products for Shopware 6", "en-GB": "VRPayment Products for Shopware 6",
"fr-FR": "VRPayment Produits for Shopware 6", "fr-FR": "VRPayment Produits for Shopware 6",
"it-IT": "VRPayment Prodotti per Shopware 6" "it-IT": "VRPayment Prodotti per Shopware 6"
}, },
"manufacturerLink": { "manufacturerLink": {
"de-DE": "https://www.vr-payment.de/", "de-DE": "https://www.vr-payment.de/",
"en-GB": "https://www.vr-payment.de/", "en-GB": "https://www.vr-payment.de/",
"fr-FR": "https://www.vr-payment.de/", "fr-FR": "https://www.vr-payment.de/",
"it-IT": "https://www.vr-payment.de/" "it-IT": "https://www.vr-payment.de/"
}, },
"supportLink": { "supportLink": {
"de-DE": "https://www.vr-payment.de/hotline", "de-DE": "https://www.vr-payment.de/hotline",
"en-GB": "https://www.vr-payment.de/hotline", "en-GB": "https://www.vr-payment.de/hotline",
"fr-FR": "https://www.vr-payment.de/hotline", "fr-FR": "https://www.vr-payment.de/hotline",
"it-IT": "https://www.vr-payment.de/hotline" "it-IT": "https://www.vr-payment.de/hotline"
}, },
"shopware-plugin-class": "VRPaymentPayment\\VRPaymentPayment" "shopware-plugin-class": "VRPaymentPayment\\VRPaymentPayment"
}, },
"homepage": "https://www.vr-payment.de//", "homepage": "https://www.vr-payment.de//",
"keywords": [ "keywords": [
"VRPay", "VRPay",
"payment", "payment",
"php", "php",
"shopware" "shopware"
], ],
"license": "Apache-2.0", "license": "Apache-2.0",
"name": "vrpayment/shopware-6", "name": "vrpayment/shopware-6",
"require": { "require": {
"ext-curl": "*", "ext-curl": "*",
"ext-json": "*", "ext-json": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"php": ">=8.2", "php": ">=8.2",
"shopware/core": "6.6.*", "shopware/core": "~6.6.0",
"shopware/administration": "~6.6.0", "shopware/administration": "~6.6.0",
"shopware/storefront": "6.6.*", "shopware/storefront":"~6.6.0",
"vrpayment/sdk": "4.6.0" "vrpayment/sdk": "^4.0.0"
}, },
"type": "shopware-platform-plugin", "type": "shopware-platform-plugin",
"version": "6.1.11" "version": "6.1.12"
} }
+1 -1
View File
@@ -23,7 +23,7 @@
</a> </a>
</li> </li>
<li> <li>
<a href="https://github.com/vr-payment/shopware-6/releases/tag/6.1.11/"> <a href="https://github.com/vr-payment/shopware-6/releases/tag/6.1.12/">
Source Source
</a> </a>
</li> </li>
@@ -213,8 +213,7 @@ class PaymentMethodConfigurationService {
{ {
// Configuration // Configuration
$settings = $this->settingsService->getSettings($this->getSalesChannelId()); $settings = $this->settingsService->getSettings($this->getSalesChannelId());
$this->setSpaceId($settings->getSpaceId()) $this->setSpaceId($settings->getSpaceId())->setApiClient($settings->getApiClient());
->setApiClient($settings->getApiClient());
$this->disablePaymentMethodConfigurations($context); $this->disablePaymentMethodConfigurations($context);
$this->enablePaymentMethodConfigurations($context); $this->enablePaymentMethodConfigurations($context);
@@ -254,9 +253,14 @@ class PaymentMethodConfigurationService {
$paymentMethodData = []; $paymentMethodData = [];
$salesChannelPaymentMethodData = []; $salesChannelPaymentMethodData = [];
$criteria = (new Criteria())->addFilter(new EqualsFilter('spaceId', $this->getSpaceId())); $criteria = (new Criteria())->addFilter(new EqualsFilter('state', 'ACTIVE'));
$paymentMethodConfigurationEntities = $this->vRPaymentPaymentMethodConfigurationRepository /**
* @var $vRPaymentPMConfigurationRepository
*/
$vRPaymentPMConfigurationRepository = $this->container->get(PaymentMethodConfigurationEntityDefinition::ENTITY_NAME . '.repository');
$paymentMethodConfigurationEntities = $vRPaymentPMConfigurationRepository
->search($criteria, $context) ->search($criteria, $context)
->getEntities(); ->getEntities();
@@ -275,16 +279,11 @@ class PaymentMethodConfigurationService {
'id' => $paymentMethodConfigurationEntity->getId(), 'id' => $paymentMethodConfigurationEntity->getId(),
'active' => false, 'active' => false,
]; ];
$salesChannelPaymentMethodData[] = [
'paymentMethodId' => $paymentMethodConfigurationEntity->getId(),
];
} }
try { try {
$this->vRPaymentPaymentMethodConfigurationRepository->update($data, $context); $this->vRPaymentPaymentMethodConfigurationRepository->update($data, $context);
$this->paymentMethodRepository->update($paymentMethodData, $context); $this->paymentMethodRepository->update($paymentMethodData, $context);
$this->salesChannelPaymentRepository->delete($salesChannelPaymentMethodData, $context);
} catch (\Exception $exception) { } catch (\Exception $exception) {
$this->logger->critical($exception->getMessage()); $this->logger->critical($exception->getMessage());
} }
@@ -369,7 +368,13 @@ class PaymentMethodConfigurationService {
]; ];
$this->upsertPaymentMethod($id, $paymentMethodConfiguration, $context); $this->upsertPaymentMethod($id, $paymentMethodConfiguration, $context);
$this->vRPaymentPaymentMethodConfigurationRepository->upsert([$data], $context);
try {
$this->container->get(PaymentMethodConfigurationEntityDefinition::ENTITY_NAME . '.repository')->upsert([$data], $context);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [$e->getTraceAsString()]);
}
} }
} }
@@ -500,7 +505,12 @@ class PaymentMethodConfigurationService {
$data = array_filter($data); $data = array_filter($data);
$this->paymentMethodRepository->upsert([$data], $context); try {
$this->paymentMethodRepository->upsert([$data], $context);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), [$e->getTraceAsString()]);
}
} }
/** /**
@@ -132,13 +132,12 @@ class TransactionService
$settings = $this->settingsService->getSettings($salesChannelId); $settings = $this->settingsService->getSettings($salesChannelId);
$apiClient = $settings->getApiClient(); $apiClient = $settings->getApiClient();
$failedStates = [ $transactionId = $_SESSION['transactionId'] ?? null;
TransactionState::DECLINE, if ($transactionId !== null) {
TransactionState::FAILED, $pendingTransaction = $this->read($_SESSION['transactionId'], $salesChannelId);
TransactionState::VOIDED, }
];
$pendingTransaction = $this->read($_SESSION['transactionId'], $salesChannelId); if ($transactionId === null || $pendingTransaction === null || $pendingTransaction->getState() !== TransactionState::PENDING) {
if (in_array($pendingTransaction->getState(), $failedStates)) {
unset($_SESSION['transactionId']); unset($_SESSION['transactionId']);
$pendingTransactionId = $this->createPendingTransaction($salesChannelContext); $pendingTransactionId = $this->createPendingTransaction($salesChannelContext);
$pendingTransaction = $this->read($pendingTransactionId, $salesChannelId); $pendingTransaction = $this->read($pendingTransactionId, $salesChannelId);
@@ -638,25 +638,46 @@ class WebHookController extends AbstractController {
private function unholdDelivery(string $orderId, Context $context): void private function unholdDelivery(string $orderId, Context $context): void
{ {
try { try {
/** $criteria = new Criteria([$orderId]);
* @var OrderDeliveryStateHandler $orderDeliveryStateHandler $criteria->addAssociation('deliveries.stateMachineState');
*/ $order = $this->container->get('order.repository')
$order = $this->getOrderEntity($orderId, $context); ->search($criteria, $context)
/** ->first();
* @var OrderDeliveryEntity $orderDelivery
*/ if (!$order) {
$this->logger->info('Order not found: ' . $orderId);
return;
}
/** @var OrderDeliveryEntity|null $orderDelivery */
$orderDelivery = $order->getDeliveries()?->last(); $orderDelivery = $order->getDeliveries()?->last();
if (null === $orderDelivery) { if (null === $orderDelivery) {
$this->logger->info('No deliveries found for order: ' . $orderId);
return; return;
} }
if ($orderDelivery->getStateMachineState()?->getTechnicalName() !== OrderDeliveryStateHandler::STATE_HOLD){
$orderDeliveryState = $orderDelivery->getStateMachineState();
if (!$orderDeliveryState) {
$this->logger->info('Order delivery state is null for order: ' . $orderId);
return; return;
} }
$technicalName = $orderDeliveryState->getTechnicalName();
$this->logger->info('Order delivery state: ' . $technicalName);
if ($technicalName !== OrderDeliveryStateHandler::STATE_HOLD) {
$this->logger->info('Order delivery is not on hold, skipping unhold process.');
return;
}
/** @var OrderDeliveryStateHandler $orderDeliveryStateHandler */
$orderDeliveryStateHandler = $this->container->get(OrderDeliveryStateHandler::class); $orderDeliveryStateHandler = $this->container->get(OrderDeliveryStateHandler::class);
$orderDeliveryStateHandler->unhold($orderDelivery->getId(), $context); $orderDeliveryStateHandler->unhold($orderDelivery->getId(), $context);
$this->logger->info('Successfully unheld order delivery for order: ' . $orderId);
} catch (\Exception $exception) { } catch (\Exception $exception) {
$this->logger->info($exception->getMessage(), $exception->getTrace()); $this->logger->error('Error unholding order delivery: ' . $exception->getMessage(), $exception->getTrace());
} }
} }
@@ -125,41 +125,21 @@ class WebHookRefundStrategy extends WebHookStrategyBase implements WebhookStrate
$orderId = $this->getOrderIdByTransaction($refund); $orderId = $this->getOrderIdByTransaction($refund);
if(!empty($orderId)) { if(!empty($orderId)) {
$this->executeLocked($orderId, $context, function () use ($orderId, $refund, $context, $request) { $this->executeLocked($orderId, $context, function () use ($orderId, $refund, $context, $request) {
if ($request->getListenerEntityTechnicalName() == WebHookRequest::REFUND && $request->getState() == RefundState::SUCCESSFUL) {
$this->refundService->upsert($refund, $context);
$orderTransactionId = $refund->getTransaction()->getMetaData()[TransactionPayload::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID];
$orderTransaction = $this->getOrderTransaction($orderId, $context);
$this->refundService->upsert($refund, $context);
$orderTransactionId = $refund->getTransaction()->getMetaData()[TransactionPayload::VRPAYMENT_METADATA_ORDER_TRANSACTION_ID];
$orderTransaction = $this->getOrderTransaction($orderId, $context);
if (
in_array(
$orderTransaction->getStateMachineState()?->getTechnicalName(),
[
OrderTransactionStates::STATE_PAID,
OrderTransactionStates::STATE_PARTIALLY_PAID,
]
) &&
($request->getState() == RefundState::SUCCESSFUL)
) {
if ($refund->getAmount() == $orderTransaction->getAmount()->getTotalPrice()) {
$this->orderTransactionStateHandler->refund($orderTransactionId, $context);
} else {
if ($refund->getAmount() < $orderTransaction->getAmount()->getTotalPrice()) {
$this->orderTransactionStateHandler->refundPartially($orderTransactionId, $context);
}
}
} elseif ($orderTransaction->getStateMachineState()?->getTechnicalName() ===
OrderTransactionStates::STATE_PARTIALLY_REFUNDED &&
($request->getState() == RefundState::SUCCESSFUL)
) {
$transactionByOrderTransactionId = $this->transactionService->getByOrderTransactionId($orderTransactionId, $context); $transactionByOrderTransactionId = $this->transactionService->getByOrderTransactionId($orderTransactionId, $context);
$totalRefundedAmount = $this->getTotalRefundedAmount($transactionByOrderTransactionId->getTransactionId(), $context); $totalRefundedAmount = $this->getTotalRefundedAmount($transactionByOrderTransactionId->getTransactionId(), $context);
if (floatval($orderTransaction->getAmount()->getTotalPrice()) - $totalRefundedAmount <= 0) { $leftToRefund = floatval($orderTransaction->getAmount()->getTotalPrice()) - $totalRefundedAmount;
if ($leftToRefund > 0) {
$this->orderTransactionStateHandler->refundPartially($orderTransactionId, $context);
} elseif ($leftToRefund === floatval(0)) { // This trick is used, because it's float type and 0 is int
$this->orderTransactionStateHandler->refund($orderTransactionId, $context); $this->orderTransactionStateHandler->refund($orderTransactionId, $context);
} }
} }
}); });
} }
@@ -306,6 +306,14 @@ abstract class WebHookStrategyBase implements WebHookStrategyInterface {
return $this->getOrderEntity($orderId, $context)->getTransactions()->last(); return $this->getOrderEntity($orderId, $context)->getTransactions()->last();
} }
/**
* Unholds the delivery of an order.
*
* This method changes the state of an order's last delivery from 'held' to 'released', allowing further processing like shipping.
*
* @param string $orderId The unique identifier of the order.
* @param Context $context The context of the current operation, including scope and permissions.
*/
/** /**
* Unholds the delivery of an order. * Unholds the delivery of an order.
* *
@@ -317,22 +325,46 @@ abstract class WebHookStrategyBase implements WebHookStrategyInterface {
protected function unholdDelivery(string $orderId, Context $context): void protected function unholdDelivery(string $orderId, Context $context): void
{ {
try { try {
$order = $this->getOrderEntity($orderId, $context); $criteria = new Criteria([$orderId]);
/** @var OrderDeliveryEntity $orderDelivery */ $criteria->addAssociation('deliveries.stateMachineState');
$order = $this->container->get('order.repository')
->search($criteria, $context)
->first();
if (!$order) {
$this->logger->info('Order not found: ' . $orderId);
return;
}
/** @var OrderDeliveryEntity|null $orderDelivery */
$orderDelivery = $order->getDeliveries()?->last(); $orderDelivery = $order->getDeliveries()?->last();
if (null === $orderDelivery) { if (null === $orderDelivery) {
$this->logger->info('No deliveries found for order: ' . $orderId);
return; return;
} }
if ($orderDelivery->getStateMachineState()?->getTechnicalName() !== OrderDeliveryStateHandler::STATE_HOLD){ $orderDeliveryState = $orderDelivery->getStateMachineState();
if (!$orderDeliveryState) {
$this->logger->info('Order delivery state is null for order: ' . $orderId);
return; return;
} }
$technicalName = $orderDeliveryState->getTechnicalName();
$this->logger->info('Order delivery state: ' . $technicalName);
if ($technicalName !== OrderDeliveryStateHandler::STATE_HOLD) {
$this->logger->info('Order delivery is not on hold, skipping unhold process.');
return;
}
/** @var OrderDeliveryStateHandler $orderDeliveryStateHandler */ /** @var OrderDeliveryStateHandler $orderDeliveryStateHandler */
$orderDeliveryStateHandler = $this->container->get(OrderDeliveryStateHandler::class); $orderDeliveryStateHandler = $this->container->get(OrderDeliveryStateHandler::class);
$orderDeliveryStateHandler->unhold($orderDelivery->getId(), $context); $orderDeliveryStateHandler->unhold($orderDelivery->getId(), $context);
$this->logger->info('Successfully unheld order delivery for order: ' . $orderId);
} catch (\Exception $exception) { } catch (\Exception $exception) {
$this->logger->info($exception->getMessage(), $exception->getTrace()); $this->logger->error('Error unholding order delivery: ' . $exception->getMessage(), $exception->getTrace());
} }
} }
+6 -3
View File
@@ -295,7 +295,9 @@ class TransactionPayload extends AbstractPayload
}); });
if ($discounts) { if ($discounts) {
$this->addDiscountLineItem(current($discounts), $lineItems); foreach ($discounts as $discount) {
$this->addDiscountLineItem($discount, $lineItems);
}
} }
} }
@@ -312,13 +314,14 @@ class TransactionPayload extends AbstractPayload
$lineItem = new LineItemCreate(); $lineItem = new LineItemCreate();
$amount = $this->calculateDiscountAmount($calculatedTax); $amount = $this->calculateDiscountAmount($calculatedTax);
$discountName = $discount->getLabel();
$lineItem->setAmountIncludingTax($amount) $lineItem->setAmountIncludingTax($amount)
->setName(sprintf('DISCOUNT: %s (%s%% tax)', $discount->getLabel(), $rate)) ->setName(sprintf('DISCOUNT: %s (%s%% tax)', $discount->getLabel(), $rate))
->setQuantity(1) ->setQuantity(1)
->setShippingRequired(false) ->setShippingRequired(false)
->setSku('sku-discount-' . $rate, 200) ->setSku('sku-discount-' . $rate . '-' . $discountName, 200)
->setType(LineItemType::DISCOUNT) ->setType(LineItemType::DISCOUNT)
->setUniqueId('coupon-sku-discount-' . $rate . '-' . $rate); ->setUniqueId('coupon-sku-discount-' . $rate . '-' . $rate . '-' . $discountName);
$taxRate = new TaxCreate(['title' => 'Discount Tax: ' . $rate, 'rate' => $rate]); $taxRate = new TaxCreate(['title' => 'Discount Tax: ' . $rate, 'rate' => $rate]);
$lineItem->setTaxes([$taxRate]); $lineItem->setTaxes([$taxRate]);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long