7

I'm having issues linking stripe webhooks to customers, since I generally use the client_reference_id or metadata field, however subscription webhooks seem to not have these fields. For example the event checkout.session.completed does contain the client_reference_id, whereas invoice.paid does not.

NodeJS code to generate payment:

        const session = await stripe.checkout.sessions.create({
            payment_method_types: ['card'],
            line_items: [
            {
                price_data: {
                    currency: 'usd',
                    product_data: {
                        name: `Premium license`,
                    },
                    unit_amount: 600,
                    recurring: {
                        interval: "month",
                        interval_count: 1
                    },
                },
                quantity: 1
            }],
            subscription_data: {
                trial_period_days: 1,
            },
            metadata: { 'userId': userId },
            client_reference_id: userId,
            mode: 'subscription',
            customer_email: customerEmail,
            success_url: `...`,
            cancel_url: `...`,
        });
Ignas Sadonis
  • 73
  • 1
  • 4

2 Answers2

4

Yes, it's a major missing that there is no option to link between events. This becomes critical when you can't rely on the order of webhook events.

I did work around this using metadata though. Pass your own reference id, say, my_database_reference_id to the metadata of both checkout.session.create and also in the subscription_data in checkout creation. This can be the same value you pass inside client_reference_id. Now you can use this while listening to webhook, to connect between the checkout session and subscription object, irrespective of the order it comes in.

NB: Please be warned that metadata can be edited by the Stripe Account, so please be careful if you are a platform and relying on this for any logic.

Ousmane
  • 2,673
  • 3
  • 30
  • 37
Abdul Vajid
  • 1,291
  • 1
  • 15
  • 25
1

The client_reference_id is a property of Checkout Session objects in Stripe, but not any other Stripe objects.

Subscription events (like customer.subscription.created) describe Subscription objects, and Invoice events (like invoice.paid) describe Invoices, neither of which are Checkout Sessions, so the property is missing.

Typically the way all of this is linked together is with the Customer object (cus_123) in Stripe, which should be present on all of the events mentioned in the customer property. Checkout will create the Customer object for you if you don't specify an existing one.

Justin Michael
  • 5,634
  • 1
  • 29
  • 32
  • But we still need to add some metadata in the customer to have access to the user id right? – Sandro_V Dec 22 '21 at 12:27
  • Yes, if you want to store arbitrary information (like the user ID from your system) you can use [metadata](https://stripe.com/docs/api/metadata), which can be set on many Stripe objects. – Justin Michael Dec 22 '21 at 17:34
  • 1
    I don't see how an authenticated user's ID in a system is arbitrary to the end-to-end events involved in checkout. If a session uniquely involves a single checkout, why wouldn't subsequent events generated due to that session not carry along this crucial information? This seems like a stripe business decision to make developers lean toward using stripe customer objects as keys, unnecessarily enmeshing systems with Stripe. – Rob Jan 03 '22 at 07:19