#trojan_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/1361851646539337910
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
You would have to retrieve the relevant object via the API to get that if it's not in the Event you're receiving.
i tried using the invoice api but it wouldn’t return the charge object even though i could see it when inspecting in the dashboard
Can you share the code you tried using?
yes one second
Also can you share a Checkout Session ID or an Event ID so I can see what you're seeing?
// Check the Checkout Session's payment_status property
// to determine if fulfillment should be performed
if (session.payment_status !== 'unpaid') {
const [upsertResult, invoiceData, checkoutData] = await Promise.all([
// await db update
upsertPromise,
// get invoice object with latest_charge
this.stripe.invoices.retrieve(
// invoice should always exist in subscription mode
typeof session.invoice == 'string'
? session.invoice!
: session.invoice!.id!,
{
expand: ['charge'],
},
),
// get full session object
this.stripe.checkout.sessions
.retrieve(session.id, {
expand: ['line_items', 'customer'],
})
.then((fullSession) => {
// ....
return {
sessionId,
userId,
name,
email,
quantity,
}
}),
])
if (isDBError(upsertResult))
throw new Error(
`Failed to upsert checkout data: ${JSON.stringify(upsertResult)}`,
)
const { receipt_url: url } = (
invoiceData as unknown as Stripe.Invoice & { charge: Stripe.Charge }
).charge
in_1REIBVAcGWmAIEGM9IV51UH1
cs_test_b1c5s4MPvADRN3bbyjXUqaK9lOck7C35LwMCnuuGD9ivS9dyDj9nFSZTZs
my hypothesis is that in subscription mode the stripe client purposefully omits data as opposed to payment mode?
Okie so you have the Invoice in the Checkout Session. The issue is you don't see the PaymentIntent anymore, correct?
Yeah on checkout session completed, payment intent is nulled. invoice is present, but charge isn't present on invoice when retrieved via the invoice api or expanded on checkout.session.retrieve by 'invoice.charge'
I can expand 'invoice.charge' from the cli tho in the dashboard
stripe checkout sessions retrieve cs_test_b1c5s4MPvADRN3bbyjXUqaK9lOck7C35LwMCnuuGD9ivS9dyDj9nFSZTZs --expand="line_items" --expand="invoice.charge"
could it be that the invoice doesn't have the charge object attached until a little later from checkout.session.completed?
Yes because the new API version doesn't have the connection between Invoice and Charge anymore. What you would want to do instead is call the Invoice Payment endpoint: https://docs.stripe.com/changelog/basil/2025-03-31/add-support-for-multiple-partial-payments-on-invoices#use-the-new-for-payments-and-invoice-connection