Angular 5中Firestore写入问题:Stripe checkout数据存错库
Let's walk through fixing your Cloud Function — there are several Firestore API mismatches and path errors in your current code that are preventing data from being saved to Firestore correctly. Here's the corrected implementation:
const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp(); // No need to pass config if using the default service account const db = admin.firestore(); const stripe = require('stripe')(functions.config().stripe.testkey); // Trigger on writes to a payment document under payments/{userId}/{paymentId} exports.stripeCharge = functions.firestore .document('payments/{userId}/{paymentId}') .onWrite(async (change, context) => { // Get the payment data from the Firestore document const payment = change.after.data(); const userId = context.params.userId; const paymentId = context.params.paymentId; // Exit if payment doesn't exist or has already been charged if (!payment || payment.charge) return null; try { // Fetch the customer data (adjust this path if your customer data lives elsewhere) const customerDoc = await db.collection('payments').doc(userId).get(); if (!customerDoc.exists) { throw new Error(`Customer document for userId ${userId} not found`); } const customer = customerDoc.data(); const amount = payment.amount; const idempotency_key = paymentId; const source = payment.token.id; // Fixed typo: was payment.testkey.id, should match your frontend token field const currency = 'php'; // Create Stripe charge const charge = await stripe.charges.create( { amount, currency, source }, { idempotency_key } ); // Update the payment document in Firestore with the charge data await db .collection('payments') .doc(userId) .collection('payments') // Matches your original database structure .doc(paymentId) .update({ charge: charge }); return null; } catch (error) { // Handle errors (you could also write the error to Firestore for debugging) console.error('Stripe charge error:', error); throw error; } });
Key Fixes Explained:
Trigger Path Correction
Changed the trigger topayments/{userId}/{paymentId}to mirror your original Realtime Database hierarchy in Firestore. This ensures we listen to writes on individual payment documents under each user's subcollection.Firestore API Replacements
Swapped Realtime Database-specific methods likeevent.data.val()with Firestore'schange.after.data()(to fetch updated document data) andcontext.params(to access wildcard values likeuserId/paymentId). Replacedonce('value')with Firestore'sget()for document reads, and useddata()instead ofval()to extract content.Variable Paths Instead of Literals
Fixed paths likedoc('{userId}')todoc(userId)— your original code was using hardcoded strings instead of the actual parameter values.Correct Update Method
Replaced the invalid.field('charge').set(charge)with.update({ charge: charge })(or use.set({ charge }, { merge: true })if preferred) to properly save the Stripe charge data to the payment document.Typo & Readability Fixes
Correctedpayment.testkey.idtopayment.token.id(matching your original database'stokenobject structure) and rewrote promise chains to use async/await for cleaner, easier-to-debug code.
Matching Firestore Structure
Your Firestore setup will now match your original Realtime Database structure:
payments (collection) └── {userId} (document) └── payments (subcollection) └── {paymentId} (document) ├── amount: number ├── token: object └── charge: object
内容的提问来源于stack exchange,提问作者ziggy

