#dev-commerciax_api
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/1413112578783055932
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
hey there! looking into your question now
Sure, If you need any details, do ask for ti
hi there!
*it
you should use proration_behavior: 'always_invoice'
We tried
But what's happening is before we can authentication 3ds, the webhook recieved payment failed
and why is that an issue? what are you trying to do exactly?
we are trying to allow user to upgrade subscripiton, And It works fine with first paid plan. but when user upgrades from one paid plan like Rs.349 to Rs. 699 some kinda error always occurs.
it works with create_prorations and default_incomplete but then it sends the remaining balance to next invoice
But we want to change immediately
some kinda error always occurs.
which error? can you share a failed Request ID (req_xxx)?
but this setting: proration_behavior: 'always_invoice', payment_behavior: 'allow_incomplete', always gives some kinda error
also, are you aware of Pending Updated? https://docs.stripe.com/billing/subscriptions/pending-updates
sure
Yes
I am really sorry, It's taking us long to look for specific failed events as we have already tried a lot of things. here's one for ya: https://dashboard.stripe.com/workbench/events/evt_1S3a4bSCN5U3Z9OGP5yt85hp
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Taking a look
Not seeing any failing update calls to the related subscription: sub_1S3ZweSCN5U3Z9OGqhLDaPx1
Let me look and share another one
But this is basically what we are doing:
items: [{ id: stripeSub.items.data[0].id, price: newPriceId }],
proration_behavior: 'always_invoice',
payment_behavior: 'allow_incomplete', // :warning: allows requires_action
collection_method: 'charge_automatically',
expand: ['latest_invoice.payment_intent'],
});
const invoice = updatedStripeSub.latest_invoice;
const paymentIntent = invoice?.payment_intent;
if (paymentIntent?.status === 'requires_action') {
console.warn(
`[upgradeSubscription] Payment requires customer action (3DS/SCA)`,
);
return responseHandler(res, 'Action required for payment', 200, {
data: {
requiresAction: true,
clientSecret: paymentIntent.client_secret,
},
});
}```
OK, but what's the exact issue with that API request? Does it error? What's the unexpected behaviour?
So, basically what's happening is client secret is recieved from payment intent but before frontend could process that for 3ds auth, the subscripiton status goes to past due
getting this:
0|backend | oldPriceId: 'price_1RRo04SCN5U3Z9OGvfbs2JT9',
0|backend | newPriceId: 'price_1RRoUMSCN5U3Z9OG5hlHIHCF'
0|backend | }
0|backend | [upgradeSubscription] Error during Paid→Paid upgrade {
0|backend | message: 'Only active mandates can be used with PaymentIntents.',
0|backend | stack: 'Error: Only active mandates can be used with PaymentIntents.\n' +
0|backend | ' at generateV1Error (/home/backend/_work/neweb-backend-2/neweb-backend-2/node_modules/stripe/cjs/Error.js:11:20)\n' +
0|backend | ' at res.toJSON.then.Error_js_1.StripeAPIError.message (/home/backend/_work/neweb-backend-2/neweb-backend-2/node_modules/stripe/cjs/RequestSender.js:108:62)\n' +
0|backend | ' at process.processTicksAndRejections (node:internal/process/task_queues:105:5)'
0|backend | }
0|backend | payment_intent.created
What's the client_secret?
paymentIntent.client_secret
coming from this:
const invoice = updatedStripeSub.latest_invoice;
const paymentIntent = invoice?.payment_intent;
which is coming from here:
const updatedStripeSub = await stripe.subscriptions.update(stripeSub.id, {
items: [{ id: stripeSub.items.data[0].id, price: newPriceId }],
proration_behavior: 'always_invoice',
payment_behavior: 'allow_incomplete', // ⚠️ allows requires_action
collection_method: 'charge_automatically',
expand: ['latest_invoice.payment_intent'],
});
I mean the actual client_secret value. I need some kind of object/ID so I can see what's going on
we are not actually logging it
but it is something like in image: from frontend log -
Paste that pi_abc_secret_xyz please
pi_3S3YPwSCN5U3Z90G1mxoB0s0_secret_E2njUghG5urPmkVzmK2TXzztE
Doesn't seem like a valid ID to me – can't find it in our system
try this one: pi_3S3bBTSCN5U3Z9OG0apDPZLa_secret_EGLaUdCZ7vtIgWXeEdKkaHLbs
Taking a look
sure, take your time
So yes, the subscription update (https://dashboard.stripe.com/logs/req_56B1GaNvs5FsPy) triggers a new invoice (and payment) which we try to charge for immediately. That fails however as 3DS/auth was requested (invoice.payment_action_required: https://dashboard.stripe.com/events/evt_1S3bBXSCN5U3Z9OG6u8Acgb2)
In that scenario, yes the subscription will transition to past_due as explained here:
Payment on the latest finalised invoice either failed or wasn’t attempted
You need to re-confirm the intent on the front-end via Stripe.js with your customer on-session to complete the 3DS/auth request and on success the subscription will transition to active
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
We are doing it but still the same error
I don't see any additional confirmation attempts on that PI
That's the exact problem. before we could make 3ds auth on frontend, the webhook updates the subscripiton status to past due
Yes, no additional attempts has been made
on the frontend, we are doing this:
if (result?.type === "requires_action") {
// 👇 Use Stripe.js to confirm payment
const stripe = await stripePromise;
const { error, paymentIntent } = await stripe.confirmCardPayment(
result.payload?.clientSecret
);
if (error) {
toast.error("Authentication failed. Please try again.");
return;
}
if (paymentIntent.status === "succeeded") {
toast.success("Subscription upgraded successfully.");
await dispatch(userActions.refreshUserData(token));
window.location.href = `/billing/home?session_id=${Date.now()}`;
}
return;
}
Sorry I don'y fully understand the issue. You've not given me a Payment Intent where there's an actual confirmation error other than from the sub update
What happens when you run that code then?
Server gives 500, before this could process
That 500 must be returned from your code, because I see no 500s in the examples you've shared
👋 taking over for my colleague. Let me know if there's any follow-up Qs I can answer!
testing the new code right now
will update soon
THis is the updated code and what's happening is it taking the propation amount to the next invoice
no 3ds auth asked
what's the behavior you're expecting?
immediate charge with 3ds