0

I'm trying to listen for a Stripe webhook call, then carry out some actions such as sending an email. My site is on Netlify and I've adapted some code I found in a tutorial:

This works locally, but not when I run it as a Netlify function (basically a lambda). Basically, the part from "client.getSpace.." doesn't appear to run at all. I suspect this is something to do with using these .then promises within an async function, but I'm not sure.

require('dotenv').config();
     const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
    
     const contentful = require('contentful-management');
     const client = contentful.createClient({
      accessToken: 
    process.env.CONTENTFUL_CONTENT_MANAGEMENT_ACCESS_TOKEN
    });
    
    var postmark = require("postmark");
    var serverToken = process.env.POSTMARK_SERVER_TOKEN;
    var postmark_client = new postmark.ServerClient(serverToken);
    
    exports.handler = async ({ body, headers }) => {
    try {
      const stripeEvent = stripe.webhooks.constructEvent(
        body,
        headers['stripe-signature'],
        process.env.STRIPE_WEBHOOK_SECRET
      );
    
      if (stripeEvent.type === 'checkout.session.completed') {
       console.log('confirm checkout session completed');
        const eventObject = stripeEvent.data.object;
        const entryId = eventObject.client_reference_id;
        let email = "";
        let secret = "";
    
      client.getSpace(process.env.WEBSITE_CONTENTFUL_SPACE_ID)
       .then(space => space.getEnvironment('master'))
          .then(environment => environment.getEntry(entryId))
          .then(entry => {
           entry.fields.paymentStatus['en-GB'] = 'Paid';
           email = entry.fields.email['en-GB'];
           return entry.update();
          })
          .then(entry => entry.publish())
       .then(entry => postmark_client.sendEmailWithTemplate({
              "From": "x@test.com",
              "To": email,
              "TemplateId": 12345678,
              "TemplateModel": {
                  "abc": "xyz"
               }
            }))
          .catch(console.error)
    
      }
    
      return {
        statusCode: 200,
        body: JSON.stringify({ received: true }),
      };
      } catch (err) {
      console.log(`Stripe webhook failed with ${err}`);
    
      return {
        statusCode: 400,
        body: `Webhook Error: ${err.message}`,
      };
    }
    };
neetso
  • 15
  • 4
  • Did you try using `await` instead of `then` syntax? – Bergi Apr 29 '20 at 09:42
  • 1
    That `client.getSpace()` chain runs asynchronously, *after* you return a status code. Maybe netlify kills the environment when the handler returns? – Bergi Apr 29 '20 at 09:44
  • @Bergi - no, I didn't. All the examples I have for this (Contentful API) code use the then syntax. How would that look? – neetso Apr 29 '20 at 09:48
  • @Bergi - as to your second question, I was wondering that myself but the code in the if statement is run ... I confirmed that with console.log('confirm checkout session completed'); – neetso Apr 29 '20 at 09:50

1 Answers1

0

For what it's worth to you and anyone else who comes across this question. I had a similar issue using NextJS on Vercel. I rewrote the .then syntax using async/await and the problem seems to be solved, so far. I'm no expert, but I think in this case you would begin by replacing

  client.getSpace(process.env.WEBSITE_CONTENTFUL_SPACE_ID)
    .then(space => space.getEnvironment('master'))

with something like

       const send = await client.getSpace(process.env.WEBSITE_CONTENTFUL_SPACE_ID)
       const getEnvironment = await space.getEnvironment('master')

so on and so forth. I'm not sure how you would rewrite everything else, or if this will even help, but it put me back on track.

volare
  • 25
  • 8