From 20c01070846d79cdabb31bc27062483f70bfd9d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 24 Jul 2025 15:15:11 +0000 Subject: [PATCH 1/2] Initial plan From 68594729e3d982fe2b8cad34c9291922943ddc96 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 24 Jul 2025 15:27:38 +0000 Subject: [PATCH 2/2] Fix invoice.upcoming webhook handling - generate ID for invoices without id Co-authored-by: Ehesp <842078+Ehesp@users.noreply.github.com> --- .../functions/src/utils.ts | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/firestore-stripe-payments/functions/src/utils.ts b/firestore-stripe-payments/functions/src/utils.ts index d6eaeee8..52eeba76 100644 --- a/firestore-stripe-payments/functions/src/utils.ts +++ b/firestore-stripe-payments/functions/src/utils.ts @@ -318,12 +318,16 @@ export const insertInvoiceRecord = async (invoice: Stripe.Invoice) => { if (customersSnap.size !== 1) { throw new Error('User not found!'); } + + // For upcoming invoices, generate a unique document ID since they don't have an id + const invoiceDocId = invoice.id || `upcoming_${invoice.subscription}_${Date.now()}`; + // Write to invoice to a subcollection on the subscription doc. await customersSnap.docs[0].ref .collection('subscriptions') .doc(invoice.subscription as string) .collection('invoices') - .doc(invoice.id) + .doc(invoiceDocId) .set(invoice); const prices = []; @@ -341,15 +345,18 @@ export const insertInvoiceRecord = async (invoice: Stripe.Invoice) => { ); } - // An Invoice object does not always have an associated Payment Intent + // Only create payment records for invoices that have a payment_intent or id + // Upcoming invoices are previews and don't represent actual payments const recordId: string = (invoice.payment_intent as string) ?? invoice.id; - - // Update subscription payment with price data - await customersSnap.docs[0].ref - .collection('payments') - .doc(recordId) - .set({ prices }, { merge: true }); - logs.firestoreDocCreated('invoices', invoice.id); + if (recordId) { + // Update subscription payment with price data + await customersSnap.docs[0].ref + .collection('payments') + .doc(recordId) + .set({ prices }, { merge: true }); + } + + logs.firestoreDocCreated('invoices', invoiceDocId); }; /**