【问题标题】:Updating data in firebase doesnt work inside async handleclick func更新firebase中的数据在异步handleclick func中不起作用
【发布时间】:2021-05-12 15:54:39
【问题描述】:

我正在开发一个有支付选项卡的应用程序,当我点击支付选项卡时,它会将我带到一个只有一个按钮的页面,当我单击该按钮时,它会将我带到条带结帐系统(https://stripe.com/docs/payments/checkout/client),一旦它处理了付款,它就会带我回到应用程序。我在 firebase 中有一个数据库,用于跟踪当前登录的用户是否已付费。如果当前用户未付款,我希望在付款成功完成后将该用户的数据库的成员资格字段从“假”更新为“真”。问题是,如果我在 try 块内完成付款后立即更新 db,则 db 不会更新,但如果我在 componentDidMount() func 内进行更新,我确实会看到对 db 所做的更改。我究竟做错了什么? func 是异步的事实是否会导致这里出现问题?如果我想在付款成功后更新数据库,那我该怎么做呢?

import React from 'react';
import firebase from "firebase/app";
import 'firebase/firestore';
import "firebase/database";
import { auth, database } from '../../firebase';

import { UserAndDbObjConsumer, UserAndDbObjContext } from '../../dbAndUserObjContext';

import { loadStripe } from '@stripe/stripe-js';
// Make sure to call `loadStripe` outside of a component’s render to avoid
// recreating the `Stripe` object on every render.

const stripePromise = loadStripe('test key here');

export default class Payment extends React.Component {
    static contextType = UserAndDbObjContext;

    constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
      }

    componentDidMount() {
        const {user, database} = this.context;

        // When i update my data below, it updates the firebase db and i can
        // see the changes taking effect
        // database.collection("userCollection").doc(user.uid).update({
        //   membership: true
        // })
      }

    handleClick = async (event) => {
        
        const {user, database} = this.context;

        console.log("i am inside handle but outside try")

        try {
          // When the customer clicks on the button, redirect them to Checkout.
          const stripe = await stripePromise;

          const { error } = await stripe.redirectToCheckout({
            lineItems: [{
              price: 'price_1IF4cPAt4f9zG3h2hTG64agQ', // Replace with the ID of your price
              quantity: 1,
            }],
            mode: 'payment',
            successUrl: 'https://app.guideanalytics.ca/',
            cancelUrl: 'https://guideanalytics.ca/termsofuse.html',
          });
          // If `redirectToCheckout` fails due to a browser or network
          // error, display the localized error message to your customer
          // using `error.message`.

          // When i update the firebase db here, than the changes on firebase dont take place
          database.collection("userCollection").doc(user.uid).update({
            membership: true
          })
        } 
        catch(e) {
          console.log(e);
        }
    }

    render() {
      return (
      <div> 
        <button role="link" onClick={(e) => this.handleClickTest()}>
          Checkout
        </button>
      </div>
      )
    }
  }

  //Payment.contextType = Context;

【问题讨论】:

    标签: reactjs firebase google-cloud-firestore stripe-payments


    【解决方案1】:

    stripe.redirectToCheckout 只会在出现浏览器或网络错误时出错,因此在几乎所有情况下您的database.collection 函数调用都不会执行。

    当用户点击您在结帐会话中定义的successUrl 时,您需要调用该函数。您可能想要自定义 successUrl 以确保您知道要更新哪个客户。例如:

    successUrl: `https://app.guideanalytics.a/?userId=${user.uid}&sessionId={CHECKOUT_SESSION_ID}`,
    

    最后一部分是通配符,然后 Stripe 将使用 Session 的 ID automatically replace

    然后在您的成功页面上,您将根据 URL 中的用户 ID 和 Checkout Session ID 更新数据库。

    【讨论】:

    • 有趣的答案,但是当我将 console.log("something") 放在代码的 stripe.redirectToCheckout 块下方(并且就在 database.collection 部分上方)并完成付款时,我确实会收到一条控制台消息,这意味着代码确实会一直执行下去。只是由于某种原因,它不执行 database.collection 部分。至于你对successUrl的建议,我真的不需要自定义它,因为我希望用户无论如何都回到应用程序并重新加载页面,所以你建议的那部分没有意义
    • 即使保留控制台日志,我也无法重新创建它,对我来说,当您调用 redirectToCheckout 时,除非重定向时出现错误,否则不会调用任何内容。至于数据库更新,大概您只想在付款完成时执行此操作,只有在您收听checkout.session.complete webhook 或在成功页面上检索会话状态时您才会知道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 2021-08-31
    • 2017-06-15
    • 1970-01-01
    • 2020-09-06
    相关资源
    最近更新 更多