首页
/ React Stripe Elements 组件库实战教程

React Stripe Elements 组件库实战教程

2025-07-10 04:01:20作者:咎岭娴Homer

前言

React Stripe Elements 是一个用于构建 Stripe 支付表单的 React 组件库,它提供了多种支付元素组件,让开发者能够轻松地在 React 应用中集成 Stripe 支付功能。本文将深入解析该库的核心组件和使用方法,帮助开发者快速掌握构建安全支付表单的技巧。

核心组件介绍

React Stripe Elements 提供了多种支付表单组件,每种组件对应不同的支付场景:

  1. CardElement - 完整的信用卡输入组件
  2. CardNumberElement - 仅信用卡号输入
  3. CardExpiryElement - 信用卡有效期输入
  4. CardCvcElement - 信用卡安全码输入
  5. PaymentRequestButtonElement - Apple Pay/Google Pay 按钮
  6. IbanElement - 欧洲银行账号(IBAN)输入
  7. IdealBankElement - iDEAL 银行选择器

基础架构

使用 React Stripe Elements 需要三个核心高阶组件:

  1. StripeProvider - 提供 Stripe 上下文
  2. Elements - 定义一组 Stripe 元素
  3. injectStripe - 将 Stripe 实例注入到表单组件中
<StripeProvider apiKey="your_publishable_key">
  <Elements>
    <YourPaymentForm />
  </Elements>
</StripeProvider>

支付表单实现详解

1. 完整信用卡表单

CardForm 组件展示了如何使用 CardElement 创建一个完整的信用卡输入表单:

class _CardForm extends React.Component {
  handleSubmit = (ev) => {
    ev.preventDefault();
    this.props.stripe.createToken().then((payload) => {
      console.log('[token]', payload);
    });
  };
  
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>Card details</label>
        <CardElement {...createOptions(this.props.fontSize)} />
        <button>Pay</button>
      </form>
    );
  }
}
const CardForm = injectStripe(_CardForm);

关键点:

  • 使用 injectStripe 注入 Stripe 实例
  • 通过 createToken 方法生成支付令牌
  • 自定义样式通过 createOptions 函数实现

2. 分体式信用卡表单

SplitForm 组件展示了如何将信用卡信息拆分成多个独立输入框:

class _SplitForm extends React.Component {
  // ...类似提交逻辑
  
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>Card number</label>
        <CardNumberElement {...createOptions(this.props.fontSize)} />
        
        <label>Expiration date</label>
        <CardExpiryElement {...createOptions(this.props.fontSize)} />
        
        <label>CVC</label>
        <CardCvcElement {...createOptions(this.props.fontSize)} />
        
        <button>Pay</button>
      </form>
    );
  }
}

3. 移动支付表单

PaymentRequestForm 组件实现了 Apple Pay/Google Pay 支付按钮:

class _PaymentRequestForm extends React.Component {
  constructor(props) {
    super(props);
    const paymentRequest = props.stripe.paymentRequest({
      country: 'US',
      currency: 'usd',
      total: { label: 'Demo total', amount: 1000 }
    });
    
    this.state = { paymentRequest, canMakePayment: false };
  }

  componentDidMount() {
    this.state.paymentRequest.on('token', ({complete, token}) => {
      console.log('Received Stripe token:', token);
      complete('success');
    });

    this.state.paymentRequest.canMakePayment().then(result => {
      this.setState({canMakePayment: !!result});
    });
  }

  render() {
    return this.state.canMakePayment ? (
      <PaymentRequestButtonElement
        paymentRequest={this.state.paymentRequest}
        style={{
          paymentRequestButton: {
            theme: 'dark',
            height: '64px',
            type: 'donate',
          },
        }}
      />
    ) : null;
  }
}

4. 欧洲银行转账表单

IbanForm 组件实现了 SEPA 直接借记支付:

