React TypeScript集成Stripe遇clientSecret格式错误如何修复?
Stripe集成错误修复方案
问题描述
在React TypeScript项目中集成Stripe时出现以下错误:
Stripe error react-Uncaught IntegrationError: Invalid value for elements(): clientSecret should be a client secret of the form ${id}secret${secret}
相关代码如下:
placeOrder.tsx
import {Elements} from '@stripe/react-stripe-js'; import {loadStripe} from '@stripe/stripe-js'; import CheckoutForm from './Checkout'; // Make sure to call `loadStripe` outside of a component’s render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe('pk_test_..Pdx'); // public key from stripe dashboard export default function PlaceORder() { const options = { // passing the client secret obtained from the server clientSecret: 'sk_test_.....YKGWngQO', // client secret from stipe dashboard theme: 'stripe', }; return ( <Elements stripe={stripePromise} options={options}> <CheckoutForm /> </Elements> ); };
checkout.tsx
import {PaymentElement} from '@stripe/react-stripe-js'; const CheckoutForm = () => { return ( <form> <PaymentElement /> <button>Submit</button> </form> ); }; export default CheckoutForm;
修复方案
错误根源
你当前传入的clientSecret是Stripe的服务器秘钥(以sk_开头),但Elements组件要求的是支付Intent/Setup Intent生成的客户端密钥(格式为pi_xxx_secret_xxx或si_xxx_secret_xxx)。服务器秘钥是后端专用的,绝对不能暴露在前端代码中,同时也不符合客户端密钥的格式要求。
具体修复步骤
后端生成客户端密钥
在你的后端服务中调用Stripe API创建PaymentIntent(用于支付场景)或SetupIntent(用于保存支付方式场景),获取返回结果里的client_secret字段。以下是Node.js后端示例:const stripe = require('stripe')('sk_test_你的服务器秘钥'); // 接口示例:创建PaymentIntent并返回客户端密钥 app.post('/create-payment-intent', async (req, res) => { const paymentIntent = await stripe.paymentIntents.create({ amount: 1000, // 金额单位为分,此处代表10美元 currency: 'usd', }); res.json({ clientSecret: paymentIntent.client_secret }); });前端从后端获取客户端密钥
在React组件中通过API请求后端接口,拿到合法的client_secret后再渲染Elements组件。修改placeOrder.tsx:import {Elements} from '@stripe/react-stripe-js'; import {loadStripe} from '@stripe/stripe-js'; import CheckoutForm from './Checkout'; import { useEffect, useState } from 'react'; const stripePromise = loadStripe('pk_test_..Pdx'); export default function PlaceORder() { const [clientSecret, setClientSecret] = useState(''); useEffect(() => { // 调用后端接口获取客户端密钥 fetch('/create-payment-intent', { method: 'POST' }) .then(res => res.json()) .then(data => setClientSecret(data.clientSecret)); }, []); // 未获取到密钥时显示加载状态 if (!clientSecret) return <div>加载中...</div>; const options = { clientSecret, theme: 'stripe', }; return ( <Elements stripe={stripePromise} options={options}> <CheckoutForm /> </Elements> ); };移除前端的服务器秘钥
彻底删除前端代码中所有sk_开头的秘钥,避免因秘钥泄露导致的安全风险。
内容的提问来源于stack exchange,提问作者Jayna Tanawala
相关产品推荐
相关产品推荐

