Serverless and Stripe payment intents

Small log today to just talk about a snag I ran into integrating Stripe into the serverless stack following :

While not strictly needed if you’re in the US but:

On September 14, 2019, Strong Customer Authentication (SCA) took effect in Europe. Under this regulation, card payments require additional authentication. Transactions that don’t follow the new guidelines may be declined.

I know this because it bit us hard in our own app where we had micropayments in a time-sensitive situation. So I wanted to follow that learning and use the payment intents stuff from Stripe.

Of course… I haven’t used serverless before and i didn’t do the backend work last time. A rod for my own back, but one I enjoyed hacking away at and reading about. I learn the most when I’m breaking things constantly.

Right away the guide was using javascript and stripe have added typescript support. It changes the implementation a little.

npm install stripe

Seen a few ways to do this when looking about but this is it.

import Stripe from 'stripe';

The apiVersion is actually quite a clever typing to keep you up to date, it fails to build if Stripe is upgraded and you haven’t updated this here (unless you use null of course).

Setting typescript: true simply sets your agent to Typescript for now. Seemed like I should… 😅

To help you a little this always made it clearer what the flow was in a payment intent checkout.

source: https://stripe.com/docs/payments/accept-a-payment?integration=elements

To summarise :

  1. We generate a payment intent on the API side via Stripe
  2. We send this to the client app
  3. The client app will use the secret and key to complete a transaction directly with stripe
  4. Stripe will return a succeeded. Also incidentally not included in this flow, it will fire to a webhook too on the API. This is useful if you need to change some state to reflect the transaction was a success e.g. trigger shipping.

Something I ran into here you might notice was the ESLINT rules were too strict here. It did not approve of snake case… but I couldn’t be bothered to do rule configuration just yet so a little ignore comment to let me carry on.

// eslint-disable-next-line

Sending the payment intent back to the client along with our publishable key and an amount that the user is being charged.

I return the amount here, which incidentally is a custom billing functions output in pence. So that the client will be able to surface the actual amount the customer is going to pay.

Technically you could take the charge and you’re done but I wanted to make sure I’d be able to configure Stripe to call me back after the user pays (or if it was a failed payment).

I’m not going to go into detail, the code is pretty straightforward and also this is as yet untested 😀. I’ve only just made it but I’ve tested it locally as far as validating it will throw an error while the signature check is invalid.

The output is a success after that regardless, and I’ve got nothing to do with it yet, I just wanted to have it ready.

Some things I’ll need to do going forward:

  • Make it easier to test — the signature thing is a pain.
  • Setup some logging so I can see this working on my side.
  • Change the ES-Lint rules, they’re a little strict for ‘learning’… no-console especially 😿

If anyone who has done this more than I see anything misinformative please comment and I’ll be sure to correct ASAP. This is just scratching the surface for me, I expect when I come to implement the front-end with Stripe Elements I’ll learn what I’ve done wrong and have to come back here and update then.

Fullish-stack engineer (codebykev.dev) and Lead front-end engineer @Pushdoctor with 15+ years developing web apps, installations, AR toys and other fun stuff.