Skip to content

Commit 623ca30

Browse files
Fix cancel payment in order transaction service
- Only cancel order when CM.com payment is canceled and method is cm_payment_creditcard - Add more tests for cancelation of order
1 parent 7cd6386 commit 623ca30

File tree

4 files changed

+195
-12
lines changed

4 files changed

+195
-12
lines changed

Client/Model/Response/Payment/Authorization.php

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
class Authorization
1212
{
1313
const STATE_AUTHORIZED = 'AUTHORIZED';
14+
const STATE_CANCELED = 'CANCELED';
1415

1516
/**
1617
* @var int|null

Service/OrderTransactionService.php

+16-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@
2929

3030
class OrderTransactionService implements OrderTransactionServiceInterface
3131
{
32+
/**
33+
* Array of payment methods which should cancel the order when CM.com Payment is canceled.
34+
* @const array
35+
*/
36+
protected const SHOULD_CANCEL_PAYMENT_METHODS = [
37+
'cm_payments_creditcard'
38+
];
39+
3240
/**
3341
* @var OrderRepositoryInterface
3442
*/
@@ -124,7 +132,7 @@ public function process(string $orderReference): void
124132
);
125133
}
126134

127-
if (empty($cmOrderDetails->getConsideredSafe()) || ! $cmOrderDetails->isSafe()) {
135+
if (empty($cmOrderDetails->getConsideredSafe()) || !$cmOrderDetails->isSafe()) {
128136
$this->cancelOrderByPaymentStatus($cmOrder, $order, $cmOrderDetails);
129137

130138
// If order is not considered 'Safe' we don't have to process.
@@ -136,7 +144,6 @@ public function process(string $orderReference): void
136144
'cmOrderDetails' => $cmOrderDetails
137145
]);
138146

139-
// Todo: move to separate method or class
140147
$this->createCMPaymentIfNotExists($cmOrder, $order, $cmOrderDetails);
141148

