Blog

ReactでStripeの決済フォームを試す

React SPAでStripeの決済フォームを組み込む方法について整理してみました。

準備

めんどうなので、create-react-appでざっと立てます。

$ create-react-app stripe-test
$ cd stripe-test
$ yarn start

とりあえずこれでReact SPAが簡単につくれます。

react-stripe-elements を試す

Stripeのカード情報入力フォームは、react-stripe-elementsを使います。stripe-elementを組み込んだライブラリなので、自力で作る手間が大幅に省けます。

$ yarn add react-stripe-elements

/public/index.htmlでスクリプトを読み込む

Stripeのライブラリを使用するため、/public/index.htmlに以下のコードを追加します。

<script src="https://js.stripe.com/v3/"></script>

/src/App.js

Providerが必要になるので、設定します。プロパティとして、Stripeの公開キーを設定しましょう。

import React, { Component } from 'react';
import {StripeProvider} from 'react-stripe-elements';
import CardForm from './CardForm';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <StripeProvider apiKey="pk_test_XXXXXXX">
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <h1 className="App-title">Welcome to React</h1>
          </header>
          <CardForm />
        </div>
      </StripeProvider>
    );
  }
}

export default App;

/src/CardForm.jsx

カード情報入力フォームを設定します。formを作るコンポーネントをinjectStripeすることで、コンポーネントがthis.props.stripeからstripe-jsのメソッドを利用することができるようになります。

import React from 'react';
import {Elements, injectStripe, CardElement} from 'react-stripe-elements';

// フォーム要素のスタイルなどを定義する
const createOptions = (fontSize: string) => {
  return {
    hidePostalCode: false,
    style: {
      base: {
        fontSize,
        color: '#424770',
        letterSpacing: '0.025em',
        fontFamily: 'Source Code Pro, monospace',
        '::placeholder': {
          color: '#aab7c4',
        },
      },
      invalid: {
        color: '#9e2146',
      },
    },
  };
};

// Cardフォームの要素を定義するコンポーネント
class CardSection extends React.Component {
  render() {
    return (
      <label>
        Card details
        <CardElement
          {...createOptions()}
        />
      </label>
    );
  }
};

// Formの定義と、submit時のアクションを定義するコンポーネント
class CheckoutForm extends React.Component {
  handleSubmit = (ev) => {
    ev.preventDefault();
    this.props.stripe.createToken({name: 'Jenny Rosen'}).then(({token}) => {
      console.log('Received Stripe token:', token);
    });
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <CardSection />
        <button>Confirm order</button>
      </form>
    );
  }
}
// ここでCheckoutFormがstripe-jsにアクセスできるようにしている
const InjectedCheckoutForm = injectStripe(CheckoutForm);

// Elementsでラップする
class MyStoreCheckout extends React.Component {
  render() {
    return (
      <Elements>
        <InjectedCheckoutForm />
      </Elements>
    );
  }
}

export default MyStoreCheckout;

完成系

上記の編集が完了すると、以下のようにStripeのカードフォームが表示されます。

ちょっとCSSで調整してます。

テスト用のカード番号を入力して[Confirm order]すると、tok_xxxxのような値を含むデータがconsoleに出力されます。

tokenでカスタマーを作成する

先ほどのスクリプトで作成されたtokenを使うことでStripeへのカード情報登録ができます。本来はAPIを作ってそこにリクエストするやり方ですが、めんどうなので今回はcurlで横着します。

curl https://api.stripe.com/v1/customers \
   -u sk_test_xxxxxxx: \
   -d description="Customer for hoge@example.com" \
   -d email="hoge@example.com" \
   -d source="tok_xxxxxxx"

実行すると、Stripeのダッシュボードにデータが登録されています。

stripe-jsとreact-stripe-elementsを使うメリット

  • カード情報を自分が管理しているサーバーに一切残さずに済む
  • いい感じのカードフォーム(4桁区切り・オートフォーカスなど)が使える
  • カスタマイズ性が高いので、自社サービスへの組み込みがしやすい

具体的なカスタマイズなどはまた追い追い紹介します。