From 39eef0fe9cbbeafb2f12728b111ca8fc571af5a7 Mon Sep 17 00:00:00 2001 From: mustapayev Date: Sun, 27 Oct 2024 11:28:51 +0100 Subject: [PATCH] tests - use mocks in response mapper tests --- .../AkbankPosResponseDataMapperTest.php | 112 +- .../EstPosResponseDataMapperTest.php | 272 ++- .../GarantiPosResponseDataMapperTest.php | 194 +- .../InterPosResponseDataMapperTest.php | 112 +- .../KuveytPosResponseDataMapperTest.php | 201 +- .../PayFlexCPV4PosResponseDataMapperTest.php | 53 +- .../PayFlexV4PosResponseDataMapperTest.php | 127 +- .../PayForPosResponseDataMapperTest.php | 2021 +++++++++-------- .../PosNetResponseDataMapperTest.php | 100 +- .../PosNetV1PosResponseDataMapperTest.php | 131 +- .../ToslaPosResponseDataMapperTest.php | 132 +- .../VakifKatilimPosResponseDataMapperTest.php | 216 +- tests/Unit/Gateways/PosNetV1PosTest.php | 39 +- 13 files changed, 2423 insertions(+), 1287 deletions(-) diff --git a/tests/Unit/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapperTest.php index 9b0ea182..596c87b9 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/AkbankPosResponseDataMapperTest.php @@ -6,6 +6,8 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\AkbankPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Factory\RequestValueMapperFactory; use Mews\Pos\Factory\ResponseValueFormatterFactory; use Mews\Pos\Factory\ResponseValueMapperFactory; @@ -26,19 +28,24 @@ class AkbankPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(AkbankPos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(AkbankPos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(AkbankPos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new AkbankPosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -70,14 +77,19 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['txnDateTime'], $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['txnCode']) + ->willReturn($expectedData['transaction_type']); + + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -94,19 +106,30 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['txnDateTime'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + if (isset($responseData['txnCode'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['txnCode']) + ->willReturn($expectedData['transaction_type']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $responseData, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->assertSame($expectedData['transaction_time'], $actualData['transaction_time']); + } $this->assertArrayHasKey('all', $actualData); if ([] !== $responseData) { @@ -128,14 +151,22 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['txnDateTime'], $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $this->responseValueMapper->expects($this->never()) + ->method('mapTxType') + ->with($responseData['txnCode']); + + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->assertSame($expectedData['transaction_time'], $actualData['transaction_time']); + } $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -152,14 +183,22 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['txnDateTime'], $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $this->responseValueMapper->expects($this->never()) + ->method('mapTxType') + ->with($responseData['txnCode']); + + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->assertSame($expectedData['transaction_time'], $actualData['transaction_time']); + } $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -206,11 +245,20 @@ public function testMapCancelResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryDataProvider */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(AkbankPos::class); + $responseDataMapper = new AkbankPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(AkbankPos::class), + ResponseValueMapperFactory::createForGateway(AkbankPos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); + if (isset($responseData['txnDetailList'])) { $this->assertCount($actualData['trans_count'], $actualData['transactions']); @@ -308,7 +356,7 @@ public static function paymentDataProvider(): iterable 'payment_model' => 'regular', 'transaction_id' => null, 'transaction_type' => 'pay', - 'transaction_time' => new \DateTimeImmutable('2022-03-01T09:29:23.851'), + 'transaction_time' => new \DateTimeImmutable('2022-03-01T09:29:23'), 'auth_code' => '064716', 'order_id' => 'b9ebfdc5-304f-49c2-8065-a2c7481a5d1f', 'recurring_id' => null, @@ -2708,7 +2756,5 @@ public static function historyDataProvider(): \Generator ], 'expectedTxCount' => 0, ]; - - } } diff --git a/tests/Unit/DataMapper/ResponseDataMapper/EstPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/EstPosResponseDataMapperTest.php index 4e6bfe1b..3d700bf8 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/EstPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/EstPosResponseDataMapperTest.php @@ -6,6 +6,9 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\EstPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\RequestValueMapperFactory; use Mews\Pos\Factory\ResponseValueFormatterFactory; @@ -27,19 +30,24 @@ class EstPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(EstV3Pos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(EstV3Pos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(EstV3Pos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new EstPosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -78,9 +86,17 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['Extra']['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueMapper->expects($this->never()) + ->method('mapTxType'); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -97,14 +113,39 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($threeDResponseData['taksit'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['currency'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($threeDResponseData['storetype'], $txType) + ->willReturn($expectedData['payment_model']); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($paymentResponse['Extra']['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order, ); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -126,9 +167,34 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['taksit'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['currency'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['storetype'], $txType) + ->willReturn($expectedData['payment_model']); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['EXTRA_TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -145,14 +211,34 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['taksit'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['currency'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['storetype'], $txType) + ->willReturn($expectedData['payment_model']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -169,29 +255,115 @@ public function testMap3DHostResponseData(array $order, string $txType, array $r */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + if (ResponseDataMapperInterface::TX_APPROVED === $expectedData['status']) { + $amountMatcher = $this->exactly($responseData['Extra']['CAPTURE_AMT'] ? 2 : 1); + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueFormatter->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $responseData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $responseData['Extra']['ORIG_TRANS_AMT']; + } + if ($amountMatcher->getInvocationCount() === 2) { + return $amount === $responseData['Extra']['CAPTURE_AMT']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($amountMatcher, $expectedData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $expectedData['first_amount']; + } + if ($amountMatcher->getInvocationCount() === 2) { + return $expectedData['capture_amount']; + } + + return false; + } + ); + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['Extra']['CHARGE_TYPE_CD']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['Extra']['TRANS_STAT']) + ->willReturn($expectedData['order_status']); + + $dateTimeMatcher = $this->atLeastOnce(); + $dates = ['AUTH_DTTM', 'CAPTURE_DTTM', 'VOID_DTTM']; + $this->responseValueFormatter->expects($dateTimeMatcher) + ->method('formatDateTime') + ->with($this->callback(function ($dateTime) use (&$dates, $responseData) { + if (isset($responseData['Extra'][$dates[0]])) { + $dateKey = $dates[0]; + $dates = array_slice($dates, 1); + + return $dateTime === $responseData['Extra'][$dateKey]; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($dateTimeMatcher, $expectedData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $expectedData['transaction_time']; + } + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $expectedData['capture_time']; + } + if ($dateTimeMatcher->getInvocationCount() === 3) { + return $expectedData['cancel_time']; + } + + return false; + } + ); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - if (isset($actualData['recurringOrders'])) { - foreach ($actualData['recurringOrders'] as $key => $actualRecurringOrder) { - $expectedRecurringOrder = $expectedData['recurringOrders'][$key]; - \ksort($expectedData['recurringOrders'][$key]); - \ksort($actualData['recurringOrders'][$key]); - $this->assertEquals($expectedRecurringOrder['transaction_time'], $actualRecurringOrder['transaction_time']); - $this->assertEquals($expectedRecurringOrder['capture_time'], $actualRecurringOrder['capture_time']); - unset($actualData['recurringOrders'][$key]['transaction_time'], $expectedData['recurringOrders'][$key]['transaction_time']); - unset($actualData['recurringOrders'][$key]['capture_time'], $expectedData['recurringOrders'][$key]['capture_time']); - } - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); + $this->assertArrayHasKey('all', $actualData); + $this->assertIsArray($actualData['all']); + $this->assertNotEmpty($actualData['all']); + unset($actualData['all']); + + \ksort($expectedData); + \ksort($actualData); + + $this->assertSame($expectedData, $actualData); + } + + + /** + * Doing integration test because of the iteration, and conditional statements it is difficult to mock values. + * @dataProvider statusRecurringOrderTestDataProvider + */ + public function testMapStatusResponseRecurringOrder(array $responseData, array $expectedData): void + { + $requestValueMapper = RequestValueMapperFactory::createForGateway(EstV3Pos::class); + $responseDataMapper = new EstPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(EstV3Pos::class), + ResponseValueMapperFactory::createForGateway(EstV3Pos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapStatusResponse($responseData); + + foreach ($actualData['recurringOrders'] as $key => $actualRecurringOrder) { + $expectedRecurringOrder = $expectedData['recurringOrders'][$key]; + \ksort($expectedData['recurringOrders'][$key]); + \ksort($actualData['recurringOrders'][$key]); + $this->assertEquals($expectedRecurringOrder['transaction_time'], $actualRecurringOrder['transaction_time']); + $this->assertEquals($expectedRecurringOrder['capture_time'], $actualRecurringOrder['capture_time']); + unset($actualData['recurringOrders'][$key]['transaction_time'], $expectedData['recurringOrders'][$key]['transaction_time']); + unset($actualData['recurringOrders'][$key]['capture_time'], $expectedData['recurringOrders'][$key]['capture_time']); } + $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); $this->assertNotEmpty($actualData['all']); @@ -234,11 +406,19 @@ public function testMapCancelResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryTestDataProvider */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(EstV3Pos::class); + $responseDataMapper = new EstPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(EstV3Pos::class), + ResponseValueMapperFactory::createForGateway(EstV3Pos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (count($responseData['Extra']) > 0) { if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] @@ -1279,7 +1459,7 @@ public static function threeDHostPaymentDataProvider(): array public static function statusTestDataProvider(): array { return [ - 'success1' => [ + 'success1' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 20221030FAC5', 'ProcReturnCode' => '00', @@ -1335,7 +1515,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'fail1' => [ + 'fail1' => [ 'responseData' => [ 'ErrMsg' => 'No record found for 2022103088D22', 'ProcReturnCode' => '99', @@ -1372,7 +1552,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'pay_order_status' => [ + 'pay_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 2024010354F1', 'ProcReturnCode' => '00', @@ -1428,7 +1608,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'pre_pay_order_status' => [ + 'pre_pay_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 202401032AF3', 'ProcReturnCode' => '00', @@ -1484,7 +1664,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'canceled_order_status' => [ + 'canceled_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 20240103BBF9', 'ProcReturnCode' => '00', @@ -1541,7 +1721,7 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], - 'refund_order_status' => [ + 'refund_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 20240128C0B7', 'ProcReturnCode' => '00', @@ -1597,6 +1777,12 @@ public static function statusTestDataProvider(): array 'installment_count' => null, ], ], + ]; + } + + public static function statusRecurringOrderTestDataProvider(): array + { + return [ 'recurring_order_status' => [ 'responseData' => [ 'ErrMsg' => 'Record(s) found for 22303O8EA19252', diff --git a/tests/Unit/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapperTest.php index 3d5d8ae0..5f1154b4 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/GarantiPosResponseDataMapperTest.php @@ -6,6 +6,9 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\GarantiPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\RequestValueMapperFactory; use Mews\Pos\Factory\ResponseValueFormatterFactory; @@ -27,19 +30,24 @@ class GarantiPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(GarantiPos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(GarantiPos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(GarantiPos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new GarantiPosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -78,9 +86,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['Transaction']['ProvDate'] ?? 'now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -97,14 +110,43 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($paymentResponse['Transaction']['ProvDate'] ?? 'now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($threeDResponseData['txntype']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($threeDResponseData['secure3dsecuritylevel'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['txnamount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['txncurrencycode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($threeDResponseData['txninstallmentcount'], $txType) + ->willReturn($expectedData['installment_count']); + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -132,14 +174,39 @@ public function testMap3DHostResponseData(): void */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['txntype']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['secure3dsecuritylevel'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['txnamount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['txncurrencycode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['txninstallmentcount'], $txType) + ->willReturn($expectedData['installment_count']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -156,15 +223,77 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['Order']['OrderInqResult']['InstallmentCnt'], $txType) + ->willReturn($expectedData['installment_count']); + + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['Order']['OrderInqResult']['Status']) + ->willReturn($expectedData['order_status']); + + $amountMatcher = $this->atLeastOnce(); + + $this->responseValueFormatter->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $responseData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $responseData['Order']['OrderInqResult']['AuthAmount']; + } + if ($amountMatcher->getInvocationCount() === 2) { + if ($responseData['Order']['OrderInqResult']['AuthAmount'] > 0) { + return $amount === $responseData['Order']['OrderInqResult']['AuthAmount']; + } + + return $amount === $responseData['Order']['OrderInqResult']['PreAuthAmount']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($amountMatcher, $expectedData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $expectedData['capture_amount']; + } + if ($amountMatcher->getInvocationCount() === 2) { + return $expectedData['first_amount']; + } + + return false; + } + ); + + $dateTimeMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($dateTimeMatcher) + ->method('formatDateTime') + ->with($this->callback(function ($dateTime) use ($dateTimeMatcher, $responseData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $dateTime === ($responseData['Order']['OrderInqResult']['ProvDate'] ?? $responseData['Order']['OrderInqResult']['PreAuthDate']); + } + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $dateTime === $responseData['Order']['OrderInqResult']['AuthDate']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($dateTimeMatcher, $expectedData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $expectedData['transaction_time']; + } + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $expectedData['capture_time']; + } + + return false; + } + ); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -177,11 +306,19 @@ public function testMapStatusResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryTestDataProvider */ public function testOrderMapHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(GarantiPos::class); + $responseDataMapper = new GarantiPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(GarantiPos::class), + ResponseValueMapperFactory::createForGateway(GarantiPos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] && null !== $actualData['transactions'][1]['transaction_time'] @@ -216,7 +353,14 @@ public function testOrderMapHistoryResponse(array $responseData, array $expected */ public function testMapHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(GarantiPos::class); + $responseDataMapper = new GarantiPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(GarantiPos::class), + ResponseValueMapperFactory::createForGateway(GarantiPos::class, $requestValueMapper), + $this->logger + ); + + $actualData = $responseDataMapper->mapHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] diff --git a/tests/Unit/DataMapper/ResponseDataMapper/InterPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/InterPosResponseDataMapperTest.php index b56911ee..09f63d43 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/InterPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/InterPosResponseDataMapperTest.php @@ -6,11 +6,9 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\InterPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; -use Mews\Pos\Factory\RequestValueMapperFactory; -use Mews\Pos\Factory\ResponseValueFormatterFactory; -use Mews\Pos\Factory\ResponseValueMapperFactory; -use Mews\Pos\Gateways\InterPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -27,19 +25,24 @@ class InterPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(InterPos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(InterPos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(InterPos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new InterPosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -78,9 +81,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TRXDATE'] ?? 'now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $responseData) { @@ -99,19 +107,29 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($paymentResponse['TRXDATE'] ?? $threeDResponseData['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -134,6 +152,23 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); @@ -151,6 +186,24 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TRXDATE'], $txType) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); @@ -168,15 +221,22 @@ public function testMap3DHostResponseData(array $order, string $txType, array $r */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['VoidDate'], $txType) + ->willReturn($expectedData['cancel_time']); + } + + if ($responseData['RefundedAmount'] > 0) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['RefundedAmount'], $txType) + ->willReturn($expectedData['refund_amount']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); diff --git a/tests/Unit/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapperTest.php index e77c493c..0f205a5c 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapperTest.php @@ -6,11 +6,10 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\KuveytPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; -use Mews\Pos\Factory\RequestValueMapperFactory; -use Mews\Pos\Factory\ResponseValueFormatterFactory; -use Mews\Pos\Factory\ResponseValueMapperFactory; -use Mews\Pos\Gateways\KuveytPos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -27,19 +26,24 @@ class KuveytPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(KuveytPos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(KuveytPos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(KuveytPos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new KuveytPosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -74,14 +78,32 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($responseData['VPosMessage'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['VPosMessage']['Amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['VPosMessage']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['VPosMessage']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); + } } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); + if ([] !== $responseData) { $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -99,6 +121,16 @@ public function testMapPaymentResponse(string $txType, array $responseData, arra */ public function testMapRefundResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_REFUND; + $drawbackResult = $responseData['PartialDrawbackResult'] ?? $responseData['DrawBackResult']; + + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($drawbackResult['Value']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->mapRefundResponse($responseData); $this->assertArrayHasKey('all', $actualData); @@ -116,6 +148,14 @@ public function testMapRefundResponse(array $responseData, array $expectedData): */ public function testMapCancelResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_CANCEL; + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['SaleReversalResult']['Value']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->mapCancelResponse($responseData); $this->assertArrayHasKey('all', $actualData); @@ -133,15 +173,57 @@ public function testMapCancelResponse(array $responseData, array $expectedData): */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $txType = PosInterface::TX_TYPE_STATUS; + $orderContract = $responseData['GetMerchantOrderDetailResult']['Value']['OrderContract']; + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($orderContract['LastOrderStatus']) + ->willReturn($expectedData['order_status']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($orderContract['FEC'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($orderContract['FirstAmount'], $txType) + ->willReturn($expectedData['first_amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($orderContract['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $dateTimeMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($dateTimeMatcher) + ->method('formatDateTime') + ->with($this->callback(function ($dateTime) use ($dateTimeMatcher, $orderContract) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $dateTime === $orderContract['OrderDate']; + } + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $dateTime === $orderContract['UpdateSystemDate']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($dateTimeMatcher, $expectedData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $expectedData['transaction_time']; + } + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $expectedData['capture_time'] ?? $expectedData['cancel_time'] ?? $expectedData['refund_time']; + } + + return false; + } + ); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -158,19 +240,78 @@ public function testMapStatusResponse(array $responseData, array $expectedData): */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if (isset($threeDResponseData['VPosMessage']['TransactionType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($threeDResponseData['VPosMessage']['TransactionType']) + ->willReturn($expectedData['transaction_type']); + } + + if ($threeDResponseData['ResponseCode'] === '00') { + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($threeDResponseData['VPosMessage']['TransactionSecurity'], $txType) + ->willReturn($expectedData['payment_model']); + + $amountMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $threeDResponseData, $paymentResponse) { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $threeDResponseData['VPosMessage']['Amount']; + } + if ($amountMatcher->getInvocationCount() === 2) { + return $amount === $paymentResponse['VPosMessage']['Amount']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($expectedData) { + return $expectedData['amount']; + } + ); + + $currencyMatcher = $this->atLeastOnce(); + $this->responseValueMapper->expects($currencyMatcher) + ->method('mapCurrency') + ->with($this->callback(function ($amount) use ($currencyMatcher, $threeDResponseData, $paymentResponse) { + if ($currencyMatcher->getInvocationCount() === 1) { + return $amount === $threeDResponseData['VPosMessage']['CurrencyCode']; + } + if ($currencyMatcher->getInvocationCount() === 2) { + return $amount === $paymentResponse['VPosMessage']['CurrencyCode']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($expectedData) { + return $expectedData['currency']; + } + ); + + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($paymentResponse['VPosMessage']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + } + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapperTest.php index a37eedf1..d7a94f60 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PayFlexCPV4PosResponseDataMapperTest.php @@ -7,10 +7,9 @@ use Generator; use Mews\Pos\DataMapper\ResponseDataMapper\PayFlexCPV4PosResponseDataMapper; -use Mews\Pos\Factory\RequestValueMapperFactory; -use Mews\Pos\Factory\ResponseValueFormatterFactory; -use Mews\Pos\Factory\ResponseValueMapperFactory; -use Mews\Pos\Gateways\PayFlexCPV4Pos; +use Mews\Pos\DataMapper\ResponseDataMapper\ResponseDataMapperInterface; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -27,20 +26,24 @@ class PayFlexCPV4PosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(PayFlexCPV4Pos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(PayFlexCPV4Pos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(PayFlexCPV4Pos::class); - + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new PayFlexCPV4PosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -74,9 +77,35 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMap3DPayResponseData(array $order, string $txType, array $bankResponse, array $expectedData): void { + if ($expectedData['status'] === ResponseDataMapperInterface::TX_APPROVED) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($bankResponse['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($bankResponse['HostDate'], $txType) + ->willReturn($expectedData['transaction_time']); + } + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($bankResponse['Amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($bankResponse['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($bankResponse['AmountCode'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->map3DPayResponseData($bankResponse, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapperTest.php index 4b77cdf3..dd3fa517 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PayFlexV4PosResponseDataMapperTest.php @@ -6,11 +6,9 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PayFlexV4PosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; -use Mews\Pos\Factory\RequestValueMapperFactory; -use Mews\Pos\Factory\ResponseValueFormatterFactory; -use Mews\Pos\Factory\ResponseValueMapperFactory; -use Mews\Pos\Gateways\PayFlexV4Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -27,19 +25,24 @@ class PayFlexV4PosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(PayFlexV4Pos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(PayFlexV4Pos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(PayFlexV4Pos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new PayFlexV4PosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -75,14 +78,55 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if (isset($paymentResponse['TLAmount'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($paymentResponse['TLAmount'], $txType) + ->willReturn($expectedData['amount']); + } + + if (isset($paymentResponse['TransactionType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($paymentResponse['TransactionType']) + ->willReturn($expectedData['transaction_type']); + } + + if (isset($paymentResponse['ThreeDSecureType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($paymentResponse['ThreeDSecureType']) + ->willReturn($expectedData['payment_model']); + } + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with( + strlen($paymentResponse['HostDate']) === 10 + ? date('Y').$paymentResponse['HostDate'] + : $paymentResponse['HostDate'], + $txType + ) + ->willReturn($expectedData['transaction_time']); + } + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($threeDResponseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($paymentResponse['CurrencyCode'] ?? $threeDResponseData['PurchCurrency'], $txType) + ->willReturn($expectedData['currency']); + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -104,9 +148,47 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMapPaymentResponse(string $txType, array $responseData, array $expectedData): void { + if (isset($responseData['TLAmount'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['TLAmount'], $txType) + ->willReturn($expectedData['amount']); + } + + if (isset($responseData['TransactionType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TransactionType']) + ->willReturn($expectedData['transaction_type']); + } + + if (isset($responseData['ThreeDSecureType'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['ThreeDSecureType']) + ->willReturn($expectedData['payment_model']); + } + + if ($expectedData['transaction_time'] instanceof \DateTimeImmutable) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with( + strlen($responseData['HostDate']) === 10 + ? date('Y').$responseData['HostDate'] + : $responseData['HostDate'], + $txType + ) + ->willReturn($expectedData['transaction_time']); + } + + if (isset($responseData['CurrencyCode'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -153,6 +235,25 @@ public function testMapRefundResponse(array $paymentResponse, array $expectedDat */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $txResultInfo = $responseData['TransactionSearchResultInfo']['TransactionSearchResultInfo']; + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($txResultInfo['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($txResultInfo['AmountCode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($txResultInfo['CurrencyAmount'] ?? $txResultInfo['Amount'], $txType) + ->willReturn($expectedData['first_amount']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); $this->assertArrayHasKey('all', $actualData); diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PayForPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PayForPosResponseDataMapperTest.php index bf3c7726..3a5e7c8b 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PayForPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PayForPosResponseDataMapperTest.php @@ -6,6 +6,8 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PayForPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Factory\RequestValueMapperFactory; use Mews\Pos\Factory\ResponseValueFormatterFactory; use Mews\Pos\Factory\ResponseValueMapperFactory; @@ -26,18 +28,24 @@ class PayForPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); + $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(PayForPos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(PayForPos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(PayForPos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new PayForPosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -76,15 +84,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -101,14 +108,44 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($threeDResponseData['TxnType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($threeDResponseData['SecureType'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($threeDResponseData['TransactionDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($threeDResponseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -130,9 +167,39 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TxnType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['SecureType'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TransactionDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -149,9 +216,39 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TxnType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapSecureType') + ->with($responseData['SecureType'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['TransactionDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -168,15 +265,56 @@ public function testMap3DHostResponseData(array $order, string $txType, array $r */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TxnType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['PurchAmount'], $txType) + ->willReturn($expectedData['first_amount']); + + $dateTimeMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($dateTimeMatcher) + ->method('formatDateTime') + ->with($this->callback(function ($dateTime) use ($dateTimeMatcher, $responseData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $dateTime === $responseData['InsertDatetime']; + } + if ($responseData['VoidDate'] > 0) { + return $dateTime === $responseData['VoidDate'].'T'.$responseData['VoidTime']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($dateTimeMatcher, $expectedData) { + if ($dateTimeMatcher->getInvocationCount() === 1) { + return $expectedData['transaction_time']; + } + if ($dateTimeMatcher->getInvocationCount() === 2) { + return $expectedData['cancel_time']; + } + + return false; + } + ); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -189,11 +327,18 @@ public function testMapStatusResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryTestDataProvider */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(PayForPos::class); + $responseDataMapper = new PayForPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(PayForPos::class), + ResponseValueMapperFactory::createForGateway(PayForPos::class, $requestValueMapper), + $this->logger + ); + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] @@ -229,7 +374,13 @@ public function testMapOrderHistoryResponse(array $responseData, array $expected */ public function testMapHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(PayForPos::class); + $responseDataMapper = new PayForPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(PayForPos::class), + ResponseValueMapperFactory::createForGateway(PayForPos::class, $requestValueMapper), + $this->logger + ); + $actualData = $responseDataMapper->mapHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] @@ -1485,914 +1636,924 @@ public static function threeDHostPaymentDataProvider(): array } - public static function statusTestDataProvider(): array + public static function statusTestDataProvider(): iterable { - return [ - 'success1' => [ - 'responseData' => [ - 'RequestGuid' => '1000000081265961', - 'InsertDatetime' => '31.10.2022 23:13:21', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202210312A24', - 'RequestIp' => '89.244.149.137', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'Auth', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'tr', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'Y', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S90370', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4320', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '26786247', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20221031', - 'SysDate' => '20221031', - 'F11' => '101605', - 'F37' => '230423101605', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '16', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '5', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '89.244.149.137', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'false', - 'IsRefunded' => 'false', - 'TrxDate' => '31.10.2022 23:13', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S90370', - 'order_id' => '202210312A24', - 'org_order_id' => null, - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => 'PAYMENT_COMPLETED', - 'transaction_type' => 'pay', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => true, - 'capture_time' => new \DateTimeImmutable('31.10.2022 23:13:21'), - 'capture_amount' => 1.01, - 'first_amount' => 1.01, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('31.10.2022 23:13:21'), - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 0, - ], + $success1CaptureTime = new \DateTimeImmutable('31.10.2022 23:13:21'); + + yield 'success1' => [ + 'responseData' => [ + 'RequestGuid' => '1000000081265961', + 'InsertDatetime' => '31.10.2022 23:13:21', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202210312A24', + 'RequestIp' => '89.244.149.137', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'Auth', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'tr', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'Y', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S90370', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4320', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '26786247', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20221031', + 'SysDate' => '20221031', + 'F11' => '101605', + 'F37' => '230423101605', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '16', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '5', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '89.244.149.137', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'false', + 'IsRefunded' => 'false', + 'TrxDate' => '31.10.2022 23:13', + 'ReturnMessage' => 'Onaylandı', ], - 'success_pre_pay' => [ - 'responseData' => [ - 'RequestGuid' => '1000000094948181', - 'InsertDatetime' => '19.01.2024 22:07:49', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202401191C51', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '2.01', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'PreAuth', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'BonusAmount' => '', - 'InstallmentCount' => '3', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'Y', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S18386', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4005', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '99712092', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20240119', - 'SysDate' => '20240119', - 'F11' => '27445', - 'F37' => '401922027445', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '16', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '2', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', - 'AuthId' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'false', - 'IsRefunded' => 'false', - 'TrxDate' => '19.01.2024 22:07', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S18386', - 'order_id' => '202401191C51', - 'org_order_id' => null, - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => null, - 'transaction_type' => 'pre', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => false, - 'capture_time' => null, - 'capture_amount' => null, - 'first_amount' => 2.01, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('19.01.2024 22:07:49'), - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 3, - ], + 'expectedData' => [ + 'auth_code' => 'S90370', + 'order_id' => '202210312A24', + 'org_order_id' => null, + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => 'PAYMENT_COMPLETED', + 'transaction_type' => 'pay', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => true, + 'capture_time' => $success1CaptureTime, + 'capture_amount' => 1.01, + 'first_amount' => 1.01, + 'transaction_id' => null, + 'transaction_time' => $success1CaptureTime, + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 0, ], - 'success_pre_pay_and_post_pay' => [ - 'responseData' => [ - 'RequestGuid' => '1000000094938529', - 'InsertDatetime' => '19.01.2024 22:13:39', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '2024011926F1', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '2.03', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'PostAuth', - 'OrgOrderId' => '2024011926F1', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'BonusAmount' => '', - 'InstallmentCount' => '3', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => '', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'Y', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S89375', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4005', - 'VoidDate' => '', - 'CardMask' => '415565******6111', - 'ReqId' => '99712640', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20240119', - 'SysDate' => '20240119', - 'F11' => '27995', - 'F37' => '401922027995', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '16', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '3', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '27994', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', - 'AuthId' => '', - 'CardAcceptorName' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'false', - 'IsRefunded' => 'false', - 'TrxDate' => '19.01.2024 22:13', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S89375', - 'order_id' => '2024011926F1', - 'org_order_id' => '2024011926F1', - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => 'PAYMENT_COMPLETED', - 'transaction_type' => 'post', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => true, - 'capture_time' => new \DateTimeImmutable('19.01.2024 22:13:39'), - 'capture_amount' => 2.03, - 'first_amount' => 2.03, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('19.01.2024 22:13:39'), - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 3, - ], + ]; + + yield 'success_pre_pay' => [ + 'responseData' => [ + 'RequestGuid' => '1000000094948181', + 'InsertDatetime' => '19.01.2024 22:07:49', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202401191C51', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '2.01', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'PreAuth', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'BonusAmount' => '', + 'InstallmentCount' => '3', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'Y', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S18386', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4005', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '99712092', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20240119', + 'SysDate' => '20240119', + 'F11' => '27445', + 'F37' => '401922027445', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '16', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '2', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', + 'AuthId' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'false', + 'IsRefunded' => 'false', + 'TrxDate' => '19.01.2024 22:07', + 'ReturnMessage' => 'Onaylandı', ], - 'success_pay_then_cancel' => [ - 'responseData' => [ - 'RequestGuid' => '1000000094947969', - 'InsertDatetime' => '19.01.2024 21:34:05', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202401194815', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'Auth', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'V', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S29682', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4005', - 'VoidDate' => '20240119', - 'CardMask' => '415565******6111', - 'ReqId' => '99709025', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20240119', - 'SysDate' => '20240119', - 'F11' => '24380', - 'F37' => '401921024380', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '15', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '2', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '213405', - 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', - 'AuthId' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'true', - 'IsRefunded' => 'false', - 'TrxDate' => '19.01.2024 21:34', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S29682', - 'order_id' => '202401194815', - 'org_order_id' => null, - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => 'CANCELED', - 'transaction_type' => 'pay', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => true, - 'capture_time' => new \DateTimeImmutable('19.01.2024 21:34:05'), - 'capture_amount' => 1.01, - 'first_amount' => 1.01, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('19.01.2024 21:34:05'), - 'cancel_time' => new \DateTimeImmutable('20240119T213405'), - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 0, - ], + 'expectedData' => [ + 'auth_code' => 'S18386', + 'order_id' => '202401191C51', + 'org_order_id' => null, + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => null, + 'transaction_type' => 'pre', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => false, + 'capture_time' => null, + 'capture_amount' => null, + 'first_amount' => 2.01, + 'transaction_id' => null, + 'transaction_time' => new \DateTimeImmutable('19.01.2024 22:07:49'), + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 3, ], - 'success_pre_pay_then_cancel' => [ - 'responseData' => [ - 'RequestGuid' => '1000000094947988', - 'InsertDatetime' => '19.01.2024 21:47:43', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202401197C78', - 'RequestIp' => '88.152.8.2', - 'RequestStat' => '1,10', - 'SecureType' => 'NonSecure', - 'PurchAmount' => '1.01', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'PreAuth', - 'OrgOrderId' => '', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => 'V', - 'Lang' => 'TR', - 'BonusAmount' => '', - 'InstallmentCount' => '3', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => 'John Doe', - 'IrcDet' => '', - 'IrcCode' => '', - 'Version' => '', - 'TxnStatus' => 'V', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Onaylandı', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => 'Success', - 'AuthCode' => 'S54087', - 'HostRefNum' => '', - 'ProcReturnCode' => '00', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4005', - 'VoidDate' => '20240119', - 'CardMask' => '415565******6111', - 'ReqId' => '99710256', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '20240119', - 'SysDate' => '20240119', - 'F11' => '25609', - 'F37' => '401921025609', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '15', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '2', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'False', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '88.152.8.2', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '214744', - 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'ArtiTaksit' => '0', - 'AuthId' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'IsVoided' => 'true', - 'IsRefunded' => 'false', - 'TrxDate' => '19.01.2024 21:47', - 'ReturnMessage' => 'Onaylandı', - ], - 'expectedData' => [ - 'auth_code' => 'S54087', - 'order_id' => '202401197C78', - 'org_order_id' => null, - 'proc_return_code' => '00', - 'error_message' => null, - 'error_code' => null, - 'ref_ret_num' => null, - 'order_status' => 'CANCELED', - 'transaction_type' => 'pre', - 'masked_number' => '415565******6111', - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'approved', - 'status_detail' => 'approved', - 'capture' => false, - 'capture_time' => null, - 'capture_amount' => null, - 'first_amount' => 1.01, - 'transaction_id' => null, - 'transaction_time' => new \DateTimeImmutable('19.01.2024 21:47:43'), - 'cancel_time' => new \DateTimeImmutable('20240119T214744'), - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 3, - ], + ]; + + $successPrePayAndPostDateTime = new \DateTimeImmutable('19.01.2024 22:13:39'); + yield 'success_pre_pay_and_post_pay' => [ + 'responseData' => [ + 'RequestGuid' => '1000000094938529', + 'InsertDatetime' => '19.01.2024 22:13:39', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '2024011926F1', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '2.03', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'PostAuth', + 'OrgOrderId' => '2024011926F1', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'BonusAmount' => '', + 'InstallmentCount' => '3', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => '', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'Y', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S89375', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4005', + 'VoidDate' => '', + 'CardMask' => '415565******6111', + 'ReqId' => '99712640', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20240119', + 'SysDate' => '20240119', + 'F11' => '27995', + 'F37' => '401922027995', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '16', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '3', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '27994', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', + 'AuthId' => '', + 'CardAcceptorName' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'false', + 'IsRefunded' => 'false', + 'TrxDate' => '19.01.2024 22:13', + 'ReturnMessage' => 'Onaylandı', ], - 'fail_order_not_found' => [ - 'responseData' => [ - 'RequestGuid' => '0', - 'InsertDatetime' => '1.01.0001 00:00:00', - 'MbrId' => '5', - 'MerchantID' => '085300000009704', - 'OrderId' => '202210312A242', - 'RequestIp' => '89.244.149.137', - 'RequestStat' => '1,10', - 'SecureType' => 'Inquiry', - 'PurchAmount' => '', - 'Exponent' => '2', - 'Currency' => '949', - 'Description' => '', - 'OkUrl' => '', - 'FailUrl' => '', - 'PayerTxnId' => '', - 'PayerAuthenticationCode' => '', - 'Eci' => '', - 'MD' => '', - 'Hash' => '', - 'TerminalID' => 'VS010481', - 'TxnType' => 'OrderInquiry', - 'OrgOrderId' => '202210312A242', - 'SubMerchantCode' => '', - 'recur_frequency' => '', - 'recur_expiry' => '', - 'CardType' => '', - 'Lang' => 'tr', - 'BonusAmount' => '', - 'InstallmentCount' => '0', - 'Rnd' => '', - 'AlphaCode' => 'TL', - 'Ecommerce' => '1', - 'MrcCountryCode' => '792', - 'MrcName' => '3D PAY TEST ISYERI', - 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', - 'CardHolderName' => '', - 'IrcDet' => 'Seçili İşlem Bulunamadı!', - 'IrcCode' => '99961', - 'Version' => '', - 'TxnStatus' => 'P', - 'CavvAlg' => '', - 'ParesVerified' => '', - 'ParesSyntaxOk' => '', - 'ErrMsg' => 'Seçili İşlem Bulunamadı!', - 'VendorDet' => '', - 'D3Status' => '-1', - 'TxnResult' => '', - 'AuthCode' => '', - 'HostRefNum' => '', - 'ProcReturnCode' => 'V013', - 'ReturnUrl' => '', - 'ErrorData' => '', - 'BatchNo' => '4320', - 'VoidDate' => '', - 'CardMask' => '', - 'ReqId' => '26786448', - 'UsedPoint' => '0', - 'SrcType' => 'VPO', - 'RefundedAmount' => '0', - 'RefundedPoint' => '0', - 'ReqDate' => '0', - 'SysDate' => '0', - 'F11' => '101906', - 'F37' => '', - 'IsRepeatTxn' => '', - 'CavvResult' => '', - 'VposElapsedTime' => '0', - 'BankingElapsedTime' => '0', - 'SocketElapsedTime' => '0', - 'HsmElapsedTime' => '0', - 'MpiElapsedTime' => '0', - 'hasOrderId' => 'True', - 'TemplateType' => '0', - 'HasAddressCount' => 'False', - 'IsPaymentFacilitator' => 'False', - 'MerchantCountryCode' => '', - 'OrgTxnType' => '', - 'F11_ORG' => '0', - 'F12_ORG' => '0', - 'F13_ORG' => '', - 'F22_ORG' => '0', - 'F25_ORG' => '0', - 'MTI_ORG' => '0', - 'DsBrand' => '', - 'IntervalType' => '0', - 'IntervalDuration' => '0', - 'RepeatCount' => '0', - 'CustomerCode' => '', - 'RequestMerchantDomain' => '', - 'RequestClientIp' => '89.244.149.137', - 'ResponseRnd' => '', - 'ResponseHash' => '', - 'BankInternalResponseCode' => '', - 'BankInternalResponseMessage' => '', - 'BankInternalResponseSubcode' => '', - 'BankInternalResponseSubmessage' => '', - 'BayiKodu' => '', - 'VoidTime' => '0', - 'VoidUserCode' => '', - 'PaymentLinkId' => '0', - 'ClientId' => '', - 'IsQRValid' => '', - 'IsFastValid' => '', - 'IsQR' => '', - 'IsFast' => '', - 'QRRefNo' => '', - 'FASTGonderenKatilimciKodu' => '', - 'FASTAlanKatilimciKodu' => '', - 'FASTReferansNo' => '', - 'FastGonderenIBAN' => '', - 'FASTGonderenAdi' => '', - 'MobileECI' => '', - 'HubConnId' => '', - 'WalletData' => '', - 'Tds2dsTransId' => '', - 'Is3DHost' => '', - 'PAYFORFROMXMLREQUEST' => '1', - 'SESSION_SYSTEM_USER' => '0', - ], - 'expectedData' => [ - 'auth_code' => null, - 'order_id' => '202210312A242', - 'org_order_id' => '202210312A242', - 'proc_return_code' => 'V013', - 'error_message' => 'Seçili İşlem Bulunamadı!', - 'ref_ret_num' => null, - 'order_status' => null, - 'transaction_type' => 'status', - 'masked_number' => null, - 'currency' => PosInterface::CURRENCY_TRY, - 'status' => 'declined', - 'status_detail' => 'reject', - 'transaction_time' => null, - 'transaction_id' => null, - 'capture_time' => null, - 'capture' => null, - 'capture_amount' => null, - 'error_code' => null, - 'first_amount' => null, - 'cancel_time' => null, - 'refund_amount' => null, - 'refund_time' => null, - 'installment_count' => 0, - ], + 'expectedData' => [ + 'auth_code' => 'S89375', + 'order_id' => '2024011926F1', + 'org_order_id' => '2024011926F1', + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => 'PAYMENT_COMPLETED', + 'transaction_type' => 'post', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => true, + 'capture_time' => $successPrePayAndPostDateTime, + 'capture_amount' => 2.03, + 'first_amount' => 2.03, + 'transaction_id' => null, + 'transaction_time' => $successPrePayAndPostDateTime, + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 3, + ], + ]; + + $successPayThenCancelDateTime = new \DateTimeImmutable('19.01.2024 21:34:05'); + $successPayThenCancelCancelDateTime = new \DateTimeImmutable('20240119T213405'); + + yield 'success_pay_then_cancel' => [ + 'responseData' => [ + 'RequestGuid' => '1000000094947969', + 'InsertDatetime' => '19.01.2024 21:34:05', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202401194815', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'Auth', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'V', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S29682', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4005', + 'VoidDate' => '20240119', + 'CardMask' => '415565******6111', + 'ReqId' => '99709025', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20240119', + 'SysDate' => '20240119', + 'F11' => '24380', + 'F37' => '401921024380', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '15', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '2', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '213405', + 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', + 'AuthId' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'true', + 'IsRefunded' => 'false', + 'TrxDate' => '19.01.2024 21:34', + 'ReturnMessage' => 'Onaylandı', + ], + 'expectedData' => [ + 'auth_code' => 'S29682', + 'order_id' => '202401194815', + 'org_order_id' => null, + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => 'CANCELED', + 'transaction_type' => 'pay', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => true, + 'capture_time' => $successPayThenCancelDateTime, + 'capture_amount' => 1.01, + 'first_amount' => 1.01, + 'transaction_id' => null, + 'transaction_time' => $successPayThenCancelDateTime, + 'cancel_time' => $successPayThenCancelCancelDateTime, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 0, + ], + ]; + + yield 'success_pre_pay_then_cancel' => [ + 'responseData' => [ + 'RequestGuid' => '1000000094947988', + 'InsertDatetime' => '19.01.2024 21:47:43', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202401197C78', + 'RequestIp' => '88.152.8.2', + 'RequestStat' => '1,10', + 'SecureType' => 'NonSecure', + 'PurchAmount' => '1.01', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'PreAuth', + 'OrgOrderId' => '', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => 'V', + 'Lang' => 'TR', + 'BonusAmount' => '', + 'InstallmentCount' => '3', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => 'John Doe', + 'IrcDet' => '', + 'IrcCode' => '', + 'Version' => '', + 'TxnStatus' => 'V', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Onaylandı', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => 'Success', + 'AuthCode' => 'S54087', + 'HostRefNum' => '', + 'ProcReturnCode' => '00', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4005', + 'VoidDate' => '20240119', + 'CardMask' => '415565******6111', + 'ReqId' => '99710256', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '20240119', + 'SysDate' => '20240119', + 'F11' => '25609', + 'F37' => '401921025609', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '15', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '2', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'False', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '88.152.8.2', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '214744', + 'VoidUserCode' => 'QNB_API_KULLANICI_3DPAY', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'ArtiTaksit' => '0', + 'AuthId' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'IsVoided' => 'true', + 'IsRefunded' => 'false', + 'TrxDate' => '19.01.2024 21:47', + 'ReturnMessage' => 'Onaylandı', + ], + 'expectedData' => [ + 'auth_code' => 'S54087', + 'order_id' => '202401197C78', + 'org_order_id' => null, + 'proc_return_code' => '00', + 'error_message' => null, + 'error_code' => null, + 'ref_ret_num' => null, + 'order_status' => 'CANCELED', + 'transaction_type' => 'pre', + 'masked_number' => '415565******6111', + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'approved', + 'status_detail' => 'approved', + 'capture' => false, + 'capture_time' => null, + 'capture_amount' => null, + 'first_amount' => 1.01, + 'transaction_id' => null, + 'transaction_time' => new \DateTimeImmutable('19.01.2024 21:47:43'), + 'cancel_time' => new \DateTimeImmutable('20240119T214744'), + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 3, + ], + ]; + + + yield 'fail_order_not_found' => [ + 'responseData' => [ + 'RequestGuid' => '0', + 'InsertDatetime' => '1.01.0001 00:00:00', + 'MbrId' => '5', + 'MerchantID' => '085300000009704', + 'OrderId' => '202210312A242', + 'RequestIp' => '89.244.149.137', + 'RequestStat' => '1,10', + 'SecureType' => 'Inquiry', + 'PurchAmount' => '', + 'Exponent' => '2', + 'Currency' => '949', + 'Description' => '', + 'OkUrl' => '', + 'FailUrl' => '', + 'PayerTxnId' => '', + 'PayerAuthenticationCode' => '', + 'Eci' => '', + 'MD' => '', + 'Hash' => '', + 'TerminalID' => 'VS010481', + 'TxnType' => 'OrderInquiry', + 'OrgOrderId' => '202210312A242', + 'SubMerchantCode' => '', + 'recur_frequency' => '', + 'recur_expiry' => '', + 'CardType' => '', + 'Lang' => 'tr', + 'BonusAmount' => '', + 'InstallmentCount' => '0', + 'Rnd' => '', + 'AlphaCode' => 'TL', + 'Ecommerce' => '1', + 'MrcCountryCode' => '792', + 'MrcName' => '3D PAY TEST ISYERI', + 'MerchantHomeUrl' => 'https://vpostest.qnbfinansbank.com/', + 'CardHolderName' => '', + 'IrcDet' => 'Seçili İşlem Bulunamadı!', + 'IrcCode' => '99961', + 'Version' => '', + 'TxnStatus' => 'P', + 'CavvAlg' => '', + 'ParesVerified' => '', + 'ParesSyntaxOk' => '', + 'ErrMsg' => 'Seçili İşlem Bulunamadı!', + 'VendorDet' => '', + 'D3Status' => '-1', + 'TxnResult' => '', + 'AuthCode' => '', + 'HostRefNum' => '', + 'ProcReturnCode' => 'V013', + 'ReturnUrl' => '', + 'ErrorData' => '', + 'BatchNo' => '4320', + 'VoidDate' => '', + 'CardMask' => '', + 'ReqId' => '26786448', + 'UsedPoint' => '0', + 'SrcType' => 'VPO', + 'RefundedAmount' => '0', + 'RefundedPoint' => '0', + 'ReqDate' => '0', + 'SysDate' => '0', + 'F11' => '101906', + 'F37' => '', + 'IsRepeatTxn' => '', + 'CavvResult' => '', + 'VposElapsedTime' => '0', + 'BankingElapsedTime' => '0', + 'SocketElapsedTime' => '0', + 'HsmElapsedTime' => '0', + 'MpiElapsedTime' => '0', + 'hasOrderId' => 'True', + 'TemplateType' => '0', + 'HasAddressCount' => 'False', + 'IsPaymentFacilitator' => 'False', + 'MerchantCountryCode' => '', + 'OrgTxnType' => '', + 'F11_ORG' => '0', + 'F12_ORG' => '0', + 'F13_ORG' => '', + 'F22_ORG' => '0', + 'F25_ORG' => '0', + 'MTI_ORG' => '0', + 'DsBrand' => '', + 'IntervalType' => '0', + 'IntervalDuration' => '0', + 'RepeatCount' => '0', + 'CustomerCode' => '', + 'RequestMerchantDomain' => '', + 'RequestClientIp' => '89.244.149.137', + 'ResponseRnd' => '', + 'ResponseHash' => '', + 'BankInternalResponseCode' => '', + 'BankInternalResponseMessage' => '', + 'BankInternalResponseSubcode' => '', + 'BankInternalResponseSubmessage' => '', + 'BayiKodu' => '', + 'VoidTime' => '0', + 'VoidUserCode' => '', + 'PaymentLinkId' => '0', + 'ClientId' => '', + 'IsQRValid' => '', + 'IsFastValid' => '', + 'IsQR' => '', + 'IsFast' => '', + 'QRRefNo' => '', + 'FASTGonderenKatilimciKodu' => '', + 'FASTAlanKatilimciKodu' => '', + 'FASTReferansNo' => '', + 'FastGonderenIBAN' => '', + 'FASTGonderenAdi' => '', + 'MobileECI' => '', + 'HubConnId' => '', + 'WalletData' => '', + 'Tds2dsTransId' => '', + 'Is3DHost' => '', + 'PAYFORFROMXMLREQUEST' => '1', + 'SESSION_SYSTEM_USER' => '0', + ], + 'expectedData' => [ + 'auth_code' => null, + 'order_id' => '202210312A242', + 'org_order_id' => '202210312A242', + 'proc_return_code' => 'V013', + 'error_message' => 'Seçili İşlem Bulunamadı!', + 'ref_ret_num' => null, + 'order_status' => null, + 'transaction_type' => 'status', + 'masked_number' => null, + 'currency' => PosInterface::CURRENCY_TRY, + 'status' => 'declined', + 'status_detail' => 'reject', + 'transaction_time' => null, + 'transaction_id' => null, + 'capture_time' => null, + 'capture' => null, + 'capture_amount' => null, + 'error_code' => null, + 'first_amount' => null, + 'cancel_time' => null, + 'refund_amount' => null, + 'refund_time' => null, + 'installment_count' => 0, ], ]; } diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PosNetResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PosNetResponseDataMapperTest.php index 08e71496..cb7470f3 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PosNetResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PosNetResponseDataMapperTest.php @@ -6,11 +6,9 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PosNetResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; -use Mews\Pos\Factory\RequestValueMapperFactory; -use Mews\Pos\Factory\ResponseValueFormatterFactory; -use Mews\Pos\Factory\ResponseValueMapperFactory; -use Mews\Pos\Gateways\PosNet; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -27,18 +25,24 @@ class PosNetResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); + $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(PosNet::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(PosNet::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(PosNet::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new PosNetResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -76,20 +80,22 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); $this->assertNotEmpty($actualData['all']); unset($actualData['all']); + \ksort($actualData); + \ksort($expectedData); $this->assertSame($expectedData, $actualData); } @@ -98,19 +104,31 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if (isset($threeDResponseData['oosResolveMerchantDataResponse'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['oosResolveMerchantDataResponse']['amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['oosResolveMerchantDataResponse']['currency'], $txType) + ->willReturn($expectedData['currency']); + } + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -132,15 +150,30 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + if (isset($responseData['transactions']['transaction'])) { + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($responseData['transactions']['transaction']['amount'], $txType) + ->willReturn($expectedData['first_amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['transactions']['transaction']['currencyCode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['transactions']['transaction']['tranDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['transactions']['transaction']['state']) + ->willReturn($expectedData['transaction_type']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -157,6 +190,13 @@ public function testMapStatusResponse(array $responseData, array $expectedData): */ public function testMapRefundResponse(array $responseData, array $expectedData): void { + if (isset($responseData['state'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['state']) + ->willReturn($expectedData['transaction_type']); + } + $actualData = $this->responseDataMapper->mapRefundResponse($responseData); $this->assertArrayHasKey('all', $actualData); diff --git a/tests/Unit/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapperTest.php index 28ffadef..c6aaa1b0 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/PosNetV1PosResponseDataMapperTest.php @@ -6,11 +6,9 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\PosNetV1PosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; -use Mews\Pos\Factory\RequestValueMapperFactory; -use Mews\Pos\Factory\ResponseValueFormatterFactory; -use Mews\Pos\Factory\ResponseValueMapperFactory; -use Mews\Pos\Gateways\PosNetV1Pos; use Mews\Pos\PosInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -27,20 +25,24 @@ class PosNetV1PosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); - $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(PosNetV1Pos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(PosNetV1Pos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(PosNetV1Pos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new PosNetV1PosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -78,14 +80,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -102,19 +104,42 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($threeDResponseData['TranType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($threeDResponseData['Amount'], $txType) + ->willReturn($expectedData['amount']); + + if (isset($threeDResponseData['CurrencyCode'])) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($threeDResponseData['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatInstallment') + ->with($paymentResponse['InstallmentData']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + } + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); if ([] !== $paymentResponse) { $this->assertArrayHasKey('all', $actualData); @@ -136,16 +161,44 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMapStatusResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapStatusResponse($responseData); + $rawTx = null; + if (isset($responseData['TransactionData'])) { + foreach ($responseData['TransactionData'] as $item) { + if ('1' === $item['TransactionStatus']) { + $rawTx = $item; + break; + } + } + } + if (null !== $rawTx) { + $txType = PosInterface::TX_TYPE_STATUS; + $this->responseValueFormatter->expects($this->once()) + ->method('formatAmount') + ->with($rawTx['Amount'], $txType) + ->willReturn($expectedData['first_amount']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($rawTx['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($rawTx['TransactionDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($rawTx['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($expectedData['transaction_type']) + ->willReturn($expectedData['order_status']); + } - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -355,7 +408,7 @@ public static function threeDPaymentDataProvider(): \Generator 'order' => [ 'id' => '20230622A1C9', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'threeDResponseData' => [ 'CCPrefix' => '450634', 'TranType' => 'Sale', @@ -401,7 +454,7 @@ public static function threeDPaymentDataProvider(): \Generator 'order' => [ 'id' => '80603153823', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'threeDResponseData' => [ 'CCPrefix' => '540061', 'TranType' => 'Sale', @@ -521,7 +574,7 @@ public static function threeDPaymentDataProvider(): \Generator 'order' => [ 'id' => '80603153823', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'threeDResponseData' => [ 'CCPrefix' => '540061', 'TranType' => 'Sale', @@ -572,7 +625,7 @@ public static function threeDPaymentDataProvider(): \Generator 'order' => [ 'id' => '202306226A90', ], - 'txType' => PosInterface::TX_TYPE_PAY_PRE_AUTH, + 'txType' => PosInterface::TX_TYPE_PAY_AUTH, 'threeDResponseData' => [ 'CCPrefix' => '450634', 'TranType' => 'Sale', @@ -629,6 +682,8 @@ public static function threeDPaymentDataProvider(): \Generator public static function mapStatusResponseDataProvider(): iterable { + $txTime = new \DateTimeImmutable('2019-11-0813:58:37.909'); + yield 'success_refunded' => [ 'response' => [ 'ServiceResponseData' => [ @@ -671,7 +726,7 @@ public static function mapStatusResponseDataProvider(): iterable 'status_detail' => null, 'error_code' => null, 'error_message' => null, - 'transaction_time' => new \DateTimeImmutable('2019-11-0813:58:37.909'), + 'transaction_time' => $txTime, 'capture_time' => null, 'capture' => null, 'capture_amount' => null, @@ -681,7 +736,7 @@ public static function mapStatusResponseDataProvider(): iterable 'masked_number' => '540061******4581', 'cancel_time' => null, 'refund_amount' => null, - 'refund_time' => new \DateTimeImmutable('2019-11-0813:58:37.909'), + 'refund_time' => $txTime, 'installment_count' => null, ], ]; diff --git a/tests/Unit/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapperTest.php index d0e10ed7..bcf28aa4 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/ToslaPosResponseDataMapperTest.php @@ -6,6 +6,8 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\ToslaPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\RequestValueMapperFactory; use Mews\Pos\Factory\ResponseValueFormatterFactory; @@ -27,19 +29,24 @@ class ToslaPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatter; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); $this->logger = $this->createMock(LoggerInterface::class); - $requestValueMapper = RequestValueMapperFactory::createForGateway(ToslaPos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(ToslaPos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(ToslaPos::class); + $this->responseValueFormatter = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapper = $this->createMock(ResponseValueMapperInterface::class); $this->responseDataMapper = new ToslaPosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatter, + $this->responseValueMapper, $this->logger ); } @@ -77,14 +84,14 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -102,14 +109,19 @@ public function testMapPaymentResponse(array $order, string $txType, array $resp */ public function testMap3DPayResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['RequestStatus']) + ->willReturn($expectedData['tx_status']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DPayResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -126,14 +138,19 @@ public function testMap3DPayResponseData(array $order, string $txType, array $re */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['RequestStatus']) + ->willReturn($expectedData['tx_status']); + + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -150,18 +167,56 @@ public function testMap3DHostResponseData(array $order, string $txType, array $r */ public function testMapStatusResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - if (isset($responseData['CreateDate'])) { - $this->assertSame($actualData['transaction_time']->format('YmdHis'), $responseData['CreateDate']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); + $txType = PosInterface::TX_TYPE_STATUS; + + $this->responseValueMapper->expects($this->once()) + ->method('mapOrderStatus') + ->with($responseData['RequestStatus']) + ->willReturn($expectedData['order_status']); + + $this->responseValueMapper->expects($this->once()) + ->method('mapTxType') + ->with($responseData['TransactionType']) + ->willReturn($expectedData['transaction_type']); + + if ($responseData['Currency'] > 0) { + $this->responseValueMapper->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['Currency'], $txType) + ->willReturn($expectedData['currency']); + + $amountMatcher = $this->atLeastOnce(); + $this->responseValueFormatter->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $responseData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $responseData['Amount']; + } + if ($amountMatcher->getInvocationCount() === 2) { + return $amount === $responseData['RefundedAmount']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($amountMatcher, $expectedData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $expectedData['first_amount']; + } + if ($amountMatcher->getInvocationCount() === 2) { + return $expectedData['refund_amount']; + } + + return false; + } + ); + + $this->responseValueFormatter->expects($this->once()) + ->method('formatDateTime') + ->with($responseData['CreateDate'], $txType) + ->willReturn($expectedData['transaction_time']); } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -204,11 +259,18 @@ public function testMapCancelResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider orderHistoryDataProvider */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $requestValueMapper = RequestValueMapperFactory::createForGateway(ToslaPos::class); + $responseDataMapper = new ToslaPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(ToslaPos::class), + ResponseValueMapperFactory::createForGateway(ToslaPos::class, $requestValueMapper), + $this->logger + ); + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (isset($responseData['Transactions'])) { $this->assertCount($actualData['trans_count'], $actualData['transactions']); if (count($actualData['transactions']) > 1 diff --git a/tests/Unit/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapperTest.php b/tests/Unit/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapperTest.php index 42f95105..c4045a81 100644 --- a/tests/Unit/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapperTest.php +++ b/tests/Unit/DataMapper/ResponseDataMapper/VakifKatilimPosResponseDataMapperTest.php @@ -6,6 +6,8 @@ namespace Mews\Pos\Tests\Unit\DataMapper\ResponseDataMapper; use Mews\Pos\DataMapper\ResponseDataMapper\VakifKatilimPosResponseDataMapper; +use Mews\Pos\DataMapper\ResponseValueFormatter\ResponseValueFormatterInterface; +use Mews\Pos\DataMapper\ResponseValueMapper\ResponseValueMapperInterface; use Mews\Pos\Exceptions\NotImplementedException; use Mews\Pos\Factory\RequestValueMapperFactory; use Mews\Pos\Factory\ResponseValueFormatterFactory; @@ -27,18 +29,28 @@ class VakifKatilimPosResponseDataMapperTest extends TestCase /** @var LoggerInterface&MockObject */ private LoggerInterface $logger; + /** @var ResponseValueFormatterInterface & MockObject */ + private ResponseValueFormatterInterface $responseValueFormatterMock; + + /** @var ResponseValueMapperInterface & MockObject */ + private ResponseValueMapperInterface $responseValueMapperMock; + + private ResponseValueMapperInterface $responseValueMapper; + protected function setUp(): void { parent::setUp(); + $this->logger = $this->createMock(LoggerInterface::class); + $this->responseValueFormatterMock = $this->createMock(ResponseValueFormatterInterface::class); + $this->responseValueMapperMock = $this->createMock(ResponseValueMapperInterface::class); $requestValueMapper = RequestValueMapperFactory::createForGateway(VakifKatilimPos::class); - $responseValueMapper = ResponseValueMapperFactory::createForGateway(VakifKatilimPos::class, $requestValueMapper); - $responseValueFormatter = ResponseValueFormatterFactory::createForGateway(VakifKatilimPos::class); + $this->responseValueMapper = ResponseValueMapperFactory::createForGateway(VakifKatilimPos::class, $requestValueMapper); $this->responseDataMapper = new VakifKatilimPosResponseDataMapper( - $responseValueFormatter, - $responseValueMapper, + $this->responseValueFormatterMock, + $this->responseValueMapperMock, $this->logger ); } @@ -73,14 +85,35 @@ public function testExtractMdStatus(array $responseData, ?string $expected): voi */ public function testMapPaymentResponse(string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if ($this->responseDataMapper::TX_APPROVED === $expectedData['status']) { + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatAmount') + ->with($responseData['VPosMessage']['Amount'], $txType) + ->willReturn($expectedData['amount']); + + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatInstallment') + ->with($responseData['VPosMessage']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapperMock->expects($this->once()) + ->method('mapCurrency') + ->with($responseData['VPosMessage']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + + if (isset($expectedData['transaction_time'])) { + $txTimeWith = 'now'; + if ('0001-01-01T00:00:00' !== $responseData['TransactionTime'] && '00010101T00:00:00' !== $responseData['TransactionTime']) { + $txTimeWith = $responseData['TransactionTime']; + } + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatDateTime') + ->with($txTimeWith, $txType) + ->willReturn($expectedData['transaction_time']); + } } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->mapPaymentResponse($responseData, $txType, []); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -97,19 +130,44 @@ public function testMapPaymentResponse(string $txType, array $responseData, arra */ public function testMap3DPaymentData(array $order, string $txType, array $threeDResponseData, array $paymentResponse, array $expectedData): void { + if ($threeDResponseData['ResponseCode'] === '00') { + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatAmount') + ->with($paymentResponse['VPosMessage']['Amount'], $txType) + ->willReturn($expectedData['amount']); + + if (isset($paymentResponse['VPosMessage']['CurrencyCode'])) { + $this->responseValueMapperMock->expects($this->once()) + ->method('mapCurrency') + ->with($paymentResponse['VPosMessage']['CurrencyCode'], $txType) + ->willReturn($expectedData['currency']); + } + + if ($expectedData['status'] === $this->responseDataMapper::TX_APPROVED) { + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatInstallment') + ->with($paymentResponse['VPosMessage']['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + if (isset($expectedData['transaction_time'])) { + $txTimeWith = 'now'; + if ('0001-01-01T00:00:00' !== $paymentResponse['TransactionTime'] && '00010101T00:00:00' !== $paymentResponse['TransactionTime']) { + $txTimeWith = $paymentResponse['TransactionTime']; + } + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatDateTime') + ->with($txTimeWith, $txType) + ->willReturn($expectedData['transaction_time']); + } + } + } + $actualData = $this->responseDataMapper->map3DPaymentData( $threeDResponseData, $paymentResponse, $txType, $order ); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - } - - unset($actualData['transaction_time'], $expectedData['transaction_time']); $this->assertArrayHasKey('all', $actualData); if ([] !== $paymentResponse) { @@ -131,14 +189,14 @@ public function testMap3DPaymentData(array $order, string $txType, array $threeD */ public function testMap3DHostResponseData(array $order, string $txType, array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); - if ($expectedData['transaction_time'] instanceof \DateTimeImmutable && $actualData['transaction_time'] instanceof \DateTimeImmutable) { - $this->assertSame($expectedData['transaction_time']->format('Ymd'), $actualData['transaction_time']->format('Ymd')); - } else { - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); + if (isset($expectedData['transaction_time'])) { + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatDateTime') + ->with('now', $txType) + ->willReturn($expectedData['transaction_time']); } - unset($actualData['transaction_time'], $expectedData['transaction_time']); + $actualData = $this->responseDataMapper->map3DHostResponseData($responseData, $txType, $order); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -191,15 +249,84 @@ public function testMapCancelResponse(array $responseData, array $expectedData): */ public function testMapStatusResponse(array $responseData, array $expectedData): void { + $txType = PosInterface::TX_TYPE_STATUS; + if ($this->responseDataMapper::TX_APPROVED === $expectedData['status']) { + $amountMatcher = $this->atLeastOnce(); + $orderContract = $responseData['VPosOrderData']['OrderContract']; + $this->responseValueFormatterMock->expects($amountMatcher) + ->method('formatAmount') + ->with($this->callback(function ($amount) use ($amountMatcher, $orderContract) { + if ($amountMatcher->getInvocationCount() === 1) { + return $amount === $orderContract['FirstAmount']; + } + if ($amountMatcher->getInvocationCount() === 2) { + return $amount === $orderContract['TranAmount']; + } + + return false; + }), $txType) + ->willReturnCallback( + function () use ($amountMatcher, $expectedData) { + if ($amountMatcher->getInvocationCount() === 1) { + return $expectedData['first_amount']; + } + if ($amountMatcher->getInvocationCount() === 2) { + return $expectedData['capture_amount']; + } + + return false; + } + ); + + $statusMatcher = $this->atLeastOnce(); + $this->responseValueMapperMock->expects($statusMatcher) + ->method('mapOrderStatus') + ->with($this->callback(function ($amount) use ($statusMatcher, $orderContract) { + if ($statusMatcher->getInvocationCount() === 1) { + return $amount === ($orderContract['LastOrderStatus'] + ?? $orderContract['LastOrderStatusDescription']); + } + if ($statusMatcher->getInvocationCount() === 2) { + return $amount === $orderContract['OrderStatus']; + } + + return false; + })) + ->willReturnCallback( + function () use ($statusMatcher, $expectedData, $orderContract) { + if ($statusMatcher->getInvocationCount() === 1) { + return $expectedData['order_status']; + } + if ($statusMatcher->getInvocationCount() === 2) { + return $this->responseValueMapper->mapOrderStatus($orderContract['OrderStatus']); + } + + return false; + } + ); + + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatDateTime') + ->with($orderContract['OrderDate'], $txType) + ->willReturn($expectedData['transaction_time']); + + $this->responseValueFormatterMock->expects($this->once()) + ->method('formatInstallment') + ->with($orderContract['InstallmentCount'], $txType) + ->willReturn($expectedData['installment_count']); + + $this->responseValueMapperMock->expects($this->once()) + ->method('mapSecureType') + ->with($orderContract['TransactionSecurity'], $txType) + ->willReturn($expectedData['payment_model']); + + $this->responseValueMapperMock->expects($this->once()) + ->method('mapCurrency') + ->with($orderContract['FEC'], $txType) + ->willReturn($expectedData['currency']); + } + $actualData = $this->responseDataMapper->mapStatusResponse($responseData); - $this->assertEquals($expectedData['transaction_time'], $actualData['transaction_time']); - $this->assertEquals($expectedData['capture_time'], $actualData['capture_time']); - $this->assertEquals($expectedData['refund_time'], $actualData['refund_time']); - $this->assertEquals($expectedData['cancel_time'], $actualData['cancel_time']); - unset($actualData['transaction_time'], $expectedData['transaction_time']); - unset($actualData['capture_time'], $expectedData['capture_time']); - unset($actualData['refund_time'], $expectedData['refund_time']); - unset($actualData['cancel_time'], $expectedData['cancel_time']); $this->assertArrayHasKey('all', $actualData); $this->assertIsArray($actualData['all']); @@ -212,11 +339,17 @@ public function testMapStatusResponse(array $responseData, array $expectedData): } /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. * @dataProvider historyTestDataProvider */ public function testMapHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapHistoryResponse($responseData); + $responseDataMapper = new VakifKatilimPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(VakifKatilimPos::class), + $this->responseValueMapper, + $this->logger + ); + $actualData = $responseDataMapper->mapHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] @@ -247,11 +380,20 @@ public function testMapHistoryResponse(array $responseData, array $expectedData) $this->assertSame($expectedData, $actualData); } + /** + * Doing integration test because of the iteration, sorting and conditional statements it is difficult to mock values. + */ public function testMapHistoryResponseWithALotOfTxs(): void { + $responseDataMapper = new VakifKatilimPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(VakifKatilimPos::class), + $this->responseValueMapper, + $this->logger + ); + $responseData = file_get_contents(__DIR__.'/../../test_data/vakifkatilimpos/history/success_history.json'); - $actualData = $this->responseDataMapper->mapHistoryResponse(json_decode($responseData, true)); + $actualData = $responseDataMapper->mapHistoryResponse(json_decode($responseData, true)); $this->assertCount(31, $actualData['transactions']); if (count($actualData['transactions']) <= 1) { @@ -278,7 +420,13 @@ public function testMapHistoryResponseWithALotOfTxs(): void */ public function testMapOrderHistoryResponse(array $responseData, array $expectedData): void { - $actualData = $this->responseDataMapper->mapOrderHistoryResponse($responseData); + $responseDataMapper = new VakifKatilimPosResponseDataMapper( + ResponseValueFormatterFactory::createForGateway(VakifKatilimPos::class), + $this->responseValueMapper, + $this->logger + ); + + $actualData = $responseDataMapper->mapOrderHistoryResponse($responseData); if (count($actualData['transactions']) > 1 && null !== $actualData['transactions'][0]['transaction_time'] diff --git a/tests/Unit/Gateways/PosNetV1PosTest.php b/tests/Unit/Gateways/PosNetV1PosTest.php index 359400b2..35783b15 100644 --- a/tests/Unit/Gateways/PosNetV1PosTest.php +++ b/tests/Unit/Gateways/PosNetV1PosTest.php @@ -135,19 +135,11 @@ public function testInit(): void */ public function testGetApiURL(string $txType, string $mappedTxType, string $expected): void { -// $this->requestValueMapper->expects(self::once()) -// ->method('mapTxType') -// ->with($txType) -// ->willReturn($mappedTxType); - $this->assertSame($expected, $this->pos->getApiURL($txType)); } public function testGetApiURLException(): void { -// $this->requestValueMapper->expects(self::never()) -// ->method('mapTxType'); - $this->expectException(\InvalidArgumentException::class); $this->pos->getApiURL(); } @@ -216,10 +208,6 @@ public function testMake3DPayment( 'create3DPaymentRequestData', ]; if ($is3DSuccess) { -// $this->requestMapperMock->expects(self::once()) -// ->method('mapTxType') -// ->with($txType) -// ->willReturn('Sale'); $this->requestMapperMock->expects(self::once()) ->method('create3DPaymentRequestData') ->with($this->account, $order, $txType, $request->request->all()) @@ -227,7 +215,7 @@ public function testMake3DPayment( $this->configureClientResponse( $txType, - 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Auth', + 'https://epostest.albarakaturk.com.tr/ALBMerchantService/MerchantJSONAPI.svc/Sale', $create3DPaymentRequestData, 'request-body', 'response-body', @@ -317,11 +305,6 @@ public function testMakeRegularPayment(array $order, string $txType, string $map $card = $this->card; $requestData = ['createNonSecurePaymentRequestData']; -// $this->requestMapperMock->expects(self::once()) -// ->method('mapTxType') -// ->with($txType) -// ->willReturn($mappedTxType); - $this->requestMapperMock->expects(self::once()) ->method('createNonSecurePaymentRequestData') ->with($account, $order, $txType, $card) @@ -356,11 +339,6 @@ public function testMakeRegularPostAuthPayment(array $order, string $apiUrl): vo $txType = PosInterface::TX_TYPE_PAY_POST_AUTH; $requestData = ['createNonSecurePostAuthPaymentRequestData']; -// $this->requestMapperMock->expects(self::once()) -// ->method('mapTxType') -// ->with($txType) -// ->willReturn('Capture'); - $this->requestMapperMock->expects(self::once()) ->method('createNonSecurePostAuthPaymentRequestData') ->with($account, $order) @@ -396,11 +374,6 @@ public function testStatusRequest(array $order, string $apiUrl): void $txType = PosInterface::TX_TYPE_STATUS; $requestData = ['createStatusRequestData']; -// $this->requestMapperMock->expects(self::once()) -// ->method('mapTxType') -// ->with($txType) -// ->willReturn('TransactionInquiry'); - $this->requestMapperMock->expects(self::once()) ->method('createStatusRequestData') ->with($account, $order) @@ -435,11 +408,6 @@ public function testCancelRequest(array $order, string $apiUrl): void $txType = PosInterface::TX_TYPE_CANCEL; $requestData = ['createCancelRequestData']; -// $this->requestMapperMock->expects(self::once()) -// ->method('mapTxType') -// ->with($txType) -// ->willReturn('Reverse'); - $this->requestMapperMock->expects(self::once()) ->method('createCancelRequestData') ->with($account, $order) @@ -473,11 +441,6 @@ public function testRefundRequest(array $order, string $apiUrl): void $account = $this->pos->getAccount(); $txType = PosInterface::TX_TYPE_REFUND; $requestData = ['createRefundRequestData']; -// -// $this->requestMapperMock->expects(self::once()) -// ->method('mapTxType') -// ->with($txType) -// ->willReturn('Return'); $this->requestMapperMock->expects(self::once()) ->method('createRefundRequestData')