FREELessons: 9Length: 50 minutes

Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

3.2 Making Our First Payment

Now that we have some data, we can begin billing our users. In this lesson, I'll show you how to process a single charge against a user. We'll build a very small shopping cart that we can fill with sample data. Then, we'll add a button to allow the user to check out and make a payment.

3.2 Making Our First Payment

In the previous lesson, we prepared our database by creating some migrations and then seeding some dummy data. Now that we have some dummy data to work with, we can start looking at how to process payments with Stripe. The first thing we're going to be doing is one-off payments, or a single charge. These sorts of payments can be used for a variety of things such as shopping carts and donation buttons. In our case, since we've got all that dummy data ready to go, we'll be doing a very simple shopping cart. In fact, our shopping cart is going to be so simple there isn't even going to be the proper interface for it. So let's just get stuck into it, shall we? In our routes file, we're going to pretend to be authenticated, just so we can retrieve our authenticated users cart and the associated products. Obviously, you don't want to do this sort of thing in production. So, outside of our route definition, we'll simply say Auth: :loginUsingId(1), to log in as the user with the Id of 1. Now, in our default route, let's make sure that it's all working, by simply dumping and dying out the auth user. In our browser, we should now be able to refresh and we'll see a user model instance for our authenticated user. Right. Now let's remove that. Instead of returning the welcome view, let's return a new view called cart. Inside resources > views, we'll create a new file called cart.blade.php. We'll start with the basic HTML 5 structure. We'll set a title just because we can, and then in the content, we'll set up a very basic table to display the items a user has in their cart. We aren't going to be doing anything fancy here, like updating quantities or removing items. We're just going to be displaying them and that's it. So we'll have a table with a thead, a new row, and it will have four headings. Next to the thead, we'll have a tbody. For our headings, we'll have Product, Price, Quantity, and Total. Now, in the body, we'll open up a foreach, and we'll iterate over $user->cart as $cart. Then we'll open up a new row with four columns. In the first column, we'll display the product's name. Then we'll display the product's price, followed by the quantity in the cart, then we'll use multiplication to get the total price for the cart item. Now, outside of the foreach, we're going to display the subtitle for the cart items. So we'll add another row, this time with two columns. In the first column, we'll add a colspan = 3, and we'll align = right. Then we'll add a strong tag for the Sub Total. Finally, we'll calculate the Sub Total in the last column. We'll use user->cart->sum, except we'll pass in a closure to calculate the sum. The closure looks at a single parameter which will be the cart item. Now we'll simply return the product price multiplied by the quantity just like we did before. What we need to do now is pass along the authenticated user to the view. In our routes file, let's set a user variable to the Auth: :user, then we'll pass it through to the view. Right, now let's see how this looks. Excellent, it's nothing flashy, but it certainly gets the job done. Now, there's a couple ways we can go about implementing the Stripe side of things. The most common methods involve Stripe.JS, a JavaScript library that lets you collect credit card details without having them touch your server. This is usually the best approach, as the credit card details are only ever sent to Stripe servers. So you don't have to worry about storing them securely in your own database. With Stripe.js, you can either implement a checkout form yourself or you can use the checkout library, which is built on top of Stripe.js and provides a very nice interface for both the web and mobile users. For this course, we're gonna be using checkout as it's a lot simpler. From the Stripe documentation, we can navigate to the checkout documentation. Integrating it is extremely easy. If you want, you can customize it a bit more by using some jQuery, but we're going to be sticking with a simple implementation for now. The beauty of the Stripe documentation is that the code samples already include our test API key for us. So let's just go ahead and copy this simple example here. And in our cart view, we'll paste it beneath our table. Instead of this form posting to the charge URI, I'm going to simply post it to the root URI. Now there's several data attributes here, however only a data key is actually required. The others are highly recommended though. And there's even more optional ones to further customize the form. We'll remove the data image as we don't have any image to show. For data name, we'll simply say My Cool Store, or something to that effect. We'll remove the description. If you'd like, you could say something like cart contents. But it's all just extra stuff that makes the form look a little bit nicer. The amount is the total cents, and don't worry, this won't actually charge the user until we send the charge through properly. You don't even need to enter an amount here, but doing so makes the form look a little bit nicer. So, what we'll do is assign the subtotal above to a variable called subTotal. Now, in the amount, we can simply display the subTotal * 100. There is one other option we're going to fill out since we already have an authenticated user, and that's their email. So we'll add a data email attribute with a value of the user's email, and we're done. If we now refresh our browser, we'll see a Pay with Card button. Clicking it will overlay a form on our page with our site name and the amount that we wish to pay. Again, we could've left that amount blank, and it will still simply say Pay. But we're not quite set up to handle the payment just yet. Let's jump back into our routes file and we'll create a new post route for the root URI. And in it, we'll simply dump and die all the input. We'll also open up our http/Kernel.php file and we'll comment out the Csrf, Middlewear. This is obviously a big no-no for a real world web application. Okay, so now that we're back in our browser, let's attempt to pay for our cart. Stripe actually has a bunch of dummy credit card numbers that we can use for testing. One of these is 4242 repeated. So lets just use that. We'll also set a future date for our expiry, and we'll use a random CVC. Now, let's just open up the develop tools and we'll switch to the networking tab, to see what happens when we hit the pay button. Make sure you've got the ticked to Preserve the log between page loads. So, a number of things have happened here, but we're really only interested in the first request. When we hit the pay button, an Ajax call is sent to API.Stripe.com/v1/tokens, the data that we provided. Stripe then validates this data, including our public key, and will return a short-lived token which represents the user's credit card details. Once the token has been retrieved, the form itself is submitted and as you can see, our token has been sent along with the request. So now that we have this token, we can now charge the user's credit card. In our post route, we're going to need to grab the total of the user's card again. So let's just copy that from the view. Instead of calling the user variable, we'll call Auth::user. Now to actually charge the user, we first need to make sure that the user is billable. To do that, our user model needs to use a trait provided by the cache component. Now this trait can be applied to just about anything. In our case, it will be a user. But it could very well be a client model or a company model, just about anything really. So let's open up our user model. At the top, we want to import Laravel\Cashier\Billable, as well as Laravel\Cashier\Contracts\Billable, as BillableContract. Then we'll simply append the billable contract to the interfaces already implemented on the model. And we'll do the same thing with the billable trade. We also need to make sure that the date columns are properly mutated into carbon instances. So we'll set a protected dates property to an array with two elements, trial_ends_at and subscription_ends_at. All right, that's the model all set up. So now in our routes file, we can call Auth:user()->charge(). Now this is a method on that billable trait that we just added to our model. The first parameter that we need to give the charge method is the amount in cents that we wish to charge the user. So we'll need to multiply the total by 100. Then we can pass in an array of options. We need to pass either a customer or a source as one of the options. The other options are detailed in the Stripe documentation underneath the charges. We'll talk more about customers later. So for now we'll be using the source option. So we'll set the source to Input::get(stripeToken). Now, this charge method will return false if the charge fails, so in a real application you'd be checking the returned value of this and handling it appropriately. Once the user has been charged, I'm just going to return charged so that we know that it's worked. Obviously in a real world application you'd want to clear out the user's cart, perhaps move it into an orders tables, and then redirect them to some sort of confirmation page. Anyway, in our browser, let's simply refresh the page and we'll resubmit the form with the Stripe token that we already have. Once it's processed, we'll see Charged is displayed on the screen. Excellent. Now, if we switch over to our Stripe dashboard and refresh, we'll see that our latest charge has come through. If we view the Payments from the left, we can see our payment and even look at some more details. If note is a Stripe fee that will be deducted from our sale. And that covers the basics of single charges. In our next lesson, we'll be looking at subscriptions and coupons.

Back to the top