MCPcopy Index your code
hub / github.com/simstudioai/sim / handleInvoicePaymentSucceeded

Function handleInvoicePaymentSucceeded

apps/sim/lib/billing/webhooks/invoices.ts:780–871  ·  view source on GitHub ↗
(event: Stripe.Event)

Source from the content-addressed store, hash-verified

778 * Handles both credit purchases and subscription payments.
779 */
780export async function handleInvoicePaymentSucceeded(event: Stripe.Event) {
781 try {
782 const invoice = event.data.object as Stripe.Invoice
783
784 if (invoice.metadata?.type === 'credit_purchase') {
785 await handleCreditPurchaseSuccess(invoice)
786 return
787 }
788
789 await stripeWebhookIdempotency.executeWithIdempotency(
790 'invoice-payment-succeeded',
791 event.id,
792 async () => {
793 const resolvedInvoice = await resolveInvoiceSubscription(
794 invoice,
795 'invoice.payment_succeeded'
796 )
797 if (!resolvedInvoice) {
798 return
799 }
800
801 const { sub } = resolvedInvoice
802 const subIsOrgScoped = await isSubscriptionOrgScoped(sub)
803
804 let wasBlocked = false
805 if (subIsOrgScoped) {
806 const membersRows = await db
807 .select({ userId: member.userId })
808 .from(member)
809 .where(eq(member.organizationId, sub.referenceId))
810 const memberIds = membersRows.map((m) => m.userId)
811 if (memberIds.length > 0) {
812 const blockedRows = await db
813 .select({ blocked: userStats.billingBlocked })
814 .from(userStats)
815 .where(inArray(userStats.userId, memberIds))
816
817 wasBlocked = blockedRows.some((row) => !!row.blocked)
818 }
819 } else {
820 const row = await db
821 .select({ blocked: userStats.billingBlocked })
822 .from(userStats)
823 .where(eq(userStats.userId, sub.referenceId))
824 .limit(1)
825 wasBlocked = row.length > 0 ? !!row[0].blocked : false
826 }
827
828 const isProrationInvoice = invoice.billing_reason === 'subscription_update'
829 const shouldUnblock = !isProrationInvoice || (invoice.amount_paid ?? 0) > 0
830
831 if (shouldUnblock) {
832 if (subIsOrgScoped) {
833 await unblockOrgMembers(sub.referenceId, 'payment_failed')
834 } else {
835 await db
836 .update(userStats)
837 .set({ billingBlocked: false, billingBlockedReason: null })

Callers 2

auth.tsFile · 0.90
invoices.test.tsFile · 0.90

Calls 11

isSubscriptionOrgScopedFunction · 0.90
unblockOrgMembersFunction · 0.90
infoMethod · 0.80
errorMethod · 0.80
setMethod · 0.65
eqFunction · 0.50

Tested by

no test coverage detected