
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 动态属性代理失败)。
✅ 正确做法一:使用独立 Subscriptions List API(推荐)
这是最高效、最符合 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)}")✅ 优势:
- 不依赖 Customer 对象膨胀,响应轻量;
- 支持分页、过滤(如 status='active')、排序;
- 符合 REST API 设计原则,避免 N+1 查询陷阱。
✅ 正确做法二:显式 expand Customer(仅当需同时访问其他 expandable 字段时)
若你确实需要在同一个请求中获取 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 后才可访问⚠️ 注意事项:
- expand 参数接收字符串列表,每个值对应文档中属性名(如 'subscriptions',非 'subscription');
- customer.subscriptions 返回的是 StripeList(支持 .data、.has_more、.auto_paging_iter()),不是 Python list;
- cash_balance 和 tax 属于 inline expandable objects,未 expand 时为 None,访问其子属性(如 .amount)会报 AttributeError;
- 不要尝试 expand=['subscriptions.data'] —— expand 只接受顶层字段名。
? 验证字段是否可 expand
- 若字段旁标注 ✅ Expandable(如 subscriptions, cash_balance, tax, test_clock),则必须 expand;
- 若标注 ? String (object ID)(如 test_clock),未 expand 时返回 ID 字符串(如 'tc_123'),expand 后才返回完整对象;
- 若无标注,则为默认返回的基础字段,可直接访问。
总之,优先使用 stripe.Subscription.list(customer=...) 获取订阅列表;仅当业务逻辑强依赖 Customer 全量上下文时,再谨慎使用 expand。这不仅规避了属性访问异常,也提升了 API 调用的可维护性与性能。