class _IbanForm extends React.Component {
  handleSubmit = (ev) => {
    ev.preventDefault();
    this.props.stripe.createSource({
      type: 'sepa_debit',
      currency: 'eur',
      owner: {
        name: ev.target.name.value,
        email: ev.target.email.value,
      },
      mandate: { notification_method: 'email' }
    }).then(payload => console.log('[source]', payload));
  };
  
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>Name<input name="name" type="text" required /></label>
        <label>Email<input name="email" type="email" required /></label>
        <label>IBAN<IbanElement supportedCountries={['SEPA']} {...createOptions(this.props.fontSize)} /></label>
        <button>Pay</button>
      </form>
    );
  }
}

5. iDEAL 银行支付表单

IdealBankForm 组件实现了荷兰 iDEAL 支付方式:

class _IdealBankForm extends React.Component {
  handleSubmit = (ev) => {
    ev.preventDefault();
    this.props.stripe.createSource({
      type: 'ideal',
      amount: 1099,
      currency: 'eur',
      owner: { name: ev.target.name.value },
      redirect: { return_url: 'https://example.com' }
    }).then(payload => console.log('[source]', payload));
  };
  
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>Name<input name="name" type="text" required /></label>
        <label>iDEAL Bank<IdealBankElement {...createOptions(this.props.fontSize, '10px 14px')} /></label>
        <button>Pay</button>
      </form>
    );
  }
}

样式定制技巧

createOptions 函数提供了自定义元素样式的能力:

const createOptions = (fontSize, padding) => ({
  style: {
    base: {
      fontSize,
      color: '#424770',
      letterSpacing: '0.025em',
      fontFamily: 'Source Code Pro, monospace',
      '::placeholder': { color: '#aab7c4' },
      ...(padding ? {padding} : {}),
    },
    invalid: { color: '#9e2146' }
  }
});

可以自定义的属性包括:

  • 字体大小和颜色
  • 占位符样式
  • 无效状态样式
  • 内边距等布局属性

响应式设计实现

Checkout 组件展示了如何根据屏幕尺寸调整支付元素的大小:

class Checkout extends React.Component {
  constructor() {
    super();
    this.state = { elementFontSize: window.innerWidth < 450 ? '14px' : '18px' };
    window.addEventListener('resize', this.handleResize);
  }

  handleResize = () => {
    if (window.innerWidth < 450 && this.state.elementFontSize !== '14px') {
      this.setState({elementFontSize: '14px'});
    } else if (window.innerWidth >= 450 && this.state.elementFontSize !== '18px') {
      this.setState({elementFontSize: '18px'});
    }
  };

  render() {
    return (
      <div className="Checkout">
        <Elements><CardForm fontSize={this.state.elementFontSize} /></Elements>
        {/* 其他表单... */}
      </div>
    );
  }
}

事件处理

所有 Stripe 元素都支持以下事件处理:

  • onBlur - 失去焦点时触发
  • onChange - 值变化时触发
  • onFocus - 获得焦点时触发
  • onReady - 元素初始化完成时触发
const handleBlur = () => console.log('[blur]');
const handleChange = (change) => console.log('[change]', change);
const handleFocus = () => console.log('[focus]');
const handleReady = () => console.log('[ready]');

<CardElement
  onBlur={handleBlur}
  onChange={handleChange}
  onFocus={handleFocus}
  onReady={handleReady}
/>

最佳实践

  1. 安全性:永远在前端使用 publishable key,secret key 必须保存在后端
  2. 错误处理:妥善处理 createTokencreateSource 的 Promise 拒绝
  3. 用户体验:提供清晰的错误提示和加载状态
  4. 移动优化:确保表单在移动设备上易于操作
  5. 合规性:遵循 PCI DSS 规范处理支付数据

结语

React Stripe Elements 提供了一种安全、便捷的方式在 React 应用中集成 Stripe 支付功能。通过本文的详细解析,开发者可以快速掌握各种支付表单的实现方法,并根据实际需求进行定制开发。记住,支付系统涉及敏感数据,务必遵循安全最佳实践,确保用户支付信息的安全。