首页 > 解决方案 > 如何在 React 和 Firebase 中使用 Stripe

问题描述

所以我使用 firebase 作为我的数据库和托管服务,并且我已经在 React 中编写了应用程序。

现在我正在尝试将 Stripe 添加到应用程序中,以便向客户收费。但是有一个问题,Stripe 似乎需要一个单独的服务器,这有点问题,因为我使用的是 Firebase。

我已阅读文档(此处 - https://firebase.google.com/docs/use-cases/payments)并观看了来自 firebase 的视频(此处 - https://www.youtube.com/watch?v= BrLTF4QdRrM和这里 - https://www.youtube.com/watch?v=BrLTF4QdRrM)我仍然迷路了。

我不知道我应该在哪里包含 Stripe Publishable Key,而且我已经陷入了这样的困境,我将不得不花费接下来的几个小时来撤销最后几个小时的努力。

如果您可以向我指出一个简单指南的方向,或者只是告诉我可发布密钥需要去哪里,那将非常有帮助!

这可能不仅仅是帮助,但这是我创建的用于创建条带客户和条带费用等的代码。

mport * as stripe from "stripe";
import * as functions from "firebase";
import getFirestoreDb from "../firebase/firestore/getFirestoreDb";


// import {firestore} from "@firebase/firestore/dist/packages/firestore/test/util/api_helpers";
// const admin = require('firebase-admin');
// admin.initializeApp();


// const logging = require('@google-cloud/logging')();
// const currency = functions.config().stripe.currency || 'USD';

const db = getFirestoreDb();

//START CUSTOMER CHARGE //
// Charge the Stripe customer whenever an amount is created in Cloud Firestore

export const createStripeCharge = functions.firestore
  .document('stripe_customers/{userId}/charges/{autoId}')
  .onCreate(async ( snap, context) => {
    const val = snap.data();
    try {
      //Look up the Stripe customer id written in createStripeCustomer
      const snapshot = await
        db.collection('stripe_customers')
        .doc(context.params.userId).get();
      const snapval = snapshot.data();
      const customer = snapval.customer_id;

      // Create a charge using the pushId as the idempotency key
      // protecting against double charges
      const amount = val.amount;
      const idempotencyKey = context.params.id;
      const currency = "USD";
      const charge = {amount, currency, customer};
      if (val.source !== null) {
        charge.source = val.source;
      }
      // setSourceOrDefault(charge, snap.data().source)
      const response = await stripe.charges.create(charge, {idempotency_key: idempotencyKey} );
      //if the result is successful, write it back to the database
      return snap.ref.set(response, {merge:true});
    } catch(error)  {
      // We want to capture errors and render them in a user-friendly way, while
      // still logging an exception with StackDriver
      await snap.ref.set({error: userFacingMessage(error)}, {merge:true});
      // return reportError(error, {user: context.params.userId});
    }
  });

// END CUSTOMER CHARGE //

// When a user is created, register them with Stripe
export const createStripeCustomer = functions.auth.user().onCreate(async (user) => {
  const customer = await stripe.customers.create({email: user.email});
  return db.collection('stripe_customers').doc(user.uid).set({customer_id: customer.id});
});

// Add a payment source (card) for a user by writing a stripe payment source token to Cloud Firestore
export const addPaymentSource = functions.firestore.document('/stripe_customers/{userId}/tokens/{pushId}').onCreate(async (snap, context) => {
  const source = snap.data();
  const token = source.token;
  if (source === null){
    return null;
  }

  try {
    const snapshot = await db.collection('stripe_customers').doc(context.params.userId).get();
    const customer =  snapshot.data().customer_id;
    const response = await stripe.customers.createSource(customer, {source: token});
    return db.collection('stripe_customers').doc(context.params.userId).collection("sources").doc(response.fingerprint).set(response, {merge: true});
  } catch (error) {
    await snap.ref.set({'error':userFacingMessage(error)},{merge:true});
    // return reportError(error, {user: context.params.userId});
  }
});

// When a user deletes their account, clean up after them
export const cleanupUser = functions.auth.user().onDelete(async (user) => {
  const snapshot = await db.collection('stripe_customers').doc(user.uid).get();
  const customer = snapshot.data();
  await stripe.customers.del(customer.customer_id);
  return db.collection('stripe_customers').doc(user.uid).delete();
});

// To keep on top of errors, we should raise a verbose error report with Stackdriver rather
// than simply relying on console.error. This will calculate users affected + send you email
// alerts, if you've opted into receiving them.
// // [START reporterror]
// function reportError(err, context = {}) {
//   // This is the name of the StackDriver log stream that will receive the log
//   // entry. This name can be any valid log stream name, but must contain "err"
//   // in order for the error to be picked up by StackDriver Error Reporting.
//   const logName = 'errors';
//   const log = logging.log(logName);
//
//   // https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/MonitoredResource
//   const metadata = {
//     resource: {
//       type: 'cloud_function',
//       labels: {function_name: process.env.FUNCTION_NAME},
//     },
//   };
//
//   // https://cloud.google.com/error-reporting/reference/rest/v1beta1/ErrorEvent
//   const errorEvent = {
//     message: err.stack,
//     serviceContext: {
//       service: process.env.FUNCTION_NAME,
//       resourceType: 'cloud_function',
//     },
//     context: context,
//   };
//
//   // Write the error log entry
//   return new Promise((resolve, reject) => {
//     log.write(log.entry(metadata, errorEvent), (error) => {
//       if (error) {
//         return reject(error);
//       }
//       return resolve();
//     });
//   });
// }
// [END report error]


function userFacingMessage(error) {
  return error.type ? error.message : 'An error has occurred, developers have been alerted';
}

stripe.setPublishableKey("STRIPE_KEY");

标签: reactjsfirebasegoogle-cloud-firestorestripe-payments

解决方案


您必须在客户端设置可发布密钥。

例如,使用 React Native 和tipsi-stripe (stripe client sdk),你可以这样做:

import stripe from 'tipsi-stripe'

stripe.setOptions({
    publishableKey: 'YOUR-PUBLISHABLE-KEY',
})

您只需要使用您的可发布密钥初始化您正在使用的条带客户端 sdk。


推荐阅读