142149
$this->logger->info('Create invoice and transaction for order '. $orderReference);
@@ -212,9 +219,14 @@ private function cancelOrderByPaymentStatus(
212219
): void {
213220
try {
214221
$cmPayment = $this->cmPaymentRepository->getByOrderKey($cmOrder->getOrderKey());
215-
if ($order->getPayment()->getMethod() === 'cm_payments_creditcard' && $cmPayment) {
222+
if (in_array($order->getPayment()->getMethod(), self::SHOULD_CANCEL_PAYMENT_METHODS) && $cmPayment) {
223+
foreach($cmOrderDetails->getPayments() as $payment) {
224+
if ($payment->getAuthorization()->getState() === Authorization::STATE_AUTHORIZED) {
225+
return;
226+
}
227+
}
216228
foreach ($cmOrderDetails->getPayments() as $payment) {
217-
if ($payment->getAuthorization()->getState() !== Authorization::STATE_AUTHORIZED) {
229+
if ($payment->getAuthorization()->getState() === Authorization::STATE_CANCELED) {
218230
$order->setState(Order::STATE_CANCELED);
219231
$order->addCommentToStatusHistory(
220232
__('Order cancelled by CM, payment id %1', $payment->getId()),

Test/Integration/Service/OrderTransactionServiceTest.php

+124-8
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
namespace CM\Payments\Test\Integration\Service;
88

9+
use CM\Payments\Api\Model\Data\PaymentInterfaceFactory;
910
use CM\Payments\Api\Model\PaymentRepositoryInterface;
1011
use CM\Payments\Client\Api\ApiClientInterface;
1112
use CM\Payments\Api\Service\OrderTransactionServiceInterface;
1213
use CM\Payments\Model\Data\Order;
14+
use CM\Payments\Model\OrderRepository;
1315
use CM\Payments\Service\OrderTransactionService;
1416
use CM\Payments\Test\Integration\IntegrationTestCase;
1517
use CM\Payments\Test\Mock\MockApiResponse;
@@ -55,13 +57,7 @@ protected function setUp(): void
5557

5658
$magentoOrder = $this->loadOrderById('100000001');
5759

58-
$cmOrder = $this->objectManager->create(Order::class);
59-
$cmOrder->setIncrementId('100000001')
60-
->setOrderId($magentoOrder->getEntityId())
61-
->setOrderKey('test123');
62-
63-
$cmOrderRepository = $this->objectManager->create(\CM\Payments\Model\OrderRepository::class);
64-
$cmOrderRepository->save($cmOrder);
60+
$this->createCmOrder($magentoOrder);
6561

6662
$magentoOrder = $this->loadOrderById('100000001');
6763
$this->adjustMagentoOrder($magentoOrder);
@@ -212,11 +208,102 @@ public function testIfCMPaymentIsCreatedInDatabase()
212208
$this->orderTransactionService->process('100000001');
213209

214210
$cmPaymentRepository = $this->objectManager->create(PaymentRepositoryInterface::class);
215-
216211
$cmPayment = $cmPaymentRepository->getByOrderKey('test123');
217212
$this->assertSame('pid4911203603t', $cmPayment->getPaymentId());
218213
}
219214

215+
/**
216+
* @magentoDataFixture Magento/Sales/_files/order.php
217+
*/
218+
public function testShouldCancelOrderWhenCreditCardDirectPaymentIsCanceled()
219+
{
220+
$this->clientMock
221+
->expects($this->once())->method('execute')
222+
->willReturn($this->mockApiResponse->getOrderDetailCanceledPayment());
223+
224+
$magentoOrder = $this->loadOrderById('100000001');
225+
$magentoOrder->getPayment()->setMethod('cm_payments_creditcard');
226+
$repository = $this->objectManager->get(OrderRepositoryInterface::class);
227+
$repository->save($magentoOrder);
228+
229+
$this->createCmOrder($magentoOrder);
230+
231+
$this->createCMPayment($magentoOrder);
232+
233+
$this->orderTransactionService->process('100000001');
234+
235+
$magentoOrder = $this->loadOrderById('100000001');
236+
$this->assertSame('canceled', $magentoOrder->getStatus());
237+
}
238+
239+
/**
240+
* @magentoDataFixture Magento/Sales/_files/order.php
241+
*/
242+
public function testShouldNotCancelOrderWhenCreditCardDirectPaymentIsRedirectedForAuthentication()
243+
{
244+
$this->clientMock
245+
->expects($this->once())->method('execute')
246+
->willReturn($this->mockApiResponse->getOrderDetailRedirectedForAuthenticationPayment());
247+
248+
249+
$magentoOrder = $this->loadOrderById('100000001');
250+
$magentoOrder->getPayment()->setMethod('cm_payments_creditcard');
251+
$repository = $this->objectManager->get(OrderRepositoryInterface::class);
252+
$repository->save($magentoOrder);
253+
254+
$this->createCmOrder($magentoOrder);
255+
256+
$this->createCMPayment($magentoOrder);
257+
258+
$this->orderTransactionService->process('100000001');
259+
260+
$magentoOrder = $this->loadOrderById('100000001');
261+
$this->assertSame('pending_payment', $magentoOrder->getStatus());
262+
}
263+
264+
/**
265+
* @magentoDataFixture Magento/Sales/_files/order.php
266+
*/
267+
public function testShouldNotCancelOrderWhenIdealPaymentIsCanceled()
268+
{
269+
$this->clientMock
270+
->expects($this->once())->method('execute')
271+
->willReturn($this->mockApiResponse->getOrderDetailCanceledPayment());
272+
273+
$magentoOrder = $this->loadOrderById('100000001');
274+
275+
$magentoOrder->getPayment()->setMethod('cm_payments_ideal');
276+
$repository = $this->objectManager->get(OrderRepositoryInterface::class);
277+
$repository->save($magentoOrder);
278+
279+
$this->createCmOrder($magentoOrder);
280+
$this->orderTransactionService->process('100000001');
281+
282+
$magentoOrder = $this->loadOrderById('100000001');
283+
$this->assertSame('pending_payment', $magentoOrder->getStatus());
284+
}
285+
286+
/**
287+
* @magentoDataFixture Magento/Sales/_files/order.php
288+
*/
289+
public function testShouldNotCancelOrderWhenCMPaymentNotExists()
290+
{
291+
$this->clientMock
292+
->expects($this->once())->method('execute')
293+
->willReturn($this->mockApiResponse->getOrderDetailCanceledPayment());
294+
295+
$magentoOrder = $this->loadOrderById('100000001');
296+
$magentoOrder->getPayment()->setMethod('cm_payments_ideal');
297+
$repository = $this->objectManager->get(OrderRepositoryInterface::class);
298+
$repository->save($magentoOrder);
299+
300+
$this->createCmOrder($magentoOrder);
301+
$this->orderTransactionService->process('100000001');
302+
303+
$magentoOrder = $this->loadOrderById('100000001');
304+
$this->assertSame('pending_payment', $magentoOrder->getStatus());
305+
}
306+
220307
/**
221308
* @param OrderInterface $magentoOrder
222309
* @return OrderInterface
@@ -234,4 +321,33 @@ private function adjustMagentoOrder(OrderInterface $magentoOrder): OrderInterfac
234321

235322
return $magentoOrder;
236323
}
324+
325+
/**
326+
* @param OrderInterface $magentoOrder
327+
*/
328+
private function createCmOrder(OrderInterface $magentoOrder): void
329+
{
330+
$cmOrder = $this->objectManager->create(Order::class);
331+
$cmOrder->setIncrementId('100000001')
332+
->setOrderId($magentoOrder->getEntityId())
333+
->setOrderKey('test123');
334+
335+
$cmOrderRepository = $this->objectManager->create(OrderRepository::class);
336+
$cmOrderRepository->save($cmOrder);
337+
}
338+
339+
/**
340+
* @param OrderInterface $magentoOrder
341+
*/
342+
private function createCMPayment(OrderInterface $magentoOrder): void
343+
{
344+
$cmPaymentRepository = $this->objectManager->create(PaymentRepositoryInterface::class);
345+
$cmPaymentDataFactory = $this->objectManager->create(PaymentInterfaceFactory::class);
346+
$cmPayment = $cmPaymentDataFactory->create();
347+
$cmPayment->setOrderId((int)$magentoOrder->getEntityId());
348+
$cmPayment->setOrderKey('test123');
349+
$cmPayment->setIncrementId($magentoOrder->getIncrementId());
350+
$cmPayment->setPaymentId('pid4911203603t');
351+
$cmPaymentRepository->save($cmPayment);
352+
}
237353
}

Test/Mock/MockApiResponse.php

+54
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,60 @@ public function getOrderDetail()
6464
];
6565
}
6666

67+
public function getOrderDetailCanceledPayment()
68+
{
69+
return [
70+
"order_reference" => "100000001",
71+
"description" => "Order 12345",
72+
"amount" => 50,
73+
"currency" => "USD",
74+
"email" => "[email protected]",
75+
"language" => "be",
76+
"country" => "NL",
77+
"profile" => "test",
78+
"timestamp" => "2021-07-01T11:59:49Z",
79+
"expires_on" => "2021-08-05T11:59:49Z",
80+
"payments" => [
81+
[
82+
"id" => "pid4911203603t",
83+
"method" => "IDEAL",
84+
"authorization" => [
85+
"amount" => 42,
86+
"currency" => "EUR",
87+
"state" => "CANCELED"
88+
]
89+
]
90+
]
91+
];
92+
}
93+
94+
public function getOrderDetailRedirectedForAuthenticationPayment()
95+
{
96+
return [
97+
"order_reference" => "100000001",
98+
"description" => "Order 12345",
99+
"amount" => 50,
100+
"currency" => "USD",
101+
"email" => "[email protected]",
102+
"language" => "be",
103+
"country" => "NL",
104+
"profile" => "test",
105+
"timestamp" => "2021-07-01T11:59:49Z",
106+
"expires_on" => "2021-08-05T11:59:49Z",
107+
"payments" => [
108+
[
109+
"id" => "pid4911203603t",
110+
"method" => "IDEAL",
111+
"authorization" => [
112+
"amount" => 42,
113+
"currency" => "EUR",
114+
"state" => "REDIRECTED_FOR_AUTHENTICATION"
115+
]
116+
]
117+
]
118+
];
119+
}
120+
67121
public function getOrderDetailMultiplePayments()
68122
{
69123
return [

0 commit comments

Comments
 (0)