Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo Server: How can I add a custom endpoint for Stripe webhook?

I have a graphql server that I want to add a custom endpoint for so that Stripe can communicate with it when a customer's Subscription status changes.

Currently, my index.js file looks like a typical Apollo Server set up:

import { ApolloServer } from "apollo-server";
import { connectDb } from "./models";

import schema from "./schema";
import resolvers from "./resolvers";
import contexts from "./contexts";

const server = new ApolloServer({
  typeDefs: schema,
  resolvers,
  context: async ({ req }) => {
    const { getCurrentUser } = contexts;

    const currentUser = await getCurrentUser(req);
    return { models, currentUser };
  },
});

connectDb().then(async () => {
  server.listen({ port: process.env.PORT || 4000 }).then(({ url }) => {
    console.log(`🚀  Server ready at ${url}`);
  });
});

So only /graphql is exposed.

How would I add a custom POST /foobar endpoint that does something similar to this? (source: https://stripe.com/docs/webhooks/build#example-code)

// This example uses Express to receive webhooks
const app = require('express')();

// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');

// Match the raw body to content type application/json
app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
  let event;

  try {
    event = JSON.parse(request.body);
  } catch (err) {
    response.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Handle the event
  switch (event.type) {
    case 'payment_intent.succeeded':
      const paymentIntent = event.data.object;
      // Then define and call a method to handle the successful payment intent.
      // handlePaymentIntentSucceeded(paymentIntent);
      break;
    case 'payment_method.attached':
      const paymentMethod = event.data.object;
      // Then define and call a method to handle the successful attachment of a PaymentMethod.
      // handlePaymentMethodAttached(paymentMethod);
      break;
    // ... handle other event types
    default:
      // Unexpected event type
      return response.status(400).end();
  }

  // Return a response to acknowledge receipt of the event
  response.json({received: true});
});

app.listen(8000, () => console.log('Running on port 8000'));
like image 206
bigpotato Avatar asked Oct 20 '25 15:10

bigpotato


2 Answers

You would need to migrate from apollo-server to apollo-server-express. Then you could add whatever additional endpoints you need. If you don't want to use Express, you can also utilize any of the other available integrations.

like image 187
Daniel Rearden Avatar answered Oct 22 '25 03:10

Daniel Rearden


here's how I set this up for anyone who stumbles on this. I'm using apollo-server-express:

import express from 'express';
import { createServer } from 'http';
import { pinoLogger } from './lib/logger.js';
import { graphql } from './api/graphql/server.js';

const PORT = process.env.PORT || 5001;

const app = express();
const httpServer = createServer(app);

// this is where I set up the ApolloServer with it's resolvers and schema
graphql({ app, httpServer });

app.post('/webhooks/stripe', async (req, res) => {
  const event = req.body;
  const logger = pinoLogger.child({ stripeEventId: event.id });
  logger.info('Received stripe event', { event });
  res.sendStatus(200);
})

httpServer.listen(PORT, () => {
  pinoLogger.info(`Server running at http://localhost:${PORT}/graphql`);
});
like image 21
Paymahn Moghadasian Avatar answered Oct 22 '25 04:10

Paymahn Moghadasian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!