Skip to content

Commit

Permalink
[ECP-9489] Implement AdyenOrderPaymentRepository
Browse files Browse the repository at this point in the history
  • Loading branch information
Can Demiralp committed Jan 17, 2025
1 parent 894b9e3 commit 9215392
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 152 deletions.
57 changes: 57 additions & 0 deletions Api/Repository/AdyenOrderPaymentRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
/**
*
* Adyen Payment Module
*
* Copyright (c) 2025 Adyen N.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\Payment\Api\Repository;

use Adyen\Payment\Api\Data\OrderPaymentInterface;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\Api\SearchResultsInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;

interface AdyenOrderPaymentRepositoryInterface
{
const AVAILABLE_CAPTURE_STATUSES = [
OrderPaymentInterface::CAPTURE_STATUS_AUTO_CAPTURE,
OrderPaymentInterface::CAPTURE_STATUS_MANUAL_CAPTURE,
OrderPaymentInterface::CAPTURE_STATUS_PARTIAL_CAPTURE,
OrderPaymentInterface::CAPTURE_STATUS_NO_CAPTURE
];

/**
* Retrieve adyen_order_payment entity by the ID.
*
* @param int $entityId
* @return OrderPaymentInterface Adyen order payment entity
* @throws NoSuchEntityException
*/
public function get(int $entityId): OrderPaymentInterface;

/**
* Retrieve adyen_order_payment entities by `payment_id`.
*
* @param int $paymentId
* @param array $captureStatuses
* @return OrderPaymentInterface[]|null
*/
public function getByPaymentId(int $paymentId, array $captureStatuses = []): ?array;

/**
* Retrieve adyen_order_payment entities which match a specified criteria.
*
* @param SearchCriteriaInterface $searchCriteria
* @return SearchResultsInterface
*
* @throws LocalizedException
*/
public function getList(SearchCriteriaInterface $searchCriteria): SearchResultsInterface;
}
20 changes: 15 additions & 5 deletions Helper/Webhook/CaptureWebhookHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,38 @@

namespace Adyen\Payment\Helper\Webhook;

use Adyen\Payment\Api\Data\OrderPaymentInterface;
use Adyen\Payment\Api\Repository\AdyenOrderPaymentRepositoryInterface;
use Adyen\Payment\Helper\AdyenOrderPayment;
use Adyen\Payment\Helper\Invoice;
use Adyen\Payment\Helper\Order;
use Adyen\Payment\Helper\PaymentMethods;
use Adyen\Payment\Logger\AdyenLogger;
use Adyen\Payment\Model\Notification;
use Adyen\Payment\Model\Order\PaymentFactory;
use Adyen\Webhook\PaymentStates;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Sales\Api\InvoiceRepositoryInterface;
use Magento\Sales\Model\Order as MagentoOrder;

