Stripe订阅创建时将client_reference_id写入Firestore的问题
解决方案
1. 核心思路
从Stripe订阅创建的Webhook事件中精准提取client_reference_id,仅将该字段写入Firestore,替代原有存储整个原始事件数据的逻辑。
2. 修改后的Firebase Cloud Functions代码
假设你原本监听的是customer.subscription.created事件,以下是调整后的代码:
const functions = require("firebase-functions"); const admin = require("firebase-admin"); const stripe = require("stripe")(functions.config().stripe.secret); admin.initializeApp(); exports.handleStripeWebhook = functions.https.onRequest(async (req, res) => { const sig = req.headers["stripe-signature"]; let event; try { event = stripe.webhooks.constructEvent( req.rawBody, sig, functions.config().stripe.webhook_secret ); } catch (err) { res.status(400).send(`Webhook Error: ${err.message}`); return; } if (event.type === "customer.subscription.created") { const subscription = event.data.object; let clientReferenceId; // 优先从订阅的metadata提取(推荐:创建支付链接时同步该字段到订阅metadata) if (subscription.metadata?.client_reference_id) { clientReferenceId = subscription.metadata.client_reference_id; } // 备选:从关联的Checkout Session中获取(需额外调用Stripe API) else if (subscription.checkout_session) { const checkoutSession = await stripe.checkout.sessions.retrieve(subscription.checkout_session); clientReferenceId = checkoutSession.client_reference_id; } if (clientReferenceId) { // 仅存储client_reference_id到Firestore await admin.firestore() .collection("subscriptions") .doc(subscription.id) .set({ client_reference_id: clientReferenceId }); functions.logger.info(`已存储client_reference_id: ${clientReferenceId},对应订阅ID: ${subscription.id}`); } else { functions.logger.warn(`未找到订阅${subscription.id}对应的client_reference_id`); } res.json({ received: true }); } });
3. 关键细节说明
- 高效提取方式:如果创建支付链接(Checkout Session)时,同步把
client_reference_id写入subscription_data.metadata(代码示例如下),可以直接从订阅对象的metadata中提取,无需额外调用Stripe API,提升性能。 - 容错处理:添加日志记录,方便排查未找到目标ID的异常情况。
- 存储结构简化:Firestore文档仅保留
client_reference_id字段,完全符合需求。
补充:创建支付链接时同步metadata的代码示例
const session = await stripe.checkout.sessions.create({ payment_method_types: ["card"], line_items: [{ price: "price_xxx", quantity: 1 }], mode: "subscription", success_url: "https://your-domain.com/success", cancel_url: "https://your-domain.com/cancel", client_reference_id: "用户自定义ID", // 将client_reference_id同步到订阅的metadata中 subscription_data: { metadata: { client_reference_id: "用户自定义ID" } } });
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

