Skip to content

Commit

Permalink
feat(PAR-427): Throw new Canceled exception when trying to capture …
Browse files Browse the repository at this point in the history
…a payment intent that is already cancelled (#14)

* feat(PAR-427): Throw new `Canceled` exception when trying to capture a payment intent that is already cancelled

* chore(PAR-427): Formatting
  • Loading branch information
rickschubert authored Jul 14, 2023
1 parent 3d8cdb9 commit 39833ab
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 11 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ composer require pod-point/payments-php

## Usage

When performing actions using a payment service, a provider-specific exception will be thrown if it's requirements to perform that action are not met. This exception will contain the data received from the provider which can be used by the consuming application to resolve any issues.
When performing actions using a payment service, a provider-specific exception will be thrown if it's requirements to perform that action are not met. This exception will contain the data received from the provider which can be used by the consuming application to resolve any issues.

For example, when trying to make a payment with the Stripe payment service, if authorisation is required, an exception will be thrown with a "payment intent" object which can be used by a clients Stripe SDK to carry out the authorisation.

Expand Down
11 changes: 11 additions & 0 deletions src/Providers/Stripe/Payment/Canceled.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace PodPoint\Payments\Providers\Stripe\Payment;

class Canceled extends \Exception
{
public function __construct()
{
parent::__construct('Unable to create payment: The stripe PaymentIntent is already cancelled.');
}
}
11 changes: 10 additions & 1 deletion src/Providers/Stripe/Payment/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ public function reserve(
);
}

public function retrievePaymentIntent(string $token): PaymentIntent
{
return PaymentIntent::retrieve($token);
}

/**
* Tries to capture funds on a payment intent using the Stripe SDK.
*
Expand All @@ -171,13 +176,17 @@ public function reserve(
* @return Payment
*
* @throws AmountTooLarge
* @throws Canceled
* @throws InvalidRequest
* @throws InvalidToken
*/
public function capture(Token $token, int $amount): Payment
{
if ($token->type === StripeToken::PAYMENT_INTENT) {
$intent = PaymentIntent::retrieve($token->value);
$intent = $this->retrievePaymentIntent($token->value);
if ($intent->status == 'canceled') {
throw new Canceled();
}

try {
$response = $intent->capture([
Expand Down
24 changes: 15 additions & 9 deletions tests/Providers/Stripe/Payment/ServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
use PodPoint\Payments\Payment;
use PodPoint\Payments\Providers\Stripe\Customer\Service as CustomerService;
use PodPoint\Payments\Providers\Stripe\Payment\AmountTooLarge;
use PodPoint\Payments\Providers\Stripe\Payment\Canceled;
use PodPoint\Payments\Providers\Stripe\Payment\Exception as StripeException;
use PodPoint\Payments\Providers\Stripe\Payment\Service;
use PodPoint\Payments\Providers\Stripe\Refund\Service as RefundService;
use PodPoint\Payments\Providers\Stripe\Token;
use PodPoint\Payments\Tests\TestCase;
use Stripe\PaymentIntent;

class ServiceTest extends TestCase
{
Expand Down Expand Up @@ -271,19 +273,23 @@ public function testCorrectExceptionIsThrownWhenCaptureAmountIsHigherThanReserve
*/
public function testPaymentIntentCanBeCancelled()
{
$amount = 1000;
$paymentMethodToken = new Token('pm_card_visa');
$mockPaymentIntent = new PaymentIntent();
$mockPaymentIntent->status = 'canceled';

$payment = $this->service->reserve(
$paymentMethodToken,
$amount
);
$mockService = $this->getMockBuilder(Service::class)
->setMethodsExcept(['capture'])
->disableOriginalConstructor()
->getMock();

$paymentIntentToken = new Token($payment->uid);
$mockService->expects($this->once())
->method('retrievePaymentIntent')
->willReturn($mockPaymentIntent);

$cancelledPayment = $this->service->cancel($paymentIntentToken);
$this->expectException(Canceled::class);

$this->assertEquals($amount, $cancelledPayment->amount);
$token = new Token('some-uid');
$token->type = Token::PAYMENT_INTENT;
$mockService->capture($token, 20);
}

/**
Expand Down

0 comments on commit 39833ab

Please sign in to comment.