diff --git a/.github/docker-compose.e2e.yml b/.github/docker-compose.e2e.yml
index d9cea1b6ec..10893da3a4 100644
--- a/.github/docker-compose.e2e.yml
+++ b/.github/docker-compose.e2e.yml
@@ -1,7 +1,7 @@
version: '3'
services:
playwright:
- image: mcr.microsoft.com/playwright:v1.47.2
+ image: mcr.microsoft.com/playwright:v1.49.1
shm_size: 1gb
ipc: host
cap_add:
diff --git a/Gateway/Http/Client/TransactionRefund.php b/Gateway/Http/Client/TransactionRefund.php
index 3484c030d0..238f18fb79 100644
--- a/Gateway/Http/Client/TransactionRefund.php
+++ b/Gateway/Http/Client/TransactionRefund.php
@@ -88,6 +88,8 @@ public function placeRequest(TransferInterface $transferObject): array
$this->adyenHelper->logResponse($responseData);
} catch (AdyenException $e) {
$this->adyenHelper->logAdyenException($e);
+ $responseData['error'] = $e->getMessage();
+ $responseData['errorCode'] = $e->getAdyenErrorCode();
}
$responses[] = $responseData;
}
diff --git a/Gateway/Request/AdditionalDataLevel23DataBuilder.php b/Gateway/Request/AdditionalDataLevel23DataBuilder.php
index c07d049e18..0ed6a23059 100644
--- a/Gateway/Request/AdditionalDataLevel23DataBuilder.php
+++ b/Gateway/Request/AdditionalDataLevel23DataBuilder.php
@@ -3,7 +3,7 @@
*
* Adyen Payment Module
*
- * Copyright (c) 2022 Adyen N.V.
+ * Copyright (c) 2024 Adyen N.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
@@ -16,90 +16,145 @@
use Adyen\Payment\Helper\Config;
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\Requests;
+use Adyen\Payment\Logger\AdyenLogger;
+use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Request\BuilderInterface;
+use Magento\Sales\Api\Data\OrderItemInterface;
use Magento\Sales\Model\Order;
-use Magento\Sales\Model\Order\Item;
use Magento\Store\Model\StoreManagerInterface;
class AdditionalDataLevel23DataBuilder implements BuilderInterface
{
+ const ENHANCED_SCHEME_DATA_PREFIX = 'enhancedSchemeData';
+ const ITEM_DETAIL_LINE_PREFIX = 'itemDetailLine';
+ const UNIT_OF_MEASURE_PCS = 'pcs';
+
/**
- * @var Config
- */
- private $config;
- /**
- * @var StoreManagerInterface
- */
- private $storeManager;
- /**
- * @var Data
- */
- private $adyenHelper;
- /**
- * @var ChargedCurrency
+ * @param Config $config
+ * @param StoreManagerInterface $storeManager
+ * @param ChargedCurrency $chargedCurrency
+ * @param Requests $adyenRequestHelper
+ * @param Data $adyenHelper
+ * @param AdyenLogger $adyenLogger
*/
- private $chargedCurrency;
+ public function __construct(
+ public Config $config,
+ public StoreManagerInterface $storeManager,
+ public ChargedCurrency $chargedCurrency,
+ public Requests $adyenRequestHelper,
+ public Data $adyenHelper,
+ public AdyenLogger $adyenLogger
+ ) { }
+
/**
- * @var Requests
+ * This data builder creates `additionalData` object for Level 2/3 enhanced scheme data.
+ * For more information refer to https://docs.adyen.com/payment-methods/cards/enhanced-scheme-data/l2-l3
+ *
+ * @param array $buildSubject
+ * @return array|array[]
+ * @throws NoSuchEntityException
*/
- private $adyenRequestHelper;
-
- public function __construct(
- Config $config,
- StoreManagerInterface $storeManager,
- ChargedCurrency $chargedCurrency,
- Requests $adyenRequestHelper,
- Data $adyenHelper
- )
+ public function build(array $buildSubject): array
{
- $this->config = $config;
- $this->storeManager = $storeManager;
- $this->adyenHelper = $adyenHelper;
- $this->chargedCurrency = $chargedCurrency;
- $this->adyenRequestHelper = $adyenRequestHelper;
- }
+ $request = [];
- public function build(array $buildSubject)
- {
- $requestBody = [];
if ($this->config->sendLevel23AdditionalData($this->storeManager->getStore()->getId())) {
$paymentDataObject = SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
+
/** @var Order $order */
$order = $payment->getOrder();
$currencyCode = $this->chargedCurrency->getOrderAmountCurrency($order)->getCurrencyCode();
- $prefix = 'enhancedSchemeData';
- $requestBody['additionalData'][$prefix . '.totalTaxAmount'] = $this->adyenHelper->formatAmount($order->getTaxAmount(), $currencyCode);
- $requestBody['additionalData'][$prefix . '.customerReference'] = $this->adyenRequestHelper->getShopperReference($order->getCustomerId(), $order->getIncrementId());
+ // `totalTaxAmount` field is required and L2/L3 data can not be generated without this field.
+ if (empty($order->getTaxAmount()) || $order->getTaxAmount() < 0 || $order->getTaxAmount() === 0) {
+ $this->adyenLogger->warning(__('L2/L3 data can not be generated if tax amount is zero.'));
+ return $request;
+ }
+
+ $additionalDataLevel23 = [
+ self::ENHANCED_SCHEME_DATA_PREFIX . '.orderDate' => date('dmy', time()),
+ self::ENHANCED_SCHEME_DATA_PREFIX . '.customerReference' =>
+ $this->adyenRequestHelper->getShopperReference($order->getCustomerId(), $order->getIncrementId()),
+ self::ENHANCED_SCHEME_DATA_PREFIX . '.totalTaxAmount' =>
+ (string) $this->adyenHelper->formatAmount($order->getTaxAmount(), $currencyCode)
+ ];
+
if ($order->getIsNotVirtual()) {
- $requestBody['additionalData'][$prefix . '.freightAmount'] = $this->adyenHelper->formatAmount($order->getBaseShippingAmount(), $currencyCode);
- $requestBody['additionalData'][$prefix . '.destinationPostalCode'] = $order->getShippingAddress()->getPostcode();
- $requestBody['additionalData'][$prefix . '.destinationCountryCode'] = $order->getShippingAddress()->getCountryId();
+ $additionalDataLevel23[self::ENHANCED_SCHEME_DATA_PREFIX . '.freightAmount'] =
+ (string) $this->adyenHelper->formatAmount($order->getBaseShippingAmount(), $currencyCode);
+
+ $additionalDataLevel23[self::ENHANCED_SCHEME_DATA_PREFIX . '.destinationPostalCode'] =
+ $order->getShippingAddress()->getPostcode();
+
+ $additionalDataLevel23[self::ENHANCED_SCHEME_DATA_PREFIX . '.destinationCountryCode'] =
+ $order->getShippingAddress()->getCountryId();
+
+ if (!empty($order->getShippingAddress()->getRegionCode())) {
+ $additionalDataLevel23[self::ENHANCED_SCHEME_DATA_PREFIX . '.destinationStateProvinceCode'] =
+ $order->getShippingAddress()->getRegionCode();
+ }
}
- $itemIndex = 0;
+ $itemIndex = 1;
foreach ($order->getItems() as $item) {
- /** @var Item $item */
- if ($item->getPrice() == 0 && !empty($item->getParentItem())) {
- // Products variants get added to the order as separate items, filter out the variants.
+ if (!$this->validateLineItem($item)) {
continue;
}
- $itemPrefix = $prefix . '.itemDetailLine';
- $requestBody['additionalData'][$itemPrefix . $itemIndex . '.description'] = $item->getName();
- $requestBody['additionalData'][$itemPrefix . $itemIndex . '.unitPrice'] = $this->adyenHelper->formatAmount($item->getPrice(), $currencyCode);
- $requestBody['additionalData'][$itemPrefix . $itemIndex . '.discountAmount'] = $this->adyenHelper->formatAmount($item->getDiscountAmount(), $currencyCode);
- $requestBody['additionalData'][$itemPrefix . $itemIndex . '.commodityCode'] = $item->getQuoteItemId();
- $requestBody['additionalData'][$itemPrefix . $itemIndex . '.quantity'] = $item->getQtyOrdered();
- $requestBody['additionalData'][$itemPrefix . $itemIndex . '.productCode'] = $item->getSku();
- $requestBody['additionalData'][$itemPrefix . $itemIndex . '.totalAmount'] = $this->adyenHelper->formatAmount($item->getRowTotal(), $currencyCode);
+ $itemPrefix = self::ENHANCED_SCHEME_DATA_PREFIX . '.' . self::ITEM_DETAIL_LINE_PREFIX;
+
+ $additionalDataLevel23[$itemPrefix . $itemIndex . '.description'] = $item->getName();
+ $additionalDataLevel23[$itemPrefix . $itemIndex . '.discountAmount'] =
+ (string) $this->adyenHelper->formatAmount($item->getDiscountAmount(), $currencyCode);
+ $additionalDataLevel23[$itemPrefix . $itemIndex . '.commodityCode'] = (string) $item->getQuoteItemId();
+ $additionalDataLevel23[$itemPrefix . $itemIndex . '.productCode'] = $item->getSku();
+ $additionalDataLevel23[$itemPrefix . $itemIndex . '.unitOfMeasure'] = self::UNIT_OF_MEASURE_PCS;
+ $additionalDataLevel23[$itemPrefix . $itemIndex . '.quantity'] = (string) $item->getQtyOrdered();
+ $additionalDataLevel23[$itemPrefix . $itemIndex . '.unitPrice'] =
+ (string) $this->adyenHelper->formatAmount($item->getPrice(), $currencyCode);
+ $additionalDataLevel23[$itemPrefix . $itemIndex . '.totalAmount'] =
+ (string) $this->adyenHelper->formatAmount($item->getRowTotal(), $currencyCode);
$itemIndex++;
}
+
+ $request = [
+ 'body' => [
+ 'additionalData' => $additionalDataLevel23
+ ]
+ ];
+ }
+
+ return $request;
+ }
+
+ /**
+ * Required fields `unitPrice`, `totalAmount` or `quantity` can not be null or zero in the line items.
+ *
+ * @param OrderItemInterface $orderItem
+ * @return bool
+ */
+ private function validateLineItem(OrderItemInterface $orderItem): bool
+ {
+ $validationResult = true;
+
+ // `unitPrice` should be a non-zero numeric value.
+ if ($orderItem->getPrice() === 0) {
+ $validationResult = false;
+ }
+
+ // `totalAmount` should be a non-zero numeric value.
+ if ($orderItem->getRowTotal() === 0) {
+ $validationResult = false;
+ }
+
+ // `quantity` should be a positive integer. If not, skip the line item.
+ if ($orderItem->getQtyOrdered() < 1) {
+ $validationResult = false;
}
- return ['body' => $requestBody];
+ return $validationResult;
}
}
diff --git a/Gateway/Request/DescriptionDataBuilder.php b/Gateway/Request/DescriptionDataBuilder.php
index 0bd7c12a26..3bd2c252e9 100644
--- a/Gateway/Request/DescriptionDataBuilder.php
+++ b/Gateway/Request/DescriptionDataBuilder.php
@@ -34,7 +34,7 @@ public function build(array $buildSubject)
'Order %1 from %2',
$order->getIncrementId(),
$order->getStore()->getGroup()->getName()
- );
+ )->render();
return $request;
}
diff --git a/Model/Sales/OrderRepository.php b/Model/Sales/OrderRepository.php
index d51680b268..0919294075 100644
--- a/Model/Sales/OrderRepository.php
+++ b/Model/Sales/OrderRepository.php
@@ -16,6 +16,7 @@
use Magento\Framework\Api\Search\FilterGroupBuilder;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\Api\SortOrderBuilder;
use Magento\Framework\Serialize\Serializer\Json as JsonSerializer;
use Magento\Payment\Api\Data\PaymentAdditionalInfoInterfaceFactory;
use Magento\Sales\Api\Data\OrderExtensionFactory;
@@ -28,6 +29,7 @@
class OrderRepository extends SalesOrderRepository
{
private SearchCriteriaBuilder $searchCriteriaBuilder;
+ private SortOrderBuilder $sortOrderBuilder;
private FilterBuilder $filterBuilder;
private FilterGroupBuilder $filterGroupBuilder;
@@ -35,6 +37,7 @@ public function __construct(
SearchCriteriaBuilder $searchCriteriaBuilder,
FilterBuilder $filterBuilder,
FilterGroupBuilder $filterGroupBuilder,
+ SortOrderBuilder $sortOrderBuilder,
Metadata $metadata,
SearchResultFactory $searchResultFactory,
CollectionProcessorInterface $collectionProcessor = null,
@@ -56,6 +59,7 @@ public function __construct(
);
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
+ $this->sortOrderBuilder = $sortOrderBuilder;
$this->filterBuilder = $filterBuilder;
$this->filterGroupBuilder = $filterGroupBuilder;
}
@@ -68,9 +72,14 @@ public function getOrderByQuoteId(int $quoteId): OrderInterface|false
->create();
$quoteIdFilterGroup = $this->filterGroupBuilder->setFilters([$quoteIdFilter])->create();
+ $sortOrder = $this->sortOrderBuilder->setField('entity_id')
+ ->setDescendingDirection()
+ ->create();
$searchCriteria = $this->searchCriteriaBuilder
->setFilterGroups([$quoteIdFilterGroup])
+ ->setSortOrders([$sortOrder])
+ ->setPageSize(1)
->create();
$orders = $this->getList($searchCriteria)->getItems();
diff --git a/Plugin/GraphQlPlaceOrderAddCartId.php b/Plugin/GraphQlPlaceOrderAddCartId.php
index ee360eb04f..bf88af05b8 100644
--- a/Plugin/GraphQlPlaceOrderAddCartId.php
+++ b/Plugin/GraphQlPlaceOrderAddCartId.php
@@ -59,6 +59,10 @@ public function __construct(
*/
public function afterResolve(PlaceOrder $placeOrder, array $result): array
{
+ if (!isset($result['order'])) {
+ return $result;
+ }
+
try {
$cart = $this->quoteHelper->getQuoteByOrderIncrementId($result['order']['order_number']);
$maskedId = $this->quoteIdToMaskedQuoteId->execute($cart->getId());
diff --git a/Test/Unit/Gateway/Http/Client/TransactionRefundTest.php b/Test/Unit/Gateway/Http/Client/TransactionRefundTest.php
index 3d98825999..21b2730451 100644
--- a/Test/Unit/Gateway/Http/Client/TransactionRefundTest.php
+++ b/Test/Unit/Gateway/Http/Client/TransactionRefundTest.php
@@ -21,6 +21,7 @@
use Adyen\Service\Checkout\ModificationsApi;
use Magento\Payment\Gateway\Http\TransferInterface;
use PHPUnit\Framework\MockObject\MockObject;
+use Adyen\AdyenException;
class TransactionRefundTest extends AbstractAdyenTestCase
{
@@ -102,4 +103,46 @@ public function testPlaceRequestIncludesHeadersInRequest()
$this->assertCount(1, $responses);
$this->assertArrayHasKey('pspReference', $responses[0]);
}
+
+ public function testPlaceRequestHandlesException()
+ {
+ $requestBody = [
+ 'amount' => ['value' => 1000, 'currency' => 'EUR'],
+ 'paymentPspReference' => '123456789'
+ ];
+
+ $headers = ['idempotencyExtraData' => ['order_id' => '1001']];
+
+ $transferObjectMock = $this->createConfiguredMock(TransferInterface::class, [
+ 'getBody' => [$requestBody],
+ 'getHeaders' => $headers,
+ 'getClientConfig' => []
+ ]);
+
+ $serviceMock = $this->createMock(ModificationsApi::class);
+ $adyenClientMock = $this->createMock(Client::class);
+
+ $this->adyenHelperMock->method('initializeAdyenClientWithClientConfig')->willReturn($adyenClientMock);
+ $this->adyenHelperMock->method('initializeModificationsApi')->willReturn($serviceMock);
+ $this->adyenHelperMock->method('buildRequestHeaders')->willReturn(['custom-header' => 'value']);
+
+ $this->idempotencyHelperMock->expects($this->once())
+ ->method('generateIdempotencyKey')
+ ->with($requestBody, $headers['idempotencyExtraData'])
+ ->willReturn('generated_idempotency_key');
+
+ $serviceMock->expects($this->once())
+ ->method('refundCapturedPayment')
+ ->willThrowException(new AdyenException());
+
+ $this->adyenHelperMock->expects($this->once())
+ ->method('logAdyenException')
+ ->with($this->isInstanceOf(AdyenException::class));
+
+ $responses = $this->transactionRefund->placeRequest($transferObjectMock);
+ $this->assertIsArray($responses);
+ $this->assertCount(1, $responses);
+ $this->assertArrayHasKey('error', $responses[0]);
+ $this->assertArrayHasKey('errorCode', $responses[0]);
+ }
}
diff --git a/Test/Unit/Gateway/Request/AdditionalDataLevel23DataBuilderTest.php b/Test/Unit/Gateway/Request/AdditionalDataLevel23DataBuilderTest.php
index 318ef93ccf..77ce4ab6eb 100644
--- a/Test/Unit/Gateway/Request/AdditionalDataLevel23DataBuilderTest.php
+++ b/Test/Unit/Gateway/Request/AdditionalDataLevel23DataBuilderTest.php
@@ -2,6 +2,8 @@
namespace Adyen\Payment\Test\Gateway\Request;
+use Adyen\Payment\Logger\AdyenLogger;
+use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Payment\Gateway\Data\OrderAdapterInterface;
use Magento\Payment\Gateway\Data\PaymentDataObject;
use Magento\Sales\Model\Order;
@@ -17,19 +19,23 @@
use Adyen\Payment\Helper\Data;
use Adyen\Payment\Helper\ChargedCurrency;
use Adyen\Payment\Helper\Requests;
+use PHPUnit\Framework\MockObject\MockObject;
class AdditionalDataLevel23DataBuilderTest extends AbstractAdyenTestCase
{
- private $storeMock;
- private $configMock;
- private $storeManagerMock;
- private $adyenHelperMock;
- private $chargedCurrencyMock;
- private $adyenRequestHelperMock;
-
-
- protected function setUp(): void
+ protected ?AdditionalDataLevel23DataBuilder $additionalDataBuilder;
+ protected MockObject|StoreInterface $storeMock;
+ protected MockObject|Config $configMock;
+ protected MockObject|StoreManagerInterface $storeManagerMock;
+ protected MockObject|Data $adyenHelperMock;
+ protected MockObject|ChargedCurrency $chargedCurrencyMock;
+ protected MockObject|Requests $adyenRequestHelperMock;
+ protected MockObject|AdyenLogger $adyenLoggerMock;
+
+ public function setUp(): void
{
+ parent::setUp();
+
$this->configMock = $this->createMock(Config::class);
$this->storeManagerMock = $this->createMock(StoreManagerInterface::class);
$this->chargedCurrencyMock = $this->createMock(ChargedCurrency::class);
@@ -37,17 +43,41 @@ protected function setUp(): void
$this->adyenHelperMock = $this->createMock(Data::class);
$this->storeMock = $this->createMock(StoreInterface::class);
$this->storeManagerMock->method('getStore')->willReturn($this->storeMock);
+ $this->adyenLoggerMock = $this->createMock(AdyenLogger::class);
$this->additionalDataBuilder = new AdditionalDataLevel23DataBuilder(
$this->configMock,
$this->storeManagerMock,
$this->chargedCurrencyMock,
$this->adyenRequestHelperMock,
- $this->adyenHelperMock
+ $this->adyenHelperMock,
+ $this->adyenLoggerMock
);
}
- public function testLevel23DataConfigurationEnabled()
+ public function tearDown(): void
+ {
+ parent::tearDown();
+
+ $this->additionalDataBuilder = null;
+ }
+
+ protected static function orderTypeDataProvider(): array
+ {
+ return [
+ ['isVirtual' => true],
+ ['isVirtual' => false],
+ ];
+ }
+
+ /**
+ * @dataProvider orderTypeDataProvider
+ *
+ * @param $isVirtual
+ * @return void
+ * @throws NoSuchEntityException
+ */
+ public function testLevel23DataConfigurationEnabled($isVirtual)
{
$storeId = 1;
$currencyCode = 'USD';
@@ -56,257 +86,150 @@ public function testLevel23DataConfigurationEnabled()
$shopperReference = '000123';
$taxAmount = 10.00;
$formattedTaxAmount = '1000';
+ $shippingAmount = 5.00;
$this->storeMock->method('getId')->willReturn($storeId);
- $this->configMock->method('sendLevel23AdditionalData')->with($storeId)->willReturn(true);
- $this->chargedCurrencyMock->method('getOrderAmountCurrency')->willReturn(new AdyenAmountCurrency(null, $currencyCode));
+ $this->configMock->method('sendLevel23AdditionalData')
+ ->with($storeId)
+ ->willReturn(true);
+
+ $this->chargedCurrencyMock->method('getOrderAmountCurrency')
+ ->willReturn(new AdyenAmountCurrency(null, $currencyCode));
+
$this->adyenHelperMock->method('formatAmount')->willReturn($formattedTaxAmount);
- $this->adyenRequestHelperMock->method('getShopperReference')->with($customerId, $orderIncrementId)->willReturn($shopperReference);
+
+ $this->adyenRequestHelperMock->method('getShopperReference')
+ ->with($customerId, $orderIncrementId)
+ ->willReturn($shopperReference);
+
$itemMock1 = $this->createMock(Item::class);
+ $itemMock1->method('getPrice')->willReturn(0);
+
$itemMock2 = $this->createMock(Item::class);
+ $itemMock2->method('getPrice')->willReturn(10);
+ $itemMock2->method('getRowTotal')->willReturn(0);
+
+ $itemMock3 = $this->createMock(Item::class);
+ $itemMock3->method('getPrice')->willReturn(10);
+ $itemMock3->method('getRowTotal')->willReturn(5);
+ $itemMock3->method('getQtyOrdered')->willReturn(0.5);
+
+ $itemMock4 = $this->createMock(Item::class);
+ $itemMock4->method('getPrice')->willReturn(15);
+ $itemMock4->method('getRowTotal')->willReturn(30);
+ $itemMock4->method('getQtyOrdered')->willReturn(2);
+ $itemMock4->method('getSku')->willReturn('ABC123');
+ $itemMock4->method('getDescription')->willReturn('Mock Product Description');
$orderMock = $this->createConfiguredMock(Order::class, [
'getCustomerId' => $customerId,
'getIncrementId' => $orderIncrementId,
'getTaxAmount' => $taxAmount,
- 'getItems' => [$itemMock1, $itemMock2]
+ 'getItems' => [$itemMock1, $itemMock2, $itemMock3, $itemMock4],
+ 'getIsNotVirtual' => !$isVirtual,
+ 'getBaseShippingAmount' => $shippingAmount
]);
+ $shippingAddressMock = $this->createMock(Address::class);
+ $shippingAddressMock->method('getPostcode')->willReturn('12345');
+ $shippingAddressMock->method('getCountryId')->willReturn('US');
+ $shippingAddressMock->method('getRegionCode')->willReturn('MI');
+
+ $orderMock->method('getShippingAddress')->willReturn($shippingAddressMock);
+
$orderAdapterMock = $this->createMock(OrderAdapterInterface::class);
$paymentMock = $this->createMock(Payment::class);
$paymentMock->method('getOrder')->willReturn($orderMock);
$paymentDataObject = new PaymentDataObject($orderAdapterMock, $paymentMock);
$buildSubject = ['payment' => $paymentDataObject, 'order' => $orderMock];
$result = $this->additionalDataBuilder->build($buildSubject);
- $expectedResult = [
- 'body' => [
- 'additionalData' => [
- 'enhancedSchemeData.totalTaxAmount' => '1000',
- 'enhancedSchemeData.customerReference' => '000123',
- 'enhancedSchemeData.itemDetailLine0.description' => null,
- 'enhancedSchemeData.itemDetailLine0.unitPrice' => '1000',
- 'enhancedSchemeData.itemDetailLine0.discountAmount' => '1000',
- 'enhancedSchemeData.itemDetailLine0.commodityCode' => null,
- 'enhancedSchemeData.itemDetailLine0.quantity' => null,
- 'enhancedSchemeData.itemDetailLine0.productCode' => null,
- 'enhancedSchemeData.itemDetailLine0.totalAmount' => '1000',
- 'enhancedSchemeData.itemDetailLine1.description' => null,
- 'enhancedSchemeData.itemDetailLine1.unitPrice' => '1000',
- 'enhancedSchemeData.itemDetailLine1.discountAmount' => '1000',
- 'enhancedSchemeData.itemDetailLine1.commodityCode' => null,
- 'enhancedSchemeData.itemDetailLine1.quantity' => null,
- 'enhancedSchemeData.itemDetailLine1.productCode' => null,
- 'enhancedSchemeData.itemDetailLine1.totalAmount' => '1000',
- ]
- ]
- ];
- $this->assertEquals($expectedResult, $result);
+ $this->assertArrayHasKey('additionalData', $result['body']);
+ $this->assertArrayHasKey(AdditionalDataLevel23DataBuilder::ENHANCED_SCHEME_DATA_PREFIX . '.orderDate', $result['body']['additionalData']);
+ $this->assertArrayHasKey(AdditionalDataLevel23DataBuilder::ENHANCED_SCHEME_DATA_PREFIX . '.customerReference', $result['body']['additionalData']);
+ $this->assertArrayHasKey(AdditionalDataLevel23DataBuilder::ENHANCED_SCHEME_DATA_PREFIX . '.totalTaxAmount', $result['body']['additionalData']);
+
+ if (!$isVirtual) {
+ $this->assertArrayHasKey(AdditionalDataLevel23DataBuilder::ENHANCED_SCHEME_DATA_PREFIX . '.freightAmount', $result['body']['additionalData']);
+ $this->assertArrayHasKey(AdditionalDataLevel23DataBuilder::ENHANCED_SCHEME_DATA_PREFIX . '.destinationPostalCode', $result['body']['additionalData']);
+ $this->assertArrayHasKey(AdditionalDataLevel23DataBuilder::ENHANCED_SCHEME_DATA_PREFIX . '.destinationCountryCode', $result['body']['additionalData']);
+ $this->assertArrayHasKey(AdditionalDataLevel23DataBuilder::ENHANCED_SCHEME_DATA_PREFIX . '.destinationStateProvinceCode', $result['body']['additionalData']);
+ }
+
+ $itemArrayKey = AdditionalDataLevel23DataBuilder::ENHANCED_SCHEME_DATA_PREFIX . '.' .
+ AdditionalDataLevel23DataBuilder::ITEM_DETAIL_LINE_PREFIX;
+
+ $this->assertArrayHasKey($itemArrayKey . '1.productCode', $result['body']['additionalData']);
+ $this->assertArrayHasKey($itemArrayKey . '1.description', $result['body']['additionalData']);
+ $this->assertArrayHasKey($itemArrayKey . '1.quantity', $result['body']['additionalData']);
+ $this->assertArrayHasKey($itemArrayKey . '1.unitOfMeasure', $result['body']['additionalData']);
+ $this->assertArrayHasKey($itemArrayKey . '1.commodityCode', $result['body']['additionalData']);
+ $this->assertArrayHasKey($itemArrayKey . '1.totalAmount', $result['body']['additionalData']);
+ $this->assertArrayHasKey($itemArrayKey . '1.unitPrice', $result['body']['additionalData']);
+
+ // Index starts from 1
+ $this->assertArrayNotHasKey($itemArrayKey . '0.productCode', $result['body']['additionalData']);
+
+ // Only one line item is valid, others should be cleaned up
+ $this->assertArrayNotHasKey($itemArrayKey . '2.productCode', $result['body']['additionalData']);
+ $this->assertArrayNotHasKey($itemArrayKey . '3.productCode', $result['body']['additionalData']);
}
+
public function testLevel23DataConfigurationDisabled()
{
$storeId = 1;
- $orderIncrementId = '000000123';
- $customerId = 123;
- $taxAmount = 10.00;
$this->storeMock->method('getId')->willReturn($storeId);
$this->configMock->method('sendLevel23AdditionalData')->with($storeId)->willReturn(false);
- $itemMock1 = $this->createMock(Item::class);
- $itemMock2 = $this->createMock(Item::class);
- $orderMock = $this->createConfiguredMock(Order::class, [
- 'getCustomerId' => $customerId,
- 'getIncrementId' => $orderIncrementId,
- 'getTaxAmount' => $taxAmount,
- 'getItems' => [$itemMock1, $itemMock2]
- ]);
+ $paymentDataObjectMock = $this->createMock(PaymentDataObject::class);
+ $orderMock = $this->createMock(Order::class);
+ $buildSubject = ['payment' => $paymentDataObjectMock, 'order' => $orderMock];
- $orderAdapterMock = $this->createMock(OrderAdapterInterface::class);
- $paymentMock = $this->createMock(Payment::class);
- $paymentMock->method('getOrder')->willReturn($orderMock);
- $paymentDataObject = new PaymentDataObject($orderAdapterMock, $paymentMock);
- $buildSubject = ['payment' => $paymentDataObject, 'order' => $orderMock];
$result = $this->additionalDataBuilder->build($buildSubject);
- $expectedResult = [
- 'body' => []
- ];
-
- $this->assertEquals($expectedResult, $result);
+ $this->assertEmpty($result);
}
- public function testVirtualOrder()
+ protected static function taxAmountDataProvider(): array
{
- $storeId = 1;
- $currencyCode = 'USD';
- $customerId = 123;
- $orderIncrementId = '000000123';
- $shopperReference = '000123';
- $taxAmount = 10.00;
- $formattedTaxAmount = '1000';
-
- $this->storeMock->method('getId')->willReturn($storeId);
- $this->configMock->method('sendLevel23AdditionalData')->with($storeId)->willReturn(true);
- $this->chargedCurrencyMock->method('getOrderAmountCurrency')->willReturn(new AdyenAmountCurrency(null, $currencyCode));
- $this->adyenHelperMock->method('formatAmount')->willReturn($formattedTaxAmount);
- $this->adyenRequestHelperMock->method('getShopperReference')->with($customerId, $orderIncrementId)->willReturn($shopperReference);
-
- $orderMock = $this->createConfiguredMock(Order::class, [
- 'getCustomerId' => $customerId,
- 'getIncrementId' => $orderIncrementId,
- 'getTaxAmount' => $taxAmount,
- 'getItems' => [],
- 'getIsNotVirtual' => false,
- 'getShippingAddress' => null,
- 'getBaseShippingAmount' => 0.00
- ]);
-
- $orderAdapterMock = $this->createMock(OrderAdapterInterface::class);
- $paymentMock = $this->createMock(Payment::class);
- $paymentMock->method('getOrder')->willReturn($orderMock);
- $paymentDataObject = new PaymentDataObject($orderAdapterMock, $paymentMock);
- $buildSubject = ['payment' => $paymentDataObject, 'order' => $orderMock];
- $result = $this->additionalDataBuilder->build($buildSubject);
-
- $expectedResult = [
- 'body' => [
- 'additionalData' => [
- 'enhancedSchemeData.totalTaxAmount' => '1000',
- 'enhancedSchemeData.customerReference' => '000123'
- ]
- ]
+ return [
+ ['taxAmount' => 0],
+ ['taxAmount' => null],
+ ['taxAmount' => -1]
];
-
- $this->assertEquals($expectedResult, $result);
}
- public function testNonVirtualOrder()
+ /**
+ * @dataProvider taxAmountDataProvider
+ *
+ * @param $taxAmount
+ * @return void
+ * @throws NoSuchEntityException
+ */
+ public function testLevel23DataInvalidTaxAmounts($taxAmount)
{
$storeId = 1;
$currencyCode = 'USD';
- $customerId = 123;
- $orderIncrementId = '000000123';
- $shopperReference = '000123';
- $taxAmount = 10.00;
- $shippingAmount = 5.00;
- $formattedAmount = '1000';
- $postalCode = '12345';
- $countryId = 'US';
+
+ $this->chargedCurrencyMock->method('getOrderAmountCurrency')
+ ->willReturn(new AdyenAmountCurrency(null, $currencyCode));
$this->storeMock->method('getId')->willReturn($storeId);
$this->configMock->method('sendLevel23AdditionalData')->with($storeId)->willReturn(true);
- $this->chargedCurrencyMock->method('getOrderAmountCurrency')->willReturn(new AdyenAmountCurrency(null, $currencyCode));
- $this->adyenHelperMock->method('formatAmount')->willReturn($formattedAmount);
- $this->adyenRequestHelperMock->method('getShopperReference')->with($customerId, $orderIncrementId)->willReturn($shopperReference);
- $shippingAddressMock = $this->createMock(Address::class);
- $shippingAddressMock->method('getPostcode')->willReturn($postalCode);
- $shippingAddressMock->method('getCountryId')->willReturn($countryId);
- $orderMock = $this->createConfiguredMock(Order::class, [
- 'getCustomerId' => $customerId,
- 'getIncrementId' => $orderIncrementId,
- 'getTaxAmount' => $taxAmount,
- 'getIsNotVirtual' => true,
- 'getShippingAddress' => $shippingAddressMock,
- 'getBaseShippingAmount' => $shippingAmount,
- 'getItems' => []
- ]);
+ $orderMock = $this->createMock(Order::class);
+ $orderMock->method('getTaxAmount')->willReturn($taxAmount);
- $orderAdapterMock = $this->createMock(OrderAdapterInterface::class);
$paymentMock = $this->createMock(Payment::class);
$paymentMock->method('getOrder')->willReturn($orderMock);
- $paymentDataObject = new PaymentDataObject($orderAdapterMock, $paymentMock);
- $buildSubject = ['payment' => $paymentDataObject, 'order' => $orderMock];
- $result = $this->additionalDataBuilder->build($buildSubject);
- $expectedResult = [
- 'body' => [
- 'additionalData' => [
- 'enhancedSchemeData.totalTaxAmount' => $formattedAmount,
- 'enhancedSchemeData.customerReference' => $shopperReference,
- 'enhancedSchemeData.freightAmount' => $formattedAmount,
- 'enhancedSchemeData.destinationPostalCode' => $postalCode,
- 'enhancedSchemeData.destinationCountryCode' => $countryId
- ]
- ]
- ];
-
- $this->assertEquals($expectedResult, $result);
- }
-
- public function testOrderWithDiscount()
- {
- $storeId = 1;
- $currencyCode = 'USD';
- $customerId = 123;
- $orderIncrementId = '000000123';
- $shopperReference = '000123';
- $taxAmount = 10.00;
- $formattedAmount = '1000';
- $discountAmount = 2.00;
-
- $this->storeMock->method('getId')->willReturn($storeId);
- $this->configMock->method('sendLevel23AdditionalData')->with($storeId)->willReturn(true);
- $this->chargedCurrencyMock->method('getOrderAmountCurrency')->willReturn(new AdyenAmountCurrency(null, $currencyCode));
- $this->adyenHelperMock->method('formatAmount')->willReturn($formattedAmount);
- $this->adyenRequestHelperMock->method('getShopperReference')->with($customerId, $orderIncrementId)->willReturn($shopperReference);
-
- $itemMock1 = $this->createConfiguredMock(Item::class, [
- 'getPrice' => 10.00,
- 'getDiscountAmount' => $discountAmount,
- 'getName' => 'Item 1',
- 'getQuoteItemId' => 101,
- 'getQtyOrdered' => 1,
- 'getSku' => 'sku-1',
- 'getRowTotal' => 8.00
- ]);
- $itemMock2 = $this->createConfiguredMock(Item::class, [
- 'getPrice' => 20.00,
- 'getDiscountAmount' => $discountAmount,
- 'getName' => 'Item 2',
- 'getQuoteItemId' => 102,
- 'getQtyOrdered' => 1,
- 'getSku' => 'sku-2',
- 'getRowTotal' => 18.00
- ]);
+ $paymentDataObjectMock = $this->createMock(PaymentDataObject::class);
+ $paymentDataObjectMock->method('getPayment')->willReturn($paymentMock);
- $orderMock = $this->createConfiguredMock(Order::class, [
- 'getCustomerId' => $customerId,
- 'getIncrementId' => $orderIncrementId,
- 'getTaxAmount' => $taxAmount,
- 'getItems' => [$itemMock1, $itemMock2]
- ]);
+ $buildSubject = ['payment' => $paymentDataObjectMock, 'order' => $orderMock];
- $orderAdapterMock = $this->createMock(OrderAdapterInterface::class);
- $paymentMock = $this->createMock(Payment::class);
- $paymentMock->method('getOrder')->willReturn($orderMock);
- $paymentDataObject = new PaymentDataObject($orderAdapterMock, $paymentMock);
- $buildSubject = ['payment' => $paymentDataObject, 'order' => $orderMock];
$result = $this->additionalDataBuilder->build($buildSubject);
- $expectedResult = [
- 'body' => [
- 'additionalData' => [
- 'enhancedSchemeData.totalTaxAmount' => '1000',
- 'enhancedSchemeData.customerReference' => '000123',
- 'enhancedSchemeData.itemDetailLine0.description' => 'Item 1',
- 'enhancedSchemeData.itemDetailLine0.unitPrice' => '1000',
- 'enhancedSchemeData.itemDetailLine0.discountAmount' => '1000',
- 'enhancedSchemeData.itemDetailLine0.commodityCode' => 101,
- 'enhancedSchemeData.itemDetailLine0.quantity' => 1,
- 'enhancedSchemeData.itemDetailLine0.productCode' => 'sku-1',
- 'enhancedSchemeData.itemDetailLine0.totalAmount' => '1000',
- 'enhancedSchemeData.itemDetailLine1.description' => 'Item 2',
- 'enhancedSchemeData.itemDetailLine1.unitPrice' => '1000',
- 'enhancedSchemeData.itemDetailLine1.discountAmount' => '1000',
- 'enhancedSchemeData.itemDetailLine1.commodityCode' => 102,
- 'enhancedSchemeData.itemDetailLine1.quantity' => 1,
- 'enhancedSchemeData.itemDetailLine1.productCode' => 'sku-2',
- 'enhancedSchemeData.itemDetailLine1.totalAmount' => '1000',
- ]
- ]
- ];
-
- $this->assertEquals($expectedResult, $result);
+ $this->assertEmpty($result);
}
}
diff --git a/Test/Unit/Model/Sales/OrderRepositoryTest.php b/Test/Unit/Model/Sales/OrderRepositoryTest.php
index 261640f068..a0e9714810 100644
--- a/Test/Unit/Model/Sales/OrderRepositoryTest.php
+++ b/Test/Unit/Model/Sales/OrderRepositoryTest.php
@@ -19,6 +19,8 @@
use Magento\Framework\Api\Search\FilterGroupBuilder;
use Magento\Framework\Api\SearchCriteria;
use Magento\Framework\Api\SearchCriteriaBuilder;
+use Magento\Framework\Api\SortOrder;
+use Magento\Framework\Api\SortOrderBuilder;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\Data\OrderSearchResultInterface;
use ReflectionClass;
@@ -41,10 +43,15 @@ public function testGetOrderByQuoteId()
$filterGroupBuilderMock->method('create')
->willReturn($this->createMock(FilterGroup::class));
+ $sortOrderBuilderMock = $this->createPartialMock(SortOrderBuilder::class, ['create']);
+ $sortOrderBuilderMock->method('create')
+ ->willReturn($this->createMock(SortOrder::class));
+
$orderRepository = $this->buildOrderRepositoryClass(
$searchCriteriaBuilderMock,
$filterBuilderMock,
- $filterGroupBuilderMock
+ $filterGroupBuilderMock,
+ $sortOrderBuilderMock
);
$order = $orderRepository->getOrderByQuoteId($quoteId);
@@ -54,7 +61,8 @@ public function testGetOrderByQuoteId()
public function buildOrderRepositoryClass(
$searchCriteriaBuilderMock = null,
$filterBuilderMock = null,
- $filterGroupBuilderMock = null
+ $filterGroupBuilderMock = null,
+ $sortOrderBuilderMock = null
): OrderRepository {
if (is_null($searchCriteriaBuilderMock)) {
$searchCriteriaBuilderMock = $this->createMock(SearchCriteriaBuilder::class);
@@ -68,6 +76,10 @@ public function buildOrderRepositoryClass(
$filterGroupBuilderMock = $this->createMock(FilterGroupBuilder::class);
}
+ if (is_null($sortOrderBuilderMock)) {
+ $sortOrderBuilderMock = $this->createMock(SortOrderBuilder::class);
+ }
+
$orderRepositoryPartialMock = $this->getMockBuilder(OrderRepository::class)
->setMethods(['getList'])
->disableOriginalConstructor()
@@ -87,6 +99,10 @@ public function buildOrderRepositoryClass(
$filterGroupBuilderProperty->setAccessible(true);
$filterGroupBuilderProperty->setValue($orderRepositoryPartialMock, $filterGroupBuilderMock);
+ $sortOrderBuilderProperty = $reflection->getProperty('sortOrderBuilder');
+ $sortOrderBuilderProperty->setAccessible(true);
+ $sortOrderBuilderProperty->setValue($orderRepositoryPartialMock, $sortOrderBuilderMock);
+
$orderSearchResultMock = $this->createConfiguredMock(OrderSearchResultInterface::class, [
'getItems' => [$this->createMock(OrderInterface::class)]
]);
diff --git a/VERSION b/VERSION
index ea5a459926..69dd356299 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-9.11.0
+9.12.1
diff --git a/composer.json b/composer.json
index b49c34c77b..a9a2f6eeca 100755
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
"name": "adyen/module-payment",
"description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.",
"type": "magento2-module",
- "version": "9.11.0",
+ "version": "9.12.1",
"license": "MIT",
"repositories": [
{
@@ -23,7 +23,7 @@
"require-dev": {
"phpunit/phpunit": "~9.6.1",
"magento/magento-coding-standard": "*",
- "squizlabs/php_codesniffer": "~3.8.0"
+ "squizlabs/php_codesniffer": "~3.11.0"
},
"autoload": {
"files": [
diff --git a/etc/adminhtml/system/adyen_card_payments.xml b/etc/adminhtml/system/adyen_card_payments.xml
index b356ad22a9..f3daaa5609 100755
--- a/etc/adminhtml/system/adyen_card_payments.xml
+++ b/etc/adminhtml/system/adyen_card_payments.xml
@@ -58,13 +58,13 @@
payment/adyen_cc/installments
-
+
Magento\Config\Model\Config\Source\Yesno
payment/adyen_abstract/send_level23_data
Adyen documentation
+ Adyen documentation
for more information.
]]>
diff --git a/etc/config.xml b/etc/config.xml
index d61cff0b2c..b432bd83ff 100755
--- a/etc/config.xml
+++ b/etc/config.xml
@@ -2274,6 +2274,204 @@
0
adyen-alternative-payment-method
+
+ 0
+ AdyenPaymentDokuAlfamartFacade
+ Alfamart via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
+
+ 0
+ AdyenPaymentDokuPermataLiteAtmFacade
+ ATM Permata VA LITE via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
+
+ 0
+ AdyenPaymentDokuBcaVaFacade
+ ATM BCA VA via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
+
+ 0
+ AdyenPaymentDokuBniVaFacade
+ BNI VA via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
+
+ 0
+ AdyenPaymentDokuBriVaFacade
+ BRI VA via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
+
+ 0
+ AdyenPaymentDokuCimbVaFacade
+ CIMB VA via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
+
+ 0
+ AdyenPaymentDokuDanamonVaFacade
+ Danamon VA via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
+
+ 0
+ AdyenPaymentDokuIndomaretFacade
+ Indomaret via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
+
+ 0
+ AdyenPaymentDokuMandiriVaFacade
+ Mandiri VA via DOKU
+ 0
+ 0
+ authorize
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ adyen-alternative-payment-method
+
-
+
\ No newline at end of file
diff --git a/etc/di.xml b/etc/di.xml
index 32896b3ff2..aefb9b552a 100755
--- a/etc/di.xml
+++ b/etc/di.xml
@@ -4316,4 +4316,247 @@
adyen_kcp_creditcard
+
+
+ adyen_doku_alfamart
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuAlfamartValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuAlfamartConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuAlfamartConfig
+
+
+
+
+ adyen_doku_alfamart
+
+
+
+
+ adyen_doku_permata_lite_atm
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuPermataLiteAtmValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuPermataLiteAtmConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuPermataLiteAtmConfig
+
+
+
+
+ adyen_doku_permata_lite_atm
+
+
+
+
+ adyen_doku_bca_va
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuBcaVaValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuBcaVaConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuBcaVaConfig
+
+
+
+
+ adyen_doku_bca_va
+
+
+
+
+ adyen_doku_bni_va
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuBniVaValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuBniVaConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuBniVaConfig
+
+
+
+
+ adyen_doku_bni_va
+
+
+
+
+ adyen_doku_bri_va
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuBriVaValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuBriVaConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuBriVaConfig
+
+
+
+
+ adyen_doku_bri_va
+
+
+
+
+ adyen_doku_cimb_va
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuCimbVaValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuCimbVaConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuCimbVaConfig
+
+
+
+
+ adyen_doku_cimb_va
+
+
+
+
+ adyen_doku_danamon_va
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuDanamonVaValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuDanamonVaConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuDanamonVaConfig
+
+
+
+
+ adyen_doku_danamon_va
+
+
+
+
+ adyen_doku_indomaret
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuIndomaretValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuIndomaretConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuIndomaretConfig
+
+
+
+
+ adyen_doku_indomaret
+
+
+
+
+ adyen_doku_mandiri_va
+ Magento\Payment\Block\Form
+ Adyen\Payment\Block\Info\PaymentMethodInfo
+ AdyenPaymentDokuMandiriVaValueHandlerPool
+ AdyenPaymentValidatorPool
+ AdyenPaymentCommandPool
+
+
+
+
+
+ - AdyenPaymentDokuMandiriVaConfigValueHandler
+
+
+
+
+
+ AdyenPaymentDokuMandiriVaConfig
+
+
+
+
+ adyen_doku_mandiri_va
+
+
\ No newline at end of file
diff --git a/etc/events.xml b/etc/events.xml
index 1520613215..8953d82977 100644
--- a/etc/events.xml
+++ b/etc/events.xml
@@ -311,4 +311,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml
index 34576cb772..9553e01b20 100755
--- a/etc/frontend/di.xml
+++ b/etc/frontend/di.xml
@@ -114,6 +114,15 @@
- kcp_naverpay
- kcp_payco
- kcp_creditcard
+ - doku_alfamart
+ - doku_permata_lite_atm
+ - doku_bca_va
+ - doku_bni_va
+ - doku_bri_va
+ - doku_cimb_va
+ - doku_danamon_va
+ - doku_indomaret
+ - doku_mandiri_va
- Adyen_Payment/js/view/payment/method-renderer/adyen-cc-method
@@ -121,6 +130,10 @@
- Adyen_Payment/js/view/payment/method-renderer/adyen-applepay-method
- Adyen_Payment/js/view/payment/method-renderer/adyen-boleto-method
- Adyen_Payment/js/view/payment/method-renderer/adyen-facilypay-3x-method
+ - Adyen_Payment/js/view/payment/method-renderer/adyen-facilypay-method
+ - Adyen_Payment/js/view/payment/method-renderer/adyen-facilypay-method
+ - Adyen_Payment/js/view/payment/method-renderer/adyen-facilypay-method
+ - Adyen_Payment/js/view/payment/method-renderer/adyen-facilypay-method
- Adyen_Payment/js/view/payment/method-renderer/adyen-googlepay-method
- Adyen_Payment/js/view/payment/method-renderer/adyen-paypal-method
- Adyen_Payment/js/view/payment/method-renderer/adyen-giftcard-method
diff --git a/etc/graphql/di.xml b/etc/graphql/di.xml
index ca8deea49d..ce48e3017e 100644
--- a/etc/graphql/di.xml
+++ b/etc/graphql/di.xml
@@ -95,6 +95,15 @@
- Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
- Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
- Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
+ - Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm
diff --git a/etc/payment.xml b/etc/payment.xml
index 5c9920a180..e8efc7767d 100755
--- a/etc/payment.xml
+++ b/etc/payment.xml
@@ -272,5 +272,32 @@
1
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
\ No newline at end of file
diff --git a/view/adminhtml/templates/support/js.phtml b/view/adminhtml/templates/support/js.phtml
index 865b1b8ec3..175681cb4b 100644
--- a/view/adminhtml/templates/support/js.phtml
+++ b/view/adminhtml/templates/support/js.phtml
@@ -20,38 +20,38 @@ require([
const linksMapping = {
required_settings: [
{
- title: 'Magento plugin setup',
- href: 'https://docs.adyen.com/plugins/magento-2/set-up-the-plugin-in-magento#step-3-configure-the-plugin-in-magento'
+ title: 'Adobe Commerce plugin setup',
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/set-up-the-plugin-in-adobe-commerce/'
},
{
title: 'How to request a new merchant account',
href: 'https://www.adyen.com/education/europe/english/modules/customer-area'
},
{
- title: 'Why Apple pay is not working',
- href: 'https://www.adyen.help/hc/en-us/articles/4871941388444-how-can-i-handle-errors-with-my-applepay-payments'
+ title: 'Why is Apple pay not working',
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/drop-in-and-components/why-do-i-receive-a-422-error-with-apple-pay-when-using-adyens-certificate'
},
{
title: 'Go-live checklist',
- href: 'https://docs.adyen.com/plugins/magento-2/go-live-checklist'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/go-live-checklist'
},
{
title: 'Troubleshooting guide',
- href: 'https://docs.adyen.com/plugins/magento-2/troubleshooting'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/troubleshooting/'
},
{
title: 'Why do I get the error 401 Unauthorized?',
- href: 'https://www.adyen.help/hc/en-us/articles/5231709306652-why-do-i-get-the-error-401-unauthorized'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/error-codes/why-do-i-get-the-error-401-unauthorized'
}
],
card_payments: [
{
title: 'How to configure card payments ',
- href: 'https://docs.adyen.com/plugins/magento-2/set-up-the-payment-methods-in-magento#api-credit-card-payments'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/set-up-the-payment-methods-in-adobe-commerce'
},
{
title: 'What are supported schemes?',
- href: 'https://docs.adyen.com/plugins/magento-2/supported-payment-methods#credit-and-debit-cards'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/supported-payment-methods'
},
{
title: '3D Secure 2 Component integration',
@@ -61,11 +61,11 @@ require([
card_tokenization: [
{
title: 'How to set up tokenization',
- href: 'https://docs.adyen.com/plugins/magento-2/set-up-tokenization'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/set-up-tokenization'
},
{
title: 'Video: How to set up tokenization',
- href: 'https://help.adyen.com/academy/how-to-videos/plugins/how-to-set-up-tokenization-in-your-magento-plugin'
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/how-do-i-set-up-tokenization-in-adobe-commerce'
},
{
title: 'Difference between One-off, Subscription and Top-ups',
@@ -73,25 +73,25 @@ require([
},
{
title: 'Why do I receive a 800 Contract not found error?',
- href: 'https://www.adyen.help/hc/en-us/articles/5231491632668-why-do-i-receive-a-800-contract-not-found-error'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/error-codes/why-do-i-receive-a-800-contract-not-found-error'
},
{
title: 'Why do I receive a 803 PaymentDetail not found error?',
- href: 'https://www.adyen.help/hc/en-us/articles/5231662267420-why-do-i-receive-a-803-paymentdetail-not-found-error'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/error-codes/why-do-i-receive-a-803-paymentdetail-not-found-error'
},
{
title: 'Why does my recurring transaction give the error "invalid card number"?',
- href: 'https://www.adyen.help/hc/en-us/articles/5234058320412-why-does-my-recurring-transaction-give-the-error-invalid-card-number'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/tokenization/why-does-my-recurring-transaction-give-the-error-invalid-card-number'
}
],
alt_payment_methods: [
{
- title: 'Why are Adyen alternative payment methods not showing up in Magento?',
- href: 'https://www.adyen.help/hc/en-us/articles/5034154365340-Why-are-Adyen-alternative-payment-methods-not-showing-up-in-Magento-'
+ title: 'Why are Adyen alternative payment methods not showing up in Adobe Commerce?',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/why-arent-all-payment-methods-displayed-adobe-commerce'
},
{
title: 'Supported Payment Methods',
- href: 'https://docs.adyen.com/plugins/magento-2/supported-payment-methods#credit-and-debit-cards'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/supported-payment-methods/'
},
{
title: 'How to add payment methods in Customer Area',
@@ -99,19 +99,15 @@ require([
},
{
title: 'How do I deactivate or delete a payment method?',
- href: 'https://www.adyen.help/hc/en-us/articles/5439872869404-how-do-i-deactivate-or-delete-a-payment-method'
+ href: 'https://help.adyen.com/knowledge/payment-methods/manage-payment-methods/how-do-i-deactivate-or-delete-a-payment-method'
},
{
title: 'Video: How to add payment methods in Customer Area',
href: 'https://www.adyen.com/education/europe/english/modules/customer-area'
},
{
- title: 'How do I change the order of payment methods on my checkout page?',
- href: 'https://www.adyen.help/hc/en-us/articles/4871657923612-how-can-i-change-the-order-of-my-payment-methods'
- },
- {
- title: 'How can we change the order of the payment methods inside Magento 2?',
- href: 'https://www.adyen.help/hc/en-us/articles/5034413982876-how-can-we-change-the-order-of-the-payment-methods-inside-magento-2'
+ title: 'How can we change the order of the payment methods inside Adobe Commerce 2?',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/how-can-i-change-the-order-of-the-payment-methods-adobe-commerce'
}
],
pos_integration: [
@@ -127,123 +123,115 @@ require([
pay_by_link: [
{
title: 'How to set up Pay By Link in the plugin',
- href: 'https://docs.adyen.com/plugins/magento-2/set-up-the-payment-methods-in-magento#pay-by-link'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/set-up-the-payment-methods-in-adobe-commerce/#pay-by-link'
},
{
title: 'Video: How to set up PayByLink',
- href: 'https://help.adyen.com/academy/how-to-videos/plugins/how-to-set-up-pay-by-link-in-your-magento-plugin'
+ href: 'https://help.adyen.com/academy/how-to-videos/plugins/how-to-set-up-pay-by-link-in-your-adobe-commerce-plugin'
}
],
adyen_giving: [
{
title: 'How to set up Donations in the plugin',
- href: 'https://docs.adyen.com/plugins/magento-2/set-up-the-payment-methods-in-magento#donations'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/set-up-the-payment-methods-in-adobe-commerce/#donations'
},
{
title: 'Video: How to set up Adyen Giving',
- href: 'https://help.adyen.com/academy/how-to-videos/plugins/how-to-set-up-giving-in-your-magento-plugin/'
+ href: 'https://help.adyen.com/academy/how-to-videos/plugins/how-to-set-up-giving-in-your-adobe-commerce-plugin'
}
],
advanced_settings: [
{
- title: 'Why does the order status in Magento remain on "Payment Review"?',
- href: 'https://www.adyen.help/hc/en-us/articles/5033911246876-Why-does-the-order-status-in-Magento-remain-on-Payment-Review-'
+ title: 'Why does the order status in Adobe Commerce remain on "Payment Review"?',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/why-is-my-payment-pending-in-adobe-commerce'
},
{
- title: 'Why is the text in Magento not being translated?',
- href: 'https://www.adyen.help/hc/en-us/articles/5034181926300-Why-is-the-text-in-Magento-not-being-translated-'
+ title: 'Why is the text in Adobe Commerce not being translated?',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/why-is-the-text-in-adobe-commerce-not-being-translated'
},
{
- title: 'How can we customise the Magento 2 plugin?',
- href: 'https://www.adyen.help/hc/en-us/articles/5034486805532-How-can-we-customise-the-Magento-2-plugin-'
+ title: 'How can we customise the Adobe Commerce plugin?',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/how-can-we-customise-the-adobe-commerce-plugin'
},
{
- title: 'Why is my order status Settled or SentForSettle after I refunded it on Magento?',
- href: 'https://www.adyen.help/hc/en-us/articles/5034488629660-Why-is-my-order-status-Settled-or-SentForSettle-after-I-refunded-it-on-Magento-'
+ title: 'Why is my order status Settled or SentForSettle after I refunded it on Adobe Commerce?',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/why-is-my-order-status-settled-or-sentforsettle-after-i-refunded-it-on-adobe-commerce'
},
{
title: 'Why are Klarna payments stuck in Pending?',
- href: 'https://www.adyen.help/hc/en-us/articles/5032453938460-why-are-klarna-payments-stuck-in-pending'
- },
- {
- title: 'Why are the orders not created in Magento after a payment is processed in Adyen?',
- href: 'https://www.adyen.help/hc/en-us/articles/5033911246876-why-does-the-order-status-in-magento-remain-on-payment-review'
+ href: 'https://help.adyen.com/knowledge/plugins/using-plugins/why-are-klarna-payments-still-pending'
},
{
title: 'How can I change the capture settings of my payment method?',
- href: 'https://www.adyen.help/hc/en-us/articles/5003914234140-how-can-i-change-the-capture-settings-of-my-payment-method'
+ href: 'https://help.adyen.com/knowledge/payment-methods/manage-payment-methods/how-can-i-change-the-capture-settings-of-my-payment-method'
}
],
payment_status: [
{
- title: 'Why is my order status Settled or SentForSettle after I refunded it on Magento?',
- href: 'https://www.adyen.help/hc/en-us/articles/5034488629660-Why-is-my-order-status-Settled-or-SentForSettle-after-I-refunded-it-on-Magento-'
+ title: 'Why is my order status Settled or SentForSettle after I refunded it on Adobe Commerce?',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/why-is-my-order-status-settled-or-sentforsettle-after-i-refunded-it-on-adobe-commerce'
},
{
title: 'Why are Klarna payments stuck in Pending?',
- href: 'https://www.adyen.help/hc/en-us/articles/5032453938460-why-are-klarna-payments-stuck-in-pending'
+ href: 'https://help.adyen.com/knowledge/plugins/using-plugins/why-are-klarna-payments-still-pending'
},
- {
- title: 'Why does the order status in Magento remain on "Payment Review"?',
- href: 'https://www.adyen.help/hc/en-us/articles/5033911246876-Why-does-the-order-status-in-Magento-remain-on-Payment-Review-'
- }
],
failed_transaction: [
{
title: 'What does it mean if a payment is refused because 3d-secure: Authentication failed?',
- href: 'https://www.adyen.help/hc/en-us/articles/5295691501596-what-does-it-mean-if-a-payment-is-refused-because-3dsecure-authentication-failed'
+ href: 'https://help.adyen.com/knowledge/3d-secure/3ds-response-codes/what-does-it-mean-if-a-payment-is-refused-because-3d-secure-authentication-failed'
},
{
title: 'Why is my payment canceled?',
- href: 'https://www.adyen.help/hc/en-us/articles/4545692297884-why-is-my-payment-canceled'
+ href: 'https://help.adyen.com/knowledge/payments/payment-statuses/why-is-my-payment-canceled'
},
{
title: 'Why do I receive a 905 Payment details are not supported error?',
- href: 'https://www.adyen.help/hc/en-us/articles/5231655519004-why-do-i-receive-a-905-payment-details-are-not-supported-error'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/error-codes/why-do-i-receive-a-905-payment-details-are-not-supported-error'
},
{
title: 'Why do I receive a 403 or 010 Not Allowed error?',
- href: 'https://www.adyen.help/hc/en-us/articles/5231707550364-why-do-i-receive-a-403-or-010-not-allowed-error'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/error-codes/why-do-i-receive-a-403-or-010-not-allowed-error'
},
{
title: 'Why do I receive the error 422 : Unable to Decrypt Data using the Card Component or Drop-In?',
- href: 'https://www.adyen.help/hc/en-us/articles/5233146584988-why-do-i-receive-the-error-422-unable-to-decrypt-data-using-the-card-component-or-dropin'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/drop-in-and-components/why-do-i-receive-the-error-422-unable-to-decrypt-data-using-the-card-component-or-dropin'
},
{
title: 'Why do I receive a 807 Invalid combination of shopper interaction and recurring contract error?',
- href: 'https://www.adyen.help/hc/en-us/articles/5231605902492-why-do-i-receive-a-807-invalid-combination-of-shopper-interaction-and-recurring-contract-error'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/error-codes/why-do-i-receive-a-807-invalid-combination-of-shopper-interaction-and-recurring-contract-error'
},
{
title: 'Why do I get errorCode 908: invalid request with HTTP status 500?',
- href: 'https://www.adyen.help/hc/en-us/articles/5231513160220-why-do-i-get-errorcode-908-invalid-request-with-http-status-500'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/error-codes/why-do-i-get-errorcode-908-invalid-request-with-http-status-500'
}
],
offer: [
{
- title: 'Why does the order status in Magento remain on "Payment Review"?',
- href: 'https://www.adyen.help/hc/en-us/articles/5033911246876-Why-does-the-order-status-in-Magento-remain-on-Payment-Review-'
+ title: 'Why does the order status in Adobe Commerce remain on "Payment Review"?',
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/troubleshooting/#orders'
}
],
webhooks: [
{
title: 'How to set up notifications in Customer Area',
- href: 'https://docs.adyen.com/plugins/magento-2/set-up-adyen-customer-area'
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/set-up-adyen-customer-area/?tab=manual_2#step-3-set-up-webhooks'
},
{
- title: 'Why does the order status in Magento remain on "Payment Review"?',
- href: 'https://www.adyen.help/hc/en-us/articles/5033911246876-Why-does-the-order-status-in-Magento-remain-on-Payment-Review-'
+ title: 'Why does the order status in Adobe Commerce remain on "Payment Review"?',
+ href: 'https://docs.adyen.com/plugins/adobe-commerce/troubleshooting/#orders'
},
{
- title: 'Why does Magento 2 does not receive notifications?',
- href: 'https://www.adyen.help/hc/en-us/articles/5034412585116-Why-does-Magento-2-does-not-receive-notifications-'
+ title: 'Why does Adobe Commerce not receive notifications?',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/why-does-adobe-commerce-does-not-receive-notifications'
},
{
- title: 'I get a 301, 302 or 401 error in Magento when testing the notification endpoint',
- href: 'https://www.adyen.help/hc/en-us/articles/5034799389980-I-get-a-301-302-or-401-error-in-Magento-when-testing-the-notification-endpoint'
+ title: 'I get a 301, 302 or 401 error in Adobe Commerce when testing the notification endpoint',
+ href: 'https://help.adyen.com/knowledge/plugins/adobe-commerce/why-am-i-receiving-301-302-or-401-error-in-adobe-commerce'
},
{
title: 'How can I get additional data in standard Notifications?',
- href: 'https://www.adyen.help/hc/en-us/articles/5234558016540-how-can-i-get-additional-data-in-standard-notifications'
+ href: 'https://help.adyen.com/knowledge/ecommerce-integrations/webhooks/how-can-i-get-additional-data-in-standard-webhooks'
}
]
};
diff --git a/view/base/web/images/logos/doku_alfamart.svg b/view/base/web/images/logos/doku_alfamart.svg
new file mode 100644
index 0000000000..76f4a967e2
--- /dev/null
+++ b/view/base/web/images/logos/doku_alfamart.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/base/web/images/logos/doku_bca_va.svg b/view/base/web/images/logos/doku_bca_va.svg
new file mode 100644
index 0000000000..45f42f70ca
--- /dev/null
+++ b/view/base/web/images/logos/doku_bca_va.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/base/web/images/logos/doku_bni_va.svg b/view/base/web/images/logos/doku_bni_va.svg
new file mode 100644
index 0000000000..e0bb021e63
--- /dev/null
+++ b/view/base/web/images/logos/doku_bni_va.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/base/web/images/logos/doku_bri_va.svg b/view/base/web/images/logos/doku_bri_va.svg
new file mode 100644
index 0000000000..30951b99a2
--- /dev/null
+++ b/view/base/web/images/logos/doku_bri_va.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/base/web/images/logos/doku_cimb_va.svg b/view/base/web/images/logos/doku_cimb_va.svg
new file mode 100644
index 0000000000..46e66acab1
--- /dev/null
+++ b/view/base/web/images/logos/doku_cimb_va.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/base/web/images/logos/doku_danamon_va.svg b/view/base/web/images/logos/doku_danamon_va.svg
new file mode 100644
index 0000000000..b5ee7fdfe5
--- /dev/null
+++ b/view/base/web/images/logos/doku_danamon_va.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/base/web/images/logos/doku_indomaret.svg b/view/base/web/images/logos/doku_indomaret.svg
new file mode 100644
index 0000000000..8d792a9560
--- /dev/null
+++ b/view/base/web/images/logos/doku_indomaret.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/base/web/images/logos/doku_mandiri_va.svg b/view/base/web/images/logos/doku_mandiri_va.svg
new file mode 100644
index 0000000000..c223e79269
--- /dev/null
+++ b/view/base/web/images/logos/doku_mandiri_va.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/base/web/images/logos/doku_permata_lite_atm.svg b/view/base/web/images/logos/doku_permata_lite_atm.svg
new file mode 100644
index 0000000000..d9747002da
--- /dev/null
+++ b/view/base/web/images/logos/doku_permata_lite_atm.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/view/frontend/layout/checkout_index_index.xml b/view/frontend/layout/checkout_index_index.xml
index 076a3d1ca0..d592dcf8f5 100755
--- a/view/frontend/layout/checkout_index_index.xml
+++ b/view/frontend/layout/checkout_index_index.xml
@@ -326,6 +326,33 @@
-
- true
+ -
+
- true
+
+ -
+
- true
+
+ -
+
- true
+
+ -
+
- true
+
+ -
+
- true
+
+ -
+
- true
+
+ -
+
- true
+
+ -
+
- true
+
+ -
+
- true
+
diff --git a/view/frontend/layout/multishipping_checkout_billing.xml b/view/frontend/layout/multishipping_checkout_billing.xml
index 64d663f2be..5841e52395 100644
--- a/view/frontend/layout/multishipping_checkout_billing.xml
+++ b/view/frontend/layout/multishipping_checkout_billing.xml
@@ -104,6 +104,15 @@
- Adyen_Payment::form/multishipping/abstract-form.phtml
- Adyen_Payment::form/multishipping/abstract-form.phtml
- Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
+ - Adyen_Payment::form/multishipping/abstract-form.phtml
false
diff --git a/view/frontend/web/js/view/payment/method-renderer/adyen-facilypay-3x-method.js b/view/frontend/web/js/view/payment/method-renderer/adyen-facilypay-3x-method.js
index cc4bf208c1..11e2d4ef15 100644
--- a/view/frontend/web/js/view/payment/method-renderer/adyen-facilypay-3x-method.js
+++ b/view/frontend/web/js/view/payment/method-renderer/adyen-facilypay-3x-method.js
@@ -6,6 +6,9 @@
* See LICENSE.txt for license details.
*
* Author: Adyen
+ *
+ * @deprecated This file will be removed on V10. Use `adyen-facilypay-method.js` instead.
+ *
*/
define(
[
diff --git a/view/frontend/web/js/view/payment/method-renderer/adyen-facilypay-method.js b/view/frontend/web/js/view/payment/method-renderer/adyen-facilypay-method.js
new file mode 100644
index 0000000000..7eb71c71d3
--- /dev/null
+++ b/view/frontend/web/js/view/payment/method-renderer/adyen-facilypay-method.js
@@ -0,0 +1,80 @@
+/**
+ *
+ * Adyen Payment module (https://www.adyen.com/)
+ *
+ * Copyright (c) 2024 Adyen N.V. (https://www.adyen.com/)
+ * See LICENSE.txt for license details.
+ *
+ * Author: Adyen
+ */
+define(
+ [
+ 'Magento_Checkout/js/model/quote',
+ 'Adyen_Payment/js/view/payment/method-renderer/adyen-pm-method',
+ ],
+ function(
+ quote,
+ adyenPaymentMethod,
+ ) {
+ return adyenPaymentMethod.extend({
+ initialize: function () {
+ this._super();
+ },
+ buildComponentConfiguration: function (paymentMethod, paymentMethodsExtraInfo) {
+ let baseComponentConfiguration = this._super();
+ let self = this;
+ let formattedShippingAddress = {};
+ let formattedBillingAddress = {};
+ let shopperDateOfBirth = '';
+ let email = {};
+
+ if (!!customerData.dob){
+ shopperDateOfBirth = customerData.dob;
+ }
+
+ if (!!customerData.email) {
+ email = customerData.email;
+ } else if (!!quote.guestEmail) {
+ email = quote.guestEmail;
+ };
+
+ if (!quote.isVirtual() && !!quote.shippingAddress()) {
+ formattedShippingAddress = self.getFormattedAddress(quote.shippingAddress());
+ }
+
+ if (!quote.isVirtual() && !!quote.billingAddress()) {
+ formattedBillingAddress = self.getFormattedAddress(quote.billingAddress());
+ }
+
+ if (formattedShippingAddress) {
+ baseComponentConfiguration.data.deliveryAddress = {
+ city: formattedShippingAddress.city,
+ country: formattedShippingAddress.country,
+ houseNumberOrName: formattedShippingAddress.houseNumber,
+ postalCode: formattedShippingAddress.postalCode,
+ street: formattedShippingAddress.street
+ }
+ }
+
+ if (formattedBillingAddress){
+ baseComponentConfiguration.data.personalDetails = {
+ firstName: formattedBillingAddress.firstName,
+ lastName: formattedBillingAddress.lastName,
+ telephoneNumber: formattedBillingAddress.telephone,
+ shopperEmail: email,
+ dateOfBirth: shopperDateOfBirth,
+ }
+ baseComponentConfiguration.data.billingAddress = {
+ city: formattedBillingAddress.city,
+ country: formattedBillingAddress.country,
+ houseNumberOrName: formattedBillingAddress.houseNumber,
+ postalCode: formattedBillingAddress.postalCode,
+ street: formattedBillingAddress.street,
+ }
+ }
+
+ return baseComponentConfiguration;
+ }
+ })
+ }
+);
diff --git a/view/frontend/web/template/payment/cc-form.html b/view/frontend/web/template/payment/cc-form.html
index b93b74ee04..a0df9a907b 100755
--- a/view/frontend/web/template/payment/cc-form.html
+++ b/view/frontend/web/template/payment/cc-form.html
@@ -63,7 +63,7 @@
-
+
diff --git a/view/frontend/web/template/payment/cc-vault-form.html b/view/frontend/web/template/payment/cc-vault-form.html
index ddc824d3c9..515ed6ba91 100644
--- a/view/frontend/web/template/payment/cc-vault-form.html
+++ b/view/frontend/web/template/payment/cc-vault-form.html
@@ -21,7 +21,7 @@
value: getId(),
click: selectPaymentMethod,
checked: isChecked,
- visible: isRadioButtonVisible()"/>
+ visible: isRadioButtonVisible()">