簡體   English   中英

Uncaught (in promise) FirebaseError: Function collection() cannot be called with an empty path

[英]Uncaught (in promise) FirebaseError: Function collection() cannot be called with an empty path

我正在嘗試構建亞馬遜克隆。 在付款部分,我有時使用 Stripe 成功付款,因為有時未設置 clientSecret(我不知道為什么它會起作用,然后又不起作用,然后又起作用)。 付款成功后,我想將訂單保存在firestore數據庫中。 因此,在“然后”之后,我想 go 將數據存儲在數據庫中。

 import React, { useEffect, useState } from "react"; import "./Payment.css"; import { Link, useNavigate } from "react-router-dom"; import CheckoutProduct from "./CheckoutProduct"; import { useStateValue } from "./StateProvider"; import { useElements, useStripe, CardElement } from "@stripe/react-stripe-js"; import CurrencyFormat from "react-currency-format"; import { getBasketTotal } from "./reducer"; import axios from "./axios"; import { db } from "./firebase"; import { collection, doc, setDoc } from "firebase/firestore"; function Payment() { const [{ basket, user }, dispatch] = useStateValue(); const [error, setError] = useState(null); const [disabled, setDisabled] = useState(true); const [succeeded, setSucceeded] = useState(false); const [processing, setProcessing] = useState(""); const [clientSecret, setClientSecret] = useState(); console.log("The total is>>>>>", Math.trunc(getBasketTotal(basket) * 100)); //Stripe HOOKS const stripe = useStripe(); const elements = useElements(); ///// const navigate = useNavigate(); //Whenever basket changes, it will make this request and it will update the special stripe secret which allows us to charge the customer the correct amount. useEffect(() => { //generate the special stripe client secret that allows us to charge the customer const getClientSecret = async () => { const response = await axios({ method: "post", //Stripe expects the total in a currencies subunits, hence * 100 url: `/payments/create?total=${Math.trunc( getBasketTotal(basket) * 100 )}`, }); setClientSecret(response.data.clientSecret); }; getClientSecret(); }, basket); //////// console.log("The Secret is>>>", clientSecret); const handleSubmit = async (event) => { //do all fancy stripe stuff... event.preventDefault(); //stops from refreshing setProcessing(true); //helps in stopping user to click Buy button multiple time while processing. basically disbales the button after one use. const payload = await stripe.confirmCardPayment(clientSecret, { payment_method: { card: elements.getElement(CardElement), }, }).then(({ paymentIntent }) => { //paymentIntent = payment confirmation console.log("I was called and didn't do shit", collection("users")) //NoSQL Type retrieval of data const paymentRef = doc( db, collection("users"), user.uid, collection("orders"), paymentIntent.id ); setDoc(paymentRef, { basket: basket, amount: paymentIntent.amount, created: paymentIntent.created, }); setSucceeded(true); setError(null); setProcessing(false); // dispatch({ // type: "EMPTY_BASKET", // }); //Move to orders page, not at the payment page again. Duh... navigate("/orders"); }); }; const handleChange = (event) => { //Listen for changes in Card Element //and display any error as the customer types their card details setDisabled(event.empty); setError(event.error? event.error.message: ""); }; return ( <div className="payment"> <div className="payment__container"> <h1> Checkout (<Link to="/checkout">{basket.length} items</Link>) </h1> {/* Payment Section - Delivery Address */} <div className="payment__section"> <div className="payment__title"> <h3>Delivery Address</h3> <div className="payment__address"> <p>{user?.email}</p> <p>123, Chaurangi Lane</p> <p>New Delhi, India</p> </div> </div> </div> {/* Payment Section - Reviewing Items */} <div className="payment__section"> <div className="payment__title"> <h3>Review Items and Delivery</h3> </div> <div className="payment__items"> {basket.map((item) => ( <CheckoutProduct id={item.id} title={item.title} image={item.image} price={item.price} rating={item.rating} /> ))} </div> </div> {/* Payment Section - Payment Method */} <div className="payment__section"> <div className="payment__title"> <h3>Payment Method</h3> </div> <div className="payment__details"> {/* Stripe Magic Happens here */} <form onSubmit={handleSubmit}> <CardElement onChange={handleChange} /> <div className="payment__priceContainer"> <CurrencyFormat renderText={(value) => ( <> <h3>Order Total: ${value}</h3> </> )} decimalScale={2} value={getBasketTotal(basket)} displayType={"text"} thousandSeparator={true} prefic={"$"} /> <button disabled={processing || disabled || succeeded}> <span>{processing? <p>Processing</p>: "Buy Now"}</span> </button> </div> {/* ERRORS */} {error && <div>{error}</div>} </form> </div> </div> </div> </div> ); } export default Payment;

Firebase.js

 import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: "Hidden from public", authDomain: "Hidden", projectId: "Hidden", storageBucket: "Hidden", messagingSenderId: "Hidden", appId: "Hidden", measurementId: "Hidden" }; // Initialize Firebase const app = initializeApp(firebaseConfig); export const db = getFirestore(app); export const auth = getAuth(app); export default app;

