如何用Stripe createUsageRecord()添加元数据实现项目级用量统计?
你说得对,Stripe的Usage Record对象确实不支持metadata,这就是你收到“未识别属性”错误的原因。下面提供几个无需自建用量存储的实现方案:
方案1:为每个项目创建独立的Subscription Item
如果你的项目数量可控,可以给每个用户的每个项目单独创建一个Subscription Item,关联同一个计量型Price。Subscription Item支持添加metadata来标记对应的projectId,完全符合你的需求。
上报用量时,针对对应项目的Subscription Item ID调用接口:
// 每个项目对应提前创建好的Subscription Item,其metadata已存入projectId const usageRecord = await stripe.subscriptionItems.createUsageRecord( 'si_PROJECT_SPECIFIC_ID', // 目标项目的Subscription Item ID { quantity: 1, timestamp: timestamp } );
后续查看用量时:
- 直接在Stripe Dashboard的用量报表中,按Subscription Item筛选,结合其metadata里的projectId区分不同项目的用量
- 通过Stripe API查询Subscription Item的用量记录,用
metadata[projectId]过滤后聚合数据生成图表
这个方案的优势是完全复用Stripe原生报表能力,无需自己处理数据聚合,省心高效。
方案2:用Usage Record的description字段存储项目标识
Usage Record虽然没有metadata,但支持description字段,你可以把projectId嵌入到这个字段中(比如格式化为project: proj_12345)。
上报代码修改为:
const usageRecord = await stripe.subscriptionItems.createUsageRecord( 'si_OgrBOJp9...', { quantity: 1, timestamp: timestamp, description: `project: ${projectId}` // 将projectId存入description } );
获取单个项目用量时,通过Stripe API拉取所有用量记录,过滤后聚合计算:
// 拉取指定Subscription Item的所有用量记录(按需分页) const usageRecords = await stripe.subscriptionItems.listUsageRecords( 'si_OgrBOJp9...', { limit: 100 } ); // 过滤目标项目的记录并聚合总量 const projectUsage = usageRecords.data .filter(record => record.description.includes(`project: ${targetProjectId}`)) .reduce((total, record) => total + record.quantity, 0);
这个方案无需创建大量Subscription Item,适合项目数量较多的场景,仅需临时查询聚合数据,不用持久化存储。
方案3:通过Stripe Webhook临时处理用量数据
你可以监听Stripe的usage_record.created事件,每当有新的用量记录上报时,在webhook中提取记录的description(含projectId)、quantity和timestamp,临时聚合这些数据生成日/月用量图表,无需将数据持久化到自有数据库。
该方案需要搭建webhook服务,适合对实时性要求较高的场景,每次生成图表时可按需拉取历史事件数据。
- 项目数量少:优先选方案1,直接用Stripe原生报表,最省心
- 项目数量多:方案2更合适,避免管理大量Subscription Item,仅需临时处理数据聚合
- 实时性要求高:可结合方案3的webhook能力实现
内容的提问来源于stack exchange,提问作者Nikolay Dyankov

