From 8d1c7c0190da8c9945394b3a6ba092e307bf0f6c Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 6 Jun 2019 15:36:46 +0200 Subject: [PATCH] Throw exception when no stripe id is found In cases where methods are called which expect the billable entity to be a Stripe customer we'll first do a check from now on to see if that's the case. Otherwise we'll throw an exception to notify the developer that the billable entity must first be registered as a Stripe customer. --- src/Billable.php | 47 +++++++++++++++++------- src/Exceptions/InvalidStripeCustomer.php | 19 ++++++++++ tests/Integration/InvoicesTest.php | 41 +++++++++++++++++++++ 3 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 src/Exceptions/InvalidStripeCustomer.php create mode 100644 tests/Integration/InvoicesTest.php diff --git a/src/Billable.php b/src/Billable.php index f842f7fa..671c5512 100644 --- a/src/Billable.php +++ b/src/Billable.php @@ -13,6 +13,7 @@ use Stripe\Customer as StripeCustomer; use Stripe\BankAccount as StripeBankAccount; use Stripe\InvoiceItem as StripeInvoiceItem; +use Laravel\Cashier\Exceptions\InvalidStripeCustomer; use Stripe\Error\InvalidRequest as StripeErrorInvalidRequest; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -82,9 +83,7 @@ public function hasCardOnFile() */ public function tab($description, $amount, array $options = []) { - if (! $this->stripe_id) { - throw new InvalidArgumentException(class_basename($this).' is not a Stripe customer. See the createAsStripeCustomer method.'); - } + $this->assertCustomerExists(); $options = array_merge([ 'customer' => $this->stripe_id, @@ -213,17 +212,15 @@ public function subscriptions() */ public function invoice(array $options = []) { - if ($this->stripe_id) { - $parameters = array_merge($options, ['customer' => $this->stripe_id]); + $this->assertCustomerExists(); - try { - return StripeInvoice::create($parameters, Cashier::stripeOptions())->pay(); - } catch (StripeErrorInvalidRequest $e) { - return false; - } - } + $parameters = array_merge($options, ['customer' => $this->stripe_id]); - return true; + try { + return StripeInvoice::create($parameters, Cashier::stripeOptions())->pay(); + } catch (StripeErrorInvalidRequest $e) { + return false; + } } /** @@ -233,6 +230,8 @@ public function invoice(array $options = []) */ public function upcomingInvoice() { + $this->assertCustomerExists(); + try { $stripeInvoice = StripeInvoice::upcoming(['customer' => $this->stripe_id], Cashier::stripeOptions()); @@ -266,7 +265,7 @@ public function findInvoice($id) } /** - * Find an invoice or throw a 404 error. + * Find an invoice or throw a 404 or 403 error. * * @param string $id * @return \Laravel\Cashier\Invoice @@ -307,6 +306,8 @@ public function downloadInvoice($id, array $data) */ public function invoices($includePending = false, $parameters = []) { + $this->assertCustomerExists(); + $invoices = []; $parameters = array_merge(['limit' => 24], $parameters); @@ -346,6 +347,8 @@ public function invoicesIncludingPending(array $parameters = []) */ public function cards($parameters = []) { + $this->assertCustomerExists(); + $cards = []; $parameters = array_merge(['limit' => 24], $parameters); @@ -391,6 +394,8 @@ public function defaultCard() */ public function updateCard($token) { + $this->assertCustomerExists(); + $customer = $this->asStripeCustomer(); $token = StripeToken::retrieve($token, Cashier::stripeOptions()); @@ -482,6 +487,8 @@ public function deleteCards() */ public function applyCoupon($coupon) { + $this->assertCustomerExists(); + $customer = $this->asStripeCustomer(); $customer->coupon = $coupon; @@ -536,6 +543,20 @@ public function hasStripeId() return ! is_null($this->stripe_id); } + /** + * Determine if the entity has a Stripe customer ID and throw an exception if not. + * + * @return void + * + * @throws \Laravel\Cashier\Exceptions\InvalidStripeCustomer + */ + protected function assertCustomerExists() + { + if (! $this->stripe_id) { + throw InvalidStripeCustomer::nonCustomer($this); + } + } + /** * Create a Stripe customer for the given model. * diff --git a/src/Exceptions/InvalidStripeCustomer.php b/src/Exceptions/InvalidStripeCustomer.php new file mode 100644 index 00000000..f076b26d --- /dev/null +++ b/src/Exceptions/InvalidStripeCustomer.php @@ -0,0 +1,19 @@ +createCustomer('require_stripe_customer_for_invoicing'); + + $this->expectException(InvalidStripeCustomer::class); + + $user->invoice(); + } + + public function test_invoicing_fails_with_nothing_to_invoice() + { + $user = $this->createCustomer('invoicing_fails_with_nothing_to_invoice'); + $user->createAsStripeCustomer(); + $user->updateCard('tok_visa'); + + $response = $user->invoice(); + + $this->assertFalse($response); + } + + public function test_customer_can_be_invoiced() + { + $user = $this->createCustomer('customer_can_be_invoiced'); + $user->createAsStripeCustomer(); + $user->updateCard('tok_visa'); + + $response = $user->invoiceFor('Laracon', 49900); + + $this->assertInstanceOf(Invoice::class, $response); + $this->assertEquals(49900, $response->total); + } +}