Skip to content

Commit

Permalink
[13.x] Add pay method (#1345)
Browse files Browse the repository at this point in the history
* Add createPaymentIntent Method

* Fix StyleCI Errors

* Fix StyleCI Errors :(

* Fix StyleCI Spacing Error

* Fix StyleCI Spacing Error :(

* Add new pay method

* Forward calls on Payment instance

* wip

* wip

* wip

* wip

* wip

* Ignore payment_method_types on pay method

* Add payWith method

* Add findPayment method

Co-authored-by: Dries Vints <dries@vints.io>
  • Loading branch information
mozex and driesvints committed Apr 19, 2022
1 parent fb5473a commit 90deda5
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 7 deletions.
77 changes: 73 additions & 4 deletions src/Concerns/PerformsCharges.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Laravel\Cashier\Checkout;
use Laravel\Cashier\Payment;
use LogicException;
use Stripe\Exception\InvalidRequestException as StripeInvalidRequestException;

trait PerformsCharges
{
Expand All @@ -27,23 +28,91 @@ public function charge($amount, $paymentMethod, array $options = [])
$options = array_merge([
'confirmation_method' => 'automatic',
'confirm' => true,
], $options);

$options['payment_method'] = $paymentMethod;

$payment = $this->createPayment($amount, $options);

$payment->validate();

return $payment;
}

/**
* Create a new PaymentIntent instance.
*
* @param int $amount
* @param array $options
* @return \Laravel\Cashier\Payment
*/
public function pay($amount, array $options = [])
{
$options['automatic_payment_methods'] = ['enabled' => true];

unset($options['payment_method_types']);

return $this->createPayment($amount, $options);
}

/**
* Create a new PaymentIntent instance for the given payment method types.
*
* @param int $amount
* @param array $paymentMethods
* @param array $options
* @return \Laravel\Cashier\Payment
*/
public function payWith($amount, array $paymentMethods, array $options = [])
{
$options['payment_method_types'] = $paymentMethods;

unset($options['automatic_payment_methods']);

return $this->createPayment($amount, $options);
}

/**
* Create a new Payment instance with a Stripe PaymentIntent.
*
* @param int $amount
* @param array $options
* @return \Laravel\Cashier\Payment
*/
public function createPayment($amount, array $options = [])
{
$options = array_merge([
'currency' => $this->preferredCurrency(),
], $options);

$options['amount'] = $amount;
$options['payment_method'] = $paymentMethod;

if ($this->hasStripeId()) {
$options['customer'] = $this->stripe_id;
}

$payment = new Payment(
return new Payment(
$this->stripe()->paymentIntents->create($options)
);
}

$payment->validate();
/**
* Find a payment intent by ID.
*
* @param string $id
* @return \Laravel\Cashier\Payment|null
*/
public function findPayment($id)
{
$stripePaymentIntent = null;

return $payment;
try {
$stripePaymentIntent = $this->stripe()->paymentIntents->retrieve($id);
} catch (StripeInvalidRequestException $exception) {
//
}

return $stripePaymentIntent ? new Payment($stripePaymentIntent) : null;
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Traits\ForwardsCalls;
use JsonSerializable;
use Laravel\Cashier\Exceptions\IncompletePayment;
use Stripe\PaymentIntent as StripePaymentIntent;

class Payment implements Arrayable, Jsonable, JsonSerializable
{
use ForwardsCalls;

/**
* The Stripe PaymentIntent instance.
*
Expand Down Expand Up @@ -249,4 +252,16 @@ public function __get($key)
{
return $this->paymentIntent->{$key};
}

/**
* Dynamically pass missing methods to the PaymentIntent instance.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->forwardCallTo($this->paymentIntent, $method, $parameters);
}
}
20 changes: 20 additions & 0 deletions tests/Feature/ChargesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ public function test_non_stripe_customer_can_be_charged()
$this->assertNull($response->customer);
}

public function test_customer_can_pay()
{
$user = $this->createCustomer('customer_can_pay');
$user->createAsStripeCustomer();

$response = $user->pay(1000);

$this->assertInstanceOf(Payment::class, $response);
$this->assertEquals(1000, $response->rawAmount());
$this->assertEquals($user->stripe_id, $response->customer);
$this->assertTrue($response->requiresPaymentMethod());
$this->assertTrue($response->automatic_payment_methods->enabled);

// Payment intent can be retrieved...
$payment = $user->findPayment($response->id);

$this->assertInstanceOf(Payment::class, $payment);
$this->assertSame($response->id, $payment->id);
}

public function test_customer_can_be_charged_and_invoiced_immediately()
{
$user = $this->createCustomer('customer_can_be_charged_and_invoiced_immediately');
Expand Down
28 changes: 25 additions & 3 deletions tests/Unit/PaymentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

use Laravel\Cashier\Payment;
use PHPUnit\Framework\TestCase;
use Stripe\PaymentIntent;
use Stripe\Subscription;
use Stripe\PaymentIntent as StripePaymentIntent;
use Stripe\Subscription as StripeSubscription;

class PaymentTest extends TestCase
{
Expand All @@ -30,7 +30,7 @@ public function test_it_can_return_its_requires_action_status()
public function test_it_can_return_its_canceled_status()
{
$paymentIntent = new PaymentIntent();
$paymentIntent->status = Subscription::STATUS_CANCELED;
$paymentIntent->status = StripeSubscription::STATUS_CANCELED;
$payment = new Payment($paymentIntent);

$this->assertTrue($payment->isCanceled());
Expand All @@ -44,4 +44,26 @@ public function test_it_can_return_its_succeeded_status()

$this->assertTrue($payment->isSucceeded());
}

public function test_method_calls_are_forward_to_the_stripe_object()
{
$payment = new Payment(new PaymentIntent());

$this->assertTrue($payment->cancel()->cancelled);
}
}

class PaymentIntent extends StripePaymentIntent
{
public $cancelled = false;

/**
* @inheritDoc
*/
public function cancel($params = null, $opts = null)
{
$this->cancelled = true;

return $this;
}
}

0 comments on commit 90deda5

Please sign in to comment.