Stripe订阅模块集成TypeScript报错:payment_intent属性不存在
解决Stripe订阅集成中的TypeScript错误:Property 'payment_intent' does not exist on type 'string | Invoice'
问题原因
Stripe的TypeScript类型定义里,Subscription对象的latest_invoice字段类型为string | Invoice:
- 未使用
expand参数时,它返回的是Invoice的ID字符串 - 你虽然在创建订阅时指定了
expand: ['latest_invoice.payment_intent'],但TypeScript编译器无法自动识别这个展开操作,仍会认为latest_invoice可能是字符串类型,因此访问payment_intent时触发类型错误。
解决方案
可以通过类型断言或类型检查来让TypeScript确认latest_invoice是展开后的Invoice对象:
方法1:类型断言(最直接)
明确告知编译器latest_invoice是Invoice类型,直接访问对应属性:
res.send({ subscriptionId: subscription.id, clientSecret: (subscription.latest_invoice as Stripe.Invoice).payment_intent?.client_secret, });
方法2:先判断类型再访问(更安全)
通过类型检查排除字符串的情况,避免潜在的运行时错误:
let clientSecret: string | undefined; if (typeof subscription.latest_invoice !== 'string') { clientSecret = subscription.latest_invoice.payment_intent?.client_secret; } res.send({ subscriptionId: subscription.id, clientSecret, });
修改后的完整代码
exports.doSubscribe = functions.https.onRequest(async (data, res) => { try { ///Create Customer const customer = await stripe.customers.create({ description: 'My First Test Customer (created for API docs at https://www.stripe.com/docs/api)', }); ///Create Payment Method const paymentMethod = await stripe.paymentMethods.create({ type: 'card', card: { number: '4242424242424242', exp_month: 10, exp_year: 2023, cvc: '314', }, }); ///Attach Payment Method with Customer await stripe.paymentMethods.attach( paymentMethod.id, {customer:customer.id} ); ///Crate Product const product = await stripe.products.create({ name: 'Gold Special', }); ///Create Price const price = await stripe.prices.create({ unit_amount: 1000, currency: 'usd', recurring: {interval: 'month'}, product: product.id, }); ///Create Subscription const subscription = await stripe.subscriptions.create({ customer: customer.id, items: [ {price: price.id}, ], payment_behavior: 'default_incomplete', payment_settings: { save_default_payment_method: 'on_subscription' }, expand: ['latest_invoice.payment_intent'], }); res.send({ subscriptionId: subscription.id, // 使用类型断言解决类型错误 clientSecret: (subscription.latest_invoice as Stripe.Invoice).payment_intent?.client_secret, }); } catch (error) { console.log(`error: ${error}`); res.status(500).send({ error: error.message }); } });
补充说明
- 使用
?.可选链操作符可以避免payment_intent为null时的运行时错误 - 如果需要更严谨的类型定义,可以手动扩展Subscription类型:
type ExpandedSubscription = Stripe.Subscription & { latest_invoice: Stripe.Invoice & { payment_intent: Stripe.PaymentIntent; }; }; const subscription = await stripe.subscriptions.create(...) as ExpandedSubscription;
内容的提问来源于stack exchange,提问作者Ali Coder
相关产品推荐
相关产品推荐