class CaptureWebhookHandler implements WebhookHandlerInterface
{
/**
* @param Invoice $invoiceHelper
* @param AdyenOrderPayment $adyenOrderPaymentHelper
* @param AdyenLogger $adyenLogger
* @param Order $orderHelper
* @param PaymentMethods $paymentMethodsHelper
* @param InvoiceRepositoryInterface $invoiceRepository
* @param AdyenOrderPaymentRepositoryInterface $adyenOrderPaymentRepository
*/
public function __construct(
private readonly Invoice $invoiceHelper,
private readonly PaymentFactory $adyenOrderPaymentFactory,
private readonly AdyenOrderPayment $adyenOrderPaymentHelper,
private readonly AdyenLogger $adyenLogger,
private readonly Order $orderHelper,
private readonly PaymentMethods $paymentMethodsHelper,
private readonly InvoiceRepositoryInterface $invoiceRepository
private readonly InvoiceRepositoryInterface $invoiceRepository,
private readonly AdyenOrderPaymentRepositoryInterface $adyenOrderPaymentRepository
) { }

/**
Expand All @@ -43,6 +52,7 @@ public function __construct(
* @param string $transitionState
* @return MagentoOrder
* @throws AlreadyExistsException
* @throws NoSuchEntityException
*/
public function handleWebhook(MagentoOrder $order, Notification $notification, string $transitionState): MagentoOrder
{
Expand All @@ -67,7 +77,7 @@ public function handleWebhook(MagentoOrder $order, Notification $notification, s
$adyenInvoice = $this->invoiceHelper->handleCaptureWebhook($order, $notification);
// Refresh the order by fetching it from the db
$order = $this->orderHelper->fetchOrderByIncrementId($notification);
$adyenOrderPayment = $this->adyenOrderPaymentFactory->create()->load($adyenInvoice->getAdyenPaymentOrderId(), OrderPaymentInterface::ENTITY_ID);
$adyenOrderPayment = $this->adyenOrderPaymentRepository->get($adyenInvoice->getAdyenPaymentOrderId());
$this->adyenOrderPaymentHelper->refreshPaymentCaptureStatus($adyenOrderPayment, $notification->getAmountCurrency());
$this->adyenLogger->addAdyenNotification(
sprintf(
Expand Down
140 changes: 140 additions & 0 deletions Model/AdyenOrderPaymentRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<?php
/**
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2025 Adyen N.V. (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <[email protected]>
*/

namespace Adyen\Payment\Model;

use Adyen\AdyenException;
use Adyen\Payment\Api\Data\OrderPaymentInterface;
use Adyen\Payment\Api\Repository\AdyenOrderPaymentRepositoryInterface;
use Adyen\Payment\Logger\AdyenLogger;
use Adyen\Payment\Model\Order\PaymentFactory as AdyenOrderPaymentFactory;
use Adyen\Payment\Model\ResourceModel\Order\Payment\CollectionFactory;
use Adyen\Payment\Model\ResourceModel\Order\Payment as AdyenOrderPaymentResourceModel;
use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\Search\FilterGroupBuilder;
use Magento\Framework\Api\Search\SearchResultFactory;
use Magento\Framework\Api\SearchCriteria\CollectionProcessor;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\Api\SearchResultsInterface;

class AdyenOrderPaymentRepository implements AdyenOrderPaymentRepositoryInterface
{
/**
* @param AdyenOrderPaymentResourceModel $resourceModel
* @param AdyenOrderPaymentFactory $adyenOrderPaymentFactory
* @param SearchResultFactory $searchResultsFactory
* @param CollectionFactory $collectionFactory
* @param CollectionProcessor $collectionProcessor
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param FilterBuilder $filterBuilder
* @param FilterGroupBuilder $filterGroupBuilder
* @param AdyenLogger $adyenLogger
*/
public function __construct(
private readonly AdyenOrderPaymentResourceModel $resourceModel,
private readonly AdyenOrderPaymentFactory $adyenOrderPaymentFactory,
private readonly SearchResultFactory $searchResultsFactory,
private readonly CollectionFactory $collectionFactory,
private readonly CollectionProcessor $collectionProcessor,
private readonly SearchCriteriaBuilder $searchCriteriaBuilder,
private readonly FilterBuilder $filterBuilder,
private readonly FilterGroupBuilder $filterGroupBuilder,
private readonly AdyenLogger $adyenLogger
) { }

/**
* @param SearchCriteriaInterface $searchCriteria
* @return SearchResultsInterface
*/
public function getList(SearchCriteriaInterface $searchCriteria): SearchResultsInterface
{
$searchResult = $this->searchResultsFactory->create();
$collection = $this->collectionFactory->create();
$this->collectionProcessor->process($searchCriteria, $collection);
$searchResult->setItems($collection->getItems());
$searchResult->setTotalCount($collection->getSize());

return $searchResult;
}

/**
* @param int $paymentId
* @param array $captureStatuses
* @return OrderPaymentInterface[]|null
* @throws AdyenException
*/
public function getByPaymentId(int $paymentId, array $captureStatuses = []): ?array
{
$paymentIdFilter = $this->filterBuilder->setField(OrderPaymentInterface::PAYMENT_ID)
->setConditionType('eq')
->setValue($paymentId)
->create();

$captureStatusFilters = [];

if (!empty($captureStatuses)) {
$this->validateCaptureStatuses($captureStatuses);

foreach ($captureStatuses as $captureStatus) {
$captureStatusFilters[] = $this->filterBuilder->setField(OrderPaymentInterface::CAPTURE_STATUS)
->setConditionType('eq')
->setValue($captureStatus)
->create();
}
}

/*
* Create two different filter groups for logical AND operation between `payment_id` and `capture_status`
* fields. Filter group `$captureStatusFilters` provides logical OR between `capture_status` values.
*/
$paymentIdFilterGroup = $this->filterGroupBuilder->setFilters([$paymentIdFilter])->create();
$captureStatusFilterGroup = $this->filterGroupBuilder->setFilters($captureStatusFilters)->create();

$searchCriteria = $this->searchCriteriaBuilder
->setFilterGroups([$paymentIdFilterGroup, $captureStatusFilterGroup])
->create();

return $this->getList($searchCriteria)->getItems();
}

/**
* @param int $entityId
* @return OrderPaymentInterface
*/
public function get(int $entityId): OrderPaymentInterface
{
$entity = $this->adyenOrderPaymentFactory->create();
$this->resourceModel->load($entity, $entityId, 'entity_id');

return $entity;
}

/**
* @param array $captureStatuses
* @return void
* @throws AdyenException
*/
private function validateCaptureStatuses(array $captureStatuses): void
{
foreach ($captureStatuses as $captureStatus) {
if (!array_contains($captureStatuses, $captureStatus)) {
$message = sprintf(
"Invalid capture status %s has been provided for adyen_order_payment repository!",
$captureStatus
);

$this->adyenLogger->error($message);
throw new AdyenException($message);
}
}
}
}
2 changes: 1 addition & 1 deletion Model/Api/GuestAdyenOrderPaymentStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function getOrderPaymentStatus(string $orderId, string $cartId): string

$order = $this->orderRepository->get($orderId);

if ($order->getQuoteId() !== $quoteId) {
if (intval($order->getQuoteId()) !== $quoteId) {
$errorMessage = sprintf("Order for ID %s not found!", $orderId);
$this->adyenLogger->error($errorMessage);

Expand Down
88 changes: 10 additions & 78 deletions Observer/CreditmemoObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,108 +11,40 @@

namespace Adyen\Payment\Observer;

use Adyen\Payment\Helper\AdyenOrderPayment;
use Adyen\Payment\Api\Repository\AdyenOrderPaymentRepositoryInterface;
use Adyen\Payment\Helper\Creditmemo as CreditMemoHelper;
use Adyen\Payment\Api\Data\OrderPaymentInterface;
use Adyen\Payment\Helper\Config;
use Adyen\Payment\Helper\Invoice as InvoiceHelper;
use Adyen\Payment\Helper\Order as OrderHelper;
use Adyen\Payment\Logger\AdyenLogger;
use Adyen\Payment\Model\Order\PaymentFactory;
use Adyen\Payment\Model\ResourceModel\Order\Payment;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Invoice;
use Magento\Sales\Model\Order\StatusResolver;
use Magento\Sales\Model\Order\Creditmemo;
use Adyen\Payment\Helper\PaymentMethods;

class CreditmemoObserver implements ObserverInterface
{
/** @var Payment $adyenPaymentResourceModel */
private $adyenPaymentResourceModel;

/** @var PaymentFactory */
private $adyenOrderPaymentFactory;

/** @var InvoiceHelper $invoiceHelper*/
private $invoiceHelper;

/** @var StatusResolver $statusResolver */
private $statusResolver;

/** @var AdyenOrderPayment $adyenOrderPaymentHelper */
private $adyenOrderPaymentHelper;

/** @var CreditmemoHelper $creditmemoHelper */
private $creditmemoHelper;

/** @var Config $configHelper */
private $configHelper;

/** @var PaymentMethods $paymentMethodsHelper */
private $paymentMethodsHelper;

/** @var OrderHelper */
private $orderHelper;

/**
* @var AdyenLogger
* @param CreditMemoHelper $creditmemoHelper
* @param AdyenOrderPaymentRepositoryInterface $adyenOrderPaymentRepository
*/
private $logger;

public function __construct(
Payment $adyenPaymentResourceModel,
PaymentFactory $adyenOrderPaymentFactory,
InvoiceHelper $invoiceHelper,
StatusResolver $statusResolver,
AdyenOrderPayment $adyenOrderPaymentHelper,
CreditmemoHelper $creditmemoHelper,
Config $configHelper,
AdyenLogger $adyenLogger,
PaymentMethods $paymentMethodsHelper,
OrderHelper $orderHelper
) {
$this->adyenPaymentResourceModel = $adyenPaymentResourceModel;
$this->adyenOrderPaymentFactory = $adyenOrderPaymentFactory;
$this->invoiceHelper = $invoiceHelper;
$this->statusResolver = $statusResolver;
$this->adyenOrderPaymentHelper = $adyenOrderPaymentHelper;
$this->creditmemoHelper = $creditmemoHelper;
$this->configHelper = $configHelper;
$this->logger = $adyenLogger;
$this->paymentMethodsHelper = $paymentMethodsHelper;
$this->orderHelper = $orderHelper;
}
private readonly CreditmemoHelper $creditmemoHelper,
private readonly AdyenOrderPaymentRepositoryInterface $adyenOrderPaymentRepository
) { }

/**
* Link all adyen_creditmemos to the appropriate magento credit memo and set the order to PROCESSING to allow
* further credit memos to be generated
*
* @param Observer $observer
* @throws AlreadyExistsException
*/
public function execute(Observer $observer)
public function execute(Observer $observer): void
{
$adyenOrderPaymentFactory = $this->adyenOrderPaymentFactory->create();

/** @var Creditmemo $creditmemo */
$creditmemo = $observer->getData('creditmemo');
$order = $creditmemo->getOrder();
$payment = $order->getPayment();

$adyenOrderPayments = $this->adyenPaymentResourceModel->getLinkedAdyenOrderPayments(
$payment->getEntityId()
);
$adyenOrderPayments = $this->adyenOrderPaymentRepository->getByPaymentId($payment->getEntityId());

foreach ($adyenOrderPayments as $adyenOrderPayment) {
/** @var \Adyen\Payment\Model\Order\Payment $adyenOrderPaymentObject */
$adyenOrderPaymentObject = $adyenOrderPaymentFactory->load(
$adyenOrderPayment[OrderPaymentInterface::ENTITY_ID],
OrderPaymentInterface::ENTITY_ID
);
$this->creditmemoHelper->linkAndUpdateAdyenCreditmemos($adyenOrderPaymentObject, $creditmemo);
$this->creditmemoHelper->linkAndUpdateAdyenCreditmemos($adyenOrderPayment, $creditmemo);
}
}
}
Loading

0 comments on commit 9215392

Please sign in to comment.