Skip to content

Commit 303c1f7

Browse files
committed
Merge branch '5.7'
2 parents e33d490 + 1dbbbcc commit 303c1f7

21 files changed

+233
-85
lines changed

billing.md

Lines changed: 80 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Laravel Cashier
22

33
- [Introduction](#introduction)
4+
- [Upgrading Cashier](#upgrading-cashier)
45
- [Configuration](#configuration)
56
- [Stripe](#stripe-configuration)
67
- [Braintree](#braintree-configuration)
@@ -14,12 +15,16 @@
1415
- [Subscription Anchor Date](#subscription-anchor-date)
1516
- [Cancelling Subscriptions](#cancelling-subscriptions)
1617
- [Resuming Subscriptions](#resuming-subscriptions)
17-
- [Updating Credit Cards](#updating-credit-cards)
1818
- [Subscription Trials](#subscription-trials)
1919
- [With Credit Card Up Front](#with-credit-card-up-front)
2020
- [Without Credit Card Up Front](#without-credit-card-up-front)
2121
- [Customers](#customers)
22-
- [Creating Customers](#create-customers)
22+
- [Creating Customers](#creating-customers)
23+
- [Cards](#cards)
24+
- [Retrieving Credit Cards](#retrieving-credit-cards)
25+
- [Determining If A Card Is On File](#determining-if-a-card-is-on-file)
26+
- [Updating Credit Cards](#updating-credit-cards)
27+
- [Deleting Credit Cards](#deleting-credit-cards)
2328
- [Handling Stripe Webhooks](#handling-stripe-webhooks)
2429
- [Defining Webhook Event Handlers](#defining-webhook-event-handlers)
2530
- [Failed Subscriptions](#handling-failed-subscriptions)
@@ -41,6 +46,11 @@ Laravel Cashier provides an expressive, fluent interface to [Stripe's](https://s
4146

4247
> {note} If you're only performing "one-off" charges and do not offer subscriptions, you should not use Cashier. Instead, use the Stripe and Braintree SDKs directly.
4348
49+
<a name="upgrading-cashier"></a>
50+
## Upgrading Cashier
51+
52+
When upgrading to a new major version of the Cashier, it's important that you carefully review [the upgrade guide](https://github.com/laravel/cashier/blob/master/UPGRADE.md).
53+
4454
<a name="configuration"></a>
4555
## Configuration
4656

@@ -389,13 +399,6 @@ If a user has cancelled their subscription and you wish to resume it, use the `r
389399

390400
If the user cancels a subscription and then resumes that subscription before the subscription has fully expired, they will not be billed immediately. Instead, their subscription will be re-activated, and they will be billed on the original billing cycle.
391401

392-
<a name="updating-credit-cards"></a>
393-
### Updating Credit Cards
394-
395-
The `updateCard` method may be used to update a customer's credit card information. This method accepts a Stripe token and will assign the new credit card as the default billing source:
396-
397-
$user->updateCard($stripeToken);
398-
399402
<a name="subscription-trials"></a>
400403
## Subscription Trials
401404

@@ -470,12 +473,63 @@ Once you are ready to create an actual subscription for the user, you may use th
470473

471474
Occasionally, you may wish to create a Stripe customer without beginning a subscription. You may accomplish this using the `createAsStripeCustomer` method:
472475

473-
$user->createAsStripeCustomer($stripeToken);
476+
$user->createAsStripeCustomer();
474477

475478
Of course, once the customer has been created in Stripe, you may begin a subscription at a later date.
476479

477480
> {tip} The Braintree equivalent of this method is the `createAsBraintreeCustomer` method.
478481
482+
<a name="cards"></a>
483+
## Cards
484+
485+
<a name="retrieving-credit-cards"></a>
486+
### Retrieving Credit Cards
487+
488+
The `cards` method on the billable model instance returns a collection of `Laravel\Cashier\Card` instances:
489+
490+
$cards = $user->cards();
491+
492+
To retrieve the default card, the `defaultCard` method may be used;
493+
494+
$card = $user->defaultCard();
495+
496+
<a name="determining-if-a-card-is-on-file"></a>
497+
### Determining If A Card Is On File
498+
499+
You may check if a customer has a credit card attached to their account using the `hasCardOnFile` method:
500+
501+
if ($user->hasCardOnFile()) {
502+
//
503+
}
504+
505+
<a name="updating-credit-cards"></a>
506+
### Updating Credit Cards
507+
508+
The `updateCard` method may be used to update a customer's credit card information. This method accepts a Stripe token and will assign the new credit card as the default billing source:
509+
510+
$user->updateCard($stripeToken);
511+
512+
To sync your card information with the customer's default card information in Stripe, you may use the `updateCardFromStripe` method:
513+
514+
$user->updateCardFromStripe();
515+
516+
<a name="deleting-credit-cards"></a>
517+
### Deleting Credit Cards
518+
519+
To delete a card, you should first retrieve the customer's cards with the `cards` method. Then, you may call the `delete` method on the card instance you wish to delete:
520+
521+
foreach ($user->cards() as $card) {
522+
$card->delete();
523+
}
524+
525+
> {note} If you delete the default card, please make sure that you sync the new default card with your database using the `updateCardFromStripe` method.
526+
527+
The `deleteCards` method will delete all of the card information stored by your application:
528+
529+
$user->deleteCards();
530+
531+
> {note} If the user has an active subscription, you should consider preventing them from deleting the last remaining payment source.
532+
479533
<a name="handling-stripe-webhooks"></a>
480534
## Handling Stripe Webhooks
481535

@@ -490,6 +544,8 @@ Both Stripe and Braintree can notify your application of a variety of events via
490544
491545
By default, this controller will automatically handle cancelling subscriptions that have too many failed charges (as defined by your Stripe settings), customer updates, customer deletions, subscription updates, and credit card changes; however, as we'll soon discover, you can extend this controller to handle any webhook event you like.
492546

547+
> {note} Make sure you protect incoming requests with Cashier's included [webhook signature verification](/docs/{{version}}/billing#verifying-webhook-signatures) middleware.
548+
493549
#### Webhooks & CSRF Protection
494550

495551
Since Stripe webhooks need to bypass Laravel's [CSRF protection](/docs/{{version}}/csrf), be sure to list the URI as an exception in your `VerifyCsrfToken` middleware or list the route outside of the `web` middleware group:
@@ -512,10 +568,10 @@ Cashier automatically handles subscription cancellation on failed charges, but i
512568
class WebhookController extends CashierController
513569
{
514570
/**
515-
* Handle a Stripe webhook.
571+
* Handle invoice payment succeeded.
516572
*
517573
* @param array $payload
518-
* @return Response
574+
* @return \Symfony\Component\HttpFoundation\Response
519575
*/
520576
public function handleInvoicePaymentSucceeded($payload)
521577
{
@@ -545,16 +601,9 @@ That's it! Failed payments will be captured and handled by the controller. The c
545601
<a name="verifying-webhook-signatures"></a>
546602
### Verifying Webhook Signatures
547603

548-
To secure your webhooks, you may use [Stripe's webhook signatures](https://stripe.com/docs/webhooks/signatures). For convenience, Cashier includes a middleware that validates the incoming Stripe webhook request is valid.
549-
550-
To get started, ensure that the `stripe.webhook.secret` configuration value is set in your `services` configuration file. Once you have configured your webhook secret, you may attach the `VerifyWebhookSignature` middleware to the route:
551-
552-
use Laravel\Cashier\Http\Middleware\VerifyWebhookSignature;
604+
To secure your webhooks, you may use [Stripe's webhook signatures](https://stripe.com/docs/webhooks/signatures). For convenience, Cashier automatically includes a middleware which validates that the incoming Stripe webhook request is valid.
553605

554-
Route::post(
555-
'stripe/webhook',
556-
'\App\Http\Controllers\WebhookController@handleWebhook'
557-
)->middleware(VerifyWebhookSignature::class);
606+
To enable webhook verification, ensure that the `stripe.webhook.secret` configuration value is set in your `services` configuration file. The webhook `secret` may be retrieved from your Stripe account dashboard.
558607

559608
<a name="handling-braintree-webhooks"></a>
560609
## Handling Braintree Webhooks
@@ -593,14 +642,14 @@ Cashier automatically handles subscription cancellation on failed charges, but i
593642
class WebhookController extends CashierController
594643
{
595644
/**
596-
* Handle a Braintree webhook.
645+
* Handle a new dispute.
597646
*
598-
* @param WebhookNotification $webhook
599-
* @return Response
647+
* @param \Braintree\WebhookNotification $webhook
648+
* @return \Symfony\Component\HttpFoundation\Responses
600649
*/
601-
public function handleDisputeOpened(WebhookNotification $notification)
650+
public function handleDisputeOpened(WebhookNotification $webhook)
602651
{
603-
// Handle The Event
652+
// Handle The Webhook...
604653
}
605654
}
606655

@@ -657,10 +706,12 @@ Sometimes you may need to make a one-time charge but also generate an invoice fo
657706
// Braintree Accepts Charges In Dollars...
658707
$user->invoiceFor('One Time Fee', 5);
659708

660-
The invoice will be charged immediately against the user's credit card. The `invoiceFor` method also accepts an array as its third argument, allowing you to pass any options you wish to the underlying Stripe / Braintree charge creation:
709+
The invoice will be charged immediately against the user's credit card. The `invoiceFor` method also accepts an array as its third argument. This array contains the billing options for the invoice item. The fourth argument accepted by the method is also an array. This final argument accepts the billing options for the invoice itself:
661710

662-
$user->invoiceFor('One Time Fee', 500, [
663-
'custom-option' => $value,
711+
$user->invoiceFor('Stickers', 500, [
712+
'quantity' => 50,
713+
], [
714+
'tax_percent' => 21,
664715
]);
665716

666717
If you are using Braintree as your billing provider, you must include a `description` option when calling the `invoiceFor` method:
@@ -669,7 +720,6 @@ If you are using Braintree as your billing provider, you must include a `descrip
669720
'description' => 'your invoice description here',
670721
]);
671722

672-
673723
> {note} The `invoiceFor` method will create a Stripe invoice which will retry failed billing attempts. If you do not want invoices to retry failed charges, you will need to close them using the Stripe API after the first failed charge.
674724
675725
<a name="refunding-charges"></a>

blade.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,13 @@ You may display the contents of the `name` variable like so:
167167

168168
Hello, {{ $name }}.
169169

170+
171+
> {tip} Blade `{{ }}` statements are automatically sent through PHP's `htmlspecialchars` function to prevent XSS attacks.
172+
170173
Of course, you are not limited to displaying the contents of the variables passed to the view. You may also echo the results of any PHP function. In fact, you can put any PHP code you wish inside of a Blade echo statement:
171174

172175
The current UNIX timestamp is {{ time() }}.
173176

174-
> {tip} Blade `{{ }}` statements are automatically sent through PHP's `htmlspecialchars` function to prevent XSS attacks.
175-
176177
#### Displaying Unescaped Data
177178

178179
By default, Blade `{{ }}` statements are automatically sent through PHP's `htmlspecialchars` function to prevent XSS attacks. If you do not want your data to be escaped, you may use the following syntax:

broadcasting.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,11 @@ If you would like to listen for events on a private channel, use the `private` m
511511
<a name="leaving-a-channel"></a>
512512
### Leaving A Channel
513513

514-
To leave a channel, you may call the `leave` method on your Echo instance:
514+
To leave a channel, you may call the `leaveChannel` method on your Echo instance:
515+
516+
Echo.leaveChannel('orders');
517+
518+
If you would like to leave a channel and also its associated private and presence channels, you may call the `leave` method:
515519

516520
Echo.leave('orders');
517521

collections.md

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ For the remainder of this documentation, we'll discuss each method available on
166166
[whenNotEmpty](#method-whennotempty)
167167
[where](#method-where)
168168
[whereStrict](#method-wherestrict)
169+
[whereBetween](#method-wherebetween)
169170
[whereIn](#method-wherein)
170171
[whereInStrict](#method-whereinstrict)
171172
[whereInstanceOf](#method-whereinstanceof)
@@ -1780,7 +1781,7 @@ The static `times` method creates a new collection by invoking the callback a gi
17801781
This method can be useful when combined with factories to create [Eloquent](/docs/{{version}}/eloquent) models:
17811782

17821783
$categories = Collection::times(3, function ($number) {
1783-
return factory(Category::class)->create(['name' => 'Category #'.$number]);
1784+
return factory(Category::class)->create(['name' => "Category No. $number"]);
17841785
});
17851786

17861787
$categories->all();
@@ -2005,37 +2006,37 @@ For the inverse of `when`, see the [`unless`](#method-unless) method.
20052006
The `whenEmpty` method will execute the given callback when the collection is empty:
20062007

20072008
$collection = collect(['michael', 'tom']);
2008-
2009+
20092010
$collection->whenEmpty(function ($collection) {
20102011
return $collection->push('adam');
20112012
});
2012-
2013+
20132014
$collection->all();
2014-
2015+
20152016
// ['michael', 'tom']
2016-
2017-
2017+
2018+
20182019
$collection = collect();
2019-
2020+
20202021
$collection->whenEmpty(function ($collection) {
20212022
return $collection->push('adam');
20222023
});
2023-
2024+
20242025
$collection->all();
2025-
2026-
// ['adam']
2027-
2028-
2026+
2027+
// ['adam']
2028+
2029+
20292030
$collection = collect(['michael', 'tom']);
2030-
2031+
20312032
$collection->whenEmpty(function($collection) {
20322033
return $collection->push('adam');
20332034
}, function($collection) {
20342035
return $collection->push('taylor');
20352036
});
20362037

20372038
$collection->all();
2038-
2039+
20392040
// ['michael', 'tom', 'taylor']
20402041

20412042
For the inverse of `whenEmpty`, see the [`whenNotEmpty`](#method-whennotempty) method.
@@ -2046,37 +2047,37 @@ For the inverse of `whenEmpty`, see the [`whenNotEmpty`](#method-whennotempty) m
20462047
The `whenNotEmpty` method will execute the given callback when the collection is not empty:
20472048

20482049
$collection = collect(['michael', 'tom']);
2049-
2050+
20502051
$collection->whenNotEmpty(function ($collection) {
20512052
return $collection->push('adam');
20522053
});
2053-
2054+
20542055
$collection->all();
2055-
2056+
20562057
// ['michael', 'tom', 'adam']
2057-
2058-
2058+
2059+
20592060
$collection = collect();
2060-
2061+
20612062
$collection->whenNotEmpty(function ($collection) {
20622063
return $collection->push('adam');
20632064
});
2064-
2065+
20652066
$collection->all();
2066-
2067-
// []
2068-
2069-
2067+
2068+
// []
2069+
2070+
20702071
$collection = collect();
2071-
2072+
20722073
$collection->whenNotEmpty(function($collection) {
20732074
return $collection->push('adam');
20742075
}, function($collection) {
20752076
return $collection->push('taylor');
20762077
});
2077-
2078+
20782079
$collection->all();
2079-
2080+
20802081
// ['taylor']
20812082

20822083
For the inverse of `whenNotEmpty`, see the [`whenEmpty`](#method-whenempty) method.
@@ -2111,6 +2112,31 @@ The `where` method uses "loose" comparisons when checking item values, meaning a
21112112

21122113
This method has the same signature as the [`where`](#method-where) method; however, all values are compared using "strict" comparisons.
21132114

2115+
<a name="method-wherebetween"></a>
2116+
#### `whereBetween()` {#collection-method}
2117+
2118+
The `whereBetween` method filters the collection within a given range:
2119+
2120+
$collection = collect([
2121+
['product' => 'Desk', 'price' => 200],
2122+
['product' => 'Chair', 'price' => 80],
2123+
['product' => 'Bookcase', 'price' => 150],
2124+
['product' => 'Pencil', 'price' => 30],
2125+
['product' => 'Door', 'price' => 100],
2126+
]);
2127+
2128+
$filtered = $collection->whereBetween('price', [100, 200]);
2129+
2130+
$filtered->all();
2131+
2132+
/*
2133+
[
2134+
['product' => 'Desk', 'price' => 200],
2135+
['product' => 'Bookcase', 'price' => 150],
2136+
['product' => 'Door', 'price' => 100],
2137+
]
2138+
*/
2139+
21142140
<a name="method-wherein"></a>
21152141
#### `whereIn()` {#collection-method}
21162142

0 commit comments

Comments
 (0)