Skip to content

Commit

Permalink
ACP-4760 Allow to return a changed PaymentTransfer from implementatio…
Browse files Browse the repository at this point in the history
…ns to be able to persist changes on the Payment. (#29)
  • Loading branch information
stereomon authored Jan 17, 2025
1 parent 1e37b5b commit e222f33
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<property name="isSuccessful" type="bool"/>
<property name="statusCode" type="int"/>
<property name="transactionId" type="string"/>
<property name="payment" type="Payment"/>
<property name="preOrderPaymentData" type="array" singular="preOrderPaymentDatum"/>
<property name="redirectUrl" type="string"/>
<property name="message" type="string"/>
Expand Down Expand Up @@ -85,6 +86,7 @@
</transfer>

<transfer name="CancelPreOrderPaymentResponse" strict="true">
<property name="payment" type="Payment"/>
<property name="isSuccessful" type="bool"/>
<property name="statusCode" type="int"/>
<property name="message" type="string"/>
Expand All @@ -98,6 +100,7 @@
</transfer>

<transfer name="CapturePaymentResponse" strict="true">
<property name="payment" type="Payment"/>
<property name="isSuccessful" type="bool"/>
<property name="transactionId" type="string"/>
<property name="message" type="string"/>
Expand All @@ -111,6 +114,7 @@
</transfer>

<transfer name="CancelPaymentResponse" strict="true">
<property name="payment" type="Payment"/>
<property name="isSuccessful" type="bool"/>
<property name="transactionId" type="string"/>
<property name="message" type="string"/>
Expand All @@ -127,6 +131,7 @@
</transfer>

<transfer name="RefundPaymentResponse" strict="true">
<property name="payment" type="Payment"/>
<property name="isSuccessful" type="bool"/>
<property name="refundId" type="string"/>
<property name="message" type="string"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ public function createPaymentRefunder(): PaymentRefunder
$this->getPlatformPlugin(),
$this->createPaymentRefundValidator(),
$this->getEntityManager(),
$this->createPaymentWriter(),
$this->getConfig(),
$this->createAppConfigLoader(),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ public function cancelPayment(CancelPaymentRequestTransfer $cancelPaymentRequest
}

/** @phpstan-var \Generated\Shared\Transfer\CancelPaymentResponseTransfer */
return $this->getTransactionHandler()->handleTransaction(function () use ($cancelPaymentRequestTransfer, $cancelPaymentResponseTransfer): \Generated\Shared\Transfer\CancelPaymentResponseTransfer {
$this->savePayment($cancelPaymentRequestTransfer->getPaymentOrFail(), $cancelPaymentResponseTransfer->getStatusOrFail());
return $this->getTransactionHandler()->handleTransaction(function () use ($cancelPaymentRequestTransfer, $cancelPaymentResponseTransfer): CancelPaymentResponseTransfer {
$paymentTransfer = $cancelPaymentResponseTransfer->getPayment() ?? $cancelPaymentRequestTransfer->getPaymentOrFail();

$this->savePayment($paymentTransfer, $cancelPaymentResponseTransfer->getStatusOrFail());

return $cancelPaymentResponseTransfer;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ public function capturePayment(CapturePaymentRequestTransfer $capturePaymentRequ
}

/** @phpstan-var \Generated\Shared\Transfer\CapturePaymentResponseTransfer */
return $this->getTransactionHandler()->handleTransaction(function () use ($capturePaymentRequestTransfer, $capturePaymentResponseTransfer): \Generated\Shared\Transfer\CapturePaymentResponseTransfer {
$this->savePayment($capturePaymentRequestTransfer->getPaymentOrFail(), $capturePaymentResponseTransfer->getStatusOrFail());
return $this->getTransactionHandler()->handleTransaction(function () use ($capturePaymentRequestTransfer, $capturePaymentResponseTransfer): CapturePaymentResponseTransfer {
$paymentTransfer = $capturePaymentResponseTransfer->getPayment() ?? $capturePaymentRequestTransfer->getPaymentOrFail();

$this->savePayment($paymentTransfer, $capturePaymentResponseTransfer->getStatusOrFail());

return $capturePaymentResponseTransfer;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Spryker\Shared\Log\LoggerTrait;
use Spryker\Zed\AppPayment\AppPaymentConfig;
use Spryker\Zed\AppPayment\Business\Payment\AppConfig\AppConfigLoader;
use Spryker\Zed\AppPayment\Business\Payment\Writer\PaymentWriterInterface;
use Spryker\Zed\AppPayment\Dependency\Plugin\AppPaymentPlatformPluginInterface;
use Spryker\Zed\AppPayment\Persistence\AppPaymentEntityManagerInterface;
use Spryker\Zed\Kernel\Persistence\EntityManager\TransactionTrait;
Expand All @@ -29,6 +30,7 @@ public function __construct(
protected AppPaymentPlatformPluginInterface $appPaymentPlatformPlugin,
protected PaymentRefundValidator $paymentRefundValidator,
protected AppPaymentEntityManagerInterface $appPaymentEntityManager,
protected PaymentWriterInterface $paymentWriter,
protected AppPaymentConfig $appPaymentConfig,
protected AppConfigLoader $appConfigLoader
) {
Expand Down Expand Up @@ -72,10 +74,20 @@ public function refundPayment(RefundPaymentRequestTransfer $refundPaymentRequest
),
);

$paymentTransfer = $refundPaymentResponseTransfer->getPayment() ?? $refundPaymentRequestTransfer->getPaymentOrFail();

$this->savePayment($paymentTransfer, $refundPaymentResponseTransfer->getStatusOrFail());

return $refundPaymentResponseTransfer;
});
}

protected function savePayment(PaymentTransfer $paymentTransfer, string $status): void
{
$paymentTransfer->setStatus($status);
$this->paymentWriter->updatePayment($paymentTransfer);
}

protected function mapRefundPaymentResponseTransferToPaymentRefundTransfer(
RefundPaymentRequestTransfer $refundPaymentRequestTransfer,
RefundPaymentResponseTransfer $refundPaymentResponseTransfer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Generated\Shared\Transfer\PaymentCanceledTransfer;
use Generated\Shared\Transfer\PaymentCancellationFailedTransfer;
use Generated\Shared\Transfer\PaymentTransfer;
use Generated\Shared\Transfer\PaymentUpdatedTransfer;
use Ramsey\Uuid\Uuid;
use Spryker\Zed\AppKernel\AppKernelConfig;
use Spryker\Zed\AppPayment\AppPaymentDependencyProvider;
Expand Down Expand Up @@ -99,6 +100,45 @@ public function testCancelPaymentMessageUpdatesPaymentToPaymentCancelledWhenPaym
$this->tester->assertMessageWasSent(PaymentCanceledTransfer::class);
}

public function testCancelPaymentMessageUpdatesPaymentToPaymentCancelledWhenPaymentIsInCancellableStateAndPersistsPaymentDetailsFromTheImplementationReturnedPayment(): void
{
// Arrange
$tenantIdentifier = Uuid::uuid4()->toString();
$transactionId = Uuid::uuid4()->toString();
$this->tester->haveAppConfigForTenant($tenantIdentifier);
$paymentTransfer = $this->tester->havePaymentForTransactionId($transactionId, $tenantIdentifier, PaymentStatus::STATUS_NEW);

$cancelPaymentTransfer = $this->tester->haveCancelPaymentTransfer(['tenantIdentifier' => $tenantIdentifier, 'orderReference' => $paymentTransfer->getOrderReference()]);

$cancelPaymentResponseTransfer = (new CancelPaymentResponseTransfer())
->setIsSuccessful(true)
->setTransactionId($transactionId)
->setStatus(PaymentStatus::STATUS_CANCELED);

$platformPluginMock = Stub::makeEmpty(AppPaymentPlatformPluginInterface::class, [
'cancelPayment' => function (CancelPaymentRequestTransfer $cancelPaymentRequestTransfer) use ($cancelPaymentResponseTransfer, $paymentTransfer) {
$this->assertInstanceOf(AppConfigTransfer::class, $cancelPaymentRequestTransfer->getAppConfig());
$this->assertInstanceOf(PaymentTransfer::class, $cancelPaymentRequestTransfer->getPayment());

$paymentTransfer->setDetails('{"foo":"bar"}');
$cancelPaymentResponseTransfer->setPayment($paymentTransfer);

return $cancelPaymentResponseTransfer;
},
]);

$this->getDependencyHelper()->setDependency(AppPaymentDependencyProvider::PLUGIN_PLATFORM, $platformPluginMock);

// Act: This will trigger the MessageHandlerPlugin for this message.
$this->tester->runMessageReceiveTest($cancelPaymentTransfer, 'payment-commands');

// Assert
$this->tester->assertPaymentHasStatus($paymentTransfer, PaymentStatus::STATUS_CANCELED);
$this->tester->assertPaymentHasDetails($paymentTransfer, '{"foo":"bar"}');
$this->tester->assertMessageWasSent(PaymentCanceledTransfer::class);
$this->tester->assertMessageWasSent(PaymentUpdatedTransfer::class);
}

public function testCancelPaymentMessageDoesNotUpdatePaymentStatusWhenPaymentIsNotInCancellableStateAndSendsPaymentCancellationFailedMessage(): void
{
// Arrange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Generated\Shared\Transfer\CapturePaymentResponseTransfer;
use Generated\Shared\Transfer\PaymentCapturedTransfer;
use Generated\Shared\Transfer\PaymentTransfer;
use Generated\Shared\Transfer\PaymentUpdatedTransfer;
use Ramsey\Uuid\Uuid;
use Spryker\Zed\AppKernel\AppKernelConfig;
use Spryker\Zed\AppPayment\AppPaymentDependencyProvider;
Expand Down Expand Up @@ -91,6 +92,44 @@ public function testHandleCapturePaymentMessageUpdatesPaymentToCapturedRequested
$this->tester->assertPaymentHasStatus($paymentTransfer, PaymentStatus::STATUS_CAPTURE_REQUESTED);
}

public function testHandleCapturePaymentMessageUpdatesPaymentToCapturedRequestedAndPersistsDetailsFromTheImplementationReturnedPayment(): void
{
// Arrange
$tenantIdentifier = Uuid::uuid4()->toString();
$transactionId = Uuid::uuid4()->toString();
$this->tester->haveAppConfigForTenant($tenantIdentifier);
$paymentTransfer = $this->tester->havePaymentForTransactionId($transactionId, $tenantIdentifier);

$capturePaymentTransfer = $this->tester->haveCapturePaymentTransfer(['tenantIdentifier' => $tenantIdentifier, 'orderReference' => $paymentTransfer->getOrderReference()]);

$capturePaymentResponseTransfer = (new CapturePaymentResponseTransfer())
->setIsSuccessful(true)
->setTransactionId($transactionId)
->setStatus(PaymentStatus::STATUS_CAPTURE_REQUESTED);

$platformPluginMock = Stub::makeEmpty(AppPaymentPlatformPluginInterface::class, [
'capturePayment' => function (CapturePaymentRequestTransfer $capturePaymentRequestTransfer) use ($capturePaymentResponseTransfer, $paymentTransfer) {
$this->assertInstanceOf(AppConfigTransfer::class, $capturePaymentRequestTransfer->getAppConfig());
$this->assertInstanceOf(PaymentTransfer::class, $capturePaymentRequestTransfer->getPayment());

$paymentTransfer->setDetails('{"foo":"bar"}');
$capturePaymentResponseTransfer->setPayment($paymentTransfer);

return $capturePaymentResponseTransfer;
},
]);

$this->getDependencyHelper()->setDependency(AppPaymentDependencyProvider::PLUGIN_PLATFORM, $platformPluginMock);

// Act: This will trigger the MessageHandlerPlugin for this message.
$this->tester->runMessageReceiveTest($capturePaymentTransfer, 'payment-commands');

// Assert
$this->tester->assertPaymentHasStatus($paymentTransfer, PaymentStatus::STATUS_CAPTURE_REQUESTED);
$this->tester->assertPaymentHasDetails($paymentTransfer, '{"foo":"bar"}');
$this->tester->assertMessageWasSent(PaymentUpdatedTransfer::class);
}

/**
* Covers partial capture. When the amount to be captured is set in the message this amount will be captured (WIP: Partial capture is not fully implemented).
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Generated\Shared\Transfer\PaymentRefundedTransfer;
use Generated\Shared\Transfer\PaymentRefundFailedTransfer;
use Generated\Shared\Transfer\PaymentTransfer;
use Generated\Shared\Transfer\PaymentUpdatedTransfer;
use Generated\Shared\Transfer\RefundPaymentRequestTransfer;
use Generated\Shared\Transfer\RefundPaymentResponseTransfer;
use Generated\Shared\Transfer\RefundPaymentTransfer;
Expand Down Expand Up @@ -102,6 +103,48 @@ public function testRefundPaymentMessageSendsPaymentRefundedMessageAndCreatesPay
$this->tester->assertMessageWasSent(PaymentRefundedTransfer::class);
}

public function testRefundPaymentMessageSendsPaymentRefundedMessageAndCreatesPaymentRefundWhenPaymentIsInCapturedStateAndPersistsDetailsFromTheImplementationReturnedPaymentAndSendsAPaymentUpdatedMessage(): void
{
// Arrange
$tenantIdentifier = Uuid::uuid4()->toString();
$transactionId = Uuid::uuid4()->toString();
$refundId = Uuid::uuid4()->toString();
$this->tester->haveAppConfigForTenant($tenantIdentifier);
$paymentTransfer = $this->tester->havePaymentForTransactionId($transactionId, $tenantIdentifier, PaymentStatus::STATUS_CAPTURED);

$refundPaymentTransfer = $this->tester->haveRefundPaymentTransfer([
MessageAttributesTransfer::TENANT_IDENTIFIER => $tenantIdentifier,
RefundPaymentTransfer::ORDER_REFERENCE => $paymentTransfer->getOrderReference(),
]);
$refundPaymentResponseTransfer = (new RefundPaymentResponseTransfer())
->setIsSuccessful(true)
->setRefundId($refundId)
->setStatus(PaymentRefundStatus::SUCCEEDED);

$platformPluginMock = Stub::makeEmpty(AppPaymentPlatformPluginInterface::class, [
'refundPayment' => function (RefundPaymentRequestTransfer $refundPaymentRequestTransfer) use ($refundPaymentResponseTransfer, $paymentTransfer) {
$this->assertInstanceOf(AppConfigTransfer::class, $refundPaymentRequestTransfer->getAppConfig());
$this->assertInstanceOf(PaymentTransfer::class, $refundPaymentRequestTransfer->getPayment());

$paymentTransfer->setDetails('{"foo":"bar"}');
$refundPaymentResponseTransfer->setPayment($paymentTransfer);

return $refundPaymentResponseTransfer;
},
]);

$this->getDependencyHelper()->setDependency(AppPaymentDependencyProvider::PLUGIN_PLATFORM, $platformPluginMock);

// Act: This will trigger the MessageHandlerPlugin for this message.
$this->tester->runMessageReceiveTest($refundPaymentTransfer, 'payment-commands');

// Assert
$this->tester->assertPaymentRefundIsInStatus($refundId, PaymentRefundStatus::SUCCEEDED);
$this->tester->assertPaymentHasDetails($paymentTransfer, '{"foo":"bar"}');
$this->tester->assertMessageWasSent(PaymentRefundedTransfer::class);
$this->tester->assertMessageWasSent(PaymentUpdatedTransfer::class);
}

/**
* @dataProvider refundSuccessfulPathStatusDataProvider
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ public function assertPaymentHasStatus(PaymentTransfer $paymentTransfer, string
$updatedPaymentTransfer = $this->getPaymentHelper()->getPaymentTransferByTransactionId($paymentTransfer->getTransactionId());
$this->assertEquals($expectedStatus, $updatedPaymentTransfer->getStatus(), sprintf('Expected payment to have status "%s" but status "%s" was found.', $expectedStatus, $updatedPaymentTransfer->getStatus()));
}

public function assertPaymentHasDetails(PaymentTransfer $paymentTransfer, string $expectedDetails): void
{
$updatedPaymentTransfer = $this->getPaymentHelper()->getPaymentTransferByTransactionId($paymentTransfer->getTransactionId());
$this->assertEquals($expectedDetails, $updatedPaymentTransfer->getDetails(), sprintf('Expected payment to have details "%s" but details "%s" was found.', $expectedDetails, $updatedPaymentTransfer->getDetails()));
}
}

0 comments on commit e222f33

Please sign in to comment.