Stripe webhook setup - Step-by-step

I don’t know how to do this.

Last week I was bale to work 15 hours a day straight trying to set up a webhook, but now I get such anxiety after 30 mins. I don’t know what has happened to my brain but maybe the fatigue after 120 hours on the same issue is causing me to understand less and less. Not sure if this is common amongst coders.

Do you (or anyone) know of a simple step-by-step tutorial?

Almost every Stripe event body object will include the attribute customer (if there is one) which is the customer ID.

So, after the User’s very first successful transaction, use the webhook request data to capture the customer ID and store in in your database on the User datatype.

I have read this sentence 10 times but I don’t understand it. I don’t know what’s wrong with me, I can see you have spelt it out clearly but something is not clicking, apologies for that.

I need screenshots, I can’t get it otherwise because I think this webhook task has adversely affected me and fatigued my mind. I will keep trying, but at a slower pace.

Specifically regarding saving the Stripe Customer ID this is how I do it in one of my apps…

It’s literally that simple.

I see, thank you Adam. That makes sense now. I am 5 minutes into repeating this tutorial and this time I am drawing diagrams on a piece of paper and noting the steps … going very slowly and carefully! I will refer to the Customer ID in my signup workflow so that I can reference that later.

@adamhholmes Forgive me for the long message, I felt my progress may be beneficial to others if documented step-by-step.

I have saved the Stripe Customer ID in a similar way to your screenshot above but still experiencing multiple issues. If you can spot any areas I am going wrong I would be most grateful.

Database set up

Most tutorials recommend adding fields in the User’s Data type for Stripe’s payment activity (such as SubscriptionEnd etc) but my User’s Data type has a lot of info and is at risk of being messy! So, I have created a new ‘Subscription’ Data type.

Here is how I am set up:

The User Data type refers to Subscription [Subscription] and I also have a Plan data type which has the default settings for a subscription plan so that I can refer to Plan’s first item.

Datatype: Plan

  • Fields: Description [Text]
  • Frequency [Text]
  • Name [Text]
  • Price [Number]
  • Stripe Price ID [Text]

I’m not sure if I should also have a Subscription field in the Plan Data type?

Stripe setup

I created a new product in Stripe and copied the API ID.

Then I added a ’ Pay now’ button on my website and opened it’s workflow:
Workflow step 1. “Subscribe the user to [API ID]”
Workflow step 2. “Make changes to a thing… Thing to change is Current User’s Subscription (see below)

Error: When a new user signs up, I want their Subscription Status to be predefined as ‘not_activated’. I have added the words ‘not_activated’ as a default in the SubscriptionStatus field, but when a User signs up the ‘SubscriptionStatus’ field is empty?

Displaying user information

New users to my site will see ‘You are on the free plan’ and I have conditions in place so that they see different messages after subscribing/cancelling.

Stripe customer portal

Now I want to give users the ability to cancel/edit their subscription. I’ve added a button to my website called ‘Manage Plan’ and in it’s workflow I add ‘Self Service Portal - Stripe Portal w/ dynamic return url’.

Customize customer portal

Note to newbies. You need to go to Stripe > Settings (cog icon) > Customer portal and make sure you have filled everything in. Be aware that the page layout is not great and whilst it looks like there are only two things to fill out, you need to scroll down to see more. Importantly, here is where you choose how to allow customers to end their billing. I have chosen ‘Cancel immediately’ so I can test cancellations easier.

Test signup

Error: When I checkout, Stripe says that a payment has been made but my database is empty?

Create Webhook

I set up a New API workflow…

I clicked on ‘Detect data’ and copied the data URL.

Note to newbies, DO NOT CLOSE THE DATA POPUP until you have completed the next steps.

Go to Stripe > Developers > Webhooks. Then Add endpoint and paste the data URL. I am listening for customer.subscription.deleted.

How to ‘sync’ Bubble and Stripe

Note to newbies, at this point you will see the new Webhook is 'Waiting for events …". To make it work you have to create a new user, pay for a subscription and then cancel it manually via Stripe’s interface by going to Customer > Click on customer and cancel immediately. Then check the webhook worked by going to Stripe > Developers > Events and you’ll see recent Webhook attempts. Also, go back to Bubble and you’ll see the data payload which has been sent (change object start_date to Date (UNIX).

My webhook appears to be active and set up correctly.

Make changes to a Thing based on the webhook data received.

In the API workflow, I make changes to a user’s subscription, I get the Customer ID and update the Status.

Note to newbies: If you’re wonder why I do a Search for instead of refering to the current user, it’s because a backend workflow can’t refer to Current User directly.

