似乎没有任何错误,据我所知我的设置是正确的。我在页面组件中有我的服务器端代码: https://github.com/erasebegin/heard-good-things-shop/blob/main/src/app/%5Bslug%5D/checkout/page.tsx
我在客户端组件中将提供程序作为 page.tsx 的子组件: https://github.com/erasebegin/heard-good-things-shop/blob/main/src/app/%5Bslug%5D/components/StripeWrapper.tsx
然后我将 PaymentElement 放在由 StripeWrapper 包装的组件内: https://github.com/erasebegin/heard-good-things-shop/blob/main/src/app/%5Bslug%5D/components/StripeCheckout.tsx
我之前也遇到过类似的问题,其中 PaymentElement 没有出现,这与 Stripe 承诺未正确实现有关,但据我所知,一切都在按需要进行,所以为什么我没有看到支付元素?
任何见解将不胜感激!
附注我想我应该使用代码链接来更简洁。将代码粘贴到问题中会更好吗?
你的思路是对的,但概念有点混淆,雨婷的评论也说对了一半。
我在 StripeCheckout.tsx 中看到您在客户端提交了句柄。
即使您已经使用私钥在服务器端正确初始化了条带,您“可以”将其传递给客户端组件,但是您将暴露服务器机密。您需要完全保留条带内容而不是服务器。
传统上实现此目的的方法是公开一个小型 api。现在,反应服务器组件方法可能涉及服务器端表单,又名“服务器操作”
Vercel 在这方面有一个有用的指南:https://vercel.com/guides/getting-started-with-nextjs-typescript-stripe
本质上而不是你这里所拥有的:
const handleSubmit = async (event: React.MouseEvent<HTMLButtonElement>) => {
// We don't want to let default form submission happen here,
// which would refresh the page.
event.preventDefault();
你会得到这样的东西:
"use server"
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
// Create a Checkout Session.
const checkoutSession: Stripe.Checkout.Session = await fetchPostJSON(
'/api/checkout_sessions',
{ amount: input.customDonation },
);
if ((checkoutSession as any).statusCode === 500) {
console.error((checkoutSession as any).message);
return;
}
// Redirect to Checkout.
const stripe = await getStripe();
const { error } = await stripe!.redirectToCheckout({
// Make the id field from the Checkout Session creation API response
// available to this file, so you can provide it as parameter here
// instead of the {{CHECKOUT_SESSION_ID}} placeholder.
sessionId: checkoutSession.id,
});
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer
// using `error.message`.
console.warn(error.message);
};