Stripe is a great platform for running an online business, especially on account of the developer-centric API that makes it easy to collect payments,  set up subscriptions and more.

Many of these APIs result in Stripe generating one or more events that you can subscribe to via a webhook. These events could represent a successful payment, or perhaps a new subscriber to your SaaS platform. In total, there are well over 100 different types of events that you can subscribe to, so how can we build a loosely-coupled cloud-native event-driven architecture to handle these events? How can we make this serverless?

It's easy, we'll use AWS EventBridge.

Why AWS EventBridge?

For those of you just learning about AWS EventBridge, it is a serverless event bus supporting event-driven architectures, released July 2019. An event bus is a central location where business events can be published and routing rules can be configured to send those events to downstream functions or services that operate on them. By using an event bus as an intermediate layer, this decouples services from needing direct knowledge of how to communicate with each other, which allows development teams to build and operate independently.

One reason, among many, why AWS EventBridge should be considered is the cost. With AWS EventBridge, you have a fully managed cloud-native event bus, requiring no effort to set up and no servers to pay for - and it costs a very reasonable $1 per million events. Latency is typically about half a second. By going with a fully managed solution, you're saving your team from spending time on 'undifferentiated heavy lifting' associated with infrastructure, giving them more time to focus on delivering customer value.

The solution

We'll show here how we can set up AWS EventBridge so that it can begin ingesting events from Stripe. As part of that ingestion, we'll check that the event is truly from Stripe by verifying the signature on the event. Let’s get started.

Using an an open-source project we created called stripe-eventbridge (https://github.com/rangle/stripe-eventbridge),  you can quickly  set up the plumbing to connect Stripe events to AWS EventBridge via a Lambda function that will then validate the authenticity of incoming events (so that downstream functions won't have to). This allows for the events that are published on the event bridge to be routed to various downstream functions through simple routing rules which we show at the end of the post.

With this deployed, you can set up many downstream Lambda functions to handle the wide array of events generated by Stripe and configure the routing to these event handlers with AWS EventBridge based on the Stripe event type. All of this without having to worry about event signatures, since events are only placed on the EventBridge if they pass validation.

The stripe-eventbridge project creates an endpoint that you configure in the Stripe Dashboard as the destination for the webhook events. When an event arrives, the endpoint will invoke a Lambda that we provide which has these responsibilities:

  1. to validate that the event has a valid signature (i.e. that it was generated by Stripe)
  2. to place validated events (only) on the AWS EventBridge
  3. to notify an SNS topic if an event fails to validate (e.g. due to an invalid signature)

Solution overview

stripe-eventbridge uses the Serverless Framework to generate the infrastructure in the AWS section of the diagram above. The Serverless Framework allows us to automatically create and deploy the CloudFormation stacks needed to realize the above configuration. The stacks can be deployed via sls deploy and rolled back via sls remove using the command line client.

Here's a diagram of what gets created:

Serverless components in stripe-eventbridge

Let's walk through what stripe-eventbridge creates:

  • A Lambda - this function validates incoming events, and if they are from Stripe (i.e. signed correctly) then they are relayed to the AWS EventBridge where downstream services can read from them.
  • An API Gateway endpoint - this is the webhook endpoint that the Lambda above is listening to for new events.
  • An AWS SecretManager secret - this secret is created with an empty value, and you populate this with the signing key assigned to your webhook endpoint in the Stripe Dashboard
  • An SNS topic - if the webhook fails validation or processing, then a notification is sent to a topic called stripe-webhook-event-failed-to-validate. You can configure subscriptions to this topic, so that you are emailed (for example) whenever an event fails processing.

If you'd like to get started, you can visit the GitHub project here:

https://github.com/rangle/stripe-eventbridge

Routing by event type

Now that you have events being published to the EventBridge, you can configure routing based on the event type using Rule patterns like this. The detail-type values are exactly the values of the underlying Stripe events - you can see a full list here: https://stripe.com/docs/api/events/types

{
  "detail-type": [
    "payment_intent.succeeded"
  ],
  "source": [
    "Stripe"
  ]
}

Alternately, if you are creating your event handlers using the Serverless Framework, then you can declare the same routing in your infrastructure code (this is really good practice) in your serverless.yml as follows:

  myLambdaFunction:
    handler: handler.myLambdaFunction
    events:
      - eventBridge:
          pattern:
            source:
              - Stripe
            detail-type:
              - payment_intent.succeeded

Here, notice how we're listening for events generated from the 'Stripe' source and the detail-type property allows you to list the types of events that you want to listen for and have routed to your lambda function.

And that's all!

I hope you have found this valuable. Stay tuned, we'll be exploring more with Serverless in upcoming posts.