Skip to content

Commit

Permalink
Merge pull request #616 from Adyen/develop
Browse files Browse the repository at this point in the history
Release version 4.2.5
  • Loading branch information
goran-stamenkovski-logeecom authored Feb 10, 2025
2 parents 8f27897 + 09110ae commit d56f38a
Show file tree
Hide file tree
Showing 31 changed files with 3,299 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test.describe.parallel("Payment via credit card", () => {
await doPrePaymentChecks(page);
});

test("without 3Ds should succeed", async ({ page }) => {
test.skip("without 3Ds should succeed", async ({ page }) => {

await makeCreditCardPayment(
page,
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/scripts/prepare-release-asset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ rm -rf AdyenPaymentShopware6/vendor
# Install dependencies
composer install --no-dev --working-dir=./AdyenPaymentShopware6

# Overwrite installed.php with an empty array
echo "<?php return array();" > AdyenPaymentShopware6/vendor/composer/installed.php

# Copy original the composer.json file
cp adyen-shopware6/composer.json AdyenPaymentShopware6/.

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
}
],
"description": "Official Shopware 6 Plugin to connect to Payment Service Provider Adyen",
"version": "4.2.4",
"version": "4.2.5",
"type": "shopware-platform-plugin",
"license": "MIT",
"require": {
Expand Down
253 changes: 253 additions & 0 deletions src/Controller/StoreApi/ExpressCheckout/ExpressCheckoutController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
<?php declare(strict_types=1);
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2021 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <[email protected]>
*/

namespace Adyen\Shopware\Controller\StoreApi\ExpressCheckout;

use Adyen\AdyenException;
use Adyen\Shopware\Exception\ResolveCountryException;
use Adyen\Shopware\Exception\ResolveShippingMethodException;
use Adyen\Shopware\Service\ExpressCheckoutService;
use Exception;
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

/**
* Class ExpressCheckoutController
* @package Adyen\Shopware\Controller\StoreApi\ExpressCheckout
* @Route(defaults={"_routeScope"={"store-api"}})
*/
class ExpressCheckoutController
{
/**
* @var ExpressCheckoutService
*/
private ExpressCheckoutService $expressCheckoutService;

/**
* StoreApiController constructor.
*
* @param ExpressCheckoutService $expressCheckoutService
*/
public function __construct(
ExpressCheckoutService $expressCheckoutService
) {
$this->expressCheckoutService = $expressCheckoutService;
}

/**
* @Route(
* "/store-api/adyen/express-checkout-config",
* name="store-api.action.adyen.express-checkout-config",
* methods={"POST"}
* )
*
* @param Request $request
* @param SalesChannelContext $salesChannelContext
* @return JsonResponse
*/
public function getExpressCheckoutConfig(
Request $request,
SalesChannelContext $salesChannelContext
): JsonResponse {
$productId = $request->request->get('productId');
$quantity = (int)$request->request->get('quantity');
$formattedHandlerIdentifier = $request->request->get('formattedHandlerIdentifier') ?? '';
$newAddress = $request->request->all()['newAddress'] ?? null;
$newShipping = $request->request->all()['newShippingMethod'] ?? null;

if ($newAddress === null) {
$newAddress = [];
}

if ($newShipping === null) {
$newShipping = [];
}

try {
$config = $this->expressCheckoutService->getExpressCheckoutConfig(
$productId,
$quantity,
$salesChannelContext,
$newAddress,
$newShipping,
$formattedHandlerIdentifier
);

if (array_key_exists('error', $config)) {
if ($config['error'] === 'ResolveCountryException') {
throw new ResolveCountryException($config['message']);
}

if ($config['error'] === 'ResolveShippingMethodException') {
throw new ResolveShippingMethodException($config['message']);
}
}

return new JsonResponse($config);
} catch (ResolveCountryException $e) {
return new JsonResponse([
'error' => [
'reason' => 'SHIPPING_ADDRESS_INVALID',
'message' => $e->getMessage(),
'intent' => 'SHIPPING_ADDRESS',
]
], 400);
} catch (ResolveShippingMethodException $e) {
return new JsonResponse([
'error' => [
'reason' => 'SHIPPING_OPTION_INVALID',
'message' => $e->getMessage(),
'intent' => 'SHIPPING_OPTION',
]
], 400);
} catch (\Exception $e) {
// Fallback for unexpected errors
return new JsonResponse([
'error' => [
'reason' => 'OTHER_ERROR',
'message' => $e->getMessage(),
]
], 400);
}
}

/**
* Creates a cart with the provided product and calculates it with the resolved shipping location and method.
*
* @param RequestDataBag $data
* @param SalesChannelContext $salesChannelContext The current sales channel context.
* @return array The cart, shipping methods, selected shipping method, and payment methods.
* @throws Exception
*/
public function createCart(
RequestDataBag $data,
SalesChannelContext $salesChannelContext
): array {
$productId = $data->get('productId');
$quantity = (int)$data->get('quantity');
$formattedHandlerIdentifier = $data->get('formattedHandlerIdentifier') ?? '';
$newAddress = $data->get('newAddress')->all();
$newShipping = $data->get('newShippingMethod')->all();
$guestEmail = $data->get('email');

$customer = $salesChannelContext->getCustomer();
$makeNewCustomer = $customer === null;
$createNewAddress = $customer && $customer->getGuest();

return $this->expressCheckoutService
->createCart(
$productId,
$quantity,
$salesChannelContext,
$newAddress,
$newShipping,
$formattedHandlerIdentifier,
$guestEmail,
$makeNewCustomer,
$createNewAddress
);
}

/**
* Updates the SalesChannelContext for guest customer.
*
* @param string $customerId The ID of the customer whose context should be updated.
* @param SalesChannelContext $salesChannelContext The existing sales channel context to be updated.
*
* @throws \Exception If the customer cannot be found.
*
* @return SalesChannelContext The updated SalesChannelContext with the customer's details.
*/
public function changeContext(string $customerId, SalesChannelContext $salesChannelContext): SalesChannelContext
{
return $this->expressCheckoutService->changeContext($customerId, $salesChannelContext);
}

/**
* @param Request $request
* @param SalesChannelContext $salesChannelContext
* @return JsonResponse
*
*/
public function updatePayPalOrder(
Request $request,
SalesChannelContext $salesChannelContext
): JsonResponse {
$newAddress = $request->request->all()['newAddress'] ?? null;
$newShipping = $request->request->all()['newShippingMethod'] ?? null;
$orderId = $request->request->all()['orderId'] ?? '';

if ($newAddress === null) {
$newAddress = [];
}

if ($newShipping === null) {
$newShipping = [];
}

$paymentData = $request->request->get('currentPaymentData');
$pspReference = $request->request->get('pspReference');

try {
$paypalUpdateOrderResponse = $this->expressCheckoutService->paypalUpdateOrder(
$orderId,
[
'paymentData' => $paymentData,
'pspReference' => $pspReference,
],
$salesChannelContext,
$newAddress,
$newShipping
);

return new JsonResponse($paypalUpdateOrderResponse->toArray());
} catch (ResolveCountryException $e) {
return new JsonResponse([
'error' => [
'reason' => 'SHIPPING_ADDRESS_INVALID',
'message' => $e->getMessage(),
'intent' => 'SHIPPING_ADDRESS',
]
], 400);
} catch (ResolveShippingMethodException $e) {
return new JsonResponse([
'error' => [
'reason' => 'SHIPPING_OPTION_INVALID',
'message' => $e->getMessage(),
'intent' => 'SHIPPING_OPTION',
]
], 400);
} catch (AdyenException $e) {
return new JsonResponse([
'error' => [
'reason' => 'OTHER_ERROR',
'message' => $e->getMessage(),
]
], 400);
}
}
}
23 changes: 23 additions & 0 deletions src/Controller/StoreApi/Payment/PaymentController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
namespace Adyen\Shopware\Controller\StoreApi\Payment;

use Adyen\Model\Checkout\PaymentDetailsRequest;
use Adyen\Shopware\Exception\ResolveCountryException;
use Adyen\Shopware\Exception\ResolveShippingMethodException;
use Adyen\Shopware\Service\ExpressCheckoutService;
use Adyen\Shopware\Util\CheckoutStateDataValidator;
use Adyen\Exception\MissingDataException;
use Adyen\Shopware\Exception\PaymentFailedException;
Expand Down Expand Up @@ -112,6 +115,9 @@ class PaymentController
*/
private ConfigurationService $configurationService;

/** @var ExpressCheckoutService */
private ExpressCheckoutService $expressCheckoutService;

/**
* @var OrderTransactionStateHandler
*/
Expand All @@ -136,6 +142,7 @@ class PaymentController
* @param InitialStateIdLoader $initialStateIdLoader
* @param EntityRepository $orderTransactionRepository
* @param ConfigurationService $configurationService
* @param ExpressCheckoutService $expressCheckoutService
* @param OrderTransactionStateHandler $orderTransactionStateHandler
* @param LoggerInterface $logger
*/
Expand All @@ -151,6 +158,7 @@ public function __construct(
InitialStateIdLoader $initialStateIdLoader,
EntityRepository $orderTransactionRepository,
ConfigurationService $configurationService,
ExpressCheckoutService $expressCheckoutService,
OrderTransactionStateHandler $orderTransactionStateHandler,
LoggerInterface $logger
) {
Expand All @@ -164,6 +172,7 @@ public function __construct(
$this->stateMachineRegistry = $stateMachineRegistry;
$this->orderTransactionRepository = $orderTransactionRepository;
$this->configurationService = $configurationService;
$this->expressCheckoutService = $expressCheckoutService;
$this->orderTransactionStateHandler = $orderTransactionStateHandler;
$this->initialStateIdLoader = $initialStateIdLoader;
$this->logger = $logger;
Expand Down Expand Up @@ -216,11 +225,25 @@ public function postPaymentDetails(
return new JsonResponse($message, 400);
}

$newAddress = $request->request->all()['newAddress'] ?? [];
$newShipping = $request->request->all()['newShipping'] ?? [];

try {
if ($newAddress || $newShipping) {
$this->expressCheckoutService->updateShopOrder($request, $orderId, $context, $newAddress, $newShipping);
}

$result = $this->paymentDetailsService->getPaymentDetails(
new PaymentDetailsRequest($stateData),
$paymentResponse->getOrderTransaction()
);
} catch (ResolveCountryException|ResolveShippingMethodException $e) {
$this->logger->error(
$e->getMessage(),
['orderId' => $orderId, 'paymentDetails' => $stateData]
);

return new JsonResponse($e->getMessage(), 400);
} catch (PaymentFailedException $exception) {
$message = 'Error occurred finalizing payment';
$this->logger->error(
Expand Down
30 changes: 30 additions & 0 deletions src/Exception/ResolveCountryException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types=1);
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2020 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <[email protected]>
*/

namespace Adyen\Shopware\Exception;

class ResolveCountryException extends \Exception
{

}
Loading

0 comments on commit d56f38a

Please sign in to comment.