无法将StripeID保存到Firestore集合文档的问题排查
问题:Firestore无法保存Stripe客户ID
由于需要更强的查询能力,我正将数据从Firebase Realtime Database迁移到Firestore,但在将客户的stripeID保存到其集合文档时遇到问题。我的Cloud Function运行正常,Stripe已成功创建客户,但stripeID并未被写入对应的Firestore集合文档。请问需要如何修改才能让集合文档正确存储stripeID?
问题现象


客户模型
struct Customer { let uid: String let stripeId: String let fullname: String let email: String let username: String let profileImageUrl: String init(dictionary: [String : Any]) { self.uid = dictionary["uid"] as? String ?? "" self.stripeId = dictionary["stripeId"] as? String ?? "" self.fullname = dictionary["fullname"] as? String ?? "" self.email = dictionary["email"] as? String ?? "" self.username = dictionary["username"] as? String ?? "" self.profileImageUrl = dictionary["profileImageUrl"] as? String ?? "" } }
AuthServices
struct CustomerCredentials { let email: String let password: String let fullname: String let username: String let profileImage: UIImage } static func createCustomer(credentials: CustomerCredentials, completion: CollectionCompletion) { Auth.auth().createUser(withEmail: credentials.email, password: credentials.password) { result, error in if let error = error { debugPrint(error.localizedDescription) return } guard let uid = result?.user.uid else { return } let values = ["uid" : uid, "email" : credentials.email, "fullname" : credentials.fullname, "username" : credentials.username, "profileImageUrl" : profileImageUrl] REF_CUSTOMERS.document(uid).setData(values, completion: completion) } } }
注册控制器(RegistrationController)
@objc func handleCreateAccount() { let credentials = CustomerCredentials(email: email, password: password, fullname: fullname, username: username, profileImage: profileImage) AuthService.createCustomer(credentials: credentials) { error in if let error = error { Auth.auth().handleFireAuthError(error: error, vc: self) self.showLoader(false) return } Functions.functions().httpsCallable("createStripeCustomer").call(["email" : email]) { result, error in if let error = error { debugPrint(error.localizedDescription) return } } } }
解决方案
问题核心是云函数未将Stripe返回的客户ID写入Firestore,且客户端未处理云函数返回结果做补全更新。
1. 修改云函数createStripeCustomer
确保创建Stripe客户后,直接更新对应Firestore文档:
exports.createStripeCustomer = functions.https.onCall(async (data, context) => { // 校验用户登录状态 if (!context.auth) { throw new functions.https.HttpsError('unauthenticated', '用户未登录'); } const email = data.email; const uid = context.auth.uid; // 创建Stripe客户 const customer = await stripe.customers.create({ email: email }); // 写入Firestore文档 await admin.firestore().collection('customers').doc(uid).update({ stripeId: customer.id }); // 返回stripeID给客户端(可选,用于本地逻辑校验) return { stripeId: customer.id }; });
2. 优化客户端注册控制器
在云函数调用成功后,处理返回的stripeID并做本地更新(双重保险):
@objc func handleCreateAccount() { let credentials = CustomerCredentials(email: email, password: password, fullname: fullname, username: username, profileImage: profileImage) AuthService.createCustomer(credentials: credentials) { error in if let error = error { Auth.auth().handleFireAuthError(error: error, vc: self) self.showLoader(false) return } guard let uid = Auth.auth().currentUser?.uid else { self.showLoader(false) return } Functions.functions().httpsCallable("createStripeCustomer").call(["email" : email]) { result, error in if let error = error { debugPrint(error.localizedDescription) self.showLoader(false) return } // 从云函数返回结果中提取stripeID if let data = result?.data as? [String: Any], let stripeId = data["stripeId"] as? String { // 更新Firestore文档 REF_CUSTOMERS.document(uid).updateData(["stripeId": stripeId]) { updateError in if let updateError = updateError { debugPrint(updateError.localizedDescription) } self.showLoader(false) // 执行后续页面跳转等逻辑 } } else { self.showLoader(false) debugPrint("无法获取Stripe客户ID") } } } }
3. 校验Firestore安全规则
确保云函数和用户拥有对应文档的更新权限:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /customers/{uid} { allow read, update: if request.auth != null && request.auth.uid == uid; allow create: if request.auth != null; // 允许云服务账号更新文档 allow update: if request.auth.token.firebase.sign_in_provider == "service_account"; } } }
内容的提问来源于stack exchange,提问作者Zachary Smouse
相关产品推荐
相关产品推荐

