React集成Stripe无法触发confirmPayment,点击按钮组件重渲染
Stripe React支付功能点击按钮无响应问题排查
我正在跟着Stripe官方React教程开发支付功能,只是把Fetch API换成了Axios实例(觉得Axios更方便传递凭证),但点击支付按钮时,Checkout组件会重渲染,却没有触发confirmPayment支付确认动作。换回Fetch API也解决不了问题,附上Wrapper组件和Checkout组件的代码,求帮忙!
Wrapper组件代码
const [stripePromise, setStripePromise] = useState(null) const [clientSecret, setClientSecret] = useState<string>() const [run1, setRun1] = useState(1) const [run2, setRun2] = useState(1) useEffect(() => { api.get('/services/pubkey').then(async (data) => { const pubkey = data?.data?.pubkey setStripePromise(loadStripe(pubkey)) }) }, []) useEffect(() => { if (id) { api.post(`/services/cs/${id}`).then(async (data) => { const clientsecret = data?.data?.clientSecret setClientSecret(clientsecret) console.log(clientsecret) }) } }, []) return ( <Stack alignItems='center'> <Typography fontSize={25}>Agora Que o Serviço foi Aceito Tá na Hora de pagar</Typography> { stripePromise && clientSecret && ( <Elements stripe={stripePromise} options={{ clientSecret: clientSecret }} key={clientSecret}> <CheckoutForm /> </Elements> ) } </Stack> )
Checkout组件代码
const stripe = useStripe() const elements = useElements() const [message, setMessage] = useState<string|null>('nada ainda') const [isProcessing, setIsProcessing] = useState<boolean>(false) const handleSubmit = async (e) => { console.log('AEEE') e.preventDefault() if (!stripe || !elements) { return } setIsProcessing(true) const { error, paymentIntent } = await stripe.confirmPayment({ elements, confirmParams: { return_url: `${window.location.origin}` }, }) console.log(error) console.log(paymentIntent) if (error) { setMessage(error == undefined ? 'error' : error?.message) } else if (paymentIntent && paymentIntent.status == 'succeeded') { setMessage(`Payment Status : ${paymentIntent?.status}`) } else { setMessage('Unexpected state') } setIsProcessing(false) } return ( <Stack alignItems='center' spacing={4} mt={3}> <PaymentElement /> <Button onClick={handleSubmit}>Pagar</Button> {message} {isProcessing} </Stack> )
问题排查与修复
表单提交上下文缺失:当前Checkout组件未使用
<form>标签包裹支付元素和按钮,Stripe的confirmPayment需要依托表单提交的上下文,直接绑定按钮onClick会导致逻辑异常,甚至触发组件重渲染。
修复:用<form>包裹内容,将handleSubmit绑定到表单的onSubmit事件,同时给按钮设置type="submit":return ( <form onSubmit={handleSubmit}> <Stack alignItems='center' spacing={4} mt={3}> <PaymentElement /> <Button type="submit" disabled={isProcessing || !stripe || !elements}> {isProcessing ? '处理中...' : 'Pagar'} </Button> {message} </Stack> </form> )useEffect依赖项遗漏:Wrapper组件中获取
clientSecret的useEffect依赖数组为空,若id是异步获取的(比如路由参数),会导致组件挂载时id为空,后续id更新后不会重新请求客户端秘钥,进而导致支付流程无法初始化。
修复:将id加入该useEffect的依赖数组:useEffect(() => { if (id) { api.post(`/services/cs/${id}`).then(async (data) => { const clientsecret = data?.data?.clientSecret setClientSecret(clientsecret) console.log(clientsecret) }) } }, [id]) // 添加id为依赖项异常处理缺失:当前代码未对Axios请求添加错误捕获,若获取Stripe公钥或客户端秘钥失败,无法及时排查问题。
修复:给Axios请求添加错误捕获逻辑:// 获取公钥的useEffect useEffect(() => { api.get('/services/pubkey') .then(data => { const pubkey = data?.data?.pubkey if (pubkey) { setStripePromise(loadStripe(pubkey)) } else { console.error('未获取到有效Stripe公钥') } }) .catch(err => console.error('获取Stripe公钥失败:', err)) }, []) // 获取客户端秘钥的useEffect useEffect(() => { if (id) { api.post(`/services/cs/${id}`) .then(data => { const clientsecret = data?.data?.clientSecret setClientSecret(clientsecret) console.log(clientsecret) }) .catch(err => console.error('获取客户端秘钥失败:', err)) } }, [id])
内容的提问来源于stack exchange,提问作者Julio Raposo
相关产品推荐
相关产品推荐

