能否仅通过Stripe API完成支付流程?请求代码示例
能否不安装Stripe类库完成支付流程?
可以,但强烈不推荐——直接处理银行卡信息会大幅提升你的PCI合规负担(需满足PCI DSS SAQ D级,成本和复杂度极高),而Stripe官方类库(如stripe.js、@stripe/react-stripe-js)会帮你将敏感卡信息直接发送到Stripe服务器,无需经过你的系统,仅需满足最低级别的PCI合规(SAQ A级)。
如果仍要尝试纯API方式,流程如下:
核心流程
- 后端创建Payment Intent并返回客户端密钥(
client_secret) - 前端自定义表单收集银行卡信息
- 前端将卡信息发送到你的后端,由后端调用Stripe的
confirmPaymentIntentAPI完成支付确认
代码示例
1. Node.js后端(创建Payment Intent + 确认支付)
const express = require('express'); const axios = require('axios'); const app = express(); app.use(express.json()); // Stripe API密钥(后端存储,绝对不能暴露给前端) const STRIPE_SECRET_KEY = 'sk_test_your_secret_key'; const STRIPE_API_BASE = 'https://api.stripe.com/v1'; // 创建Payment Intent app.post('/create-payment-intent', async (req, res) => { try { const response = await axios.post( `${STRIPE_API_BASE}/payment_intents`, new URLSearchParams({ amount: req.body.amount, // 金额,单位为分 currency: 'usd', payment_method_types: ['card'] }), { headers: { 'Authorization': `Bearer ${STRIPE_SECRET_KEY}`, 'Content-Type': 'application/x-www-form-urlencoded' } } ); res.json({ clientSecret: response.data.client_secret }); } catch (error) { res.status(500).json({ error: error.response.data.error.message }); } }); // 确认支付(接收前端传来的卡信息,调用Stripe API) app.post('/confirm-payment', async (req, res) => { const { clientSecret, cardDetails } = req.body; // 从clientSecret中提取payment_intent_id const paymentIntentId = clientSecret.split('_secret_')[0]; try { const response = await axios.post( `${STRIPE_API_BASE}/payment_intents/${paymentIntentId}/confirm`, new URLSearchParams({ payment_method: { card: { number: cardDetails.number, exp_month: cardDetails.expMonth, exp_year: cardDetails.expYear, cvc: cardDetails.cvc }, type: 'card' }, confirm: true }), { headers: { 'Authorization': `Bearer ${STRIPE_SECRET_KEY}`, 'Content-Type': 'application/x-www-form-urlencoded' } } ); res.json({ success: true, paymentIntent: response.data }); } catch (error) { res.status(400).json({ success: false, error: error.response.data.error.message }); } }); app.listen(3001, () => console.log('Server running on port 3001'));
2. React前端(自定义表单收集卡信息)
import { useState } from 'react'; function CustomPaymentForm() { const [cardNumber, setCardNumber] = useState(''); const [expMonth, setExpMonth] = useState(''); const [expYear, setExpYear] = useState(''); const [cvc, setCvc] = useState(''); const [amount, setAmount] = useState('1000'); // $10.00 const [message, setMessage] = useState(''); // 创建Payment Intent const createPaymentIntent = async () => { try { const res = await fetch('http://localhost:3001/create-payment-intent', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: parseInt(amount) }) }); const data = await res.json(); return data.clientSecret; } catch (err) { setMessage('创建支付意向失败:' + err.message); return null; } }; // 提交支付 const handleSubmit = async (e) => { e.preventDefault(); setMessage('处理支付中...'); const clientSecret = await createPaymentIntent(); if (!clientSecret) return; try { const res = await fetch('http://localhost:3001/confirm-payment', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ clientSecret, cardDetails: { number: cardNumber.replace(/\s/g, ''), expMonth: parseInt(expMonth), expYear: parseInt(expYear), cvc } }) }); const data = await res.json(); if (data.success) { setMessage('支付成功!'); } else { setMessage('支付失败:' + data.error); } } catch (err) { setMessage('支付请求出错:' + err.message); } }; return ( <form onSubmit={handleSubmit}> <div> <label>银行卡号:</label> <input type="text" value={cardNumber} onChange={(e) => setCardNumber(e.target.value)} placeholder="4242 4242 4242 4242" required /> </div> <div> <label>有效期(月/年):</label> <input type="text" value={expMonth} onChange={(e) => setExpMonth(e.target.value)} placeholder="12" maxLength={2} required /> <span>/</span> <input type="text" value={expYear} onChange={(e) => setExpYear(e.target.value)} placeholder="25" maxLength={2} required /> </div> <div> <label>CVC:</label> <input type="text" value={cvc} onChange={(e) => setCvc(e.target.value)} placeholder="123" maxLength={4} required /> </div> <div> <label>金额(分):</label> <input type="number" value={amount} onChange={(e) => setAmount(e.target.value)} required /> </div> <button type="submit">提交支付</button> {message && <p>{message}</p>} </form> ); } export default CustomPaymentForm;
关键注意事项
- PCI合规风险:直接处理银行卡信息意味着你的系统需要符合PCI DSS SAQ D级要求,这涉及严格的安全审计、数据加密、访问控制等,成本极高。
- 3D Secure处理:上述示例未处理3D Secure验证流程,实际支付中若触发3DS,需要额外处理Stripe返回的
next_action(如跳转验证页面),纯API方式会大幅增加复杂度。 - 错误处理:示例仅做基础错误处理,实际场景需覆盖更多边缘情况(如卡过期、余额不足、网络错误等)。
内容的提问来源于stack exchange,提问作者Aliton Oliveira
相关产品推荐
相关产品推荐

