Revana Docs

Stripe Integration

Revana Stripe webhook integration for a NestJS route

We assume at this point that your route file has the following configured already:

  • a NestJS app running on the Express adapter
  • a configured stripe instance
  • a valid STRIPE_WEBHOOK_SECRET
  • raw body already enabled for the Stripe route in your Nest bootstrap

Install the package

Before wiring the webhook route into your application, install the Revana JavaScript package using the package manager your project already uses.

npm install @revana/js
pnpm add @revana/js
yarn add @revana/js
bun add @revana/js

Revana Setup

In your environment variables create a new variable called REVANA_API_KEY and make sure you pass the correct space api key which you would like the daa to feed into, this is explained over in the revana dashboard under the user dropdown the api managment

simply add the following code to your project where you have your stripe webhook endpoint

import { Revana } from "@revana/js";

const revana = new Revana({
  apiKey: process.env.REVANA_API_KEY,
});

Webhook Integration

To get started if you just copy this following snippet into your router, this wil fully handle the revana payment revover module for incoming stripe events. its important to note all we do is forward the events were interested in capturing and once done we pass the event straight back to you so you can implement eny webhook logic required on yourside for your application.

@Post("webhooks/stripe")
stripeWebhook(@Req() request, @Res() response) {
  const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
  if (!webhookSecret) {
    return response.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
      error: "Missing required environment variable: STRIPE_WEBHOOK_SECRET",
    });
  }

  return revana.handleNestStripeWebhook(
    { stripe, webhookSecret },
    (stripeEvent, _request, nestResponse) => {
      console.log(`received Stripe event ${stripeEvent.type} (${stripeEvent.id})`);

      return nestResponse.status(HttpStatus.OK).json({
        received: true,
        type: stripeEvent.type,
        id: stripeEvent.id,
      });
    },
  )(request, response);
}

stripeEvent is the verified, already-parsed Stripe event returned by stripe.webhooks.constructEvent(...) inside Revana. That means your route callback receives the safe event object directly instead of neading to re-read the raw body, extracting the signature, and constructing the event itself like seen in he example below

Code you no longer need in the route

Without Revana, your NestJS route usually needs to do the verification work itself before it can access the parsed Stripe event.

@Post("webhooks/stripe")
stripeWebhook(@Req() request, @Res() response) {
  const signature = request.header("stripe-signature");

  const cleanStripeEvent = stripe.webhooks.constructEvent(
    request.body,
    signature,
    webhookSecret,
  );

  console.log(
    `received Stripe event ${cleanStripeEvent.type} (${cleanStripeEvent.id})`,
  );

  return response.status(HttpStatus.OK).json({
    received: true,
    type: cleanStripeEvent.type,
    id: cleanStripeEvent.id,
  });
}

What Revana's doing behind the scenes

  • verifies the Stripe signature using your stripe instance and webhookSecret
  • parses the Stripe event for you
  • forwards the verified payload to the Revana backend for processing and revenue recapture
  • passes the verified event into your route callback as stripeEvent so you can perform your own actions on any given stripe event

What still matters in NestJS

  • This pattern assumes Nest is using the Express platform.
  • The Stripe route must receive raw body data before standard JSON parsing.
  • Your callback is where you return the final HTTP response for the route. -simply copy the code above and everything will just work

On this page