#benjamin-fazli_checkout-subscriptions-saved-pms
1 messages · Page 1 of 1 (latest)
👋 Welcome to your new thread!
⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1349752132437282927
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
Is not showing the card, it has on the cards, so when a new payment happens so he can use it
When I go to the customer portal, i see the cart, is set as default
But when I create a new subscription, the card is not showing
How are you creating a new Subscription?
You can't create new Subscriptions via the Customer Portal.
So not exactly sure what you mean?
I'm doing it using create subscription api, not in portal
import type { StripePayloadType, SubscriptionBuilderFunctionProps } from '@/ts'
import { FREE_TRIAL_DAYS, PLAN_PERIODS } from '@/data/constants'
import { STRIPE_REDIRECT_URL } from '@/data/constants/Envs'
const SubscriptionBuilder = (props: SubscriptionBuilderFunctionProps): unknown => {
const {
user,
period,
monthlyPlanId,
yearlyPlanId,
code
} = props
const planId = period === PLAN_PERIODS.MONTHLY ? monthlyPlanId : yearlyPlanId
const usedTrial = user.Subscription?.UsedTrial
const stripe_payload: StripePayloadType = {
mode: 'subscription',
payment_method_types: ['card'],
success_url: `${STRIPE_REDIRECT_URL}/?success=true`,
cancel_url: `${STRIPE_REDIRECT_URL}/?success=false`,
customer: user.StripeCustomerId,
allow_promotion_codes: true,
line_items: [
{
price: planId,
quantity: 1
}
]
}
if (code) {
const codeFormatted = code?.toLocaleLowerCase().trim()
if (!stripe_payload.metadata) stripe_payload.metadata = {}
stripe_payload.metadata.referrer = codeFormatted
}
if (!usedTrial) {
if (!stripe_payload.subscription_data) stripe_payload.subscription_data = {}
stripe_payload.subscription_data.trial_period_days = FREE_TRIAL_DAYS
}
return stripe_payload
}
export default SubscriptionBuilder
See: https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-customer which explains how this works:
In subscription mode, the customer’s default payment method will be used if it’s a card, otherwise the most recently saved card will be used.
Of course when the user has cards from before for some reaon
So does the customer have a different card set as their default?
Unfortunately Checkout will never show a list of options
It will only pre-fill one card if applicable
No, its the same card
It has only one card, that previously used to do a subscription
Still is not showing that option
Can you share the Customer ID and Checkout Session ID that you are testing with?
Yes, wait for me a little
For example I also want to pay an invoice
I click it and it doesnt show the default card below
Here then is the checkout with no card prefilled
Also when i try to do another subscription with the same user, that has the default card, is not showing it on the checkout
CustomerId: cus_Rt0E9j7Dbfvua4
Stripe Checkout: https://checkout.stripe.com/c/pay/cs_live_b1YcChckr3A3yDCI8sgj8dPfjMsiSY118HcqVjW9blyyPS0FE9GlNxKRc0#fid2cGd2ZndsdXFsamtQa2x0cGBrYHZ2QGtkZ2lgYSc%2FY2RpdmApJ2R1bE5gfCc%2FJ3VuWmlsc2BaMDRVNGprREJLVzxSPEpjS2hQMHd9ZEZfSUx0ZGx1bjY8SVxjTTVuTnZfdzFQdkxJZm1ia090VX9DTH9vbHVXNXNvVWhIb29tREBWXTZQbGI3YDZBVmRDTEo1NTc2alNwVEZmJyknY3dqaFZgd3Ngdyc%2FcXdwYCknaWR8anBxUXx1YCc%2FJ2hwaXFsWmxxYGgnKSdga2RnaWBVaWRmYG1qaWFgd3YnP3F3cGB4JSUl
Looking
Ah okay from the doc I shared above:
A valid billing address, billing name and billing email are required on the payment method for Checkout to prefill the customer’s card details.
That PaymentMethod does not have a billing address collected
So it can't be prefilled
Okay sure
thanks then
I have
Another question, can i ask it here
But is not that much related with this one i had
Yeah you can ask here
subscription_data: {
payment_behavior: 'error_if_incomplete'
},
error: Invalid subscription_data[payment_behavior]: must be allow_incomplete
is not allowing me to set this opton, so if a payment is failed to not show as incomplete, or payable invoice
In the example you provided you used payment_behavior: 'default_incomplete' which is the correct behavior to use here.
Why are you trying to use error_if_incomplete?
Ah sorry!
I mixed up with another thread.
because its creating subscriptions, even if the payment fails
I don't want that behaviour
If a payment fails, I want to consider its as failed without creaitng a bill nor susbcription
Using the pre-collected PaymentMethod still, yes?
You are not talking about Checkout here
import { FREE_TRIAL_DAYS, PLAN_PERIODS } from '@/data/constants'
import { STRIPE_REDIRECT_URL } from '@/data/constants/Envs'
const SubscriptionBuilder = (props: SubscriptionBuilderFunctionProps): unknown => {
const {
user,
period,
monthlyPlanId,
yearlyPlanId,
code
} = props
const planId = period === PLAN_PERIODS.MONTHLY ? monthlyPlanId : yearlyPlanId
const usedTrial = user.Subscription?.UsedTrial
const stripe_payload: StripePayloadType = {
mode: 'subscription',
payment_method_types: ['card'],
success_url: `${STRIPE_REDIRECT_URL}/?success=true`,
cancel_url: `${STRIPE_REDIRECT_URL}/?success=false`,
customer: user.StripeCustomerId,
allow_promotion_codes: true,
subscription_data: {
payment_behavior: 'error_if_incomplete'
},
line_items: [
{
price: planId,
quantity: 1
}
]
}
if (code) {
const codeFormatted = code?.toLocaleLowerCase().trim()
if (!stripe_payload.metadata) stripe_payload.metadata = {}
stripe_payload.metadata.referrer = codeFormatted
}
if (!usedTrial) stripe_payload.subscription_data.trial_period_days = FREE_TRIAL_DAYS
return stripe_payload
}
export default SubscriptionBuilder
i read that i need to add it on the checkout, when the checkout its inicalized
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
With Stripe Checkout you don't control payment_behavior
You can't prevent a Subscription from being created if you are using Stripe Checkout
That is for the Subscriptions API
The code you provided above is for the Checkout Session API
The Subscriptions API creates the Subscription directly and you use a pre-collected PaymentMethod to charge the initial invoice or you use a custom flow using Stripe Elements to collect a payment method.
Stripe Checkout is our hosted solution where you just redirect your customer to the checkout page and we both start the Subscription and collect the payment method.
okay makes sense
but how can i manage this on checkout then
as this is how we do currently
and we do not want that behaviour
You can't
what
A Subscription is always created if you use Stripe Checkout
why that 😦
It will expire in 23 hours if the initial payment fails
yes but i don't want that behaviour
is there any altnerative?
in the sense to handle this
to delete this inital payment
on fail
or soemthing?
Yes if you use the Subscriptions API directly.
But no not if you use Stripe Checkout
Yes but
There should be an alentavie
Can i delete the inital payment fail?
so to listen wehen that fails and the ndelete it
so its kinda the same effect?
Yes you can cancel the Subscription, sure.
You could use https://docs.stripe.com/api/subscriptions/cancel
And then also void the initial Invoice
Thanks, is there
A custom event that triggers? on this incomplete period
So i can cancel that subscription and also void the same invoice attached to it?
Why do you want to do this immediately instead of just waiting the 23 hours for this to happen automatically?
If you do this immediately then your customer could still be on the checkout page trying to pay with a different payment method
Its fine
I cancel all the tries
If all fail then i dont mind it, if it pays i dont touch those
I also think this should be an option on checkout, same as it is on the stripe create
Sure I can file some feedback internally about that.
You would need to listen for eithe payment_intent.payment_failed or invoice.payment_failed
But neither of these are unique to this situation.
So when you receive that Event you need to check if the Subscription is in an incomplete status
I highly recommend you don't do this
You just let the Subscription expire if payment fails
Okay makes sense
I will do because I don't want Stripe to try to charge the user again after 24 hours, nor show invoices due to pay on Stripe Portal.
Does payment_Failed invoice includes in the object if it was incomplete? or we need to do another request to check the subscription?
The Subscription would move to incomplete_expired after 23 hours and the Invoice would be automatically voided at that point as well... we already do this for you.
No, you would need to retrieve the relevant object and then expand to the Subscription level
you mean retirve the subscription, not the object
because the object its included on the event that comes from stripe, right?
You retrieve the object within the Event and expand the necessary properties to get to the Subscription. See: https://stripe.com/docs/expand for how expansion works
try {
const customerId = event.data.object?.customer```
for example here i get the customerId
can you help me clarify more?
When you receive invoice.payment_failed you use https://docs.stripe.com/api/invoices/retrieve to retrieve the Invocie using its ID and then you also pass expand: ['subscription'] in that request (see: https://docs.stripe.com/api/expanding_objects) and then the response will include the full Subscription object as well so you can check the status from there.
Yes, so its not included in the default object, we need to retrive the invoice, then vodi it
But what about that specific subscription it created, it is included on the invoice or in the default event that comes on payment_failed webook
I just explained above how you get the Subscription... it is a property on the Invoice object: https://docs.stripe.com/api/invoices/object#invoice_object-subscription
So you must expand it to see its details.
When you receive Webhooks properties are never expanded.
Sorry, I'm trying to understand you dont be harsh to me hehe
So you need to make a separate request to retrieve the object and expand those properties that you care about (in this case, subscription)
Best thing to do at this point is test it out!
okay so i need to get the invoice object, then the subscrption object, then cancel the subscription with the id, and also void the invoice with the id
but if i have the invoice id, and subscription id on the default event, then i dont need to exctend just call the methods to do those two operaitons
this is what i mean
t
Yep, so 3 requests after receiving the Webhook.
- Retrieve Invoice (and expand
subscriptionto check the Subscription status)
Then if Subscription is in astatus: incomplete - Cancel Subscription
- Void Invoice
Thanks much, you really helped me alot
Happy to help!
hello i need help not even stripe support can help me. what is this? it says contact support. support can't help me
@maiden forge looks like you're in the wrong place, this thread is for someone else's question.
- If you have your own thread please chat there.
- If you have a question or a followup to a closed thread use one of the buttons in https://discord.com/channels/841573134531821608/842637025524842496 to get help (we don't reopen closed threads).
Note that posting inappropriate messages in other people's threads is against the rules. No worries if this was just an honest mistake, but anyone who violates the rules multiple times will be removed from this server.
@maiden forge this is not your thread. Please stop posting here.
ok