Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

firebase function for stripe webhook does not work with async-await

I am using the excellent stripe documentation to build a webhook to respond to a stripe successful payment. The code works fine however as soon as I introduced async-await, I get a 500 Internal server error.

I am testing the firebase onRequest webhook function through the send test webhook on the stripe website. My code lives here

What am I missing?

firebase function with async-await does not work:

exports.stripeEvents = functions.https.onRequest(async (request, response) => 
{
  try
  {    
    let stripesignature = request.headers['stripe-signature'] as string;
    let stripeevent:Stripe.Event= stripe.webhooks.constructEvent(request.rawBody.toString('utf8'), stripesignature, config.stripewebhooksecretkey);

    if(stripeevent.type === 'payment_intent.succeeded')
    {
      let payment_intent1 = stripeevent.data.object as Stripe.PaymentIntent;
      let datafirstelement=null;
      if(payment_intent1?.charges?.data && payment_intent1?.charges?.data.length>0)
      {
        datafirstelement=payment_intent1?.charges?.data[0];
      }        
      let userid='someuserid';
      let documentreference=config.db.collection('users').doc(userid);
      await documentreference.update({payments: admin.firestore.FieldValue.arrayUnion(datafirstelement)}); 
      response.status(200).send({'result':true});
    }
  }
  catch(error)
  {
    //log error into sentry
    throw error;
  }
});

firebase function without async-await, works:

exports.stripeEvents = functions.https.onRequest((request, response) => 
{
  try
  {    
    let stripesignature = request.headers['stripe-signature'] as string;
    let stripeevent:Stripe.Event= stripe.webhooks.constructEvent(request.rawBody.toString('utf8'), stripesignature, config.stripewebhooksecretkey);

    if(stripeevent.type === 'payment_intent.succeeded')
    {
      let payment_intent1 = stripeevent.data.object as Stripe.PaymentIntent;
      let datafirstelement=null;
      if(payment_intent1?.charges?.data && payment_intent1?.charges?.data.length>0)
      {
        datafirstelement=payment_intent1?.charges?.data[0];
      }        
      let userid='someuserid';
      let documentreference=config.db.collection('users').doc(userid);
      //await documentreference.update({payments: //admin.firestore.FieldValue.arrayUnion(datafirstelement)}); 
      response.status(200).send({'result':true});
    }
  }
  catch(error)
  {
    //log error into sentry
    throw error;
  }
});

update 1: I am testing the firebase onRequest webhook function through the send test webhook on the stripe website.

successful stripe payments when not using async-await, internal server error when using async-await:

enter image description here

webhook success logs when not using async-await(and no logs when using async-await):

enter image description here

update 2: firebase function log:

stripeEvents
Error: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.
    at Object.validateResourcePath (/workspace/node_modules/@google-cloud/firestore/build/src/path.js:403:15)
    at CollectionReference.doc (/workspace/node_modules/@google-cloud/firestore/build/src/reference.js:1988:20)
    at exports.stripeEvents.functions.https.onRequest (/workspace/lib/index.js:115:85)
    at cloudFunction (/workspace/node_modules/firebase-functions/lib/providers/https.js:51:16)
    at process.nextTick (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:99:17)
    at process._tickCallback (internal/process/next_tick.js:61:11)

update 3: firebase function log: I changed line await documentreference.update({payments: //admin.firestore.FieldValue.arrayUnion(datafirstelement)}); to await documentreference.set({payments: admin.firestore.FieldValue.arrayUnion(datafirstelement)}, {merge:true}); and the application still throws the following errors. The code lives here.

12:02:30.464 AM
stripeEvents
Function execution started 
12:02:54.174 AM
stripeEvents
Function execution started 
12:02:54.901 AM
stripeEvents
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason: 
12:02:54.905 AM
stripeEvents
Function execution took 732 ms, finished with status: 'crash' 
12:03:30.467 AM
stripeEvents
Function execution took 60004 ms, finished with status: 'timeout' 
like image 730
Ajit Goel Avatar asked Dec 18 '25 10:12

Ajit Goel


1 Answers

From the comments above and from the error you get (Error: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.), it seems that the value you pass to the doc() method while testing your Cloud Function is an empty string.

You need to mock data in your test in order to pass a correct value to the doc() method.


Note that I’m not sure that testing it "from the web application" (as you mention in the comments above) will change something, since the stripe Webhook has nothing to do with your web application (the Stripe backend calls your backend, i.e. your Cloud Function). You may send the userId as payment metadata to Stripe and (1) add it as query string parameter to the URL called by the webhook and (2) parse and use this value in your Cloud Function.


Note also that the difference between your "async version" that does not work and you "non async version" that works is not about async/await but is just that you comment out the line that generates the error.

like image 176
Renaud Tarnec Avatar answered Dec 21 '25 04:12

Renaud Tarnec



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!