You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否仅通过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的confirmPaymentIntent API完成支付确认

代码示例

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:52:36