# Stripe webhooks on Fastify

Fastify parses JSON request bodies into objects before your handler runs. `stripe.webhooks.constructEvent` needs the raw bytes. Override the content type parser so the body arrives as a Buffer.

## The setup

```
import Fastify from 'fastify';
import Stripe from 'stripe';

const fastify = Fastify();
const stripe = new Stripe(process.env.STRIPE_API_KEY_VALUE);

// Keep the raw bytes for Stripe's signature check
fastify.addContentTypeParser(
  'application/json',
  { parseAs: 'buffer' },
  function (req, body, done) {
    done(null, body);
  }
);

fastify.post('/webhooks/stripe', async (req, reply) => {
  const sig = req.headers['stripe-signature'];
  let event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body.toString('utf8'),
      sig,
      process.env.STRIPE_WEBHOOK_SIGNING_VALUE
    );
  } catch (err) {
    return reply.code(400).send('bad signature');
  }
  // switch on event.type ...
  return reply.code(200).send({ received: true });
});
```

## Scope it if you can

Overriding the parser globally changes body handling for every route. If the app has other JSON routes, register the webhook in a scoped plugin with its own parser, or check the URL inside the parser and only buffer the webhook path.

## Checklist

- `parseAs: 'buffer'` is the documented Fastify option for raw access.
- Convert the Buffer to a UTF-8 string before passing it to constructEvent.
- Stripe sends webhooks as `application/json`, so match that content type exactly.