#paulc7053_webhooks
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/1279085561117675713
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Hello!
Hi ๐ are you talking about this Event?
https://dashboard.stripe.com/test/events/evt_1PtVGWJ4ILijjURSInZIwY6f
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
Wait, that's for the first Invoice isn't it?
It looks like the Invoice is still in a draft state, so the payment attempt hasn't happened yet which is why you haven't seen an invoice.finalized or payment related Events for it.
I'm not sure yet
No, I'm not spotting why this didn't progress.
Are you able to consistently reproduce this behavior?
yes...
tried it with multiple trial subs
and double-triple checked the webhook listens to the invoice events
Can you advance the billing clock like another hour? It's really close to the finalization time for the Invoice and I'm wondering if you've just not advanced past that yet. My test Invoice finalized fine.
Can you provide the ID of the Invoice that you're not seeing progress states?
yes
also I tried on another subscripion, and this one seems to give out payment vailed evt_1PtWHpJ4ILijjURSemijvujw
This is the invoiceId in draft in_1PtWGjJ4ILijjURSxwBKCz65
Ah, okay, you created a new Billing Clock. Can you now advance that clock another hour?
For Invoices that aren't the first for a Subscription, the Invoices wait about an hour after they are created before they are finalized. It looks like your new billing clock is currently frozen in that hour block.
yes, i thought the clock actually 'keeps ticking'
Nope, test clocks freeze at the specified times
Yeah that should do it
Like looking at the most recent Invoice you shared, I see the following:
creation time (relative to the test clock) - 2024-09-02 13:39:06
test clock's current time - 2024-09-02 14:30:00
I think if that clock were to be advanced about 15 minutes you'd see the Invoice finalize and attempt payment. (which will fail because there is no default payment method to be used)
(which will fail because there is no default payment method to be used) why is that?
Yes, you're right
now im trying to understand why does it fail? This is how I handle it: `
const handlePaymentButtonClick = async (e) => {
e.preventDefault();
if (!stripe || !elements) {
return;
};
setIsLoading(true);
const { error: submitError } = await elements.submit();
if (submitError) {
setStripeError(submitError.message);
return;
};
// create the customer
const stripeCustomerIdRes = await fetch('/api/stripe/findOrCreateCustomer', {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
billingEmail,
country,
language,
currency,
totalPrice
}),
});
const stripeCustomerId = (await stripeCustomerIdRes.json()).stripeCustomerId;
// create the subscription
const subscriptionRes = await fetch('/api/stripe/createSubscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
stripeCustomerId,
billingEmail,
country,
language,
currency,
totalPrice
}),
});
const clientSecret = (await subscriptionRes.json()).clientSecret;
console.log({clientSecret})
if (!clientSecret) {
console.log("No immediate payment required due to trial period.");
router.push(returnUrl); // Example redirect
return;
};`
and this is how I create the subscription :"
const stripe = new Stripe(
process.env.NODE_ENV === 'development'
? process.env.STRIPE_TEST_API_KEY
: process.env.STRIPE_PRODUCTION_API_KEY
);
export default async function createSubscription(req, res) {
const {
stripeCustomerId,
...
} = req.body;
const metadata = {
stripeCustomerId,
...
};
//create a dynamic product
const product = await stripe.products.create({
name: `${currency.toUpperCase()}${totalPrice} Subscription`,
});
console.log("Stripe product has been created.");
//create the subscription
const subscription = await stripe.subscriptions.create({
customer: stripeCustomerId,
items: [{
price_data: {
currency: currency.toLowerCase(),
product: product.id,
unit_amount: Math.round(totalPrice * 100),
recurring: { interval: 'year' },
}
}],
payment_behavior: 'default_incomplete',
payment_settings: { save_default_payment_method: 'on_subscription' },
expand: ['latest_invoice.payment_intent'],
metadata: metadata,
trial_period_days: 3
});
console.log("Stripe subscription has been created.");
const clientSecret = subscription.latest_invoice?.payment_intent?.client_secret || null;
res.send({
subscriptionId: subscription.id,
clientSecret: clientSecret,
});
};" (the clientSecret is always null)
It fails because the a default payment method isn't set up, so the Subscription doesn't have anything to charge for the Invoice's payment.
You either need to set a default payment method on the Subscription:
https://docs.stripe.com/api/subscriptions/object#subscription_object-default_payment_method
Currently your flow will do this when the first payment succeeds since you're setting
payment_settings: { save_default_payment_method: 'on_subscription' },
but no payment happens due to the Subscription starting with a free trial, so there isn't a payment method to save.
Or you can set a default payment method on the Customer object, which will be used for all Subscriptions that don't have their own default payment method set:
https://docs.stripe.com/api/customers/update#update_customer-invoice_settings-default_payment_method
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
if I understand it correctly, then ai just need to replace it with 'default_source'?
I don't know what you mean by that, but it doesn't sound right.
I have looked at your links, yet it's not entirely clear to me what value should the payment_settings have when creating the subscription
It has nothing to do with payment_settings, you need to collect payment method details from your customer. Do you want to collect those when the Subscription is started in a trail phase, or do you want to wait for the trail to end before collecting those details?
Then instead of trying to get the intent from the first Invoice, which will be null for a Subscription starting with a trial period, you'll want to get the ID of the Setup Intent that the Subscription creates. It's stored in the pending_setup_intent field:
https://docs.stripe.com/api/subscriptions/object#subscription_object-pending_setup_intent
Then you can use the client secret from that intent to use Elements to collect payment method details.
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.