Skip to content

Commit

Permalink
Webhook for payment links
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrii Onufriichuk committed Mar 1, 2024
1 parent 6d7d550 commit 262f659
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 35 deletions.
2 changes: 2 additions & 0 deletions Controller/Webhook/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public function execute(): ResultInterface
$eventType = $this->request->getParam('event_type', false);
$paymentId = $this->request->getParam('payment_id', false);
$refundId = $this->request->getParam('refund_id', false);
$paymentLinkId = $this->request->getParam('payment_link_id', false);

// Ensure required params are present
if (!$merchantId || !$rvvupOrderId) {
Expand All @@ -118,6 +119,7 @@ public function execute(): ResultInterface
'refund_id' => $refundId,
'payment_id' => $paymentId,
'event_type' => $eventType,
'payment_link_id' => $paymentLinkId
];

if ($payload['event_type'] == Complete::TYPE) {
Expand Down
13 changes: 11 additions & 2 deletions Model/Data/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Rvvup\Payments\Api\Data\ValidationInterface;
use Rvvup\Payments\Api\Data\ValidationInterfaceFactory;
use Rvvup\Payments\Gateway\Method;
use Rvvup\Payments\Service\Capture;
use Rvvup\Payments\Service\Hash;
use Psr\Log\LoggerInterface;

Expand All @@ -24,19 +25,25 @@ class Validation extends DataObject implements ValidationInterface
/** @var OrderIncrementIdChecker */
private $orderIncrementChecker;

/** @var Capture */
private $captureService;

/**
* @param Hash|null $hashService
* @param OrderIncrementIdChecker|null $orderIncrementIdChecker
* @param Capture $captureService
* @param LoggerInterface|null $logger
* @param array $data
*/
public function __construct(
Hash $hashService,
OrderIncrementIdChecker $orderIncrementIdChecker,
Capture $captureService,
LoggerInterface $logger,
array $data = []
) {
$this->logger = $logger;
$this->captureService = $captureService;
$this->orderIncrementChecker = $orderIncrementIdChecker;
$this->hashService = $hashService;
parent::__construct($data);
Expand Down Expand Up @@ -80,8 +87,10 @@ public function validate(
}

if (!$quote->getItems()) {
$quote = $this->getQuoteByRvvupId($rvvupId);
$lastTransactionId = (string)$quote->getPayment()->getAdditionalInformation('transaction_id');
$quote = $this->captureService->getQuoteByRvvupId($rvvupId);
if ($quote->getId()) {
$lastTransactionId = (string)$quote->getPayment()->getAdditionalInformation('transaction_id');
}
}
if (empty($quote->getId())) {
$this->logger->error('Missing quote for Rvvup payment', [$rvvupId, $lastTransactionId]);
Expand Down
4 changes: 2 additions & 2 deletions Model/ProcessOrder/ProcessorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
interface ProcessorInterface
{
/**
* @param \Magento\Sales\Api\Data\OrderInterface $order
* @param OrderInterface $order
* @param array $rvvupData
* @return \Rvvup\Payments\Api\Data\ProcessOrderResultInterface
* @return ProcessOrderResultInterface
*/
public function execute(OrderInterface $order, array $rvvupData): ProcessOrderResultInterface;
}
2 changes: 1 addition & 1 deletion Model/ProcessRefund/Complete.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ public function __construct(

/**
* Complete refund
*
* @param array $payload
* @return void
* @throws Exception
*/
public function execute(array $payload): void
{
Expand Down
52 changes: 32 additions & 20 deletions Model/Queue/Handler/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Serialize\SerializerInterface;
use Magento\Sales\Api\Data\OrderInterface;
use Psr\Log\LoggerInterface;
use Rvvup\Payments\Api\WebhookRepositoryInterface;
use Rvvup\Payments\Gateway\Method;
Expand Down Expand Up @@ -75,6 +76,14 @@ public function execute(int $id)

$rvvupOrderId = $payload['order_id'];

if ($paymentLinkId = $payload['payment_link_id']) {
$order = $this->captureService->getOrderByRvvupPaymentLinkId($paymentLinkId);
if ($order) {
$this->processOrder($order);
return;
}
}

if ($payload['event_type'] == Method::STATUS_PAYMENT_AUTHORIZED) {
$quote = $this->captureService->getQuoteByRvvupId($rvvupOrderId);
if (!$quote) {
Expand Down Expand Up @@ -123,31 +132,34 @@ public function execute(int $id)
}

$order = $this->captureService->getOrderByRvvupId($rvvupOrderId);

// if Payment method is not Rvvup, exit.
if (strpos($order->getPayment()->getMethod(), Method::PAYMENT_TITLE_PREFIX) !== 0) {
return;
}

if (isset($rvvupOrderId)) {
$rvvupData = $this->paymentDataGet->execute($rvvupOrderId);
if (empty($rvvupData) || !isset($rvvupData['payments'][0]['status'])) {
$this->logger->error('Webhook error. Rvvup order data could not be fetched.', [
'rvvup_order_id' => $rvvupOrderId
]);
return;
}
$this->processorPool->getProcessor($rvvupData['payments'][0]['status'])->execute(
$order,
$rvvupData
);
}

$this->processOrder($order);
return;
} catch (\Exception $e) {
$this->logger->error('Queue handling exception:' . $e->getMessage(), [
'order_id' => $rvvupOrderId,
]);
}
}

private function processOrder(OrderInterface $order): void
{
// if Payment method is not Rvvup, exit.
if (strpos($order->getPayment()->getMethod(), Method::PAYMENT_TITLE_PREFIX) !== 0) {
return;
}

if (isset($rvvupOrderId)) {
$rvvupData = $this->paymentDataGet->execute($rvvupOrderId);

Check failure on line 152 in Model/Queue/Handler/Handler.php

View workflow job for this annotation

GitHub Actions / PHP Stan

Undefined variable: $rvvupOrderId
if (empty($rvvupData) || !isset($rvvupData['payments'][0]['status'])) {
$this->logger->error('Webhook error. Rvvup order data could not be fetched.', [
'rvvup_order_id' => $rvvupOrderId

Check failure on line 155 in Model/Queue/Handler/Handler.php

View workflow job for this annotation

GitHub Actions / PHP Stan

Undefined variable: $rvvupOrderId
]);
return;
}
$this->processorPool->getProcessor($rvvupData['payments'][0]['status'])->execute(
$order,
$rvvupData
);
}
}
}
34 changes: 26 additions & 8 deletions Plugin/Order/Create/PaymentLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class PaymentLink
/** @var Config */
private $config;

/** @var SerializerInterface */
/** @var SerializerInterface */
private $json;

/** @var OrderStatusHistoryInterfaceFactory $orderStatusHistoryFactory */
Expand All @@ -33,7 +33,7 @@ class PaymentLink
/** @var OrderManagementInterface $orderManagement */
private $orderManagement;

/** @var Http */
/** @var Http */
private $request;

/**
Expand Down Expand Up @@ -86,7 +86,8 @@ public function afterImportPostData(Create $subject, Create $result, array $data
$amount = (float)$quote->getGrandTotal();
$orderId = $quote->reserveOrderId()->getReservedOrderId();
$currencyCode = $quote->getQuoteCurrencyCode();
$this->createRvvupPayByLink($storeId, $amount, $orderId, $currencyCode, $subject, $data);
$id = $this->createRvvupPayByLink($storeId, $amount, $orderId, $currencyCode, $subject, $data);
$this->savePaymentLink($subject, $id);
}
}
return $result;
Expand All @@ -103,19 +104,35 @@ public function afterCreateOrder(Create $subject, Order $result): Order
{
$order = $this->request->getPost('order');
if (!(isset($order['send_confirmation']) && $order['send_confirmation'])) {
$this->createRvvupPayByLink(
$id = $this->createRvvupPayByLink(
(string)$result->getStoreId(),
$result->getGrandTotal(),
$result->getId(),
$result->getOrderCurrencyCode(),
$subject,
['status' => $result->getStatus()]
);
$this->savePaymentLink($subject, $id);
}

return $result;
}

/**
* @param Create $subject
* @param string $id
* @return void
*/
private function savePaymentLink(Create $subject, string $id): void
{
try {
$payment = $subject->getQuote()->getPayment();
$payment->setAdditionalInformation('rvvup_payment_link_id', $id);
} catch (\Exception $e) {
$this->logger->error('Error saving rvvup payment link: ' . $e->getMessage());
}
}

/**
* Create Rvvup pay-by-link and save it to comment
* @param string $storeId
Expand All @@ -124,8 +141,7 @@ public function afterCreateOrder(Create $subject, Order $result): Order
* @param string $currencyCode
* @param Create $subject
* @param array $data
* @return void
* @throws NoSuchEntityException
* @return string|null
*/
private function createRvvupPayByLink(
string $storeId,
Expand All @@ -134,17 +150,19 @@ private function createRvvupPayByLink(
string $currencyCode,
Create $subject,
array $data
): void {
): ?string {
try {
$amount = number_format($amount, 2, '.', '');
$params = $this->getData($amount, $storeId, $orderId, $currencyCode);

$request = $this->curl->request(Request::METHOD_POST, $this->getApiUrl($storeId), $params);
$body = $this->json->unserialize($request->body);
$this->processApiResponse($body, $amount, $subject, $data, $orderId);
return $body['id'];
} catch (\Exception $e) {
$this->logger->error('Rvvup payment link creation failed with error: ' . $e->getMessage());
}
return null;
}

/**
Expand All @@ -159,7 +177,7 @@ private function processApiResponse(array $body, string $amount, Create $subject
{
if ($body['status'] == 'ACTIVE') {
if ($amount == $body['amount']['amount']) {
$message = 'This order requires payment, please pay using following link:'. PHP_EOL . $body['url'];
$message = PHP_EOL . $body['url'];
if (isset($data['send_confirmation']) && $data['send_confirmation']) {
$message .= PHP_EOL . $data['comment']['customer_note'];
$subject->getQuote()->addData(['customer_note' => $message, 'customer_note_notify' => true]);
Expand Down
32 changes: 30 additions & 2 deletions Service/Capture.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\Quote\Payment;
use Magento\Quote\Model\QuoteManagement;
use Magento\Quote\Model\ResourceModel\Quote\Payment\Collection;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\Data\OrderPaymentInterface;
use Magento\Sales\Api\OrderPaymentRepositoryInterface;
Expand Down Expand Up @@ -121,7 +122,7 @@ public function __construct(
*/
public function getOrderByRvvupId(string $rvvupOrderId): OrderInterface
{
// Saerch for the payment record by the Rvvup order ID which is stored in the credit card field.
// Search for the payment record by the Rvvup order ID
$searchCriteria = $this->searchCriteriaBuilder->addFilter(
'additional_information',
'%' . $rvvupOrderId . '%',
Expand Down Expand Up @@ -280,7 +281,7 @@ public function paymentCapture(
*/
public function getQuoteByRvvupId(string $rvvupId): ?Quote
{
/** @var \Magento\Quote\Model\ResourceModel\Quote\Payment\Collection $collection */
/** @var Collection $collection */
$collection = $this->collectionFactory->create();
$collection->addFieldToFilter(
'additional_information',
Expand All @@ -300,6 +301,33 @@ public function getQuoteByRvvupId(string $rvvupId): ?Quote
}
}

/**
* @param string $paymentLinkId
* @return Quote|null
*/
public function getOrderByRvvupPaymentLinkId(string $paymentLinkId): ?OrderInterface
{
/** @var Collection $collection */
$collection = $this->collectionFactory->create();
$collection->addFieldToFilter(
'additional_information',
[
'like' => "%\"rvvup_payment_link_id\":\"$paymentLinkId\"%"
]
);
$items = $collection->getItems();
if (count($items) !== 1) {
return null;
}
$quoteId = end($items)->getQuoteId();
try {
$cart = $this->cartRepository->get($quoteId);
return $this->orderRepository->get($cart->getOrigOrderId());
} catch (NoSuchEntityException $ex) {
return null;
}
}

/**
* Set checkout method
*
Expand Down

0 comments on commit 262f659

Please sign in to comment.