diff --git a/.github/Makefile b/.github/Makefile index d9d1c02fb..50c271281 100644 --- a/.github/Makefile +++ b/.github/Makefile @@ -49,6 +49,14 @@ configure: n98-magerun2.phar flush: bin/magento cache:flush +# Setup upgrade +enable-express: + bin/magento module:enable Adyen_ExpressCheckout + bin/magento setup:upgrade + bin/magento config:set payment/adyen_hpp/show_google_pay_on "1,2,3" + bin/magento config:set payment/adyen_hpp/show_apple_pay_on "1,2,3" + bin/magento cache:clean + # Full plugin setup plugin: install configure flush diff --git a/.github/docker-compose.e2e.yml b/.github/docker-compose.e2e.yml index 4afb1465e..84a6215c7 100644 --- a/.github/docker-compose.e2e.yml +++ b/.github/docker-compose.e2e.yml @@ -18,7 +18,12 @@ services: - ADYEN_API_KEY - ADYEN_CLIENT_KEY - ADYEN_MERCHANT + - GOOGLE_USERNAME + - GOOGLE_PASSWORD + - WEBHOOK_USERNAME + - WEBHOOK_PASSWORD volumes: - ../../scripts/e2e.sh:/e2e.sh + - ../../scripts/e2e-all.sh:/e2e-all.sh - ../../../test-report:/tmp/test-report diff --git a/.github/scripts/e2e-all.sh b/.github/scripts/e2e-all.sh new file mode 100755 index 000000000..b1c6c36f7 --- /dev/null +++ b/.github/scripts/e2e-all.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -euo pipefail + +# Checkout E2E tests +cd /tmp; +git clone https://github.com/Adyen/adyen-integration-tools-tests.git; +cd adyen-integration-tools-tests; +git checkout $INTEGRATION_TESTS_BRANCH; + +# Setup environment +rm -rf package-lock.json; +npm i; + +# Run tests +npm run test:ci:magento:all diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 1f9d5d6c1..f20e08282 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -1,11 +1,18 @@ -name: E2E Test -run-name: Headless E2E tests for Adyen Magento2 Plugin +name: Magento 2 E2E Pipeline +run-name: E2E tests for Adyen Magento2 Plugin -on: [pull_request] +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches-ignore: [main] jobs: build: - if: ${{ github.actor != 'renovate[bot]' || github.actor != 'lgtm-com[bot]' }} + if: | + ${{ + github.event.pull_request.draft == false && + (github.actor != 'renovate' || github.actor != 'lgtm-com') + }} runs-on: group: larger-runners labels: ubuntu-latest-8-cores @@ -58,6 +65,8 @@ jobs: ADYEN_API_KEY: ${{secrets.ADYEN_API_KEY}} ADYEN_CLIENT_KEY: ${{secrets.ADYEN_CLIENT_KEY}} ADYEN_MERCHANT: ${{secrets.ADYEN_MERCHANT}} + WEBHOOK_USERNAME: ${{secrets.WEBHOOK_USERNAME}} + WEBHOOK_PASSWORD: ${{secrets.WEBHOOK_PASSWORD}} - name: Archive test result artifacts if: always() diff --git a/.github/workflows/templates/docker-compose.yml b/.github/workflows/templates/docker-compose.yml index d1b443111..636788f6d 100644 --- a/.github/workflows/templates/docker-compose.yml +++ b/.github/workflows/templates/docker-compose.yml @@ -76,8 +76,13 @@ services: - ADYEN_API_KEY - ADYEN_CLIENT_KEY - ADYEN_MERCHANT + - GOOGLE_USERNAME + - GOOGLE_PASSWORD + - WEBHOOK_USERNAME + - WEBHOOK_PASSWORD volumes: - ../../scripts/e2e.sh:/e2e.sh + - ../../scripts/e2e-all.sh:/e2e-all.sh - ../../../test-report:/tmp/test-report networks: backend: diff --git a/.github/workflows/test-repo-e2e-release.yml b/.github/workflows/test-repo-e2e-release.yml new file mode 100644 index 000000000..a033083ef --- /dev/null +++ b/.github/workflows/test-repo-e2e-release.yml @@ -0,0 +1,77 @@ +name: Magento 2 Release E2E Pipeline +run-name: E2E tests against Test Repository with Express Checkout + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches: [main] + +jobs: + build: + runs-on: + group: larger-runners + labels: ubuntu-latest-8-cores + timeout-minutes: 20 + env: + PHP_VERSION: "8.1" + MAGENTO_VERSION: "2.4.5" + ADMIN_USERNAME: ${{secrets.MAGENTO_ADMIN_USERNAME}} + ADMIN_PASSWORD: ${{secrets.MAGENTO_ADMIN_PASSWORD}} + steps: + - uses: actions/checkout@v3 + + - name: Install Magento + run: docker-compose -f .github/workflows/templates/docker-compose.yml run --rm web make magento + + - name: Start web server in background + run: docker-compose -f .github/workflows/templates/docker-compose.yml up -d web + env: + DONATION_ACCOUNT: ${{secrets.DONATION_ACCOUNT}} + ADYEN_MERCHANT: ${{secrets.ADYEN_MERCHANT}} + ADYEN_API_KEY: ${{secrets.ADYEN_API_KEY}} + ADYEN_CLIENT_KEY: ${{secrets.ADYEN_CLIENT_KEY}} + + - name: Setup permissions + run: docker exec magento2-container make fs + + - name: Check install + run: docker exec magento2-container make sys-check + + - name: Install plugin + run: docker exec -u www-data magento2-container make plugin + + - name: Install Express module + run: docker exec -u www-data magento2-container composer require adyen/adyen-magento2-expresscheckout + + - name: Enable Express module + run: docker exec -u www-data magento2-container make enable-express + + - name: Switch to production mode + run: docker exec -u www-data magento2-container make production + + - name: Setup permissions + run: docker exec magento2-container make fs + + - name: Run E2E tests + run: docker-compose -f .github/workflows/templates/docker-compose.yml run --rm playwright /e2e-all.sh + env: + INTEGRATION_TESTS_BRANCH: develop + MAGENTO_ADMIN_USERNAME: ${{secrets.MAGENTO_ADMIN_USERNAME}} + MAGENTO_ADMIN_PASSWORD: ${{secrets.MAGENTO_ADMIN_PASSWORD}} + MAGENTO_BASE_URL: ${{secrets.MAGENTO_BASE_URL}} + PAYPAL_USERNAME: ${{secrets.PLAYWRIGHT_PAYPAL_USERNAME}} + PAYPAL_PASSWORD: ${{secrets.PLAYWRIGHT_PAYPAL_PASSWORD}} + ADYEN_API_KEY: ${{secrets.ADYEN_API_KEY}} + ADYEN_CLIENT_KEY: ${{secrets.ADYEN_CLIENT_KEY}} + ADYEN_MERCHANT: ${{secrets.ADYEN_MERCHANT}} + GOOGLE_USERNAME: ${{secrets.GOOGLE_USERNAME}} + GOOGLE_PASSWORD: ${{secrets.GOOGLE_PASSWORD}} + WEBHOOK_USERNAME: ${{secrets.WEBHOOK_USERNAME}} + WEBHOOK_PASSWORD: ${{secrets.WEBHOOK_PASSWORD}} + + - name: Archive test result artifacts + if: always() + uses: actions/upload-artifact@v3 + with: + name: html-report + path: test-report diff --git a/.github/workflows/test-repo-e2e.yml b/.github/workflows/test-repo-e2e.yml index 2960e082d..6a8ed8121 100644 --- a/.github/workflows/test-repo-e2e.yml +++ b/.github/workflows/test-repo-e2e.yml @@ -1,5 +1,5 @@ -name: Integration Test Repository Pipeline -run-name: Headless E2E test run triggered by adyen-integration-tools-tests ${{inputs.testBranch}} +name: Integration Test Repository Dispatch Pipeline +run-name: E2E tests against Test Repository ${{inputs.testBranch}} with Express Checkout ${{inputs.expressBranch}} on: workflow_dispatch: @@ -8,12 +8,22 @@ on: description: "Integration Test Repository Pipeline" required: true default: "develop" + expressBranch: + description: "Express Checkout Repository Pipeline" + required: true + default: "develop" jobs: build: + if: | + ${{ + github.event.pull_request.draft == false && + (github.actor != 'renovate' || github.actor != 'lgtm-com') + }} runs-on: group: larger-runners labels: ubuntu-latest-8-cores + timeout-minutes: 20 env: PHP_VERSION: "8.1" MAGENTO_VERSION: "2.4.5" @@ -42,6 +52,12 @@ jobs: - name: Install plugin run: docker exec -u www-data magento2-container make plugin + - name: Install Express module + run: docker exec -u www-data magento2-container composer require adyen/adyen-magento2-expresscheckout:dev-${{inputs.expressBranch}} + + - name: Enable Express module + run: docker exec -u www-data magento2-container make enable-express + - name: Switch to production mode run: docker exec -u www-data magento2-container make production @@ -49,7 +65,7 @@ jobs: run: docker exec magento2-container make fs - name: Run E2E tests - run: docker-compose -f .github/workflows/templates/docker-compose.yml run --rm playwright /e2e.sh + run: docker-compose -f .github/workflows/templates/docker-compose.yml run --rm playwright /e2e-all.sh env: INTEGRATION_TESTS_BRANCH: ${{inputs.testBranch}} MAGENTO_ADMIN_USERNAME: ${{secrets.MAGENTO_ADMIN_USERNAME}} @@ -60,6 +76,10 @@ jobs: ADYEN_API_KEY: ${{secrets.ADYEN_API_KEY}} ADYEN_CLIENT_KEY: ${{secrets.ADYEN_CLIENT_KEY}} ADYEN_MERCHANT: ${{secrets.ADYEN_MERCHANT}} + GOOGLE_USERNAME: ${{secrets.GOOGLE_USERNAME}} + GOOGLE_PASSWORD: ${{secrets.GOOGLE_PASSWORD}} + WEBHOOK_USERNAME: ${{secrets.WEBHOOK_USERNAME}} + WEBHOOK_PASSWORD: ${{secrets.WEBHOOK_PASSWORD}} - name: Archive test result artifacts if: always() diff --git a/Gateway/Http/Client/TransactionCancel.php b/Gateway/Http/Client/TransactionCancel.php index a0a28427e..9ca967455 100644 --- a/Gateway/Http/Client/TransactionCancel.php +++ b/Gateway/Http/Client/TransactionCancel.php @@ -15,7 +15,7 @@ use Adyen\Client; use Adyen\Payment\Helper\Data; use Adyen\Payment\Helper\Idempotency; -use Adyen\Service\Modification; +use Adyen\Service\Checkout\ModificationsApi; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Payment\Gateway\Http\ClientInterface; use Magento\Payment\Gateway\Http\TransferInterface; @@ -59,9 +59,8 @@ public function placeRequest(TransferInterface $transferObject): array $request = $transferObject->getBody(); $headers = $transferObject->getHeaders(); - $service = new Modification( - $this->adyenHelper->initializeAdyenClient($transferObject->getClientConfig()['storeId']) - ); + $client = $this->adyenHelper->initializeAdyenClient(); + $service = $this->adyenHelper->createAdyenCheckoutService($client); $idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey( $request, @@ -70,10 +69,9 @@ public function placeRequest(TransferInterface $transferObject): array $requestOptions['idempotencyKey'] = $idempotencyKey; - $this->adyenHelper - ->logRequest($request, Client::API_PAYMENT_VERSION, '/pal/servlet/Payment/{version}/cancel'); + $this->adyenHelper->logRequest($request, Client::API_CHECKOUT_VERSION, '/cancels'); try { - $response = $service->cancel($request, $requestOptions); + $response = $service->cancels($request, $requestOptions); } catch (AdyenException $e) { $response['error'] = $e->getMessage(); } diff --git a/Gateway/Http/Client/TransactionCapture.php b/Gateway/Http/Client/TransactionCapture.php index 3c7b3f44e..a5afa8a33 100644 --- a/Gateway/Http/Client/TransactionCapture.php +++ b/Gateway/Http/Client/TransactionCapture.php @@ -18,7 +18,7 @@ use Adyen\Payment\Helper\Idempotency; use Adyen\Payment\Helper\Requests; use Adyen\Payment\Logger\AdyenLogger; -use Adyen\Service\Modification; +use Adyen\Service\Checkout\ModificationsApi; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Payment\Gateway\Http\ClientInterface; use Magento\Payment\Gateway\Http\TransferInterface; @@ -31,8 +31,8 @@ class TransactionCapture implements ClientInterface const MULTIPLE_AUTHORIZATIONS = 'multiple_authorizations'; const FORMATTED_CAPTURE_AMOUNT = 'formatted_capture_amount'; const CAPTURE_AMOUNT = 'capture_amount'; - const ORIGINAL_REFERENCE = 'original_reference'; - const CAPTURE_RECEIVED = '[capture-received]'; + const ORIGINAL_REFERENCE = 'paymentPspReference'; + const CAPTURE_RECEIVED = 'received'; /** * @var Data @@ -76,9 +76,9 @@ public function placeRequest(TransferInterface $transferObject): array $request = $transferObject->getBody(); $headers = $transferObject->getHeaders(); - $service = new Modification( - $this->adyenHelper->initializeAdyenClient($transferObject->getClientConfig()['storeId']) - ); + $client = $this->adyenHelper->initializeAdyenClient(); + $service = $this->adyenHelper->createAdyenCheckoutService($client); + $idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey( $request, @@ -91,10 +91,10 @@ public function placeRequest(TransferInterface $transferObject): array return $this->placeMultipleCaptureRequests($service, $request, $requestOptions); } - $this->adyenHelper - ->logRequest($request, Client::API_PAYMENT_VERSION, '/pal/servlet/Payment/{version}/capture'); + $this->adyenHelper->logRequest($request, Client::API_CHECKOUT_VERSION, '/captures'); + try { - $response = $service->capture($request, $requestOptions); + $response = $service->captures($request, $requestOptions); $response = $this->copyParamsToResponse($response, $request); } catch (AdyenException $e) { $response['error'] = $e->getMessage(); @@ -105,22 +105,22 @@ public function placeRequest(TransferInterface $transferObject): array } /** - * @param Modification $service + * @param $service * @param $requestContainer * @return array */ - private function placeMultipleCaptureRequests(Modification $service, $requestContainer, $requestOptions) + private function placeMultipleCaptureRequests($service, $requestContainer, $requestOptions): array { $response = []; foreach ($requestContainer[self::MULTIPLE_AUTHORIZATIONS] as $request) { try { // Copy merchant account from parent array to every request array $request[Requests::MERCHANT_ACCOUNT] = $requestContainer[Requests::MERCHANT_ACCOUNT]; - $singleResponse = $service->capture($request, $requestOptions); - $singleResponse[self::FORMATTED_CAPTURE_AMOUNT] = $request['modificationAmount']['currency'] . ' ' . + $singleResponse = $service->captures($request, $requestOptions); + $singleResponse[self::FORMATTED_CAPTURE_AMOUNT] = $request['amount']['currency'] . ' ' . $this->adyenHelper->originalAmount( - $request['modificationAmount']['value'], - $request['modificationAmount']['currency'] + $request['amount']['value'], + $request['amount']['currency'] ); $singleResponse = $this->copyParamsToResponse($singleResponse, $request); $response[self::MULTIPLE_AUTHORIZATIONS][] = $singleResponse; @@ -149,8 +149,8 @@ private function placeMultipleCaptureRequests(Modification $service, $requestCon */ private function copyParamsToResponse(array $response, array $request): array { - $response[self::CAPTURE_AMOUNT] = $request['modificationAmount']['value']; - $response[self::ORIGINAL_REFERENCE] = $request['originalReference']; + $response[self::CAPTURE_AMOUNT] = $request['amount']['value']; + $response[self::ORIGINAL_REFERENCE] = $request[self::ORIGINAL_REFERENCE]; return $response; } diff --git a/Gateway/Http/Client/TransactionRefund.php b/Gateway/Http/Client/TransactionRefund.php index 710fbab46..8d8168fd5 100644 --- a/Gateway/Http/Client/TransactionRefund.php +++ b/Gateway/Http/Client/TransactionRefund.php @@ -60,10 +60,9 @@ public function placeRequest(TransferInterface $transferObject): array $headers = $transferObject->getHeaders(); foreach ($requests as $request) { - // call lib - $service = new \Adyen\Service\Modification( - $this->adyenHelper->initializeAdyenClient($transferObject->getClientConfig()['storeId']) - ); + + $client = $this->adyenHelper->initializeAdyenClient(); + $service = $this->adyenHelper->createAdyenCheckoutService($client); $idempotencyKey = $this->idempotencyHelper->generateIdempotencyKey( $request, @@ -73,15 +72,15 @@ public function placeRequest(TransferInterface $transferObject): array $requestOptions['idempotencyKey'] = $idempotencyKey; $this->adyenHelper - ->logRequest($request, Client::API_PAYMENT_VERSION, '/pal/servlet/Payment/{version}/refund'); + ->logRequest($request, Client::API_CHECKOUT_VERSION, '/refunds'); try { - $response = $service->refund($request, $requestOptions); + $response = $service->refunds($request, $requestOptions); // Add amount original reference and amount information to response - $response[self::REFUND_AMOUNT] = $request['modificationAmount']['value']; - $response[self::REFUND_CURRENCY] = $request['modificationAmount']['currency']; + $response[self::REFUND_AMOUNT] = $request['amount']['value']; + $response[self::REFUND_CURRENCY] = $request['amount']['currency']; - $response[self::ORIGINAL_REFERENCE] = $request['originalReference']; + $response[self::ORIGINAL_REFERENCE] = $request['paymentPspReference']; } catch (AdyenException $e) { $response = ['error' => $e->getMessage()]; } diff --git a/Gateway/Request/CancelDataBuilder.php b/Gateway/Request/CancelDataBuilder.php index f19ab57fb..fcca91d6b 100644 --- a/Gateway/Request/CancelDataBuilder.php +++ b/Gateway/Request/CancelDataBuilder.php @@ -35,8 +35,8 @@ public function build(array $buildSubject): array $pspReference = $payment->getCcTransId(); $request['body'] = [ + "paymentPspReference" => $pspReference, "reference" => $order->getOrderIncrementId(), - "originalReference" => $pspReference ]; $request['clientConfig'] = ["storeId" => $order->getStoreId()]; diff --git a/Gateway/Request/CaptureDataBuilder.php b/Gateway/Request/CaptureDataBuilder.php index 60781f179..bf3412927 100644 --- a/Gateway/Request/CaptureDataBuilder.php +++ b/Gateway/Request/CaptureDataBuilder.php @@ -17,6 +17,7 @@ use Adyen\Payment\Helper\AdyenOrderPayment; use Adyen\Payment\Helper\ChargedCurrency; use Adyen\Payment\Helper\Data as DataHelper; +use Adyen\Payment\Helper\OpenInvoice; use Adyen\Payment\Logger\AdyenLogger; use Adyen\Payment\Model\ResourceModel\Order\Payment; use Adyen\Payment\Observer\AdyenHppDataAssignObserver; @@ -62,6 +63,11 @@ class CaptureDataBuilder implements BuilderInterface */ private $context; + /** + * @var OpenInvoice + */ + protected $openInvoiceHelper; + /** * CaptureDataBuilder constructor. * @@ -71,6 +77,7 @@ class CaptureDataBuilder implements BuilderInterface * @param AdyenLogger $adyenLogger * @param Context $context * @param Payment $orderPaymentResourceModel + * @param OpenInvoice $openInvoiceHelper */ public function __construct( DataHelper $adyenHelper, @@ -78,7 +85,8 @@ public function __construct( AdyenOrderPayment $adyenOrderPaymentHelper, AdyenLogger $adyenLogger, Context $context, - Payment $orderPaymentResourceModel + Payment $orderPaymentResourceModel, + OpenInvoice $openInvoiceHelper ) { $this->adyenHelper = $adyenHelper; $this->chargedCurrency = $chargedCurrency; @@ -86,6 +94,7 @@ public function __construct( $this->adyenLogger = $adyenLogger; $this->context = $context; $this->orderPaymentResourceModel = $orderPaymentResourceModel; + $this->openInvoiceHelper = $openInvoiceHelper; } /** @@ -133,16 +142,17 @@ public function build(array $buildSubject): array return $this->buildPartialOrMultipleCaptureData($payment, $currency, $adyenOrderPayments, $invoiceAmountCurrency->getAmount()); } - $modificationAmount = ['currency' => $currency, 'value' => $amount]; + $modificationAmount = ['value' => $amount, 'currency' => $currency]; $requestBody = [ - "modificationAmount" => $modificationAmount, + "amount" => $modificationAmount, "reference" => $payment->getOrder()->getIncrementId(), - "originalReference" => $pspReference + "paymentPspReference" => $pspReference ]; + //Check additionaldata if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($brandCode)) { - $openInvoiceFields = $this->getOpenInvoiceData($payment); - $requestBody["additionalData"] = $openInvoiceFields; + $openInvoiceFields = $this->openInvoiceHelper->getOpenInvoiceData($order); + $requestBody = array_merge($requestBody, $openInvoiceFields); } $request['body'] = $requestBody; $request['clientConfig'] = ["storeId" => $payment->getOrder()->getStoreId()]; @@ -150,71 +160,6 @@ public function build(array $buildSubject): array return $request; } - /** - * @param $payment - * @return mixed - * @internal param $formFields - */ - protected function getOpenInvoiceData($payment) - { - $formFields = []; - $count = 0; - $order = $payment->getOrder(); - $invoices = $order->getInvoiceCollection(); - - $currency = $this->chargedCurrency - ->getOrderAmountCurrency($payment->getOrder(), false) - ->getCurrencyCode(); - - // The latest invoice will contain only the selected items(and quantities) for the (partial) capture - $latestInvoice = $invoices->getLastItem(); - - /* @var \Magento\Sales\Model\Order\Invoice\Item $invoiceItem */ - foreach ($latestInvoice->getItems() as $invoiceItem) { - $numberOfItems = (int)$invoiceItem->getQty(); - - if ($invoiceItem->getOrderItem()->getParentItem() || $numberOfItems <= 0) { - continue; - } - - ++$count; - $itemAmountCurrency = $this->chargedCurrency->getInvoiceItemAmountCurrency($invoiceItem); - - $formFields = $this->adyenHelper->createOpenInvoiceLineItem( - $formFields, - $count, - $invoiceItem->getName(), - $itemAmountCurrency->getAmount(), - $currency, - $itemAmountCurrency->getTaxAmount(), - $itemAmountCurrency->getAmount() + $itemAmountCurrency->getTaxAmount(), - $invoiceItem->getOrderItem()->getTaxPercent(), - $numberOfItems, - $payment, - $invoiceItem->getId() - ); - } - - // Shipping cost - if ($latestInvoice->getShippingAmount() > 0) { - ++$count; - $adyenInvoiceShippingAmount = $this->chargedCurrency->getInvoiceShippingAmountCurrency($latestInvoice); - $formFields = $this->adyenHelper->createOpenInvoiceLineShipping( - $formFields, - $count, - $order, - $adyenInvoiceShippingAmount->getAmount(), - $adyenInvoiceShippingAmount->getTaxAmount(), - $adyenInvoiceShippingAmount->getCurrencyCode(), - $payment - ); - } - - $formFields['openinvoicedata.numberOfLines'] = $count; - - return $formFields; - } - /** * Return the data of the multiple capture requests required to capture the full amount OR * multiple capture requests required to capture a partial amount OR @@ -259,14 +204,14 @@ public function buildPartialOrMultipleCaptureData($payment, $currency, $adyenOrd 'value' => $amountCents ]; $authToCapture = [ - "modificationAmount" => $modificationAmount, + "amount" => $modificationAmount, "reference" => $payment->getOrder()->getIncrementId(), "originalReference" => $adyenOrderPayment[OrderPaymentInterface::PSPREFRENCE] ]; if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($adyenOrderPayment[OrderPaymentInterface::PAYMENT_METHOD])) { - $openInvoiceFields = $this->getOpenInvoiceData($payment); - $authToCapture["additionalData"] = $openInvoiceFields; + $openInvoiceFields = $this->openInvoiceHelper->getOpenInvoiceData($payment); + $authToCapture = array_merge($authToCapture, $openInvoiceFields); } $captureData[] = $authToCapture; diff --git a/Gateway/Request/CheckoutDataBuilder.php b/Gateway/Request/CheckoutDataBuilder.php index e58b65f38..38e3c2a66 100644 --- a/Gateway/Request/CheckoutDataBuilder.php +++ b/Gateway/Request/CheckoutDataBuilder.php @@ -15,11 +15,11 @@ use Adyen\Payment\Helper\Config; use Adyen\Payment\Helper\Data; use Adyen\Payment\Helper\StateData; +use Adyen\Payment\Helper\OpenInvoice; use Adyen\Payment\Model\Ui\AdyenBoletoConfigProvider; use Adyen\Payment\Model\Ui\AdyenPayByLinkConfigProvider; use Adyen\Payment\Observer\AdyenCcDataAssignObserver; use Adyen\Payment\Observer\AdyenHppDataAssignObserver; -use Magento\Catalog\Helper\Image; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Payment\Gateway\Data\PaymentDataObject; use Magento\Payment\Gateway\Helper\SubjectReader; @@ -49,10 +49,6 @@ class CheckoutDataBuilder implements BuilderInterface */ private $chargedCurrency; - /** - * @var Image - */ - private $imageHelper; /** * @var StateData */ @@ -61,29 +57,32 @@ class CheckoutDataBuilder implements BuilderInterface /** @var Config */ private $configHelper; + /** @var OpenInvoice */ + private $openInvoiceHelper; + /** * CheckoutDataBuilder constructor. * @param Data $adyenHelper * @param StateData $stateData * @param CartRepositoryInterface $cartRepository * @param ChargedCurrency $chargedCurrency - * @param Image $imageHelper * @param Config $configHelper + * @param OpenInvoice $openInvoiceHelper */ public function __construct( Data $adyenHelper, StateData $stateData, CartRepositoryInterface $cartRepository, ChargedCurrency $chargedCurrency, - Image $imageHelper, - Config $configHelper + Config $configHelper, + OpenInvoice $openInvoiceHelper ) { $this->adyenHelper = $adyenHelper; $this->stateData = $stateData; $this->cartRepository = $cartRepository; $this->chargedCurrency = $chargedCurrency; - $this->imageHelper = $imageHelper; $this->configHelper = $configHelper; + $this->openInvoiceHelper = $openInvoiceHelper; } /** @@ -128,7 +127,8 @@ public function build(array $buildSubject): array (isset($brandCode) && $this->adyenHelper->isPaymentMethodOpenInvoiceMethod($brandCode)) || $payment->getMethod() === AdyenPayByLinkConfigProvider::CODE ) { - $openInvoiceFields = $this->getOpenInvoiceData($order); + + $openInvoiceFields = $this->openInvoiceHelper->getOpenInvoiceData($order); $requestBody = array_merge($requestBody, $openInvoiceFields); if (isset($brandCode) && @@ -250,135 +250,4 @@ private function getOtherDeliveryInformation(Order $order): ?array return $otherDeliveryInformation ?? null; } - /** - * @param string $item - * @return string - */ - protected function getImageUrl($item): string - { - $product = $item->getProduct(); - $imageUrl = ""; - - if ($image = $product->getSmallImage()) { - $imageUrl = $this->imageHelper->init($product, 'product_page_image_small') - ->setImageFile($image) - ->getUrl(); - } - - return $imageUrl; - } - - /** - * @param Order $order - * - * @return array - * @throws NoSuchEntityException - * - */ - protected function getOpenInvoiceData($order): array - { - $formFields = [ - 'lineItems' => [] - ]; - - /** @var \Magento\Quote\Model\Quote $cart */ - $cart = $this->cartRepository->get($order->getQuoteId()); - $amountCurrency = $this->chargedCurrency->getOrderAmountCurrency($order); - $currency = $amountCurrency->getCurrencyCode(); - $discountAmount = 0; - - foreach ($cart->getAllVisibleItems() as $item) { - $numberOfItems = (int)$item->getQty(); - - $itemAmountCurrency = $this->chargedCurrency->getQuoteItemAmountCurrency($item); - - // Summarize the discount amount item by item - $discountAmount += $itemAmountCurrency->getDiscountAmount(); - - $formattedPriceExcludingTax = $this->adyenHelper->formatAmount( - $itemAmountCurrency->getAmount(), - $itemAmountCurrency->getCurrencyCode() - ); - - $formattedPriceIncludingTax = $this->adyenHelper->formatAmount( - $itemAmountCurrency->getAmountIncludingTax(), - $itemAmountCurrency->getCurrencyCode() - ); - - $formattedTaxAmount = $this->adyenHelper->formatAmount( - $itemAmountCurrency->getTaxAmount(), - $itemAmountCurrency->getCurrencyCode() - ); - - $formattedTaxPercentage = $this->adyenHelper->formatAmount($item->getTaxPercent(), $currency); - - $formFields['lineItems'][] = [ - 'id' => $item->getId(), - 'amountExcludingTax' => $formattedPriceExcludingTax, - 'amountIncludingTax' => $formattedPriceIncludingTax, - 'taxAmount' => $formattedTaxAmount, - 'description' => $item->getName(), - 'quantity' => $numberOfItems, - 'taxPercentage' => $formattedTaxPercentage, - 'productUrl' => $item->getProduct()->getUrlModel()->getUrl($item->getProduct()), - 'imageUrl' => $this->getImageUrl($item) - ]; - } - - // Discount cost - if ($discountAmount != 0) { - $description = __('Discount'); - $itemAmount = -$this->adyenHelper->formatAmount( - $discountAmount + $cart->getShippingAddress()->getShippingDiscountAmount(), - $itemAmountCurrency->getCurrencyCode() - ); - $itemVatAmount = "0"; - $itemVatPercentage = "0"; - $numberOfItems = 1; - - $formFields['lineItems'][] = [ - 'id' => 'Discount', - 'amountExcludingTax' => $itemAmount, - 'amountIncludingTax' => $itemAmount, - 'taxAmount' => $itemVatAmount, - 'description' => $description, - 'quantity' => $numberOfItems, - 'taxPercentage' => $itemVatPercentage - ]; - } - - // Shipping cost - if ($cart->getShippingAddress()->getShippingAmount() > 0 || - $cart->getShippingAddress()->getShippingTaxAmount() > 0 - ) { - $shippingAmountCurrency = $this->chargedCurrency->getQuoteShippingAmountCurrency($cart); - - $formattedPriceExcludingTax = $this->adyenHelper->formatAmount( - $shippingAmountCurrency->getAmount(), - $currency - ); - - $formattedPriceIncludingTax = $this->adyenHelper->formatAmount( - $shippingAmountCurrency->getAmountIncludingTax(), - $currency - ); - - $formattedTaxAmount = $this->adyenHelper->formatAmount( - $shippingAmountCurrency->getTaxAmount(), - $currency - ); - - $formFields['lineItems'][] = [ - 'id' => 'shippingCost', - 'amountExcludingTax' => $formattedPriceExcludingTax, - 'amountIncludingTax' => $formattedPriceIncludingTax, - 'taxAmount' => $formattedTaxAmount, - 'description' => $order->getShippingDescription(), - 'quantity' => 1, - 'taxPercentage' => (int) round(($formattedTaxAmount / $formattedPriceExcludingTax) * 100 * 100) - ]; - } - - return $formFields; - } } diff --git a/Gateway/Request/RefundDataBuilder.php b/Gateway/Request/RefundDataBuilder.php index a861c3d69..bdded190b 100644 --- a/Gateway/Request/RefundDataBuilder.php +++ b/Gateway/Request/RefundDataBuilder.php @@ -13,8 +13,10 @@ use Adyen\Payment\Helper\ChargedCurrency; use Adyen\Payment\Helper\Data; +use Adyen\Payment\Helper\OpenInvoice; use Adyen\Payment\Model\ResourceModel\Invoice\CollectionFactory; use Adyen\Payment\Model\ResourceModel\Order\Payment\CollectionFactory as PaymentCollectionFactory; +use Adyen\Payment\Observer\AdyenHppDataAssignObserver; use Magento\Payment\Gateway\Data\PaymentDataObject; use Magento\Payment\Gateway\Helper\SubjectReader; use Magento\Payment\Gateway\Request\BuilderInterface; @@ -50,6 +52,11 @@ class RefundDataBuilder implements BuilderInterface */ private $chargedCurrency; + /** + * @var OpenInvoice + */ + protected $openInvoiceHelper; + /** * RefundDataBuilder constructor. * @@ -57,17 +64,20 @@ class RefundDataBuilder implements BuilderInterface * @param PaymentCollectionFactory $orderPaymentCollectionFactory * @param CollectionFactory $adyenInvoiceCollectionFactory * @param ChargedCurrency $chargedCurrency + * @param OpenInvoice $openInvoiceHelper */ public function __construct( Data $adyenHelper, PaymentCollectionFactory $orderPaymentCollectionFactory, CollectionFactory $adyenInvoiceCollectionFactory, - ChargedCurrency $chargedCurrency + ChargedCurrency $chargedCurrency, + OpenInvoice $openInvoiceHelper ) { $this->adyenHelper = $adyenHelper; $this->orderPaymentCollectionFactory = $orderPaymentCollectionFactory; $this->adyenInvoiceCollectionFactory = $adyenInvoiceCollectionFactory; $this->chargedCurrency = $chargedCurrency; + $this->openInvoiceHelper = $openInvoiceHelper; } /** @@ -91,6 +101,11 @@ public function build(array $buildSubject): array $currency = $creditMemoAmountCurrency->getCurrencyCode(); $amount = $creditMemoAmountCurrency->getAmount(); + //Get Merchant Account + $storeId = $order ->getStoreId(); + $method = $payment->getMethod(); + $merchantAccount = $this->adyenHelper->getAdyenMerchantAccount($method, $storeId); + // check if it contains a partial payment $orderPaymentCollection = $this->orderPaymentCollectionFactory ->create() @@ -100,7 +115,7 @@ public function build(array $buildSubject): array if ($orderPaymentCollection->getSize() > self::REFUND_STRATEGY_ASCENDING_ORDER) { $refundStrategy = $this->adyenHelper->getAdyenAbstractConfigData( 'partial_payments_refund_strategy', - $order->getStoreId() + $storeId ); $ratio = null; @@ -151,9 +166,10 @@ public function build(array $buildSubject): array ]; $requestBody[] = [ - "modificationAmount" => $modificationAmountObject, + "merchantAccount" => $merchantAccount, + "amount" => $modificationAmountObject, "reference" => $payment->getOrder()->getIncrementId(), - "originalReference" => $partialPayment->getPspreference(), + "paymentPspReference" => $partialPayment->getPspreference(), ]; } } @@ -164,21 +180,21 @@ public function build(array $buildSubject): array $requestBody = [ [ - "modificationAmount" => $modificationAmount, + "merchantAccount" => $merchantAccount, + "amount" => $modificationAmount, "reference" => $payment->getOrder()->getIncrementId(), - "originalReference" => $pspReference, + "paymentPspReference" => $pspReference, ] ]; $brandCode = $payment->getAdditionalInformation( - \Adyen\Payment\Observer\AdyenHppDataAssignObserver::BRAND_CODE + AdyenHppDataAssignObserver::BRAND_CODE ); if ($this->adyenHelper->isPaymentMethodOpenInvoiceMethod($brandCode)) { - $openInvoiceFields = $this->getOpenInvoiceData($payment); - + $openInvoiceFieldsCreditMemo = $this->openInvoiceHelper->getOpenInvoiceData($creditMemo->getOrder()); //There is only one payment, so we add the fields to the first(and only) result - $requestBody[0]["additionalData"] = $openInvoiceFields; + $requestBody[0] = array_merge($requestBody[0], $openInvoiceFieldsCreditMemo); } } $request['clientConfig'] = ["storeId" => $payment->getOrder()->getStoreId()]; @@ -193,91 +209,4 @@ public function build(array $buildSubject): array return $request; } - /** - * @param InfoInterface $payment - * @return array|mixed - */ - protected function getOpenInvoiceData($payment) - { - $formFields = []; - $count = 0; - - // Construct AdyenAmountCurrency from creditmemo - /** - * @var Creditmemo $creditMemo - */ - $creditMemo = $payment->getCreditMemo(); - - foreach ($creditMemo->getItems() as $refundItem) { - $numberOfItems = (int)$refundItem->getQty(); - if ($numberOfItems == 0) { - continue; - } - - ++$count; - $itemAmountCurrency = $this->chargedCurrency->getCreditMemoItemAmountCurrency($refundItem); - - $formFields = $this->adyenHelper->createOpenInvoiceLineItem( - $formFields, - $count, - $refundItem->getName(), - $itemAmountCurrency->getAmount(), - $itemAmountCurrency->getCurrencyCode(), - $itemAmountCurrency->getTaxAmount(), - $itemAmountCurrency->getAmount() + $itemAmountCurrency->getTaxAmount(), - $refundItem->getOrderItem()->getTaxPercent(), - $numberOfItems, - $payment, - $refundItem->getId() - ); - } - - // Shipping cost - $shippingAmountCurrency = $this->chargedCurrency->getCreditMemoShippingAmountCurrency($creditMemo); - if ($shippingAmountCurrency->getAmount() > 0) { - ++$count; - $formFields = $this->adyenHelper->createOpenInvoiceLineShipping( - $formFields, - $count, - $payment->getOrder(), - $shippingAmountCurrency->getAmount(), - $shippingAmountCurrency->getTaxAmount(), - $shippingAmountCurrency->getCurrencyCode(), - $payment - ); - } - - // Adjustment - $adjustmentAmountCurrency = $this->chargedCurrency->getCreditMemoAdjustmentAmountCurrency($creditMemo); - if ($adjustmentAmountCurrency->getAmount() != 0) { - $positive = $adjustmentAmountCurrency->getAmount() > 0 ? 'Positive' : ''; - $negative = $adjustmentAmountCurrency->getAmount() < 0 ? 'Negative' : ''; - $description = "Adjustment - " . implode(' | ', array_filter([$positive, $negative])); - - ++$count; - $formFields = $this->adyenHelper->createOpenInvoiceLineAdjustment( - $formFields, - $count, - $description, - $adjustmentAmountCurrency->getAmount(), - $adjustmentAmountCurrency->getCurrencyCode(), - $payment - ); - } - - $formFields['openinvoicedata.numberOfLines'] = $count; - - //Retrieve acquirerReference from the adyen_invoice - $invoiceId = $creditMemo->getInvoice()->getId(); - $invoices = $this->adyenInvoiceCollectionFactory->create() - ->addFieldToFilter('invoice_id', $invoiceId); - - $invoice = $invoices->getFirstItem(); - - if ($invoice) { - $formFields['acquirerReference'] = $invoice->getAcquirerReference(); - } - - return $formFields; - } } diff --git a/Gateway/Request/RefundMerchantAccountDataBuilder.php b/Gateway/Request/RefundMerchantAccountDataBuilder.php deleted file mode 100644 index c6812d598..000000000 --- a/Gateway/Request/RefundMerchantAccountDataBuilder.php +++ /dev/null @@ -1,57 +0,0 @@ - - */ - -namespace Adyen\Payment\Gateway\Request; - -use Adyen\Payment\Helper\Data; -use Magento\Payment\Gateway\Request\BuilderInterface; - -/** - * Class RefundMerchantAccountDataBuilder - */ -class RefundMerchantAccountDataBuilder implements BuilderInterface -{ - /** - * @var Data - */ - private $adyenHelper; - - /** - * RefundMerchantAccountDataBuilder constructor. - * - * @param Data $adyenHelper - */ - public function __construct( - Data $adyenHelper - ) { - $this->adyenHelper = $adyenHelper; - } - - /** - * @param array $buildSubject - * @return array - */ - public function build(array $buildSubject) - { - /** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */ - $paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject); - $order = $paymentDataObject->getOrder(); - $payment = $paymentDataObject->getPayment(); - $storeId = $order ->getStoreId(); - $method = $payment->getMethod(); - $merchantAccount = $this->adyenHelper->getAdyenMerchantAccount($method, $storeId); - - $requestBody[] = ["merchantAccount" => $merchantAccount]; - - $request['body'] = $requestBody; - return $request; - } -} diff --git a/Gateway/Response/PaymentCaptureDetailsHandler.php b/Gateway/Response/PaymentCaptureDetailsHandler.php index a1bd307cc..e50c8b6a4 100644 --- a/Gateway/Response/PaymentCaptureDetailsHandler.php +++ b/Gateway/Response/PaymentCaptureDetailsHandler.php @@ -63,7 +63,7 @@ public function handle(array $handlingSubject, array $response) // The capture request will return a capture-received message, but it doesn't mean the capture has been final // so the invoice is set to Pending - if ($response["response"] === TransactionCapture::CAPTURE_RECEIVED) { + if ($response["status"] === TransactionCapture::CAPTURE_RECEIVED) { $this->setInvoiceToPending($payment); } } diff --git a/Gateway/Validator/CancelResponseValidator.php b/Gateway/Validator/CancelResponseValidator.php index 66b0ecfa9..83840bc34 100644 --- a/Gateway/Validator/CancelResponseValidator.php +++ b/Gateway/Validator/CancelResponseValidator.php @@ -45,10 +45,10 @@ public function validate(array $validationSubject) $isValid = true; $errorMessages = []; - // The available response codes that the API can return in case of a successful cancellation - $expectedResponses = ['[cancelOrRefund-received]', '[cancel-received]']; + // The available response code that the API can return in case of a successful cancellation + $expectedResponses = ['received']; - if (empty($response['response']) || !in_array($response['response'], $expectedResponses)) { + if (empty($response['status']) || !in_array($response['status'], $expectedResponses)) { $errorMsg = __('Error with cancellation'); $this->adyenLogger->error($errorMsg); diff --git a/Gateway/Validator/CaptureResponseValidator.php b/Gateway/Validator/CaptureResponseValidator.php index ee2ec67c0..a27fb8999 100644 --- a/Gateway/Validator/CaptureResponseValidator.php +++ b/Gateway/Validator/CaptureResponseValidator.php @@ -50,7 +50,7 @@ public function validate(array $validationSubject) return $this->validateMultipleCaptureRequests($response); } - if (empty($response['response']) || $response['response'] != TransactionCapture::CAPTURE_RECEIVED) { + if (empty($response['status']) || $response['status'] != TransactionCapture::CAPTURE_RECEIVED) { $errorMessages[] = $this->buildErrorMessages($response); $isValid = false; } diff --git a/Gateway/Validator/RefundResponseValidator.php b/Gateway/Validator/RefundResponseValidator.php index bcae5c0d3..47c8745c5 100644 --- a/Gateway/Validator/RefundResponseValidator.php +++ b/Gateway/Validator/RefundResponseValidator.php @@ -46,7 +46,7 @@ public function validate(array $validationSubject) $errorMessages = []; foreach ($responses as $response) { - if (empty($response['response']) || $response['response'] != '[refund-received]') { + if (empty($response['status']) || $response['status'] != 'received') { $errorMsg = __('Error with refund'); $this->adyenLogger->error($errorMsg); diff --git a/Helper/OpenInvoice.php b/Helper/OpenInvoice.php new file mode 100644 index 000000000..ab57d3584 --- /dev/null +++ b/Helper/OpenInvoice.php @@ -0,0 +1,186 @@ + + */ + +namespace Adyen\Payment\Helper; + +use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Catalog\Helper\Image; + +class OpenInvoice +{ + /** + * @var AbstractHelper + */ + protected $adyenHelper; + + /** + * @var CartRepositoryInterface + */ + protected $cartRepository; + + /** + * @var ChargedCurrency + */ + protected $chargedCurrency; + + /** + * @var Config + */ + protected $configHelper; + + /** + * @var Image + */ + protected $imageHelper; + + public function __construct( + Data $adyenHelper, + CartRepositoryInterface $cartRepository, + ChargedCurrency $chargedCurrency, + Config $configHelper, + Image $imageHelper + ) { + $this->adyenHelper = $adyenHelper; + $this->cartRepository = $cartRepository; + $this->chargedCurrency = $chargedCurrency; + $this->configHelper = $configHelper; + $this->imageHelper = $imageHelper; + } + + public function getOpenInvoiceData($order): array + { + $formFields = [ + 'lineItems' => [] + ]; + + /** @var \Magento\Quote\Model\Quote $cart */ + $cart = $this->cartRepository->get($order->getQuoteId()); + $amountCurrency = $this->chargedCurrency->getOrderAmountCurrency($order); + $currency = $amountCurrency->getCurrencyCode(); + $discountAmount = 0; + + foreach ($cart->getAllVisibleItems() as $item) { + $numberOfItems = (int)$item->getQty(); + + $itemAmountCurrency = $this->chargedCurrency->getQuoteItemAmountCurrency($item); + + // Summarize the discount amount item by item + $discountAmount += $itemAmountCurrency->getDiscountAmount(); + + $formattedPriceExcludingTax = $this->adyenHelper->formatAmount( + $itemAmountCurrency->getAmount(), + $itemAmountCurrency->getCurrencyCode() + ); + + $formattedPriceIncludingTax = $this->adyenHelper->formatAmount( + $itemAmountCurrency->getAmountIncludingTax(), + $itemAmountCurrency->getCurrencyCode() + ); + + $formattedTaxAmount = $this->adyenHelper->formatAmount( + $itemAmountCurrency->getTaxAmount(), + $itemAmountCurrency->getCurrencyCode() + ); + + $formattedTaxPercentage = $this->adyenHelper->formatAmount($item->getTaxPercent(), $currency); + + $formFields['lineItems'][] = [ + 'id' => $item->getProduct()->getId(), + 'amountExcludingTax' => $formattedPriceExcludingTax, + 'amountIncludingTax' => $formattedPriceIncludingTax, + 'taxAmount' => $formattedTaxAmount, + 'description' => $item->getName(), + 'quantity' => $numberOfItems, + 'taxPercentage' => $formattedTaxPercentage, + 'productUrl' => $item->getProduct()->getUrlModel()->getUrl($item->getProduct()), + 'imageUrl' => $this->getImageUrl($item) + ]; + } + + // Discount cost + if ($discountAmount != 0) { + $description = __('Discount'); + $itemAmount = -$this->adyenHelper->formatAmount( + $discountAmount + $cart->getShippingAddress()->getShippingDiscountAmount(), + $itemAmountCurrency->getCurrencyCode() + ); + $itemVatAmount = "0"; + $itemVatPercentage = "0"; + $numberOfItems = 1; + + $formFields['lineItems'][] = [ + 'id' => 'Discount', + 'amountExcludingTax' => $itemAmount, + 'amountIncludingTax' => $itemAmount, + 'taxAmount' => $itemVatAmount, + 'description' => $description, + 'quantity' => $numberOfItems, + 'taxPercentage' => $itemVatPercentage + ]; + } + + // Shipping cost + if ($cart->getShippingAddress()->getShippingAmount() > 0 || + $cart->getShippingAddress()->getShippingTaxAmount() > 0 + ) { + $shippingAmountCurrency = $this->chargedCurrency->getQuoteShippingAmountCurrency($cart); + + $formattedPriceExcludingTax = $this->adyenHelper->formatAmount( + $shippingAmountCurrency->getAmount(), + $currency + ); + + + $formattedPriceIncludingTax = $this->adyenHelper->formatAmount( + $shippingAmountCurrency->getAmountIncludingTax(), + $currency + ); + + + $formattedTaxAmount = $this->adyenHelper->formatAmount( + $shippingAmountCurrency->getTaxAmount(), + $currency + ); + + + $formFields['lineItems'][] = [ + 'id' => 'shippingCost', + 'amountExcludingTax' => $formattedPriceExcludingTax, + 'amountIncludingTax' => $formattedPriceIncludingTax, + 'taxAmount' => $formattedTaxAmount, + 'description' => $order->getShippingDescription(), + 'quantity' => 1, + 'taxPercentage' => (int) round(($formattedTaxAmount / $formattedPriceExcludingTax) * 100 * 100) + ]; + } + + return $formFields; + } + + /** + * @param string $item + * @return string + */ + protected function getImageUrl($item): string + { + $product = $item->getProduct(); + $imageUrl = ""; + + if ($image = $product->getSmallImage()) { + $imageUrl = $this->imageHelper->init($product, 'product_page_image_small') + ->setImageFile($image) + ->getUrl(); + } + + return $imageUrl; + } +} diff --git a/Helper/Util/PaymentMethodUtil.php b/Helper/Util/PaymentMethodUtil.php index 1265ebded..b9a17eefe 100644 --- a/Helper/Util/PaymentMethodUtil.php +++ b/Helper/Util/PaymentMethodUtil.php @@ -61,7 +61,14 @@ class PaymentMethodUtil 'walley_b2b', 'mc_clicktopay', 'visa_clicktopay', - 'ach' + 'ach', + 'visa_amazonpay', + 'mc_amazonpay', + 'amex_amazonpay', + 'discover_amazonpay', + 'maestro_amazonpay', + 'elo_amazonpay', + 'jcb_amazonpay' ]; const OPEN_INVOICE_PAYMENT_METHODS = [ diff --git a/Test/Unit/Helper/OpenInvoiceTest.php b/Test/Unit/Helper/OpenInvoiceTest.php new file mode 100644 index 000000000..be90e05cb --- /dev/null +++ b/Test/Unit/Helper/OpenInvoiceTest.php @@ -0,0 +1,154 @@ +adyenHelperMock = $this->createMock(\Adyen\Payment\Helper\Data::class); + + $this->adyenHelperMock->method('formatAmount') + ->will($this->returnCallback(function($amount, $currency) { + if ($amount === null) { + return 0; + } + if ($amount == 450 && $currency == 'EUR'){ + return 4500; + } + if ($amount == 500.0 && $currency == 'EUR') { + return 500; // Mocked formattedPriceExcludingTax value + } + if ($amount == 50.0 && $currency == 'EUR') { + return 50; // Mocked formattedTaxAmount value + } + return (int)number_format($amount, 0, '', ''); // For any other calls, return this default value + })); + + + $this->cartRepositoryMock = $this->createMock(\Magento\Quote\Api\CartRepositoryInterface::class); + $this->chargedCurrencyMock = $this->createMock(\Adyen\Payment\Helper\ChargedCurrency::class); + $this->configHelperMock = $this->createMock(\Adyen\Payment\Helper\Config::class); + $this->imageHelperMock = $this->createMock(\Magento\Catalog\Helper\Image::class); + $this->orderMock = $this->createMock(\Magento\Sales\Model\Order::class); + $this->cartMock = $this->createMock(\Magento\Quote\Model\Quote::class); + $this->itemMock = $this->createMock(\Magento\Quote\Model\Quote\Item::class); + $this->productMock = $this->createMock(\Magento\Catalog\Model\Product::class); + + $amountCurrencyMock = $this->createMock(\Adyen\Payment\Model\AdyenAmountCurrency::class); + $amountCurrencyMock->method('getCurrencyCode')->willReturn('EUR'); + $this->chargedCurrencyMock->method('getOrderAmountCurrency')->willReturn($amountCurrencyMock); + + $itemAmountCurrencyMock = $this->createMock(\Adyen\Payment\Model\AdyenAmountCurrency::class); + $itemAmountCurrencyMock->method('getAmount')->willReturn(4500); + $itemAmountCurrencyMock->method('getAmountIncludingTax')->willReturn(4500); + $itemAmountCurrencyMock->method('getDiscountAmount')->willReturn(0); + $this->chargedCurrencyMock->method('getQuoteItemAmountCurrency')->willReturn($itemAmountCurrencyMock); + + $this->orderMock->method('getQuoteId')->willReturn('12345'); + + $this->cartMock = $this->createMock(\Magento\Quote\Model\Quote::class); + + $shippingAddressMock = $this->createMock(\Magento\Quote\Model\Quote\Address::class); + + $shippingAddressMock->method('__call')->willReturnMap([ + ['getShippingAmount', [], 500.0], + ['getShippingTaxAmount', [], 0.0], + ['getShippingDescription', [], 'Flat Rate - Fixed'], + ['getShippingAmountCurrency', [], 'EUR'], + ['getShippingAmountCurrency', [], 'EUR'], + ]); + + + $shippingAmountCurrencyMock = $this->createMock(\Adyen\Payment\Model\AdyenAmountCurrency::class); + $shippingAmountCurrencyMock->method('getAmount')->willReturn(500); + $shippingAmountCurrencyMock->method('getAmountIncludingTax')->willReturn(500); + $shippingAmountCurrencyMock->method('getTaxAmount')->willReturn(0); + $this->chargedCurrencyMock->method('getQuoteShippingAmountCurrency')->willReturn($shippingAmountCurrencyMock); + + $this->cartMock->method('getShippingAddress')->willReturn($shippingAddressMock); + + $this->cartRepositoryMock->method('get')->willReturn($this->cartMock); + + } + + public function testGetOpenInvoiceData() + { + // Arrange: Set up the object with the mocks + $openInvoice = new OpenInvoice( + $this->adyenHelperMock, + $this->cartRepositoryMock, + $this->chargedCurrencyMock, + $this->configHelperMock, + $this->imageHelperMock + ); + + // Stub methods to return expected values + $this->cartMock->method('getAllVisibleItems')->willReturn([$this->itemMock]); + $this->itemMock->method('getQty')->willReturn(1); + $this->itemMock->method('getProduct')->willReturn($this->productMock); + $this->itemMock->method('getName')->willReturn('Push It Messenger Bag'); + $this->productMock->method('getId')->willReturn('14'); + + $this->productMock->method('getUrlModel')->willReturn(new class { + public function getUrl() { + return 'https://192.168.58.20/index.php/push-it-messenger-bag.html'; + } + }); + + + $this->orderMock->method('getShippingDescription')->willReturn('Flat Rate - Fixed'); + + + $this->imageHelperMock->method('init')->willReturnSelf(); + $this->imageHelperMock->method('setImageFile')->willReturnSelf(); + $this->imageHelperMock->method('getUrl')->willReturn('https://192.168.58.20/media/catalog/product/cache/3d0891988c4d57b25ce48fde378871d2/w/b/wb04-blue-0.jpg'); + + + + + $expectedResult = [ + 'lineItems' => [ + [ + 'id' => '14', + 'amountExcludingTax' => 4500, + 'amountIncludingTax' => 4500, + 'taxAmount' => 0, + 'description' => 'Push It Messenger Bag', + 'quantity' => 1, + 'taxPercentage' => 0, + 'productUrl' => 'https://192.168.58.20/index.php/push-it-messenger-bag.html', + 'imageUrl' => '' + ], + [ + 'id' => 'shippingCost', + 'amountExcludingTax' => 500, + 'amountIncludingTax' => 500, + 'taxAmount' => 0, + 'description' => 'Flat Rate - Fixed', + 'quantity' => 1, + 'taxPercentage' => 0 + ], + ], + ]; + + // Act: Call the method with the mocked parameters + $result = $openInvoice->getOpenInvoiceData($this->orderMock); + + // Assert: Verify that the output matches your expectations + $this->assertEquals($expectedResult, $result); + } + } \ No newline at end of file diff --git a/composer.json b/composer.json index e9e5000c7..20ce70ddf 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": "8.21.0", + "version": "8.22.0", "license": "MIT", "repositories": [ { diff --git a/etc/di.xml b/etc/di.xml index b3fbe80c7..92e3c6efe 100755 --- a/etc/di.xml +++ b/etc/di.xml @@ -789,7 +789,6 @@ - Adyen\Payment\Gateway\Request\RefundMerchantAccountDataBuilder Adyen\Payment\Gateway\Request\RefundDataBuilder diff --git a/etc/module.xml b/etc/module.xml index 7662ae244..9849bce56 100755 --- a/etc/module.xml +++ b/etc/module.xml @@ -12,7 +12,7 @@ --> - + diff --git a/sonar-project.properties b/sonar-project.properties index 35658201e..a918f8320 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,6 +1,5 @@ sonar.organization=adyen sonar.projectKey=Adyen_adyen-magento2 -sonar.sources=. sonar.tests=Test/ sonar.exclusions=vendor/**/*, or Test/**/* sonar.php.coverage.reportPaths=build/clover.xml diff --git a/view/adminhtml/templates/config/webhook_test.phtml b/view/adminhtml/templates/config/webhook_test.phtml index 8718e1101..34be1bce4 100644 --- a/view/adminhtml/templates/config/webhook_test.phtml +++ b/view/adminhtml/templates/config/webhook_test.phtml @@ -5,7 +5,6 @@ ], function(jQuery) { - jQuery('#adyen_webhook_test_errors').hide(); let progressSpan = jQuery('#webhook_progress'); jQuery('#adyen_webhook_test').click(function () { @@ -15,28 +14,28 @@ loaderArea: false, asynchronous: true, onCreate: function() { - progressSpan.find('.configured').hide(); - progressSpan.find('.processing').show(); + progressSpan.find('.test-configured').hide(); + progressSpan.find('.test-processing').show(); jQuery('#adyen_webhook_test_message').text(''); jQuery("#adyen_webhook_test").prop('disabled', true); }, onSuccess: function (response) { //add html response - progressSpan.find('.processing').hide(); + progressSpan.find('.test-processing').hide(); let resultText = ''; if (response.responseJSON === null) { resultText = "No response"; } else { resultText = response.responseJSON.statusCode; if(resultText==='Success'){ - progressSpan.find('.configured').show(); + progressSpan.find('.test-configured').show(); } } jQuery('#adyen_webhook_test_message').text(resultText); }, onFailure: function(response) { - progressSpan.find('.processing').hide(); + progressSpan.find('.test-processing').hide(); jQuery('#adyen_webhook_test_message').text("Failed").show(); }, onComplete: function() @@ -51,12 +50,9 @@ isWebhookIdConfigured()) : ?> getButtonHtml() ?> - - + + -
-
-

