我正在使用 Next.js 14.2.3 并尝试使用 getServerSideProps 中 @stripe/firestore-stripe- payment 中的 getProducts 函数从 Firestore 获取产品列表。但是,我遇到了序列化错误:
服务器错误
错误:序列化从“/”中的返回的.products
时出错。getServerSideProps
原因:无法序列化为JSON。请使用undefined
或省略此值。null
这是我的代码的相关部分:
import Head from "next/head";
import Header from "@/components/Header";
import Banner from "@/components/Banner";
import { Movie } from "@/typings";
import requests from "@/utils/requests";
import Row from "@/components/Row";
import useAuth from "@/hooks/useAuth";
import { useRecoilValue } from "recoil";
import { modalState } from "@/atoms/moduleAtom";
import Modal from "@/components/Modal";
import Plans from "@/components/Plans";
import { Product, getProducts } from "@stripe/firestore-stripe-payments";
import payments from "@/lib/stripe";
interface Props {
netflixOriginals: Movie[];
trendingNow: Movie[];
topRated: Movie[];
actionMovies: Movie[];
comedyMovies: Movie[];
horrorMovies: Movie[];
romanceMovies: Movie[];
documentaries: Movie[]
products: Product[]
}
const Home = ({
netflixOriginals,
actionMovies,
comedyMovies,
documentaries,
horrorMovies,
romanceMovies,
topRated,
trendingNow,
products
Props) => {
console.log(products)
const { logout, loading } = useAuth()
const showModal = useRecoilValue(modalState)
const subscription = false
if (loading || subscription === null) return
null
if (!subscription) return <Plans/>
return (
<div
this is so we cant scroll when we open the modal
className={`relative h-screen bg-gradient-to-b lg:h-[140vh] ${showModal && "!h-screen overflow-hidden"}`}
>
<Head>
<title>Home - Netflix</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<Header />
<main className="relative pl-4 pb-24 lg:space-y24 lg:pl-16">
<Banner netflixOriginals={netflixOriginals}/>
<section className="md:space-y-24">
<Row title="Trending Now" movies={trendingNow} />
<Row title="Top Rated" movies={topRated} />
<Row title="Action Thrillers" movies={actionMovies} />
My List Component*/}
<Row title="Comedies" movies={comedyMovies} />
<Row title="Scary Movies" movies={horrorMovies} />
<Row title="Romance Movies" movies={romanceMovies} />
<Row title="Documentaries" movies={documentaries} />
</section>
</main>
{showModal} && <Modal />
</div>
);
}
export const getServerSideProps = async () => {
const products = await getProducts(payments, {
includePrices: true,
activeOnly: true
}).then((res) => res).catch((error) => console.log(error.message))
const [
netflixOriginals,
trendingNow,
topRated,
actionMovies,
comedyMovies,
horrorMovies,
romanceMovies,
documentaries,
await Promise.all([
fetch(requests.fetchNetflixOriginals).then((res) => res.json()),
fetch(requests.fetchTrending).then((res) => res.json()),
fetch(requests.fetchTopRated).then((res) => res.json()),
fetch(requests.fetchActionMovies).then((res) => res.json()),
fetch(requests.fetchComedyMovies).then((res) => res.json()),
fetch(requests.fetchHorrorMovies).then((res) => res.json()),
fetch(requests.fetchRomanceMovies).then((res) => res.json()),
fetch(requests.fetchDocumentaries).then((res) => res.json()),
]);
return {
props: {
netflixOriginals: netflixOriginals.results,
trendingNow: trendingNow.results,
topRated: topRated.results,
actionMovies: actionMovies.results,
comedyMovies: comedyMovies.results,
horrorMovies: horrorMovies.results,
romanceMovies: romanceMovies.results,
documentaries: documentaries.results,
products
},
};
};
export default Home;
我尝试过的:
我希望
getServerSideProps
函数能够在不遇到序列化问题的情况下获取产品和其他电影数据,从而允许将产品数组传递到组件而不会出现任何错误。
大家好
对于遇到类似问题的人来说,问题似乎是 源于使用过时版本的 Stripe SDK。解决 为此,我建议直接实现 Stripe API,而不是 依赖过时的 SDK。
以下是您可以采取的方法的概述:
获取产品和价格:如果您仍然需要获取产品和价格 来自 Firestore 的价格数据,创建 fetchProducts.ts 文件以 动态检索此信息。这是获取代码 产品:
// fetchProducts.ts
import { db } from '../firebase';
import { collection, query, where, getDocs } from 'firebase/firestore';
const fetchProducts = async (): Promise<any[]> => {
const products: any[] = [];
try {
const productsCollection = collection(db, 'products');
const q = query(productsCollection, where('active', '==', true));
const querySnapshot = await getDocs(q);
for (const doc of querySnapshot.docs) {
const productData = doc.data();
const pricesCollection = collection(doc.ref, 'prices');
const priceSnap = await getDocs(pricesCollection);
const prices = priceSnap.docs.map((priceDoc) => ({
id: priceDoc.id,
...priceDoc.data(),
}));
products.push({
id: doc.id,
...productData,
prices,
});
}
} catch (error) {
console.error('Error fetching products:', error);
}
return products;
};
export default fetchProducts;
使用 Stripe Checkout 开始订阅:使用以下代码 通过在中创建新文档来启动订阅的代码片段 用户的 checkout_sessions 集合。 Firestore 扩展 将使用 Stripe Checkout 会话 ID 更新此文档,您可以使用该 ID 可用于将用户重定向到结帐页面。
import { collection, addDoc, doc, onSnapshot } from 'firebase/firestore';
import { auth, db } from '../firebase';
const createCheckoutSession = async (priceId: string) => {
const user = auth.currentUser;
if (!user) throw new Error('No authenticated user found.');
const uid = user.uid;
// Create a checkout session in Firestore
const col = collection(db, 'customers', uid, 'checkout_sessions');
const docRef = await addDoc(col, {
price: priceId,
success_url: window.location.origin,
cancel_url: window.location.origin,
});
// 监听要创建的结帐会话并获取 URL
return new Promise<string>((resolve, reject) => {
const unsub = onSnapshot(doc(db, 'customers', uid, 'checkout_sessions', docRef.id), (snap) => {
const data = snap.data();
if (data?.url) {
unsub();
resolve(data.url);
} else if (data?.error) {
unsub();
reject(new Error(`An error occurred: ${data.error.message}`));
}
});
});
};
export default createCheckoutSession;
集成到您的组件中:使用 createCheckoutSession 函数 在您的组件中处理订阅过程。这是一个 如何集成它的示例:
import createCheckoutSession from './path/to/your/createCheckoutSession';
const subscribeToPlan = async (priceId: string) => {
try {
const url = await createCheckoutSession(priceId);
window.location.assign(url);
} catch (error) {
console.error('Error creating checkout session:', error);
}
};
另外,你可以参考这个视频
查看如何设置 Stripe Checkout Firestore。
我希望这有助于解决您面临的问题!