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

Cloud Function添加额外用户信息创建完整Stripe Customer的实现问题

问题修复方案

核心错误原因

  • 云函数取值逻辑错误:context.auth.uid是字符串类型的用户唯一ID,不是包含用户信息的对象,你当前写的context.auth.uid.fullname必然返回undefined
  • 传参类型错误:前端调用云函数时传入的profileImage是UIImage对象,无法直接被云函数解析,应该传入你已经上传到Storage生成的图片URL字符串
  • Stripe接口参数不匹配:Stripe创建客户的原生接口不支持fullname/username/profileImage三个自定义字段,自定义参数需要放在metadata字段下才能正常存储
  • 数据库写入逻辑冲突:云函数里用set写入customers节点会直接覆盖你之前在AuthService中写入的同uid用户数据,导致其他字段丢失

修复步骤

1. 调整AuthService逻辑,把生成的图片URL回传给注册回调

把你的AuthService代码修改为回调时返回图片URL:

static func createCustomer(credentials: CustomerCredentials, completion: @escaping(Error?, DatabaseReference?, String?) -> Void) {
        
        guard let imageData = credentials.profileImage.jpegData(compressionQuality: 0.3) else { return }
        let filename = NSUUID().uuidString
        let storageRef = STORAGE_REF.reference(withPath: "/customer_profile_images/\(filename)")
        
        storageRef.putData(imageData, metadata: nil) { (meta, error) in
            if let error = error {
                debugPrint(error.localizedDescription)
                completion(error, nil, nil)
                return
            }
            
            storageRef.downloadURL { (url, error) in
                guard let profileImageUrl = url?.absoluteString else {
                    completion(error, nil, nil)
                    return
                }
                
                Auth.auth().createUser(withEmail: credentials.email, password: credentials.password) { (result, error) in
                    if let error = error {
                        debugPrint(error.localizedDescription)
                        completion(error, nil, nil)
                        return
                    }
                    
                    guard let uid = result?.user.uid else { return }
                    
                    let values = ["email" : credentials.email,
                                  "fullname" : credentials.fullname,
                                  "username" : credentials.username,
                                  "uid" : uid,
                                  "profileImageUrl" : profileImageUrl] as [String : Any]
                    
                    CustomerDataService.saveCustomerData(uid: uid, fullname: credentials.fullname, email: credentials.email,
                                                         username: credentials.username, profileImagUrl: profileImageUrl)
                    REF_CUSTOMERS.child(uid).setValue(values) { error, ref in
                        completion(error, ref, profileImageUrl)
                    }
                }
            }
        }
        
}

2. 修改注册逻辑的云函数调用参数,传入图片URL而非UIImage

修改你的handleCreateAccount中的云函数调用部分:

AuthService.createCustomer(credentials: credentials) { (error, ref, profileImageUrl) in
    if let error = error {
        Auth.auth().handleFireAuthError(error: error, vc: self)
        self.showLoader(false)
        return
    }
    guard let profileImageUrl = profileImageUrl else {
        self.showLoader(false)
        return
    }
    Functions.functions().httpsCallable("createStripeCustomer").call([
        "email": credentials.email,
        "fullname": credentials.fullname,
        "username": credentials.username,
        "profileImage": profileImageUrl
    ]) { result, error in
        if let error = error {
            Auth.auth().handleFireAuthError(error: error, vc: self)
            self.showLoader(false)
            return
        }
    }
    
    // 原有跳转逻辑保留
    self.showLoader(false)
    guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return }
    guard let tab = window.rootViewController as? MainTabController else { return }
    tab.setupNavigationControllers()
    self.handleDismissal()
}

3. 修复云函数的取值和Stripe参数逻辑

修改后的云函数代码如下:

exports.createStripeCustomer = functions.https.onCall( async (data, context) => {
    // 验证登录状态
    const uid = context.auth?.uid
    if (!uid) {
      console.log('Illegal access attempt due to unauthenticated attempt.')
      throw new functions.https.HttpsError('internal', 'Illegal access attempt')
    }
    // 所有参数从前端传入的data中取
    const email = data.email
    const fullname = data.fullname
    const username = data.username
    const profileImage = data.profileImage
  
    return stripe.customers.create({
       email : email,
       // 自定义参数放入metadata
       metadata: {
         fullname : fullname,
         username : username,
         profileImage : profileImage
       }
    }).then( customer => {
      return customer.id
    }).then( customerId => {
      // 用update代替set,避免覆盖原有用户数据
      return admin.database().ref("customers").child(uid).update({
          stripeId: customerId
      })
    }).catch( err => {
      console.error(err)
      throw new functions.https.HttpsError('internal', 'Unable to create Stripe customer.')
    })
})

额外说明

不需要拆分注册流程为两步,按照上述修改后,注册时就可以一次性完成用户创建、头像上传、Stripe客户生成、数据同步的全流程,不会出现字段丢失的问题。

内容的提问来源于stack exchange,提问作者Zachary Smouse

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:42:03