Skip to content

Commit

Permalink
Feature/capture later flow (#62)
Browse files Browse the repository at this point in the history
* Add support for separate auth and capture card flow
  • Loading branch information
andrii-onufriichuk authored Dec 6, 2023
1 parent 700209b commit becaa3f
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 24 deletions.
5 changes: 4 additions & 1 deletion Controller/Redirect/In.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Psr\Log\LoggerInterface;
use Rvvup\Payments\Api\Data\ProcessOrderResultInterface;
use Rvvup\Payments\Api\Data\SessionMessageInterface;
use Rvvup\Payments\Gateway\Method;
use Rvvup\Payments\Model\Payment\PaymentDataGetInterface;
use Rvvup\Payments\Model\ProcessOrder\ProcessorPool;
use Rvvup\Payments\Service\Order;
Expand Down Expand Up @@ -166,7 +167,9 @@ public function execute()
}

if ($rvvupData['status'] != $rvvupData['payments'][0]['status']) {
$this->processorPool->getProcessor($rvvupData['status'])->execute($order, $rvvupData);
if ($rvvupData['payments'][0]['status'] !== Method::STATUS_AUTHORIZED) {
$this->processorPool->getProcessor($rvvupData['status'])->execute($order, $rvvupData);
}
}

$result = $this->processorPool->getProcessor($rvvupData['payments'][0]['status'])
Expand Down
4 changes: 4 additions & 0 deletions Gateway/Command/CreatePayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public function execute(array $commandSubject)
]
];

if ($captureType = $payment->getMethodInstance()->getCaptureType()) {
$data['input']['captureType'] = $captureType;
}

return $this->sdkProxy->createPayment(
$data
);
Expand Down
16 changes: 16 additions & 0 deletions Gateway/Method.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class Method extends Adapter
public const STATUS_EXPIRED = 'EXPIRED';
public const STATUS_PENDING = 'PENDING';
public const STATUS_REQUIRES_ACTION = 'REQUIRES_ACTION';
public const STATUS_AUTHORIZED = "AUTHORIZED";
public const STATUS_AUTHORIZATION_EXPIRED = "AUTHORIZATION_EXPIRED";
public const STATUS_SUCCEEDED = 'SUCCEEDED';

/**
Expand All @@ -57,6 +59,9 @@ class Method extends Adapter

/** @var string */
private $title;

/** @var string */
private $captureType;
/** @var array */
private $limits;
/** @var StoreManagerInterface */
Expand All @@ -77,6 +82,7 @@ class Method extends Adapter
* @param string $infoBlockType
* @param StoreManagerInterface $storeManager
* @param LoggerInterface|RvvupLog $logger // Set via di.xml
* @param string $captureType
* @param CommandPoolInterface|null $commandPool
* @param ValidatorPoolInterface|null $validatorPool
* @param CommandManagerInterface|null $commandExecutor
Expand All @@ -92,6 +98,7 @@ public function __construct(
string $infoBlockType,
StoreManagerInterface $storeManager,
LoggerInterface $logger,
string $captureType = '',
CommandPoolInterface $commandPool = null,
ValidatorPoolInterface $validatorPool = null,
CommandManagerInterface $commandExecutor = null,
Expand All @@ -112,6 +119,7 @@ public function __construct(

$this->title = $title;
$this->limits = $limits;
$this->captureType = $captureType;
$this->storeManager = $storeManager;
$this->logger = $logger;
}
Expand Down Expand Up @@ -171,4 +179,12 @@ public function getMaxOrderTotal(string $currencyCode): ?string
{
return $this->limits[$currencyCode]['max'] ?? null;
}

/**
* @return string
*/
public function getCaptureType(): string
{
return $this->captureType;
}
}
35 changes: 32 additions & 3 deletions Model/ProcessOrder/Processing.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Rvvup\Payments\Controller\Redirect\In;
use Rvvup\Payments\Exception\PaymentValidationException;
use Rvvup\Payments\Gateway\Method;
use Magento\Framework\Stdlib\DateTime\DateTime;