diff --git a/view/base/web/images/logos/afterpay_default.png b/view/base/web/images/logos/afterpay_default.png index 06b418a05..de9c07a17 100644 Binary files a/view/base/web/images/logos/afterpay_default.png and b/view/base/web/images/logos/afterpay_default.png differ diff --git a/view/base/web/images/logos/afterpay_default_small.png b/view/base/web/images/logos/afterpay_default_small.png index 24f53857f..b3f9fed63 100644 Binary files a/view/base/web/images/logos/afterpay_default_small.png and b/view/base/web/images/logos/afterpay_default_small.png differ diff --git a/view/frontend/web/js/view/payment/method-renderer/adyen-hpp-method.js b/view/frontend/web/js/view/payment/method-renderer/adyen-hpp-method.js index 37b0cad13..8dfc95fe2 100755 --- a/view/frontend/web/js/view/payment/method-renderer/adyen-hpp-method.js +++ b/view/frontend/web/js/view/payment/method-renderer/adyen-hpp-method.js @@ -523,7 +523,12 @@ define( selectedAlternativePaymentMethodType(); var validate = $(form).validation() && $(form).validation('isValid'); - return validate && additionalValidators.validate() && this.isPlaceOrderActionAllowed(); + + if (['googlepay', 'paywithgoogle'].includes(selectedAlternativePaymentMethodType())) { + return validate && additionalValidators.validate() && this.isPlaceOrderActionAllowed(); + } + + return validate && additionalValidators.validate(); }, isButtonActive: function() { return this.getCode() == this.isChecked() &&