diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 9c9805543f..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: 2 - -updates: - - package-ecosystem: "composer" - directory: "/" - schedule: - interval: "daily" - open-pull-requests-limit: 3 - labels: - - "dependencies" - target-branch: "main" - - - package-ecosystem: "docker" - directory: "/" - schedule: - interval: "daily" - open-pull-requests-limit: 3 - labels: - - "dependencies" - target-branch: "main" diff --git a/.github/docker-compose.e2e.yml b/.github/docker-compose.e2e.yml index 468be5840b..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.49.0 + image: mcr.microsoft.com/playwright:v1.49.1 shm_size: 1gb ipc: host cap_add: diff --git a/Controller/Adminhtml/Configuration/DownloadApplePayCertificate.php b/Controller/Adminhtml/Configuration/DownloadApplePayCertificate.php deleted file mode 100644 index 5af0c4dcea..0000000000 --- a/Controller/Adminhtml/Configuration/DownloadApplePayCertificate.php +++ /dev/null @@ -1,158 +0,0 @@ - - */ - -namespace Adyen\Payment\Controller\Adminhtml\Configuration; - -use Adyen\AdyenException; -use Adyen\Payment\Helper\Config; -use Adyen\Payment\Logger\AdyenLogger; -use Magento\Framework\App\ResponseInterface; -use Magento\Framework\Controller\Result\Redirect; -use Magento\Framework\Controller\ResultInterface; -use Magento\Framework\Exception\FileSystemException; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Filesystem\DirectoryList; -use Magento\Backend\App\Action\Context; -use Magento\Framework\Controller\ResultFactory; -use Magento\Backend\App\Action; -use Magento\Framework\Filesystem\Io\File; -use Exception; -use ZipArchive; - -class DownloadApplePayCertificate extends Action -{ - const READ_LENGTH = 2048; - const MAX_FILES = 10; - const MAX_SIZE = 1000000; - const MAX_RATIO = 5; - const FILE_NAME = 'apple-developer-merchantid-domain-association'; - const APPLEPAY_CERTIFICATE_URL = 'https://docs.adyen.com/payment-methods/apple-pay/web-component/apple-developer-merchantid-domain-association-2024.zip'; - private $directoryList; - private $fileIo; - private $adyenLogger; - - public function __construct( - Context $context, - DirectoryList $directoryList, - File $fileIo, - AdyenLogger $adyenLogger - ) - { - parent::__construct($context); - $this->directoryList = $directoryList; - $this->fileIo = $fileIo; - $this->adyenLogger = $adyenLogger; - } - - /** - * @return ResponseInterface|Redirect|Redirect&ResultInterface|ResultInterface - * @throws FileSystemException - * @throws LocalizedExceptionff - */ - public function execute() - { - $redirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); - $redirect->setUrl($this->_redirect->getRefererUrl()); - - $pubPath = $this->directoryList->getPath('pub'); - $directoryName = '.well-known'; - - $wellknownPath = $pubPath . '/' . $directoryName; - $applepayPath = $wellknownPath . '/' . self::FILE_NAME; - - $applepayUrl = self::APPLEPAY_CERTIFICATE_URL; - - try { - if ($this->fileIo->checkAndCreateFolder($wellknownPath, 0700)) { - $this->downloadAndUnzip($applepayUrl, $wellknownPath); - } else { - $this->fileIo->chmod($wellknownPath, 0770); - if (!$this->fileIo->fileExists($applepayPath)) { - $this->downloadAndUnzip($applepayUrl, $wellknownPath); - } - } - } catch (Exception $e) { - $errormessage = 'Failed to download the ApplePay certificate, please do so manually'; - $this->adyenLogger->addAdyenWarning($errormessage); - $this->messageManager->addErrorMessage($errormessage); - } - - return $redirect; - } - - /** - * @param string $applepayUrl - * @param string $applepayPath - * @return void - * @throws LocalizedException - */ - private function downloadAndUnzip(string $applepayUrl, string $applepayPath) - { - $tmpPath = tempnam(sys_get_temp_dir(), self::FILE_NAME); - file_put_contents($tmpPath, file_get_contents($applepayUrl)); - - $zip = new ZipArchive; - $fileCount = 0; - $totalSize = 0; - - if ($zip->open($tmpPath) === true) { - for ($i = 0; $i < $zip->numFiles; $i++) { - $filename = $zip->getNameIndex($i); - if (self::FILE_NAME !== $filename) { - continue; - } - $stats = $zip->statIndex($i); - - // Prevent ZipSlip path traversal (S6096) - if (strpos($filename, '../') !== false || - substr($filename, 0, 1) === '/') { - throw new AdyenException('The zip file is trying to ZipSlip please check the file'); - } - - if (substr($filename, -1) !== '/') { - $fileCount++; - if ($fileCount > 10) { - // Reached max. number of files - throw new AdyenException('Reached max number of files please check the zip file'); - } - - $applepayCerticateFilestream = $zip->getStream($filename); // Compliant - $currentSize = 0; - while (!feof($applepayCerticateFilestream)) { - $currentSize += self::READ_LENGTH; - $totalSize += self::READ_LENGTH; - - if ($totalSize > self::MAX_SIZE) { - // Reached max. size - throw new AdyenException('The file is larger than expected please check the zip file'); - } - - // Additional protection: check compression ratio - if ($stats['comp_size'] > 0) { - $ratio = $currentSize / $stats['comp_size']; - if ($ratio > self::MAX_RATIO) { - // Reached max. compression ratio - throw new AdyenException('The uncompressed file is larger than expected'); - } - } - file_put_contents( - $applepayPath .'/' . $filename, - fread($applepayCerticateFilestream, $totalSize), - FILE_APPEND - ); - } - fclose($applepayCerticateFilestream); - } - } - $zip->close(); - } - } -} diff --git a/Controller/Adminhtml/Configuration/DownloadApplePayDomainAssociationFile.php b/Controller/Adminhtml/Configuration/DownloadApplePayDomainAssociationFile.php new file mode 100644 index 0000000000..0726b316cc --- /dev/null +++ b/Controller/Adminhtml/Configuration/DownloadApplePayDomainAssociationFile.php @@ -0,0 +1,82 @@ + + */ + +namespace Adyen\Payment\Controller\Adminhtml\Configuration; + +use Adyen\Payment\Logger\AdyenLogger; +use Exception; +use Magento\Framework\App\ResponseInterface; +use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Filesystem\DirectoryList; +use Magento\Backend\App\Action\Context; +use Magento\Framework\Controller\ResultFactory; +use Magento\Backend\App\Action; +use Magento\Framework\Filesystem\Io\File; + +class DownloadApplePayDomainAssociationFile extends Action +{ + const FILE_NAME = 'apple-developer-merchantid-domain-association'; + const REMOTE_PATH = 'https://bae81f955b.cdn.adyen.com/checkoutshopper/.well-known'; + const PUB_PATH = 'pub'; + const WELL_KNOWN_PATH = '.well-known'; + + public function __construct( + private readonly Context $context, + private readonly DirectoryList $directoryList, + private readonly File $fileIo, + private readonly AdyenLogger $adyenLogger + ) { + parent::__construct($context); + } + + /** + * @return ResultInterface|ResponseInterface + * @throws FileSystemException + */ + public function execute(): ResultInterface|ResponseInterface + { + $redirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $redirect->setUrl($this->_redirect->getRefererUrl()); + + try { + $pubPath = $this->directoryList->getPath(self::PUB_PATH); + + $this->fileIo->checkAndCreateFolder( + sprintf("%s/%s", $pubPath, self::WELL_KNOWN_PATH), + 0700 + ); + + $source = sprintf("%s/%s", self::REMOTE_PATH, self::FILE_NAME); + $destination = sprintf("%s/%s/%s", $pubPath, self::WELL_KNOWN_PATH, self::FILE_NAME); + + $file = $this->fileIo->read($source, $destination); + + if (!$file) { + $errorMessage = + __('Error while downloading Apple Pay domain association file from the remote source!'); + $this->adyenLogger->error(sprintf("%s %s", $errorMessage, $source)); + $this->messageManager->addErrorMessage($errorMessage); + } else { + $successMessage = __('Apple Pay domain association file has been downloaded successfully!'); + $this->adyenLogger->addAdyenDebug($successMessage); + $this->messageManager->addSuccessMessage($successMessage); + } + } catch (Exception $e) { + $errorMessage = + __('Unknown error while downloading Apple Pay domain association file!'); + $this->adyenLogger->error(sprintf("%s %s", $errorMessage, $e->getMessage())); + $this->messageManager->addErrorMessage($errorMessage); + } + + return $redirect; + } +} diff --git a/Gateway/Http/Client/TransactionCancel.php b/Gateway/Http/Client/TransactionCancel.php index 707412d06d..f7d1406469 100644 --- a/Gateway/Http/Client/TransactionCancel.php +++ b/Gateway/Http/Client/TransactionCancel.php @@ -66,7 +66,7 @@ public function placeRequest(TransferInterface $transferObject): array $headers['idempotencyExtraData'] ?? null ); $requestOptions['idempotencyKey'] = $idempotencyKey; - $requestOptions['headers'] = $this->adyenHelper->buildRequestHeaders(); + $requestOptions['headers'] = $headers; $this->adyenHelper->logRequest($request, Client::API_CHECKOUT_VERSION, '/cancels'); $request['applicationInfo'] = $this->adyenHelper->buildApplicationInfo($client); $paymentCancelRequest = new PaymentCancelRequest($request); diff --git a/Gateway/Http/Client/TransactionCapture.php b/Gateway/Http/Client/TransactionCapture.php index ad699a9ba6..0ed6dbb109 100644 --- a/Gateway/Http/Client/TransactionCapture.php +++ b/Gateway/Http/Client/TransactionCapture.php @@ -72,12 +72,14 @@ public function placeRequest(TransferInterface $transferObject): array { $request = $transferObject->getBody(); $headers = $transferObject->getHeaders(); + $idempotencyKeyExtraData = $headers['idempotencyExtraData']; + unset($headers['idempotencyExtraData']); $clientConfig = $transferObject->getClientConfig(); $client = $this->adyenHelper->initializeAdyenClientWithClientConfig($clientConfig); $service = $this->adyenHelper->initializeModificationsApi($client); - $requestOptions['headers'] = $this->adyenHelper->buildRequestHeaders(); + $requestOptions['headers'] = $headers; $request['applicationInfo'] = $this->adyenHelper->buildApplicationInfo($client); if (array_key_exists(self::MULTIPLE_AUTHORIZATIONS, $request)) { @@ -86,7 +88,7 @@ public function placeRequest(TransferInterface $transferObject): array $idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey( $request, - $headers['idempotencyExtraData'] ?? null + $idempotencyKeyExtraData ?? null ); $requestOptions['idempotencyKey'] = $idempotencyKey; diff --git a/Gateway/Http/Client/TransactionPaymentLinks.php b/Gateway/Http/Client/TransactionPaymentLinks.php index c43d5d81bf..71e0f8237a 100644 --- a/Gateway/Http/Client/TransactionPaymentLinks.php +++ b/Gateway/Http/Client/TransactionPaymentLinks.php @@ -55,10 +55,12 @@ public function placeRequest(TransferInterface $transferObject): array { $request = $transferObject->getBody(); $headers = $transferObject->getHeaders(); + $idempotencyKeyExtraData = $headers['idempotencyExtraData'] ?? null; + unset($headers['idempotencyExtraData']); $clientConfig = $transferObject->getClientConfig(); $client = $this->adyenHelper->initializeAdyenClientWithClientConfig($clientConfig); - $service = new PaymentLinksApi($client); + $service = $this->adyenHelper->initializePaymentLinksApi($client); // If the payment links call is already done return the request if (!empty($request['resultCode'])) { @@ -68,11 +70,11 @@ public function placeRequest(TransferInterface $transferObject): array $idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey( $request, - $headers['idempotencyExtraData'] ?? null + $idempotencyKeyExtraData ); $requestOptions['idempotencyKey'] = $idempotencyKey; - $requestOptions['headers'] = $this->adyenHelper->buildRequestHeaders(); + $requestOptions['headers'] = $headers; $request['applicationInfo'] = $this->adyenHelper->buildApplicationInfo($client); $this->adyenHelper->logRequest($request, Client::API_CHECKOUT_VERSION, '/paymentLinks'); diff --git a/Gateway/Http/Client/TransactionRefund.php b/Gateway/Http/Client/TransactionRefund.php index 3484c030d0..6474c300de 100644 --- a/Gateway/Http/Client/TransactionRefund.php +++ b/Gateway/Http/Client/TransactionRefund.php @@ -56,6 +56,8 @@ public function placeRequest(TransferInterface $transferObject): array { $requests = $transferObject->getBody(); $headers = $transferObject->getHeaders(); + $idempotencyKeyExtraData = $headers['idempotencyExtraData']; + unset($headers['idempotencyExtraData']); $clientConfig = $transferObject->getClientConfig(); $client = $this->adyenHelper->initializeAdyenClientWithClientConfig($clientConfig); @@ -66,10 +68,11 @@ public function placeRequest(TransferInterface $transferObject): array $responseData = []; $idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey( $request, - $headers['idempotencyExtraData'] ?? null + $idempotencyKeyExtraData ?? null ); $requestOptions['idempotencyKey'] = $idempotencyKey; - $requestOptions['headers'] = $this->adyenHelper->buildRequestHeaders(); + $requestOptions['headers'] = $headers; + $this->adyenHelper->logRequest($request, Client::API_CHECKOUT_VERSION, '/refunds'); $request['applicationInfo'] = $this->adyenHelper->buildApplicationInfo($client); $paymentRefundRequest = new PaymentRefundRequest($request); @@ -88,6 +91,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/HeaderDataBuilder.php b/Gateway/Request/Header/HeaderDataBuilder.php similarity index 84% rename from Gateway/Request/HeaderDataBuilder.php rename to Gateway/Request/Header/HeaderDataBuilder.php index 66cd1aa703..d2c772f1e6 100644 --- a/Gateway/Request/HeaderDataBuilder.php +++ b/Gateway/Request/Header/HeaderDataBuilder.php @@ -9,18 +9,15 @@ * Author: Adyen */ -namespace Adyen\Payment\Gateway\Request; +namespace Adyen\Payment\Gateway\Request\Header; use Adyen\Payment\Helper\Data; use Magento\Payment\Gateway\Data\PaymentDataObject; use Magento\Payment\Gateway\Helper\SubjectReader; use Magento\Payment\Gateway\Request\BuilderInterface; -class HeaderDataBuilder implements BuilderInterface +class HeaderDataBuilder implements BuilderInterface, HeaderDataBuilderInterface { - const FRONTENDTYPE = 'external-platform-frontendtype'; - const FRONTENDTYPE_HEADLESS = 'headless'; - /** * @var Data */ diff --git a/Gateway/Request/Header/HeaderDataBuilderInterface.php b/Gateway/Request/Header/HeaderDataBuilderInterface.php new file mode 100644 index 0000000000..ac10244854 --- /dev/null +++ b/Gateway/Request/Header/HeaderDataBuilderInterface.php @@ -0,0 +1,15 @@ +getMagentoDetails(); $headers = [ - 'external-platform-name' => $magentoDetails['name'], - 'external-platform-version' => $magentoDetails['version'], - 'external-platform-edition' => $magentoDetails['edition'], - 'merchant-application-name' => $this->getModuleName(), - 'merchant-application-version' => $this->getModuleVersion() + HeaderDataBuilderInterface::EXTERNAL_PLATFORM_NAME => $magentoDetails['name'], + HeaderDataBuilderInterface::EXTERNAL_PLATFORM_VERSION => $magentoDetails['version'], + HeaderDataBuilderInterface::EXTERNAL_PLATFORM_EDITION => $magentoDetails['edition'], + HeaderDataBuilderInterface::MERCHANT_APPLICATION_NAME => $this->getModuleName(), + HeaderDataBuilderInterface::MERCHANT_APPLICATION_VERSION => $this->getModuleVersion() ]; - if(isset($payment) && !is_null($payment->getAdditionalInformation(HeaderDataBuilder::FRONTENDTYPE))) { - $headers[HeaderDataBuilder::FRONTENDTYPE] = - $payment->getAdditionalInformation(HeaderDataBuilder::FRONTENDTYPE); + if(isset($payment) && !is_null($payment->getAdditionalInformation(HeaderDataBuilderInterface::ADDITIONAL_DATA_FRONTEND_TYPE_KEY))) { + $headers[HeaderDataBuilderInterface::EXTERNAL_PLATFORM_FRONTEND_TYPE] = + $payment->getAdditionalInformation(HeaderDataBuilderInterface::ADDITIONAL_DATA_FRONTEND_TYPE_KEY); } return $headers; @@ -1248,6 +1249,11 @@ public function initializeOrdersApi(Client $client): OrdersApi return new OrdersApi($client); } + public function initializePaymentLinksApi(Client $client):PaymentLinksApi + { + return new PaymentLinksApi($client); + } + /** * @param Client $client * @return PosPayment diff --git a/Helper/Invoice.php b/Helper/Invoice.php index 1a71d6540a..9f99422304 100644 --- a/Helper/Invoice.php +++ b/Helper/Invoice.php @@ -437,8 +437,6 @@ public function createInvoiceFromWebhook(Order $order, Notification $notificatio ); $transactionSave->save(); - $this->sendInvoiceMail($invoice); - //Send Invoice mail to customer $invoiceAutoMail = (bool)$this->scopeConfig->isSetFlag( InvoiceIdentity::XML_PATH_EMAIL_ENABLED, diff --git a/Model/Config/Adminhtml/ApplepayCertificateButton.php b/Model/Config/Adminhtml/ApplePayDomainAssociationFileButton.php similarity index 76% rename from Model/Config/Adminhtml/ApplepayCertificateButton.php rename to Model/Config/Adminhtml/ApplePayDomainAssociationFileButton.php index 4dc52c5ded..16de30dd46 100644 --- a/Model/Config/Adminhtml/ApplepayCertificateButton.php +++ b/Model/Config/Adminhtml/ApplePayDomainAssociationFileButton.php @@ -16,14 +16,14 @@ use Magento\Backend\Helper\Data; use Magento\Framework\Data\Form\Element\AbstractElement; -class ApplepayCertificateButton extends Field +class ApplePayDomainAssociationFileButton extends Field { - const APPLEPAY_BUTTON = 'Adyen_Payment::config/applepay_button.phtml'; + const APPLEPAY_BUTTON = 'Adyen_Payment::config/applepay_domain_association_file_button.phtml'; /** * @var Data */ - protected $backendHelper; + protected Data $backendHelper; /** * @param Context $context @@ -40,9 +40,9 @@ public function __construct( } /** - * @return $this|ApplepayCertificateButton + * @return $this|ApplePayDomainAssociationFileButton */ - protected function _prepareLayout() + protected function _prepareLayout(): ApplePayDomainAssociationFileButton|static { parent::_prepareLayout(); @@ -57,7 +57,7 @@ protected function _prepareLayout() * @param AbstractElement $element * @return string */ - protected function _getElementHtml(AbstractElement $element) + protected function _getElementHtml(AbstractElement $element): string { $this->addData([ 'id' => 'addbutton_button', @@ -73,6 +73,6 @@ protected function _getElementHtml(AbstractElement $element) */ public function getActionUrl(): string { - return $this->backendHelper->getUrl("adyen/configuration/DownloadApplePayCertificate"); + return $this->backendHelper->getUrl("adyen/configuration/DownloadApplePayDomainAssociationFile"); } } 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/Observer/AdyenCcDataAssignObserver.php b/Observer/AdyenCcDataAssignObserver.php index 6168deebb3..79ed087eab 100644 --- a/Observer/AdyenCcDataAssignObserver.php +++ b/Observer/AdyenCcDataAssignObserver.php @@ -19,7 +19,7 @@ use Magento\Framework\Event\Observer; use Magento\Payment\Observer\AbstractDataAssignObserver; use Magento\Quote\Api\Data\PaymentInterface; -use Adyen\Payment\Gateway\Request\HeaderDataBuilder; +use Adyen\Payment\Gateway\Request\Header\HeaderDataBuilderInterface; class AdyenCcDataAssignObserver extends AbstractDataAssignObserver { @@ -46,7 +46,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver self::CC_TYPE, self::RETURN_URL, self::RECURRING_PROCESSING_MODEL, - HeaderDataBuilder::FRONTENDTYPE + HeaderDataBuilderInterface::ADDITIONAL_DATA_FRONTEND_TYPE_KEY ]; /** diff --git a/Observer/AdyenPaymentMethodDataAssignObserver.php b/Observer/AdyenPaymentMethodDataAssignObserver.php index e90ce7b0a0..efe803a0fc 100644 --- a/Observer/AdyenPaymentMethodDataAssignObserver.php +++ b/Observer/AdyenPaymentMethodDataAssignObserver.php @@ -11,7 +11,7 @@ namespace Adyen\Payment\Observer; -use Adyen\Payment\Gateway\Request\HeaderDataBuilder; +use Adyen\Payment\Gateway\Request\Header\HeaderDataBuilderInterface; use Adyen\Payment\Helper\StateData; use Adyen\Payment\Helper\Util\CheckoutStateDataValidator; use Adyen\Payment\Helper\Util\DataArrayValidator; @@ -39,7 +39,7 @@ class AdyenPaymentMethodDataAssignObserver extends AbstractDataAssignObserver self::RETURN_URL, self::RECURRING_PROCESSING_MODEL, self::CC_NUMBER, - HeaderDataBuilder::FRONTENDTYPE + HeaderDataBuilderInterface::ADDITIONAL_DATA_FRONTEND_TYPE_KEY ]; protected CheckoutStateDataValidator $checkoutStateDataValidator; 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/Controller/Adminhtml/Configuration/DownloadApplePayDomainAssociationFileTest.php b/Test/Unit/Controller/Adminhtml/Configuration/DownloadApplePayDomainAssociationFileTest.php new file mode 100644 index 0000000000..954e61f634 --- /dev/null +++ b/Test/Unit/Controller/Adminhtml/Configuration/DownloadApplePayDomainAssociationFileTest.php @@ -0,0 +1,144 @@ +redirectMock = $this->createMock(RedirectInterface::class); + + $this->resultMock = $this->createGeneratedMock( + Redirect::class + ); + + $this->resultFactoryMock = $this->createGeneratedMock( + ResultFactory::class, + ['create'] + ); + $this->resultFactoryMock->method('create')->willReturn($this->resultMock); + + $this->managerMock = $this->createMock(ManagerInterface::class); + + $this->contextMock = $this->createMock(Context::class); + $this->contextMock->method('getResultFactory')->willReturn($this->resultFactoryMock); + $this->contextMock->method('getRedirect')->willReturn($this->redirectMock); + $this->contextMock->method('getMessageManager')->willReturn($this->managerMock); + + $this->directoryListMock = $this->createMock(DirectoryList::class); + $this->fileIoMock = $this->createMock(File::class); + $this->adyenLoggerMock = $this->createMock(AdyenLogger::class); + + + $this->downloadApplePayDomainAssociationFile = new DownloadApplePayDomainAssociationFile( + $this->contextMock, + $this->directoryListMock, + $this->fileIoMock, + $this->adyenLoggerMock + ); + } + + /** + * @return void + * @throws FileSystemException + */ + public function testDownloadFileSuccessfully(): void + { + $this->directoryListMock->method('getPath') + ->with('pub') + ->willReturn('/var/www/html/pub'); + + $this->fileIoMock->method('checkAndCreateFolder') + ->with('/var/www/html/pub/.well-known') + ->willReturn(true); + + $this->fileIoMock->method('read') + ->with( + 'https://bae81f955b.cdn.adyen.com/checkoutshopper/.well-known/apple-developer-merchantid-domain-association', + '/var/www/html/pub/.well-known/apple-developer-merchantid-domain-association' + ) + ->willReturn(true); + + $this->adyenLoggerMock->expects($this->atLeastOnce())->method('addAdyenDebug'); + $this->managerMock->expects($this->once())->method('addSuccessMessage'); + + $redirectResponse = $this->downloadApplePayDomainAssociationFile->execute(); + + $this->assertInstanceOf(Redirect::class, $redirectResponse); + } + + /** + * @return void + * @throws FileSystemException + */ + public function testHttpNotFound(): void + { + $this->directoryListMock->method('getPath') + ->with('pub') + ->willReturn('/var/www/html/pub'); + + $this->fileIoMock->method('checkAndCreateFolder') + ->with('/var/www/html/pub/.well-known') + ->willReturn(true); + + $this->fileIoMock->method('read') + ->with( + 'https://bae81f955b.cdn.adyen.com/checkoutshopper/.well-known/apple-developer-merchantid-domain-association', + '/var/www/html/pub/.well-known/apple-developer-merchantid-domain-association' + ) + ->willReturn(false); + + $this->adyenLoggerMock->expects($this->atLeastOnce())->method('error'); + $this->managerMock->expects($this->once())->method('addErrorMessage'); + + $redirectResponse = $this->downloadApplePayDomainAssociationFile->execute(); + + $this->assertInstanceOf(Redirect::class, $redirectResponse); + } + + /** + * @return void + * @throws FileSystemException + */ + public function testFileSystemIOError(): void + { + $this->directoryListMock->method('getPath') + ->with('pub') + ->willReturn('/var/www/html/pub'); + + $this->fileIoMock->method('checkAndCreateFolder') + ->willThrowException(new LocalizedException(__('mock error message'))); + + $this->adyenLoggerMock->expects($this->atLeastOnce())->method('error'); + $this->managerMock->expects($this->once())->method('addErrorMessage'); + + $redirectResponse = $this->downloadApplePayDomainAssociationFile->execute(); + + $this->assertInstanceOf(Redirect::class, $redirectResponse); + } +} diff --git a/Test/Unit/Gateway/Http/Client/TransactionPaymentLinksTest.php b/Test/Unit/Gateway/Http/Client/TransactionPaymentLinksTest.php new file mode 100644 index 0000000000..c52733c959 --- /dev/null +++ b/Test/Unit/Gateway/Http/Client/TransactionPaymentLinksTest.php @@ -0,0 +1,120 @@ +adyenHelperMock = $this->createMock(Data::class); + $this->idempotencyHelperMock = $this->createMock(Idempotency::class); + $this->transferObjectMock = $this->createMock(TransferInterface::class); + $this->applicationInfoMock = $this->createMock(ApplicationInfo::class); + $this->adyenHelperMock->method('buildApplicationInfo')->willReturn($this->applicationInfoMock); + $this->transferObjectMock->method('getClientConfig')->willReturn([]); + $this->clientMock = $this->createMock(Client::class); + $this->adyenHelperMock->method('initializeAdyenClientWithClientConfig')->willReturn($this->clientMock); + $this->paymentLinksApiMock = $this->createMock(PaymentLinksApi::class); + $this->adyenHelperMock + ->method('initializePaymentLinksApi') + ->with($this->clientMock) + ->willReturn($this->paymentLinksApiMock); + + $this->transactionPaymentLinks = new TransactionPaymentLinks( + $this->adyenHelperMock, + $this->idempotencyHelperMock + ); + } + + public function testSuccessfulPlaceRequest() + { + $requestBody = [ + 'allowedPaymentMethods' => ['ideal','giropay'], + 'amount' => ['value' => 1000, 'currency' => 'EUR'], + 'applicationInfo' => $this->applicationInfoMock + ]; + + $headers = [ 'idempotencyExtraData' => [], 'header' => 'some-data']; + $idempotencyKey = 'generated_idempotency_key'; + + $this->transferObjectMock->method('getBody')->willReturn($requestBody); + $this->transferObjectMock->method('getHeaders')->willReturn($headers); + + $this->idempotencyHelperMock->expects($this->once()) + ->method('generateIdempotencyKey') + ->with($requestBody, $headers['idempotencyExtraData']) + ->willReturn('generated_idempotency_key'); + + $this->paymentLinksApiMock->expects($this->once()) + ->method('paymentLinks') + ->with( + $this->callback(function (PaymentLinkRequest $paymentLinkRequest) use ($requestBody) { + $amount = $paymentLinkRequest->getAmount(); + $this->assertEquals($amount, ['value' => 1000, 'currency' => 'EUR']); + $allowedPaymentMethods = $paymentLinkRequest->getAllowedPaymentMethods(); + $this->assertEquals($allowedPaymentMethods, ['ideal', 'giropay']); + return true; + }), + $this->callback(function ($requestOptions) use ($idempotencyKey, $headers) { + $this->assertArrayHasKey('idempotencyKey', $requestOptions); + $this->assertArrayHasKey('headers', $requestOptions); + $this->assertEquals($idempotencyKey, $requestOptions['idempotencyKey']); + $this->assertEquals(['header' => 'some-data'], $requestOptions['headers']); + return true; + }) + )->willReturn(new PaymentLinkResponse(['url' => 'https://paymentlink.com'])); + + $response = $this->transactionPaymentLinks->placeRequest($this->transferObjectMock); + $this->assertIsArray($response); + $this->assertArrayHasKey('url', $response); + } + + public function testRequestWithAdyenException() + { + $requestBody = [ + 'amount' => ['currency' => 'EUR', 'value' => 1000], + 'merchantAccount' => 'TestMerchant', + 'reference' => 'TestReference', + ]; + $this->transferObjectMock->method('getBody')->willReturn($requestBody); + $this->transferObjectMock->method('getHeaders')->willReturn([]); + $this->transferObjectMock->method('getClientConfig')->willReturn([]); + + $this->paymentLinksApiMock + ->method('paymentLinks') + ->willThrowException(new AdyenException()); + + $response = $this->transactionPaymentLinks->placeRequest($this->transferObjectMock); + + $this->assertArrayHasKey('error', $response); + } + + public function testRequestWithResultCodePresent() + { + $requestBody = ['resultCode' => 'Authorised']; + $this->transferObjectMock->method('getBody')->willReturn($requestBody); + + $response = $this->transactionPaymentLinks->placeRequest($this->transferObjectMock); + $this->assertEquals($requestBody, $response); + } + +} diff --git a/Test/Unit/Gateway/Http/Client/TransactionRefundTest.php b/Test/Unit/Gateway/Http/Client/TransactionRefundTest.php index 3d98825999..3ba9370ac4 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 { @@ -70,7 +71,6 @@ public function testPlaceRequestIncludesHeadersInRequest() $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') @@ -90,7 +90,6 @@ public function testPlaceRequestIncludesHeadersInRequest() $this->assertArrayHasKey('idempotencyKey', $requestOptions); $this->assertArrayHasKey('headers', $requestOptions); $this->assertEquals('generated_idempotency_key', $requestOptions['idempotencyKey']); - $this->assertArrayHasKey('custom-header', $requestOptions['headers']); return true; }) ) @@ -102,4 +101,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/HeaderDataBuilderTest.php b/Test/Unit/Gateway/Request/Header/HeaderDataBuilderTest.php similarity index 97% rename from Test/Unit/Gateway/Request/HeaderDataBuilderTest.php rename to Test/Unit/Gateway/Request/Header/HeaderDataBuilderTest.php index 7c15e659a1..b270347fb1 100644 --- a/Test/Unit/Gateway/Request/HeaderDataBuilderTest.php +++ b/Test/Unit/Gateway/Request/Header/HeaderDataBuilderTest.php @@ -2,7 +2,7 @@ namespace Adyen\Payment\Test\Unit\Gateway\Request; -use Adyen\Payment\Gateway\Request\HeaderDataBuilder; +use Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder; use Adyen\Payment\Test\Unit\AbstractAdyenTestCase; use Adyen\Payment\Helper\Data; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; diff --git a/Test/Unit/Helper/DataTest.php b/Test/Unit/Helper/DataTest.php index ffb82e21cc..ffc52261e3 100755 --- a/Test/Unit/Helper/DataTest.php +++ b/Test/Unit/Helper/DataTest.php @@ -15,7 +15,7 @@ use Adyen\Config as AdyenConfig; use Adyen\Model\Checkout\ApplicationInfo; use Adyen\Model\Checkout\CommonField; -use Adyen\Payment\Gateway\Request\HeaderDataBuilder; +use Adyen\Payment\Gateway\Request\Header\HeaderDataBuilderInterface; use Adyen\Payment\Helper\Config as ConfigHelper; use Adyen\Payment\Helper\Data; use Adyen\Payment\Helper\Locale; @@ -27,6 +27,7 @@ use Adyen\Payment\Test\Unit\AbstractAdyenTestCase; use Adyen\Service\Checkout\ModificationsApi; use Adyen\Service\Checkout\OrdersApi; +use Adyen\Service\Checkout\PaymentLinksApi; use Adyen\Service\Checkout\PaymentsApi; use Adyen\Service\RecurringApi; use Magento\Backend\Helper\Data as BackendHelper; @@ -1090,15 +1091,15 @@ public function testBuildRequestHeadersWithNonNullFrontendType() // Set up expectations for the getAdditionalInformation method $payment->method('getAdditionalInformation') - ->with(HeaderDataBuilder::FRONTENDTYPE) + ->with(HeaderDataBuilderInterface::ADDITIONAL_DATA_FRONTEND_TYPE_KEY) ->willReturn('some_frontend_type'); // Call the method under test $result = $this->dataHelper->buildRequestHeaders($payment); // Assert that the 'frontend-type' header is correctly set - $this->assertArrayHasKey(HeaderDataBuilder::FRONTENDTYPE, $result); - $this->assertEquals('some_frontend_type', $result[HeaderDataBuilder::FRONTENDTYPE]); + $this->assertArrayHasKey(HeaderDataBuilderInterface::EXTERNAL_PLATFORM_FRONTEND_TYPE, $result); + $this->assertEquals('some_frontend_type', $result[HeaderDataBuilderInterface::EXTERNAL_PLATFORM_FRONTEND_TYPE]); // Assert other headers as needed } @@ -1110,7 +1111,7 @@ public function testBuildRequestHeadersWithoutPayment() $result = $this->dataHelper->buildRequestHeaders(); // Assert that the 'frontend-type' header is not set - $this->assertArrayNotHasKey(HeaderDataBuilder::FRONTENDTYPE, $result); + $this->assertArrayNotHasKey(HeaderDataBuilderInterface::EXTERNAL_PLATFORM_FRONTEND_TYPE, $result); } public function testLogResponse() @@ -1892,6 +1893,12 @@ public function testInitializeOrdersApi() $this->assertInstanceOf(OrdersApi::class, $service); } + public function testInitializePaymentLinksApi() + { + $service = $this->dataHelper->initializePaymentLinksApi($this->clientMock); + $this->assertInstanceOf(PaymentLinksApi::class, $service); + } + public function testLogAdyenException() { $this->store->method('getId')->willReturn(1); diff --git a/Test/Unit/Model/Config/Adminhtml/ApplePayDomainAssociationFileButtonTest.php b/Test/Unit/Model/Config/Adminhtml/ApplePayDomainAssociationFileButtonTest.php new file mode 100644 index 0000000000..f79be89c48 --- /dev/null +++ b/Test/Unit/Model/Config/Adminhtml/ApplePayDomainAssociationFileButtonTest.php @@ -0,0 +1,102 @@ +createMock(ObjectManagerInterface::class); + ObjectManager::setInstance($objectManagerMock); + + $this->managerMock = $this->createMock(ManagerInterface::class); + $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class); + + $this->contextMock = $this->createMock(Context::class); + $this->contextMock->method('getScopeConfig')->willReturn($this->scopeConfigMock); + $this->contextMock->method('getEventManager')->willReturn($this->managerMock); + + $this->backendHelperMock = $this->createMock(Data::class); + $this->layoutMock = $this->createMock(LayoutInterface::class); + + $this->applePayDomainAssociationFileButton = new ApplePayDomainAssociationFileButton( + $this->contextMock, + $this->backendHelperMock, + [] + ); + } + + /** + * @return void + */ + public function tearDown(): void + { + $this->applePayDomainAssociationFileButton = null; + } + + /** + * Asserts default HTML template value + * + * @return void + */ + public function testGetElementHtml() + { + $expected = ''; + + $result = $this->applePayDomainAssociationFileButton + ->render($this->createMock(AbstractElement::class)); + + $this->assertEquals($expected, $result); + } + + /** + * Asserts return type of the button's backend model + * + * @return void + */ + public function testPrepareLayout() + { + $result = $this->applePayDomainAssociationFileButton->setLayout($this->layoutMock); + $this->assertInstanceOf(ApplePayDomainAssociationFileButton::class, $result); + } + + /** + * Asserts file download controller URL + * + * @return void + */ + public function testGetActionUrl() + { + $expected = 'https://www.magento.demo/adyen/configuration/DownloadApplePayDomainAssociationFile'; + $this->backendHelperMock->expects($this->once()) + ->method('getUrl') + ->with('adyen/configuration/DownloadApplePayDomainAssociationFile', []) + ->willReturn($expected); + + $url = $this->applePayDomainAssociationFileButton->getActionUrl(); + + $this->assertEquals($expected, $url); + } +} 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 69dd356299..be62bf9b12 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -9.12.1 +9.12.2 diff --git a/composer.json b/composer.json index 01f29571ee..d9be60eaa9 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.12.1", + "version": "9.12.2", "license": "MIT", "repositories": [ { @@ -24,7 +24,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_alternative_payment_methods.xml b/etc/adminhtml/system/adyen_alternative_payment_methods.xml index 21dcfb7a81..ae858674c6 100755 --- a/etc/adminhtml/system/adyen_alternative_payment_methods.xml +++ b/etc/adminhtml/system/adyen_alternative_payment_methods.xml @@ -19,8 +19,8 @@ Set up additional payment methods to accept online and in-app payments and eliminate the need for traditional card-based transactions.

]]> - - Adyen\Payment\Model\Config\Adminhtml\ApplepayCertificateButton + + Adyen\Payment\Model\Config\Adminhtml\ApplePayDomainAssociationFileButton diff --git a/etc/di.xml b/etc/di.xml index 2472409ddc..e7fc019f4f 100755 --- a/etc/di.xml +++ b/etc/di.xml @@ -1079,7 +1079,7 @@ Adyen\Payment\Gateway\Request\ReturnUrlDataBuilder Adyen\Payment\Gateway\Request\ChannelDataBuilder Adyen\Payment\Gateway\Request\OriginDataBuilder - Adyen\Payment\Gateway\Request\HeaderDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder Adyen\Payment\Gateway\Request\GiftcardDataBuilder @@ -1113,6 +1113,7 @@ Adyen\Payment\Gateway\Request\PaymentDataBuilder Adyen\Payment\Gateway\Request\DescriptionDataBuilder Adyen\Payment\Gateway\Request\CheckoutDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder @@ -1132,7 +1133,7 @@ Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder Adyen\Payment\Gateway\Request\RecurringVaultDataBuilder Adyen\Payment\Gateway\Request\ShopperInteractionDataBuilder - Adyen\Payment\Gateway\Request\HeaderDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder Adyen\Payment\Gateway\Request\GiftcardDataBuilder @@ -1152,7 +1153,7 @@ Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder Adyen\Payment\Gateway\Request\RecurringVaultDataBuilder Adyen\Payment\Gateway\Request\ShopperInteractionDataBuilder - Adyen\Payment\Gateway\Request\HeaderDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder Adyen\Payment\Gateway\Request\GiftcardDataBuilder @@ -1200,7 +1201,7 @@ Adyen\Payment\Gateway\Request\RecurringDataBuilder Adyen\Payment\Gateway\Request\ShopperInteractionDataBuilder Adyen\Payment\Gateway\Request\CheckoutDataBuilder - Adyen\Payment\Gateway\Request\HeaderDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder Adyen\Payment\Gateway\Request\ReturnUrlDataBuilder Adyen\Payment\Gateway\Request\ChannelDataBuilder Adyen\Payment\Gateway\Request\OriginDataBuilder @@ -1220,7 +1221,7 @@ Adyen\Payment\Gateway\Request\BrowserInfoDataBuilder Adyen\Payment\Gateway\Request\ShopperInteractionDataBuilder Adyen\Payment\Gateway\Request\CheckoutDataBuilder - Adyen\Payment\Gateway\Request\HeaderDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder Adyen\Payment\Gateway\Request\ReturnUrlDataBuilder Adyen\Payment\Gateway\Request\ChannelDataBuilder Adyen\Payment\Gateway\Request\OriginDataBuilder @@ -1248,7 +1249,7 @@ Adyen\Payment\Gateway\Request\RecurringDataBuilder Adyen\Payment\Gateway\Request\ShopperInteractionDataBuilder Adyen\Payment\Gateway\Request\CheckoutDataBuilder - Adyen\Payment\Gateway\Request\HeaderDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder Adyen\Payment\Gateway\Request\ReturnUrlDataBuilder Adyen\Payment\Gateway\Request\ChannelDataBuilder Adyen\Payment\Gateway\Request\OriginDataBuilder @@ -1269,6 +1270,7 @@ Adyen\Payment\Gateway\Request\MerchantAccountDataBuilder Adyen\Payment\Gateway\Request\CaptureDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder @@ -1286,6 +1288,7 @@ Adyen\Payment\Gateway\Request\RefundDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder @@ -1302,6 +1305,7 @@ Adyen\Payment\Gateway\Request\CancelDataBuilder + Adyen\Payment\Gateway\Request\Header\HeaderDataBuilder @@ -4564,4 +4568,4 @@ adyen_doku_mandiri_va - \ No newline at end of file + diff --git a/view/adminhtml/templates/config/applepay_button.phtml b/view/adminhtml/templates/config/applepay_button.phtml deleted file mode 100644 index e57195c9fe..0000000000 --- a/view/adminhtml/templates/config/applepay_button.phtml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/view/adminhtml/templates/config/applepay_domain_association_file_button.phtml b/view/adminhtml/templates/config/applepay_domain_association_file_button.phtml new file mode 100644 index 0000000000..a25f333024 --- /dev/null +++ b/view/adminhtml/templates/config/applepay_domain_association_file_button.phtml @@ -0,0 +1,4 @@ + + 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/frontend/web/js/view/payment/method-renderer/adyen-cc-vault-method.js b/view/frontend/web/js/view/payment/method-renderer/adyen-cc-vault-method.js index dbad6e1d5a..45a44078e1 100644 --- a/view/frontend/web/js/view/payment/method-renderer/adyen-cc-vault-method.js +++ b/view/frontend/web/js/view/payment/method-renderer/adyen-cc-vault-method.js @@ -260,7 +260,7 @@ define([ stateData: stateData, public_hash: this.publicHash, numberOfInstallments: this.installment(), - frontendType: 'luma' + frontendType: 'default' }, }; }, diff --git a/view/frontend/web/js/view/payment/method-renderer/adyen-pm-method.js b/view/frontend/web/js/view/payment/method-renderer/adyen-pm-method.js index f6bf2dffc9..c3918236f7 100755 --- a/view/frontend/web/js/view/payment/method-renderer/adyen-pm-method.js +++ b/view/frontend/web/js/view/payment/method-renderer/adyen-pm-method.js @@ -155,7 +155,7 @@ define( fullScreenLoader.stopLoader(); errorProcessor.process(error, this.currentMessageContainer); }, - + renderCheckoutComponent: function() { let methodCode = this.getMethodCode(); let configuration = this.buildComponentConfiguration(this.paymentMethod(), this.paymentMethodsExtraInfo()); @@ -294,7 +294,7 @@ define( let additionalData = {}; additionalData.brand_code = this.paymentMethod().type; - additionalData.frontendType = 'luma'; + additionalData.frontendType = 'default'; let stateData; if (this.paymentComponent) { diff --git a/view/frontend/web/js/view/payment/method-renderer/adyen-pm-vault-method.js b/view/frontend/web/js/view/payment/method-renderer/adyen-pm-vault-method.js index 5452313181..3f56674671 100644 --- a/view/frontend/web/js/view/payment/method-renderer/adyen-pm-vault-method.js +++ b/view/frontend/web/js/view/payment/method-renderer/adyen-pm-vault-method.js @@ -54,6 +54,15 @@ define([ */ getIcons: function (type) { return this.details.icon; + }, + getData: function () { + return { + method: this.code, + additional_data: { + public_hash: this.publicHash, + frontendType: 'default' + }, + }; } }); }); 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()">