使用Firebase Stripe支付扩展,如何在支付成功后向Firestore写入Job对象?
我正在使用Firebase的Run Payments with Stripe扩展,已配置包括checkout.session.completed在内的多个Webhook,想了解如何仅在支付成功后将Job对象提交到Firestore?
我的.ts代码:
const docRef = await db .collection('users') .doc(uid) .collection('checkout_sessions') .add({ automatic_tax: true, // Automatically calculate tax based on the customer's address tax_id_collection: true, // Collect the customer's tax ID (important for B2B transactions) payment_method_types: ["card"], mode: 'subscription', line_items: [ { price: this.paymentPlan.stripePriceId, quantity: 1, description: jobData.jobLevel + ' ' + jobData.jobTitle, }, ], allow_promotion_codes: true, success_url: 'http://localhost:4200/success', cancel_url: 'http://localhost:4200/success', metadata: { payId: payId } }); // Wait for the CheckoutSession to get attached by the extension docRef.onSnapshot((snap) => { const { error, url } = snap.data() as any;; if (error) { // Show an error to your customer and // inspect your Cloud Function logs in the Firebase console. alert(`An error occured: ${error.message}`); } if (url) { // We have a Stripe Checkout URL, let's redirect. window.location.assign(url); } this.loading = false; }); this.db.collection('users').doc(uid).collection('jobs').add(job).then(() => { console.log('Job posted successfully!'); }).catch(error => { console.error('Error posting job:', error); });
我是否需要编写自定义Firebase函数来监听Webhook,以此方式提交Job?
回答
是的,必须通过自定义Firebase云函数监听Stripe的checkout.session.completed Webhook事件,才能确保只有支付成功时才创建Job对象。你当前代码里的jobs.add(job)是在生成Checkout Session后立即执行的,不管后续支付是否成功,这不符合需求。
具体操作步骤:
移除前端的Job创建代码
把代码最后那段直接添加Job的逻辑删掉,避免用户还没完成支付就生成Job。补充Checkout Session的metadata字段
将创建Job所需的所有关键数据(比如用户ID、职位等级、职位名称等)放到metadata中,这样支付成功后,云函数能拿到这些信息来生成Job:metadata: { payId: payId, uid: uid, jobLevel: jobData.jobLevel, jobTitle: jobData.jobTitle // 按需添加其他Job相关字段 }编写Firebase云函数处理支付成功事件
有两种常见的监听方式,选其一即可:方式一:监听Firestore中checkout_sessions文档的更新
当Stripe支付成功后,Firebase Stripe扩展会更新对应的checkout_sessions文档状态,我们可以监听这个更新:
import * as functions from "firebase-functions"; import * as admin from "firebase-admin"; admin.initializeApp(); export const createJobOnPaymentSuccess = functions.firestore .document("users/{userId}/checkout_sessions/{sessionId}") .onUpdate(async (change, context) => { const afterSession = change.after.data(); // 确认会话状态为已完成 if (afterSession?.status === "complete") { const { uid, jobLevel, jobTitle } = afterSession.metadata; // 创建Job对象到Firestore await admin.firestore() .collection("users") .doc(uid) .collection("jobs") .add({ jobLevel, jobTitle, createdAt: admin.firestore.FieldValue.serverTimestamp(), paymentStatus: "success" }); } });方式二:直接监听Stripe的checkout.session.completed事件(通过Eventarc)
如果你的Firebase Stripe扩展配置了将Webhook事件转发到Eventarc,可以直接监听该事件:
import * as functions from "firebase-functions"; import * as admin from "firebase-admin"; admin.initializeApp(); export const handleStripeCheckoutCompleted = functions.eventarc.onCustomEventPublished( "stripe.checkout.session.completed", async (event) => { const session = event.data.data.object; const metadata = session.metadata; // 验证metadata中存在创建Job所需的字段 if (metadata.uid && metadata.jobLevel && metadata.jobTitle) { await admin.firestore() .collection("users") .doc(metadata.uid) .collection("jobs") .add({ jobLevel: metadata.jobLevel, jobTitle: metadata.jobTitle, createdAt: admin.firestore.FieldValue.serverTimestamp(), paymentStatus: "success" }); } } );配置扩展确保事件触发
进入Firebase控制台的Stripe扩展设置页面,确认checkout.session.completed事件已被启用,并且对应的事件转发配置正确(比如指向你的云函数或Eventarc)。
注意事项
- 必须在后端(云函数)处理Job创建,避免前端篡改逻辑导致未支付就生成Job。
- Firebase Stripe扩展已经自动验证了Stripe Webhook的签名,无需额外处理。
- 可以通过metadata中的
payId关联支付会话和Job,方便后续对账或查询。
内容的提问来源于stack exchange,提问作者spikeycakes

