stripe python sdk 默认不返回嵌套的 `subscriptions` 等字段,需显式展开(expand)或直接调用独立的 list api;对 `cash_balance`、`tax` 等标记为 “expandable” 的字段,也必须通过 `expand` 参数加载,否则会触发 keyerror 或 attributeerror。
在 Stripe 的 Python SDK 中,Customer 对象默认仅返回基础字段(如 name、email、address),而像 subscriptions、cash_balance、tax 这类被文档标注为 Expandable 的属性,并不会自动加载——它们要么为 None(inline object),要么仅返回 ID 字符串(reference object),绝不会以可访问属性的形式存在。因此直接访问 customer.subscriptions 会先触发 KeyError(底层字典无该 key),继而引发 AttributeError(SDK 动态属性代理失败)。
这是最高效、最符合 Stripe 最佳实践的方式,避免过度膨胀 Customer 对
象:
import stripe
stripe.api_key = os.environ['STRIPE_KEY']
customer_id = 'cus_*******'
subscriptions = stripe.Subscription.list(customer=customer_id, limit=10)
for sub in subscriptions.auto_paging_iter():
print(f"ID: {sub.id}, Status: {sub.status}, Items: {len(sub.items.data)}")✅ 优势:
若你确实需要在同一个请求中获取 subscriptions、cash_balance 和 tax,则必须在 retrieve() 时声明 expand:
customer = stripe.Customer.retrieve(
'cus_*******',
expand=['subscriptions', 'cash_balance', 'tax']
)
# ✅ 现在可以安全访问(注意:subscriptions 是 StripeList 对象,非普通 list)
print(len(customer.subscriptions.data)) # 获取实际订阅数
print(customer.cash_balance.amount) # 需确认 cash_balance 存在且非 None
print(customer.tax.location.country) # tax 是 inline object,expand 后才可访问⚠️ 注意事项:
查阅 Stripe Customer API 文档:
总之,优先使用 stripe.Subscription.list(customer=...) 获取订阅列表;仅当业务逻辑强依赖 Customer 全量上下文时,再谨慎使用 expand。这不仅规避了属性访问异常,也提升了 API 调用的可维护性与性能。