Note to newbies: Go to Stripe > Developers > Webhooks and remove ‘/initialize’ from the end of the webhook URL or it will not work again.

Test new user

I created a new user and signed up to a plan
I went to Stripe > Developers > Webhooks and refreshed the page, I see ‘Waiting for events …’ has cleared and “The endpoint test_webhook1 was successfully initialized”.

Error 1: Even though Stripe registered the new users payment, the fields in my ‘Subscription’ Data type are empty with no new payment info saved. Also, if I click the ‘Manage Plan’ button on my website I see an error preventing me from going to the customer portal (see below).

error

What are your search constraints when searching for the User in the API workflow?

The only constraint I have is for the Customer ID. When I click on ‘Search for’ in the right hand window (below) I get the second left window with the User constraint option.

So how are you setting Stripe Customer ID on the User datatype?

You’re a patient man @adamhholmes :slight_smile:

3 Likes

I was expecting the Request Data's object customer to be saved to the Stripe Customer ID on the User datatype as per the image above. Clearly this is wrong but this is how the tutorial did it and it worked for him!?

Are you saving the Customer ID to the User datatype?

Nothing you’ve mentioned or shown so far in this thread suggests that you are… but if you are then it should be working fine.

But my guess is that you’re not, which is why your search isn’t working.

The image you posted above had nothing at all to do with saving the Customer ID to the User datatype (unless you posted the wrong image by mistake)?..

I thought if I make changes to the User with the Request Data's object customer (as I have done) that would save the Customer ID to the User datatype, clearly not!

I have been thinking how to save the Customer ID to the User datatype, the User only get’s a Customer ID once they have subscribed in Stripe (as far as I am aware). Once subscribed, they are redirected back to my app, so perhaps I can save their Customer ID during this redirection.

The other idea I have is to redirect them to a separate group and have a workflow action trigger on page load, this action would automatically save their Customer ID.

May I ask how you save your Customer ID’s?

Yes, that’s exactly how you need to do it… but that’s not remotely what you’re doing in the screenshot you posted (unless you’re doing that anyway but just haven’t mentioned it or posted any relevant screenshots here…)

In the picture you posted you’re making changes to a Subscription, not a User, and you’re defining that subscription by doing a search for Users based on the Customer ID, which you haven’t yet set, so of course it won’t work.

Seriously (and don’t take this the wrong way), if you haven’t yet understood the difference between searching for data and making changes to data (which is about as basic and fundamental as it gets in Bubble) then you’re going to struggle with more complicated things like Webhooks (as is evident from this thread)…

Honestly, I’d recommend you taking a step back from what you’re currently doing to really try to get to grips with the basics (searching for data, making changes to things etc.)…

Otherwise you’ll just keep going round in circles and getting nowhere…

I don’t want to make changes to a User because I have the database set up to save it in ‘Subscriptions’. However, I had missed adding the CustomerID in the field to change.

In the below image, I select 'Make changes to a User’s:first item’s Subscription, this produces the following which doesn’t work.

1

I had another realisation, the test webhook is set up to listen for customer.subscription.deleted so the backend won’t trigger on checkout regardless. I assume when a user unsubscribes then the webhook will trigger and (if set up correctly) save the Stripe Customer ID. I will need to set up a workflow to trigger as soon as a user subscribes.

I appreciate your thoughts and I don’t take it the wrong way. I do, however think I understand (the basics of) searching for data, making changes to things etc. The other day I set up an ‘Expenses’ Datatype, I was able to save data fine and display data no problem, the expenses feature on my site is now complete. This webhook setup seems much harder for some reason.

Yes he is, and I am trying my best.

So what are the constraints on your search for Users now?

The constraints on the search for Users is still Stripe Customer ID = Request Data's object customer.

So you searching for users based on their Stripe Customer ID…

So I’ll ask once again, how/where are you setting the Stripe Customer ID on the User datatype in the first place?

Sorry I’m not avoiding that question, I thought Stripe saved that info automatically and the Request Data's object customer function would pull that in via the webhook.

However, when a user clicks the ‘Pay now’ button on my site I think I am saving the CustomerID (see below), although I sense something is not right.

I feel I should be creating a new ID using something like an email, soCustomerID = Current User's email. As you can tell, I have no clue how to save the Customer ID, reading the Stripe Documentation isn’t helping as there’s no reference to Customer ID, only Customer tax IDs.

I’m can’t test things easily currently, Earlier today I updated my DNS settings in Godaddy and now I’m getting a message that says “Sorry, your login session has changed / expired…please try again” when I try and log in on Preview. I’ve reached out to Bubble for help on this.