在函數文件夾中,我有 index.js

 const functions = require("firebase-functions"); const express = require("express"); const cors = require("cors"); const stripe = require("stripe")('my_key'); //API // - App config const app = express(); // - Middlewares app.use(cors({ origin: true })); app.use(express.json()); // - API routes app.get("/", (request, response) => response.status(200).send("hello world")); app.post("/payments/create", async (request, response) => { const total = request.query.total; console.log( "Payment Request Received BOOM,; BOOM.. for this amount >>> ": total ), const paymentIntent = await stripe:paymentIntents,create({ amount; total. //subunits of the currency currency. "inr": }). // - 201 => OK - Created response,status(201);send({ clientSecret; paymentIntent.client_secret. }). }); // - Listen command exports.api = functions.https.onRequest(app);

不,當我 go 付款並將測試卡設置為 42424242...,然后單擊“立即購買”。按鈕文本更改為“正在處理”,如果有 clientSecret 設置它會付款,但有時會顯示不完整並且會支付。 該頁面永遠不會進入 /orders 頁面。 它也不會 goto.then function 和 console.log("I was called") 並且永遠不會將數據保存在 Firestore 中。 而是在瀏覽器控制台中給出此錯誤->

The total is - 383106
Payment.js:47 The Secret is: pi_3LmGzhAkzUGZaOjE0j5CQGDX_secret_mEUL5ROsMK4JP0SNCjmMCh34Z
Payment.js:95 Uncaught (in promise) FirebaseError: Function collection() cannot be called with an empty path.

await (async) callCallback @ react-dom.development.js:4164
invokeGuardedCallbackDev @ react-dom.development.js:4213
invokeGuardedCallback @ react-dom.development.js:4277
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:4291
executeDispatch @ react-dom.development.js:9041
processDispatchQueueItemsInOrder @ react-dom.development.js:9073
processDispatchQueue @ react-dom.development.js:9086
dispatchEventsForPlugins @ react-dom.development.js:9097
(anonymous) @ react-dom.development.js:9288
batchedUpdates$1 @ react-dom.development.js:26140
batchedUpdates @ react-dom.development.js:3991
dispatchEventForPluginEventSystem @ react-dom.development.js:9287
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js:6465
dispatchEvent @ react-dom.development.js:6457
dispatchDiscreteEvent @ react-dom.development.js:6430

另外,為什么我的條帶付款在后台進行了如此多的嘗試后會成功。 ->條帶支付的快照

collection()將 Firestore 實例作為第一個參數,但您傳遞的是集合名稱本身。 此外,您不必在doc() function 中使用collection()來為嵌套文檔創建DocumentReference 嘗試:

const paymentRef = doc(db, "users", user.uid, "orders", paymentIntent.id);

setDoc()返回一個 Promise 所以在將用戶重定向到任何其他路由之前嘗試等待它解決,如下所示:

const payload = await stripe.confirmCardPayment(clientSecret, {
  payment_method: {
    card: elements.getElement(CardElement),
  },
}).then(async ({ paymentIntent }) => {
  // ^^ async function
  const paymentRef = doc(db, "users", user.uid, "orders", paymentIntent.id);

  // await here
  await setDoc(paymentRef, {
    basket: basket,
    amount: paymentIntent.amount,
    created: paymentIntent.created,
  });

  setSucceeded(true);
  setError(null);
  setProcessing(false);
  navigate("/orders");
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM