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

如何通过Cloud Functions将Stripe支付数据保存至Firestore?

解决Stripe支付记录无法保存到Firestore的问题

我来帮你搞定这个问题!你已经完成了大部分工作——Stripe支付成功触发了Cloud Function,现在只需要在支付成功的回调里加上Firestore的写入逻辑就行。

核心修改点

在你标注// I WANNA RECORD DATA INTO MY DATABASE HERE!!的位置,我们需要添加Firestore的异步写入操作。注意:Firestore的操作是异步的,所以要使用async/await确保写入完成后再给客户端返回响应,避免函数提前终止导致写入失败。

另外,要注意不要存储完整的Stripe Token对象(这是敏感信息,Stripe禁止存储),只需要保存Token的ID即可。

修改后的完整代码

const functions = require('firebase-functions');
const admin = require('firebase-admin');
// 新版本Firebase Functions无需传参,直接初始化即可
admin.initializeApp();
const express = require('express');
const cors = require('cors')({origin: true});
const app = express();
const stripe = require('stripe')(functions.config().stripe.token);

// 将charge函数改为async,支持await异步操作
async function charge(req, res) {
  const body = req.body;
  const userId = body.userId;
  const token = body.token;
  const amount = body.amount;
  const currency = body.currency;

  try {
    // 发起Stripe支付请求
    const charge = await stripe.charges.create({
      amount,
      currency,
      description: 'Firebase Example',
      source: token,
    });

    // 准备要保存到Firestore的交易数据
    const paymentData = {
      tokenId: token.id, // 仅存储Token ID,禁止存储完整Token对象
      currency: currency,
      amount: amount,
      stripeChargeId: charge.id, // 保存Stripe的Charge ID,方便后续对账
      createdAt: admin.firestore.FieldValue.serverTimestamp() // 添加服务器时间戳,便于排序查询
    };

    // 按照你要求的payments>userId路径,将交易存入payments集合下的userId子集合
    // 这种结构每个用户的交易都是独立文档,便于后续管理和查询
    await admin.firestore()
      .collection('payments')
      .doc(userId)
      .collection('transactions')
      .add(paymentData);

    // 如果你的需求是把交易直接存在payments集合的文档中(包含userId字段),可以替换为下面的代码:
    // await admin.firestore().collection('payments').add({
    //   userId: userId,
    //   ...paymentData
    // });

    // 返回成功响应
    send(res, 200, {
      message: 'Success',
      charge,
      paymentSaved: true
    });
  } catch (err) {
    console.error('支付或存储失败:', err);
    send(res, 500, {
      error: err.message,
    });
  }
}

function send(res, code, body) {
  res.send({
    statusCode: code,
    body: JSON.stringify(body),
  });
}

app.use(cors);
app.post('/', (req, res) => {
  charge(req, res).catch(e => {
    console.error('服务器异常:', e);
    send(res, 500, {
      error: `The server received an unexpected error. Please try again and contact the site admin if the error persists.`,
    });
  });
});

exports.charge = functions.https.onRequest(app);

关键注意事项

  1. 敏感信息处理:永远不要存储完整的Stripe Token、信用卡信息等敏感数据,只保留必要的标识(如Token ID、Charge ID)。
  2. 异步操作处理:使用async/await确保Firestore写入完成后再返回响应,否则Cloud Functions可能在写入完成前就被终止。
  3. 权限检查:确保Cloud Functions的服务账号拥有Firestore的写入权限(默认情况下,Cloud Functions的默认服务账号有完全权限,若修改过Firestore安全规则,需确认规则允许服务账号写入)。
  4. 数据结构设计:推荐用payments/{userId}/transactions的子集合结构存储交易,每个交易是独立文档,避免单文档过大,同时便于后续查询、分页和管理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:22:32