class Processing implements ProcessorInterface
{
Expand All @@ -27,23 +28,28 @@ class Processing implements ProcessorInterface
/** @var LoggerInterface|RvvupLog */
private $logger;

/** @var DateTime */
private $dateTime;

/**
* @param EventManager $eventManager
* @param OrderRepositoryInterface $orderRepository
* @param ProcessOrderResultInterfaceFactory $processOrderResultFactory
* @param LoggerInterface $logger
* @return void
* @param DateTime $dateTime
*/
public function __construct(
EventManager $eventManager,
OrderRepositoryInterface $orderRepository,
ProcessOrderResultInterfaceFactory $processOrderResultFactory,
LoggerInterface $logger
LoggerInterface $logger,
DateTime $dateTime
) {
$this->eventManager = $eventManager;
$this->orderRepository = $orderRepository;
$this->processOrderResultFactory = $processOrderResultFactory;
$this->logger = $logger;
$this->dateTime = $dateTime;
}

/**
Expand Down Expand Up @@ -71,10 +77,26 @@ public function execute(OrderInterface $order, array $rvvupData): ProcessOrderRe

$order = $this->changeNewOrderStatus($order);

$eventMessage = 'Rvvup Payment is being processed.';

$payment = $rvvupData['payments'][0];
if ($this->inAuthorizedManualPayment($payment)) {
$formattedExpirationDate = $this->dateTime->date(
"jS M Y H:i:s T",
strtotime($payment["authorizationExpiresAt"])
);

$eventMessage = "Payment authorization expires at " .
$formattedExpirationDate .
". Please navigate to the Rvvup dashboard to manually capture the payment. " .
"When the authorization expires, the order will be cancelled " .
"and the funds will be returned to the customer.";
}

$this->eventManager->dispatch('rvvup_payments_process_order_processing_after', [
'payment_process_type' => self::TYPE,
'payment_process_result' => true,
'event_message' => 'Rvvup Payment is being processed.',
'event_message' => $eventMessage,
'order_id' => $order->getEntityId(),
'rvvup_id' => $rvvupData['id'] ?? null,
'original_order_state' => $originalOrderState,
Expand Down Expand Up @@ -124,4 +146,11 @@ private function changeNewOrderStatus(OrderInterface $order): OrderInterface

return $this->orderRepository->save($order);
}

private function inAuthorizedManualPayment(array $payment): bool
{
return isset($payment["authorizationExpiresAt"]) &&
$payment["captureType"] === "MANUAL" &&
$payment['status'] == Method::STATUS_AUTHORIZED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ private function addEventMessageComment(Observer $observer, OrderInterface $orde

// Prepare comment.
$comment = is_string($eventMessage) ? trim($eventMessage) : 'Rvvup Order Process was performed.';
$comment .= $rvvupId !== null ? ' Rvvup Payment ID: ' . $rvvupId : ' Rvvup Payment ID: N/A';
$comment .= $rvvupId !== null ? ' Rvvup Order ID: ' . $rvvupId : ' Rvvup Payment ID: N/A';

$orderStatusHistory = $this->createNewOrderStatusHistoryObject($order);
$orderStatusHistory->setComment($comment);
Expand Down
30 changes: 13 additions & 17 deletions Plugin/LoadMethodInstances.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,20 @@ public function aroundGetMethodInstance(\Magento\Payment\Helper\Data $subject, c

if (isset($this->processed[$code])) {
$method = $this->processed[$code];
} else {
$method = [
'code' => $code
];
/** @var Method $instance */
$instance = $this->methodFactory->create(
'RvvupFacade',
[
'code' => $code,
'title' => $method['title'] ?? 'Rvvup',
'summary_url' => $method['summaryUrl'] ?? '',
'logo_url' => $method['logoUrl'] ?? '',
'limits' => $method['limits'] ?? null,
'captureType' => $method['captureType'] ?? '',
]
);
return $instance;
}

/** @var Method $instance */
$instance = $this->methodFactory->create(
'RvvupFacade',
[
'code' => $code,
'title' => $method['title'] ?? 'Rvvup',
'summary_url' => $method['summaryUrl'] ?? '',
'logo_url' => $method['logoUrl'] ?? '',
'limits' => $method['limits'] ?? null,
]
);
return $instance;
}
return $proceed($code);
}
Expand Down
1 change: 1 addition & 0 deletions Traits/LoadMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ protected function processMethods(array $methods): array
$processed[$code]['summaryUrl'] = $method['summaryUrl'];
$processed[$code]['logoUrl'] = $method['logoUrl'] ?? '';
$processed[$code]['limits'] = $this->processLimits($method['limits']['total'] ?? []);
$processed[$code]['captureType'] = $method['captureType'] ?? '';
}
$this->processed = $processed;
}
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"guzzlehttp/guzzle": ">=6",
"magento/module-catalog": "^103.0 || ^104.0",
"magento/module-grouped-product": ">=100.1",
"rvvup/sdk": "0.13.6",
"rvvup/sdk": "0.13.7",
"ext-json": "*",
"php": "^7.3 || ^8.0"
},
Expand Down
2 changes: 2 additions & 0 deletions etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,10 @@
<item name="DECLINED" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\Cancel</item>
<item name="EXPIRED" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\Cancel</item>
<item name="FAILED" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\Cancel</item>
<item name="AUTHORIZATION_EXPIRED" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\Cancel</item>
<item name="PENDING" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\Processing</item>
<item name="REQUIRES_ACTION" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\Processing</item>
<item name="AUTHORIZED" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\Processing</item>
<item name="SUCCEEDED" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\Complete</item>
<item name="REQUIRES_PAYMENT" xsi:type="object">Rvvup\Payments\Model\ProcessOrder\UpdateOrder</item>
</argument>
Expand Down
17 changes: 17 additions & 0 deletions view/frontend/web/js/action/place-order-mixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
define([
'mage/utils/wrapper',
'jquery',
], function (wrapper, $) {
'use strict';

return function (placeOrderAction) {
return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, redirectOnSuccess) {
if (paymentData && paymentData.method.startsWith('rvvup_')) {
// do not create order for rvvup payments as it will be created later on.
//return;
}

return originalAction(paymentData, redirectOnSuccess);
});
};
});
3 changes: 2 additions & 1 deletion view/frontend/web/js/view/payment/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ define([
'mage/storage',
'mage/translate',
'Magento_Checkout/js/model/url-builder',
'Magento_Ui/js/model/messageList'
'Magento_Ui/js/model/messageList',
'domReady!',
], function (Component, $, _, storage, $t, urlBuilder, globalMessages) {
return Component.extend({
/**
Expand Down

0 comments on commit becaa3f

Please sign in to comment.