How to Set Up Payments in Your App With Stripe, Angular, and Express
By: Klement Omeri
Tags: Expressjs, Programming, JavaScript, Angular, Stripe

Stripe Integration

What we will do at the back-end side is to take order data and the Stripe token and implement our custom logic. So, we will do it in three main steps.

We will immediately create a Stripe Charge but do not capture it ( capture: false ). Operate with the creation of the order. After the order creation, if it is successful, we will charge the authorized funds, otherwise, we will refund them back to the client.

Let’s suppose that we have an API endpoint like so:

// index.js

router.post('order',

token({ required: true }),

controller.create)

Inside the create() controller, we need to take pricing of that order and then create a charge on Stripe for that price with the Stripe token in the request.body .

Let’s note two key things here.

1. We get pricing with a helper function.

2. We convert it to pence.

You may already have pricing inside the request.body and now you may think: “Oh yes, he is getting the price with a helper because he doesn’t have it already in the order data,” but that is wrong.

Even if you have an attribute like req.body.order.price , do not use it to create a charge object on Stripe. It is easy to manipulate the request payload coming from the front end, and that price in req.body may not be the real price of that order.

Always recalculate it at the back-end side, which is a more secure environment compared to the front end.

“What about this conversion?” you might ask. That’s because Stripe accepts price only as pence and it has to be an integer, not a decimal. So, if you want to charge $1, the amount is $1 x 100 = 100 pence. If you want to charge $100, the amount must be 10,000 pence.

This is an important thing that requires some attention. If charge creation will take place on many controllers, I strongly recommend writing createCharge() and getChargeData() helper functions to be used everywhere we must create a charge.

That’s the way I am working with my implementation at my every-day job to make it less error-prone. So, the helpers would look something like:

Let’s get back to the point we created the charge. One important thing to note here is the capture: false attribute.

By default, Stripe will create and charge the client immediately for the amount given. What we want is to place a hold as we want to authorize those funds. That’s because we are not sure if the order will create successfully.

If the charge can be created successfully, Stripe’s response would be like:

At this moment, we have a charge object created but not captured on Stripe’s side for the client related to the token and for the amount we specified.

What does it mean that we have created a charge object? It means that we have transferred the required funds for the client’s order from the client’s bank to Stripe, and we’ve placed a hold on that card.

We do not transfer those funds to our side. They are just blocked by Stripe and will be on hold for seven days. This is another important part. This authorization process can last for a max. of seven days.

What happens after that? After that, Stripe will automatically refund all the funds that the charge is holding back from the client.

So, if you have a flow that requires some time to know if the service or goods you provide can be sent to the client, make sure that this time is no more than seven days or choose another checkout flow.

OK, now, let’s create the client’s order and then capture those funds.

What happens inside makeOrderCreation() ?

So, we have used another helper function to create the order in the database and then after the order is created, we return the success response to the front end. After that, we will capture the authorized funds.

To capture a charge that was previously created, we need to perform a capture action and all we need is the charge’s ID.

Let’s perform the capture action, it is as simple as follows.

“Capturing a charge will always succeed, unless the charge is already refunded, expired, captured, or an invalid capture

amount is specified, in which case this method will throw an error.” — Stripe docs

Now, by default, if you don’t specify the amount to capture, Stripe will capture the full amount inside that charge object which is exactly what we want.