Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog
All notable changes to this project will be documented in this file.

## [2.0.9]
### Added
- Support for sales channel–specific terminals for payment methods.

## [2.0.8]
### Fixed
- Payment status was shown as Failed even though the order was placed successfully.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Docs/Configuration/shopware_setup_altapay_credentials.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "AltaPay plugin for Shopware 6",
"type": "shopware-platform-plugin",
"license": "MIT",
"version": "2.0.8",
"version": "2.0.9",
"authors": [
{
"name": "AltaPay A/S",
Expand Down
35 changes: 18 additions & 17 deletions src/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ public function __construct(
public function getPayments(Request $request): JsonApiResponse|Response
{
$orderId = $request->get('orderId');
/** @var ?OrderEntity $order */
$order = $this->orderRepository->search(new Criteria([$orderId]), Context::createDefaultContext())->first();
if (!$order) {
return new Response(status: 400);
}
/** @var $order OrderEntity */
$response = $this->paymentService->getTransaction($order, $order->getSalesChannelId());
$responseAsXml = new \SimpleXMLElement($response->getBody()->getContents());
return new JsonApiResponse(json_encode($responseAsXml));
Expand All @@ -45,10 +45,7 @@ public function capture(Request $request): JsonApiResponse|Response
$orderId = $request->get('orderId');
$captureAmount = $request->get('captureAmount');
$context = Context::createDefaultContext();
$criteria = new Criteria([$orderId]);
$criteria->addAssociation('transactions')
->addSorting(new FieldSorting('transactions.createdAt', FieldSorting::DESCENDING));
$order = $this->orderRepository->search($criteria, $context)->first();
$order = $this->getOrder($orderId, $context);
if (!$order) {
return new JsonApiResponse(['success' => false, 'message' => 'Order not found.'], 400);
}
Expand All @@ -69,7 +66,6 @@ public function capture(Request $request): JsonApiResponse|Response
return new JsonApiResponse(['success' => false, 'message' => 'The capture amount exceeds the remaining amount.'], 400);
}

/** @var $order OrderEntity */
$response = $this->paymentService->captureReservation($order, $order->getSalesChannelId(), null, $captureAmount);
$responseAsXml = new \SimpleXMLElement($response->getBody()->getContents());
if ((string)$responseAsXml->Body?->Result === "Success") {
Expand All @@ -96,10 +92,7 @@ public function refund(Request $request): JsonApiResponse|Response
$orderId = $request->get('orderId');
$refundAmount = $request->get('refundAmount');
$context = Context::createDefaultContext();
$criteria = new Criteria([$orderId]);
$criteria->addAssociation('transactions')
->addSorting(new FieldSorting('transactions.createdAt', FieldSorting::DESCENDING));
$order = $this->orderRepository->search($criteria, $context)->first();
$order = $this->getOrder($orderId, $context);
if (!$order) {
return new JsonApiResponse(['success' => false, 'message' => 'Order not found.'], 400);
}
Expand All @@ -120,7 +113,6 @@ public function refund(Request $request): JsonApiResponse|Response
return new JsonApiResponse(['success' => false, 'message' => 'The order has already been fully refunded.'], 400);
}

/** @var $order OrderEntity */
$response = $this->paymentService->refundCapturedReservation(
$order->getCustomFields()[PaymentService::ALTAPAY_TRANSACTION_ID_CUSTOM_FIELD],
$order->getSalesChannelId(),
Expand Down Expand Up @@ -149,25 +141,34 @@ public function cancel(Request $request): JsonApiResponse|Response
{
$orderId = $request->get('orderId');
$context = Context::createDefaultContext();
$criteria = new Criteria([$orderId]);
$criteria->addAssociation('transactions')
->addSorting(new FieldSorting('transactions.createdAt', FieldSorting::DESCENDING));
$order = $this->orderRepository->search($criteria, $context)->first();
$order = $this->getOrder($orderId, $context);
if (!$order) {
return new Response(status: 400);
}
/** @var $order OrderEntity */

$response = $this->paymentService->releaseReservation(
$order->getCustomFields()[PaymentService::ALTAPAY_TRANSACTION_ID_CUSTOM_FIELD],
$order->getSalesChannelId()
);
$responseAsXml = new \SimpleXMLElement($response->getBody()->getContents());
if ((string)$responseAsXml->Body?->Result === "Success") {
$this->orderTransactionStateHandler->cancel(
$order->getTransactions()->first()->getId(), // todo get right transaction
$order->getTransactions()?->first()->getId(),
$context
);
}
return new JsonApiResponse(json_encode($responseAsXml));
}
private function getOrder(string $orderId, ?Context $context = null): ?OrderEntity
{
if ($context === null) {
$context = Context::createDefaultContext();
}
$criteria = new Criteria([$orderId]);
$criteria->addAssociation('transactions')
->addSorting(new FieldSorting('transactions.createdAt', FieldSorting::DESCENDING));

/** @var ?OrderEntity */
return $this->orderRepository->search($criteria, $context)->first();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected function restoreCart(Cart $cart, OrderEntity $orderEntity, SalesChanne
->addAssociation('paymentMethod');


/** @var OrderTransactionEntity $orderTransaction */
/** @var OrderTransactionEntity|null $orderTransaction */
$orderTransaction = $this->orderTransactionRepository->search($criteria, $context->getContext())->first();

if ($orderTransaction) {
Expand Down
43 changes: 43 additions & 0 deletions src/Resources/config/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,47 @@
<defaultValue>form_checkout_div</defaultValue>
</input-field>
</card>
<card>
<title>Terminal setup</title>
<input-field>
<name>terminal1</name>
<label>Terminal 1</label>
</input-field>
<input-field>
<name>terminal2</name>
<label>Terminal 2</label>
</input-field>
<input-field>
<name>terminal3</name>
<label>Terminal 3</label>
</input-field>
<input-field>
<name>terminal4</name>
<label>Terminal 4</label>
</input-field>
<input-field>
<name>terminal5</name>
<label>Terminal 5</label>
</input-field>
<input-field>
<name>terminal6</name>
<label>Terminal 6</label>
</input-field>
<input-field>
<name>terminal7</name>
<label>Terminal 7</label>
</input-field>
<input-field>
<name>terminal8</name>
<label>Terminal 8</label>
</input-field>
<input-field>
<name>terminal9</name>
<label>Terminal 9</label>
</input-field>
<input-field>
<name>terminal10</name>
<label>Terminal 10</label>
</input-field>
</card>
</config>
13 changes: 13 additions & 0 deletions src/Service/PaymentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class PaymentService extends AbstractPaymentHandler
public const ALTAPAY_TRANSACTION_PAYMENT_NATURE_CUSTOM_FIELD = "wexoAltapayTransactionPaymentNature";
public const ALTAPAY_IP_ADDRESS_SET = ["185.206.120.0/24", "2a10:a200::/29", '185.203.232.129', '185.203.233.129']; //NOSONAR
public const ALTAPAY_ORDER_STATUS = "altaPayOrderStatus";
public const ALTAPAY_SALES_CHANNEL_TERMINAL_ID = "altapaySalesChannelTerminalId";

public function __construct(
protected readonly SystemConfigService $systemConfigService,
Expand Down Expand Up @@ -179,6 +180,18 @@ public function pay(

$paymentMethod = $salesChannelContext->getPaymentMethod();
$terminal = $paymentMethod->getTranslated()['customFields'][self::ALTAPAY_TERMINAL_ID_CUSTOM_FIELD];
$salesChannelTerminal = $paymentMethod->getTranslated()['customFields'][self::ALTAPAY_SALES_CHANNEL_TERMINAL_ID];

if (!empty($salesChannelTerminal)) {
$field = 'WexoAltaPay.config.' . $salesChannelTerminal;
$salesChannelTerminalValue = $this->systemConfigService->get($field, $order->getSalesChannelId());

if (!empty($salesChannelTerminalValue)) {
$terminal = $salesChannelTerminalValue;
}

}

$paymentRequestType = ($paymentMethod->getTranslated()['customFields'][self::ALTAPAY_AUTO_CAPTURE_CUSTOM_FIELD] ?? null) ? 'paymentAndCapture' : 'payment';
try {
$altaPayResponse = $this->createPaymentRequest(
Expand Down
54 changes: 54 additions & 0 deletions src/Service/Setup/CustomFieldSetupService.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,60 @@ private function createPaymentMethodCustomField(Context $context): void
context: $context
);

$terminals = [];
$languages = ['de-DE', 'en-GB', 'da-DK'];

// Add default empty option
$terminals[] = [
'label' => [
'de-DE' => 'Wählen Sie ein Terminal aus',
'en-GB' => 'Select a terminal',
'da-DK' => 'Vælg en terminal',
],
'value' => '',
];

for ($i = 1; $i <= 10; $i++) {
$label = [];

foreach ($languages as $lang) {
$label[$lang] = 'terminal ' . $i;
}

$terminals[] = [
'label' => $label,
'value' => 'terminal' . $i,
];
}

$this->addCustomField(
name: PaymentService::ALTAPAY_SALES_CHANNEL_TERMINAL_ID,
type: CustomFieldTypes::SELECT,
config: [
'customFieldPosition' => 4,
'componentName' => 'sw-single-select',
'customFieldType' => 'select',
'label' => [
'de-DE' => 'Sales Channel - AltaPay Terminal-ID',
'en-GB' => 'Sales Channel - AltaPay Terminal ID',
'da-DK' => 'Sales Channel - AltaPay Terminal-ID',
],
'placeholder' => [
'de-DE' => 'Wählen Sie ein Terminal aus...',
'en-GB' => 'Select a terminal...',
'da-DK' => 'Vælg en terminal...',
],
'helpText' => [
'de-DE' => 'Wählen Sie die Terminal-Konfiguration für den Vertriebskanal aus. Falls leer gelassen, wird die Standard-Terminal-ID aus der Zahlungsmethode verwendet.',
'en-GB' => 'Select the terminal configuration for the sales channel. If left empty, the default terminal ID from the payment method will be used.',
'da-DK' => 'Vælg terminal-konfigurationen for salgskanalen. Hvis den efterlades tom, vil standard terminal-ID fra betalingsmetoden blive brugt.',
],
'options' => $terminals,
],
customFieldSetId: $fieldSetId,
context: $context
);

}

private function addCustomField(
Expand Down
4 changes: 4 additions & 0 deletions src/Subscriber/PaymentMethodSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\DefaultPayment;
use Shopware\Core\Checkout\Payment\PaymentEvents;
use Shopware\Core\Checkout\Payment\PaymentMethodCollection;
use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
Expand All @@ -16,6 +17,9 @@

class PaymentMethodSubscriber implements EventSubscriberInterface
{
/**
* @param EntityRepository<PaymentMethodCollection> $paymentMethodRepository
*/
public function __construct(
protected EntityRepository $paymentMethodRepository,
protected PluginIdProvider $pluginIdProvider
Expand Down
2 changes: 1 addition & 1 deletion src/WexoAltaPay.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class WexoAltaPay extends Plugin
public const ALTAPAY_FIELD_SET_NAME = "wexoAltaPay";
public const ALTAPAY_PAYMENT_METHOD_FIELD_SET_NAME = "wexoAltaPayPaymentMethod";
public const ALTAPAY_CART_TOKEN = "wexoAltaPayCartToken";
public const ALTAPAY_PLUGIN_VERSION = '2.0.8';
public const ALTAPAY_PLUGIN_VERSION = '2.0.9';
public const ALTAPAY_PLUGIN_NAME = 'WexoAltaPay';

public function update(UpdateContext $updateContext): void
Expand Down
13 changes: 8 additions & 5 deletions wiki.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ be provided by AltaPay.

![Checkout v2](Docs/Configuration/checkout_v2.png)

7. Enter the terminal names from your AltaPay account that you want to use for specific sales channels in the **Terminal Setup** section. Link these terminals from the Payment Method page.

## Add Payment Methods

Expand All @@ -107,19 +108,21 @@ be provided by AltaPay.
8. Once saved, a new section, **Custom fields**, will appear with the options **AltaPay Terminal ID**(where you must enter the terminal name from AltaPay), **Auto Capture**, and **Surcharge**.
![shopware_configure_altapay_terminal_detail](Docs/Configuration/shopware_configure_altapay_terminal_detail.png)

9. Click the **Save** button again.
9. Select a sales channel-specific terminal configuration. If left empty, the default terminal ID (from the field above) will be used.

10. Now click on your desired shop from the **Sales Channels** menu on the left.
10. Click the **Save** button again.

11. Now click on your desired shop from the **Sales Channels** menu on the left.

11. In the **General** tab, scroll down to the **Payment and shipping** section & search by name for the payment method you just created.
12. In the **General** tab, scroll down to the **Payment and shipping** section & search by name for the payment method you just created.

![shopware_show_payment_method_on_checkout.png](Docs/Configuration/shopware_show_payment_method_on_checkout.png)

12. Choose the payment method and click Save button in the top-right corner.
13. Choose the payment method and click Save button in the top-right corner.

![shopware_verify_payment_method.png](Docs/Configuration/shopware_verify_payment_method.png)

13. Once the payment methods are configured, you will be ready to process transactions through AltaPay.
14. Once the payment methods are configured, you will be ready to process transactions through AltaPay.

![shopware_checkout_page.png](Docs/Configuration/shopware_checkout_page.png)

Expand Down