What are the best practices for webhooks in actions?
Can I encapsulate the Stripe webhook into my convex Action when I'm using the Stripe integration project? I tried using httpAction before, but encountered verification errors that prevented it from working. Here is the API code in my Next.js application:
27 Replies
Here is my http api code:
My development environment consists of Next.js v12 + Node v20 + Convex v0.16.
Invoking the API request returns a 500 status code, along with the following error message:
Additionally, I have implemented relevant validations within the create function.
Is there a way for me to migrate this webhook API from Next.js to a convex Action, thereby avoiding the use of httpAction?
Hey @Francismiko, ingesting stripe webhooks with
httpAction
is totally possible! In this case, it looks like your xxx:create
function is expecting auth to be setup, but since this request is coming from stripe, there is no user to authenticate. So, I'd recommend using an internalMutation
here instead so it can only be run by other convex functions
You can certainly migrate this next function to Convex! I've done this in one of my apps before, I can send you an example in a bit, once I make it into the officeThank you very much @ari , and I noticed that the official documentation has an integration usage of ConvexHttpClient with Next.js. I'm not sure if this would also work for my webhook or if the authorization issue would still arise.
Oh hm I see! Would you like to keep using nextjs for receiving the stripe webhook? You can actually setup convex to replace that nextjs function altogether!
Stripe can send the webhook events directly to your convex httpAction, and that action could do the stripe webhook secret validation, and perform all your mutations
(Going afk to drive in to work, but will be back in about an hour)
@Francismiko essentially, what arnold is suggesting is the http action can be the webhook and authenticate the call from stripe. and then you can call subsequent "internal" mutations without worrying about authentication information tunneling into that layer because convex ensures internal mutations can only be called by your own code, by authorized contexts
Internal Functions | Convex Developer Hub
Internal functions can only be called by other functions
Cool! I get it. I can use the convex http action as the endpoint for the webhook, without the need for an additional Next/api. This way, I can avoid the hassle of passing authentication around.
you got it
This is the code after I migrated to http action:
but errors occurred:
Can you provide me with some more guidance? Thank you very much!
looks like your action is bundling vercel open graph image generation stuff. I'm guessing you probably don't need that in your webhook. maybe @presley has an idea here on how to manage this?
Ah! I found the cause of this bug. It was due to referencing the stripe object defined in Next.js from within Convex, resulting in an incompatible runtime environment error. After redefining a new stripe object, the bug was resolved.
Thank you to the developers of Convex @jamwt @ari for their assistance. If there are any issues regarding webhooks in the future, I will continue to follow up here. 🙂
sounds great @Francismiko ! glad to hear you're unblocked and moving forward on your project.
Can someone give me a sample code about stripe webhook? Because it takes the original object of the request (buffer or string) as a parameter.
Something err like this:
400 Bad Request: InvalidModules: Loading the pushed modules encountered the following
error:
Failed to analyze http.js: Uncaught ReferenceError: Event is not defined
at <anonymous> (../node_modules/stripe/esm/StripeEmitter.js:6:16)
When I refer here: https://discord.com/channels/1019350475847499849/1100122735872577596/1100122735872577596. After I migrated the steps of instantiating stripe to action, new error content appeared:
Discord
Discord - A New Way to Chat with Friends & Communities
Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.
Hey, this does look like an odd error! Would you mind sharing the code you have so far? Feel free to DM it to me, but be sure to remove any secrets from the code
@ari Of course I can! Here is my code in the project:
action.ts
http.ts
At first I thought that the reason for the error was that I did not pass the original object of the request as a parameter to the stripe webhook (http defaults to the
Request
type of the fetch api? I am not sure if this has any effect) but after debugging, I found that the same error still occurs , so the possibility of this error should be ruled out?
By the way, I am using version 0.16 of convexThanks! OK I see what's going on now. the
createStripe
action returns the stripe class, but you can't exchange classes between convex actions, only data. My suggestion would be to use your HTTP action only for processing the request an response, and pushing all the logic down into a single internalAction
The code would roughly look like this:
Awesome! Now all the issues with webhooks are finally resolved perfectly. If in the future we can "use node" in HTTP, then can we migrate the core logic to it without the need to define it in the action (although that way is also concise)?In any case, I'm extremely grateful for @ari assistance!
Awesome glad it's working! Time to get paid with Stripe 😄
For anyone finding this thread in the future, we put out a Stack article describing an end-to-end Convex integration with Stripe, with a working code repo and demo.
https://stack.convex.dev/stripe-with-convex
Wake up, you need to make money! (ft. Stripe)
If you’re building a full-stack app, chances are you’ll want some of your users to pay you for the service you provide. How to use Stripe with Convex ...
Thanks for the article, I'm most of the way through but stuck on the webhooks.
Is there anything else that needs to be done to allow the webhooks to call?
It's a 404 from the stipe end
The endpoint shows up in the convex dashboard but it's never been hit
I'm probably missing something simple
Okay, I figured it out!
It wasn't clear on the article that it was meant to point to
".convex.site"
I had it pointing to:
"convex.cloud/stripe"
Thanks for following up!
No problem, looks like I'm going to be using convex on my Project so happy to post solutions if I find them.