You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Firebase Stripe订阅扩展时重复创建客户是什么原因?

问题原因

你遇到的重复创建Stripe客户的核心原因是两个云函数的并行执行冲突:

  • Firebase Stripe订阅扩展默认有两个触发逻辑:
    • 当你在collection-users集合新增用户文档时,自动触发createCustomer函数创建对应Stripe客户,创建完成后会把生成的Stripe客户ID回写到用户文档的stripeCustomerId字段
    • 当你在用户的checkout_sessions子集合新增文档时,自动触发createCheckoutSession函数创建结账会话,执行时会先查当前用户是否已有stripeCustomerId,如果没有就会自行创建一个Stripe客户
  • 你现有代码在用户文档写入完成后立刻调用subscribe()新增结账会话,导致两个云函数几乎同时启动:createCustomer还没完成客户创建、还没把stripeCustomerId回写到用户文档,createCheckoutSession就已经执行到客户查询步骤,查不到有效ID就触发了重复创建。
解决方案

最可靠的修复方式是修改注册逻辑,不要写完用户文档就立刻创建结账会话,改为监听用户文档的stripeCustomerId字段,等扩展把该字段写入完成后再调用subscribe():

if (agreeToTerms == true && name != '' && surname != '' && companyName != '' && companyActivity != '' ) {

    auth.createUserWithEmailAndPassword(email, password).then(cred => {
        return db.collection('collection-users').doc(cred.user.uid).set({
            name: name,
            surname: surname,
            email: email,
            companyName: companyName,
            companyActivity: companyActivity
        })
        
    }).then(() => {
            // 改为监听用户文档,等Stripe客户ID生成后再跳转结账
            const userDocRef = db.collection('collection-users').doc(firebase.auth().currentUser.uid)
            const unsubscribe = userDocRef.onSnapshot((snap) => {
                const userData = snap.data()
                if (userData?.stripeCustomerId) {
                    unsubscribe() // 拿到ID后立刻取消监听,避免重复触发
                    subscribe()
                    container_signup.querySelector(".error").innerHTML = '';
                }
            })
    }).catch(err => {
        container_signup.querySelector(".error").innerHTML = err.message;
    });

} else {
    container_signup.querySelector(".error").innerHTML = "Please add all the required informations."
}
可选优化

你现有subscribe函数中的onSnapshot监听器没有做取消处理,极端情况下可能被多次触发,可以在拿到结账URL跳转前加上取消监听的逻辑:

async function subscribe() {
    const docRef = await db
      .collection('collection-users')
      .doc(firebase.auth().currentUser.uid)
      .collection('checkout_sessions')
      .add({
        price: 'price_id',
        success_url: 'https://mywebsite.com',
        cancel_url: 'https://mywebsite.com',
    });
    // 保存监听器引用,后续取消
    const unsubscribeSnapshot = docRef.onSnapshot((snap) => {
      const { error, url } = snap.data();
      if (error) {
        unsubscribeSnapshot()
        alert(`An error occured: ${error.message}`);
      }
      if (url) {
        unsubscribeSnapshot() // 拿到URL后先取消监听再跳转
        window.location.assign(url);
      }
    });
}

内容的提问来源于stack exchange,提问作者Max Trautwein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:15:01