#Timmmy-subscription-events
1 messages ยท Page 1 of 1 (latest)
It really depends on your integration/what you need, but another one that a lot of integrations listen for is invoice.paid and invoice.payment_failed to be notified of payment success/failure
I just want to make sure users that pay 100% get access to what they paid for
and users that cancel should loose their access
CheckoutSessionCompleted != Paid right?
A Checkout Session completing in subscription mode typically does mean that payment has been made
So should I give the user access in CheckoutSessionCompleted or in CustomerSubscriptionCreated
I would do CheckoutSessionCompleted - in general flows CustomerSubscriptionCreated does not mean that a subscription has been paid for
CustomerSubscriptionCreated what is that used for then=
Sorry for all these questions
I just want to make sure this works haha
No worries at all! CustomerSubscriptionCreated tells you that a Subscription object has been created, but depending on your integration that does not necessarily mean that payment has been made since you can create a subscription with payment_behavior: default_incomplete (which won't complete payment during the creation step).
Alright so I dont even need to have that right? (CustomerSubscriptionCreated )
And do I need CustomerSubscriptionUpdated if I only have one product (one package the customer can choose)
If you don't need it you don't have to use it - one reason why a user may choose to use CustomerSubscriptionCreated is that they want the information that is provided in that webhook event since it would be slightly different compared to what is in CheckoutSessionCompleted
For CustomerSubscriptionUpdated again it really is up to you and what your webhook is doing/controlling - if you need to keep track of the billing cycles as they renew then the updated event will notify you of that (and that's just one example use case) but if you don't need it at all then you don't have to use it
Awesome thanks
so In theory
this should be enough to make sure paying customers get access
and not paying customers loose access
switch (stripeEvent.Type)
{
case Events.CheckoutSessionCompleted:
user.StripeCustomerId = subscription.CustomerId;
user.SubscriptionType = "basic";
break;
case Events.CustomerSubscriptionDeleted:
user.SubscriptionType = string.Empty;
break;
default:
_logger.LogWarning("Unhandled event type: {0}", new { stripeEvent.Type });
break;
}
Something you'll want to make sure you have configured is that your dashboard settings are set up so that if all payment retries fail for a subscription it automatically cancels. You can check that at https://dashboard.stripe.com/settings/billing/automatic under the "Manage failed payments for subscriptions" section for "Subscription status" you would control the behavior by selecting an option for "If all retries for a payment fail"
yup! That way if all payments fail for a subscription it will automatically cancel and send the CustomerSubscriptionDeleted event
Awesome thanks
switch (stripeEvent.Type)
{
case Events.CheckoutSessionCompleted:
user.StripeCustomerId = subscription.CustomerId;
user.SubscriptionType = "basic";
break;
case Events.CustomerSubscriptionDeleted:
user.SubscriptionType = string.Empty;
break;
default:
_logger.LogWarning("Unhandled event type: {0}", new { stripeEvent.Type });
break;
}`
this should do the trick then
thanks for your help
๐ and one more thing I do want to call out - your settings are currently made to retry 4 times within 3 weeks, so a subscription won't be cancelled until 3 weeks after the failed invoice was created
Sorry let me clarify - if you look under "Use Smart retries for subscription" it says "Retry up to 4 times within 3 weeks". That means the last retry could happen 3 weeks after the invoice was first created. Since you subscriptions will only automatically cancel after all retries fail that means it could be three weeks until it is automatically cancelled. If you want it to happen at a faster pace then that you'd simply change the retry setting
that makes more sense I guess
that way if a user doesnt pay
it will cancel within a week right?
yup! that's the idea ๐
There's so much variety in billing/subscription integrations that it's hard to pick a default that fits everyone's use case. I'd really just suggest you try the whole flow out in test mode to make sure everything behaving like you'd expect it to
Yeah I need to figure out how to test webhooks
seems a bit complicated tbh
anyway
thats probably it for now
so thanks a lot for your help and have a good day โค๏ธ
๐ happy to help!
this is gonna be a bit off-topic
Do you just help people on this discord while working at Stripe
Or is there something like Discord duty ๐
because you guys provide great help
We have a team of folks that rotate out to help here ๐
As an example, my shift is actually done, so @old crest is here if you happen to have any follow-ups
nah, I'm at the start of my day but thank you! and i hope the rest of your integration goes well!
Oh have a good day then, thanks ๐
Okay so I actually encountered a smoll problem
var stripeEvent = EventUtility.ParseEvent(json);
stripeEvent = EventUtility.ConstructEvent(json,
Request.Headers["Stripe-Signature"], endpointSecret);
Subscription subscription;
ApplicationUser user;
switch (stripeEvent.Type)
{
case Events.CheckoutSessionCompleted:
subscription = stripeEvent.Data.Object as Subscription;
user = await _userManager.FindByIdAsync(subscription.Metadata["UserId"]);
subscription == null for some reason
even though I just copied what is described in the quick start guide:
https://stripe.com/docs/billing/quickstart
stripeEvent.Data.Object is not empty btw
Interesting, what is it then?
what do you man? ^^
What is stripeEvent.Data.Object?
And thank you for the assist in the main channel by the way!
{<Stripe.Checkout.Session@35686241 id=cs_test_a1ZaIjXOb5M1FnXmYWn2igL22hSSHks7eQQxamyOQG1aHFbmXGSGScXM3b> JSON: {
"id": "cs_test_a1ZaIjXOb5M1FnXmYWn2igL22hSSHks7eQQxamyOQG1aHFbmXGSGScXM3b",
"object": "checkout.session",
"after_expiration": null,
"allow_promotion_codes": null,
"amount_subtotal": 3500,
"amount_total": 3500,
"automatic_tax": {
"enabled": false,
"status": null
},
"billing_address_collection": null,
"cancel_url": "https://localhost:7191/Payment/CancelProcess",
"client_reference_id": null,
"consent": null,
"consent_collection": null,
"currency": "eur",
"customer": "cus_KwNZxk9y5bf1If",
"customer_details": {
"email": "my.email@protonmail.com",
"phone": null,
"tax_exempt": "none",
"tax_ids": []
},
"customer_email": null,
"expires_at": 1641934122,
"line_items": null,
"livemode": false,
"locale": null,
"metadata": {
"UserId": "4ce6d793-8c43-42b9-9b3a-10d49efe97fa"
},
"mode": "subscription",
"payment_intent": null,
"payment_method_options": {
"acss_debit": null,
"boleto": null,
"oxxo": null
},
"payment_method_types": [
"card"
],
"payment_status": "paid",
"phone_number_collection": {
"enabled": false
},
"recovered_from": null,
"setup_intent": null,
"shipping": null,
"shipping_address_collection": null,
"shipping_options": [],
"shipping_rate": null,
"status": "complete",
"submit_type": null,
"subscription": "sub_1KGUnuIqNhXOt8bgVYANh5XN",
"success_url": "https://localhost:7191/Payment/Success?sessionId={CHECKOUT_SESSION_ID}",
"tax_id_collection": null,
"total_details": {
"amount_discount": 0,
"amount_shipping": 0,
"amount_tax": 0,
"breakdown": null
},
"url": null
}}
I hope that doesnt contain any secrets ๐
No worries you guys help me a lot so I might as well try to be at least a bit helpful ๐
Also the first part of that json looks a bit weird tbh (maybe that causes the trouble?)
Don't worry, that object is safe to share here.
And ah that makes sense. Try casting it to a Stripe.Checkout.Session
That object is not a subscription so it won't be able to cast to one
Eyy it works
Great to hear!
btw what object does CustomerSubscriptionDeleted return?
and is the object that is returned by the event always the same?
The type of object? Yes
That object will be a Subscription https://stripe.com/docs/api/events/types#event_types-customer.subscription.deleted
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Interesting is the documentation just not up to date or does the type somehow change?
The doc for the checkout session completing says it will be a checkout session https://stripe.com/docs/api/events/types#event_types-checkout.session.completed
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Do you know what doc said it should be a subscription?
I will put in feedback to correct it
wait let me double check the events first
nvm I confused CheckoutSessionCompleted with CustomerSubscriptionCreated sorry my bad
Ah, glad we could clear that up
Depending on your needs you can definitely just listen to that event as well
Really? I have been told that CustomerSubscriptionCreated does not always mean that the user paid
No worries at all!
CustomerSubscriptionCreatedtells you that a Subscription object has been created, but depending on your integration that does not necessarily mean that payment has been made since you can create a subscription with payment_behavior: default_incomplete (which won't complete payment during the creation step).
Apologies, missed that context. They were correct, the checkout session completed event makes much more sense for your scenario.
Of course, have a good day yourself
thanks ๐