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()">