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

Function getPaymentMethodDetails

apps/sim/lib/billing/webhooks/invoices.ts:195–275  ·  view source on GitHub ↗

* Get payment method details from Stripe invoice

(
  invoice: Stripe.Invoice
)

Source from the content-addressed store, hash-verified

193 * Get payment method details from Stripe invoice
194 */
195async function getPaymentMethodDetails(
196 invoice: Stripe.Invoice
197): Promise<{ lastFourDigits?: string; failureReason?: string }> {
198 let lastFourDigits: string | undefined
199 let failureReason: string | undefined
200
201 // Try to get last 4 digits from payment method
202 try {
203 const stripe = requireStripeClient()
204
205 // Try to get from default payment method
206 if (invoice.default_payment_method && typeof invoice.default_payment_method === 'string') {
207 const paymentMethod = await stripe.paymentMethods.retrieve(invoice.default_payment_method)
208 if (paymentMethod.card?.last4) {
209 lastFourDigits = paymentMethod.card.last4
210 }
211 }
212
213 // If no default payment method, try getting from customer's default
214 if (!lastFourDigits && invoice.customer && typeof invoice.customer === 'string') {
215 const customer = await stripe.customers.retrieve(invoice.customer)
216 if (customer && !('deleted' in customer)) {
217 const defaultPm = customer.invoice_settings?.default_payment_method
218 if (defaultPm && typeof defaultPm === 'string') {
219 const paymentMethod = await stripe.paymentMethods.retrieve(defaultPm)
220 if (paymentMethod.card?.last4) {
221 lastFourDigits = paymentMethod.card.last4
222 }
223 }
224 }
225 }
226 } catch (error) {
227 logger.warn('Failed to retrieve payment method details', { error, invoiceId: invoice.id })
228 }
229
230 // Get failure message - check multiple sources
231 if (invoice.last_finalization_error?.message) {
232 failureReason = invoice.last_finalization_error.message
233 }
234
235 // If not found, check the payments array (requires expand: ['payments'])
236 if (!failureReason && invoice.payments?.data) {
237 const defaultPayment = invoice.payments.data.find((p) => p.is_default)
238 const payment = defaultPayment || invoice.payments.data[0]
239
240 if (payment?.payment) {
241 try {
242 const stripe = requireStripeClient()
243
244 if (payment.payment.type === 'payment_intent' && payment.payment.payment_intent) {
245 const piId =
246 typeof payment.payment.payment_intent === 'string'
247 ? payment.payment.payment_intent
248 : payment.payment.payment_intent.id
249
250 const paymentIntent = await stripe.paymentIntents.retrieve(piId)
251 if (paymentIntent.last_payment_error?.message) {
252 failureReason = paymentIntent.last_payment_error.message

Callers 1

sendPaymentFailureEmailsFunction · 0.85

Calls 2

requireStripeClientFunction · 0.90
warnMethod · 0.65

Tested by

no test coverage detected