For Data Engineers

How to Integrate Stripe Webhooks and Amberflo to Create Seamless Pay-As-You-Go Options

Alongside our work to build the fastest and most efficient analytical database, our team is constantly striving to ensure that using FeatureBase is as easy as possible. Recently, our team has been working on developing a pay-as-you-go business model. This means that our customers can provision and deprovision all the databases that they need, anytime they want, and get charged based on the hourly consumption.

Two other software providers were necessary to achieve this business model: Amberflo and Stripe. Amberflo allows us to meter the infrastructure we deploy, can scale with our growth, and enables us to build and operate modern, usage-based pricing plans. Stripe allows us to securely store our customers' payment information and process charges according to their FeatureBase usage.

One recent security measure our team has been working through is tracking event updates for payments through Stripe and flagging any issues in real-time.

We documented our experience integrating Stripe Webhooks with Amberflo and are sharing our process with other teams who may be curious or interested in implementing a similar capability on their own product.

What technologies were used?

Stripe is our payment processing platform in which we securely store all customer payment information. Webhooks are an HTTP event driven communication mechanism between two applications, and when configured in Stripe, they notify us of payment events. Amberflo is a usage-based pricing and billing platform with real-time meter event ingestion and aggregation. 

Amberflo monitors customers’ database consumption and produces the invoice. Stripe charges customers when it receives the Amberflo invoice and payment intent object, allowing us to automatically charge customers based on payment information we stored in Stripe.

The Problem

To-date, our product has required manual invoicing on a monthly basis or payment through the AWS marketplace, but many of our customers would prefer to set up automatic payments directly in our product instead of dealing with the hassle of monthly invoices. Because of this, we sought to offer a user-friendly experience in which our trial users are able to seamlessly continue using FeatureBase with an easy pay-as-you-go option, and our existing customers are able to set up automatic, recurring payments. To ensure that payments would not fail for reasons such as expired payment information or insufficient funds on the given stored payment method, we began building an integration to notify us of payment anomalies.

Stripe provides an API that sends objects called events. These events contain information about what is going on in Stripe’s system. Our objective was to make sure that:

  1. Each paymentintent sent from Amberflo results in a successful charge from Stripe to the customer; if Stripe is unsuccessful in charging the customer, we want to prevent the allocation of further resources until the payment issues are resolved.  
  2. We are able to monitor and verify validity of payment methods on file with Stripe at all times.

In order to achieve those goals, we needed to collect and track real-time updates of the following Stripe events:

payment_intent.payment_failed : this event occurs when a paymentintent sent out by Amberflo has failed to have been paid.

customer.source.deleted : occurs whenever a payment source is removed from a customer.

customer.source.expiring : occurs whenever a source input by a customer will expire by the end of the month.

Steps to Integrate the Stripe Webhooks Architecture 

Since Stripe sends events through Webhooks, we needed to expose an endpoint to collect events that would indicate for us to perform some action on the events received. Here’s how we approached this integration:

  1. Identify the events you want to monitor and the event payloads to parse (for us, the events of interest are: payment_intent.payment_failed, customer.source.deleted, customer.source.expiring).
  2. Create a webhook endpoint as an HTTP endpoint (URL) on your local server or backend which can listen to those events.
  3. Handle requests from Stripe parsing each event object and responding with the 200 response status codes.
  4. Test that your webhook endpoint is working properly using the Stripe CLI 
  5. Deploy your webhook endpoint so it is a publicly accessible HTTPS URL
  6. Register your publicly accessible HTTPS URL in the Stripe Dashboard 

Back End Implementation Components

We needed to make our webhook endpoint publicly accessible, so we created a public facing service. This service listens to Stripe webhooks and verifies that the incoming request signature events are sent by Stripe and not another 3rd party. 

  • Stripe generates a unique secret key for each endpoint that contains the event timestamp and encodes it into the header of the request under Stripe signature to prevent a “reply attack”.
  • Using our internal Stripe library containing a secret key attached to the Stripe server, we verify the signature Stripe sends us in the Stripe-Signature request headers of each event. This verification mechanism is encapsulated in the SDK library.

The service will handle the received Stripe Event and return one of two possible responses to Stripe:

  • 200 OK response if everything has been handled correctly 
  • 400 Bad Error response if something went wrong when processing the webhook. When this occurs, we get an email notification from Stripe allowing us to see the trace and track down the issue.

Failure Handling Mechanisms

To make sure this process runs successfully we had to implement some failure handling mechanisms. A couple issues we wanted to proactively troubleshoot were: 

Potential Issue #1: Our backend could fail to handle the Stripe events sent out because of some error.

Solution: To track this process, we configured Stripe to notify us of a misconfigured endpoint that has not responded with the 200 HTTP status code (indicating successful payment). 

Potential Issue #2: Webhook endpoints might occasionally receive the same event more than once. 

Solution: Make event processing idempotent. One way of doing this could be logging and storing the events we’ve processed with a time stamp to avoid processing duplicate events. 

Potential Issue #3: Listening for unnecessary, extra events (or all events). This would put undue strain on the server.

Solution: We configured our webhook endpoint to receive only the types of events required by our integration. 

Using this process, we are able to prevent the incorrect allocation of resources when our platform runs into issues with payments. If you’re interested in trying FeatureBase for yourself, start your free trial now!