こんにちは、ryohei(@ityryohei)です!

本記事では、StripeとPHPでシンプルな決済フォームの作成する方法をご紹介しています。

Stripeで基本的な決済フォームの作りたいんだけど、どうすればいいんだろう?

上記の疑問にお答えします。

では、解説していきます。

StripeのAPIキーを取得する

Stripeの最初の一歩ということで、アカウントを作成してAPIキーを取得します。アカウントの作成は下記から行えますので、まだアカウント作成してないよ、という方はリンク先から作成しておきましょう。

https://dashboard.stripe.com/register

アカウントの作成が完了すると、各アカウントに紐づいたダッシュボードへアクセスすることができます。ダッシュボードのトップには本番用のAPIキーが表示されています。こちらはサイトを公開する段階で使用するもので、開発中はテスト用のAPIキーを使用します。テスト用のAPIキーは左メニュー内にあるテストデータを表示中をオンにするか、下記のページにアクセスしてテスト用のAPIキーを取得することができます。

https://dashboard.stripe.com/test/apikeys

テスト用のAPIキー(公開可能キー)は下記赤線部分のようにpk_testとなっています。シークレットキーはsk_testからなるトークン名です。APIキーの文字列の上にマウスカーソルを合わせてクリックするとコピーすることができますので、APIキーが必要な場合はダッシュボードにアクセスして取得しましょう。

以上でStripeのAPIキーが取得できました。続いて取得したAPIキーを使って、決済フォームを作成していきます。

決済フォームを作成する

決済フォームの作成は、下記のページを参考に進めていきます。

https://stripe.com/docs/payments/accept-a-payment-charges

本記事ではシンプルなフォームを作成したいので、作成するファイルは下記の2ファイルのみとします。

  • 入力画面:form.php
  • 完了画面:thanks.php

入力画面はクレジットカード番号等を入力してサーバーに送信するまで。完了画面はStripeに入力画面で得た情報を渡して、処理結果を受け取るまでを実装します。

作成するファイルは以上2ファイルとなりますが、途中でStripeのライブラリをインストールする手順があります。ライブラリは同じ階層に設置していただければ大丈夫です。

では、続きを解説していきます。

Stripeモジュールを読み込んでインスタンス化する

Stripeを使用するためにモジュールを読み込みます。HTMLのhead内に下記のスクリプトタグを追加します。

//form.php

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

上記を読み込むことでStripeオブジェクトにアクセスできますので、そのままStripeオブジェクトをインスタンス化します。インスタンス化する際に先程取得したAPIキーを引数に指定しましょう。本記事ではStripe Elementsを使用しますので、併せてElementsインスタンスも作成しておきます。

//form.php

<script src="https://js.stripe.com/v3/"></script>
<script>
    //公開可能キー
    var stripe = Stripe('pk_test_xxxxxx');
    var elements = stripe.elements();

    //以降のスクリプトはこちらに追加していきます

</script>

以上でStripeのモジュールの読み込み~インスタンス化が完了しました。続いてHTMLでフォームのレイアウトを作成していきます。

Stripe Elementsでフォームを作成する

Stripe Elementsは事前にStripe側で用意されたUIコンポーネント(インプットやボタン等)を提供します。クレジットカードのような機密情報を自分のサーバーを介することなく扱うことができます。

詳しくは下記ページをご参照ください。

https://stripe.com/docs/stripe-js#elements

本記事ではクレジットカード情報のみを入力し、サーバーに情報を送信してStripeで決済するというフォームを作成します。入力項目にはStripeを使用するのに最低限必要なカード番号、有効期限、セキュリティコードを用意します。これらはStripe ElementsでUIコンポーネントが用意されているので、自分でinput要素を用意する必要はありませんが、マウントする場所(UIコンポーネントを表示する場所)をどこにするかを指定する必要があります。

本記事では構築例を参考に、idを持たせた要素を設置したいと思います。

//form.php

<form id="card-form" method="post" action="thanks.php">
    <table>
        <tbody>
            <tr>
                <th>カード番号</th>
                <td>
                    <label for="card-number"></label>
                    <div id="card-number"></div>
                </td>
            </tr>
            <tr>
                <th>有効期限</th>
                <td>
                    <label for="card-expiry"></label>
                    <div id="card-expiry"></div>
                </td>
            </tr>
            <tr>
                <th>セキュリティコード</th>
                <td>
                    <label for="card-cvc"></label>
                    <div id="card-cvc"></div>
                </td>
            </tr>
        </tbody>
    </table>
    <div id="card-errors"></div>
    <button>支払いをする</button>
</form>

補足

クレジットカードの有効期限とセキュリティコード(CVC)をサーバーへ送信するには下記のinputが必要になります。公式サイトにの構築例では触れられていないですが、サンプルソースでは指定されていますので、後々のエラー解消のために必ず設置しておきましょう。

<input type="hidden" name="cardExpMonth" data-stripe="exp_month">
<input type="hidden" name="cardExpYear" data-stripe="exp_year">

inputタグはStripe Elementsにマウントすることで生成されます。それぞれのidを指定しStripe Elementsにマウントしていきます。せっかくですので、併せて入力時のバリデーション処理も追加します。エラーメッセージは Stripe Elements がよしなにやってくれるので意識する必要はありません。

//form.php

//カード番号
var cardNumber = elements.create('cardNumber');
cardNumber.mount('#card-number');
cardNumber.on('change', function (event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
        displayError.textContent = event.error.message;
    } else {
        displayError.textContent = '';
    }
});

//有効期限
var cardExpiry = elements.create('cardExpiry');
cardExpiry.mount('#card-expiry');
cardExpiry.on('change', function (event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
        displayError.textContent = event.error.message;
    } else {
        displayError.textContent = '';
    }
});

//セキュリティコード
var cardCvc = elements.create('cardCvc');
cardCvc.mount('#card-cvc');
cardCvc.on('change', function (event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
        displayError.textContent = event.error.message;
    } else {
        displayError.textContent = '';
    }
});

フォームバリデーションについては下記で詳しく説明されています。Stripeでフォームを構築する際に参考にしていただければと思います。

https://stripe.com/docs/js/element/input_validation

カード情報をトークン化してサーバーへ送信する

入力したクレジットカード等の情報をサーバーへ送信する処理(PHPに渡す処理)を作成します。基本的に公式サイトの構築例の通りですが、フォーム要素のidはご自身が指定した名称に変更してください。

//form.php

var form = document.getElementById('card-form');
form.addEventListener('submit', function (event) {
    event.preventDefault();
    var errorElement = document.getElementById('card-errors');
    if (event.error) {
        errorElement.textContent = event.error.message;
    } else {
        errorElement.textContent = '';
    }

    stripe.createToken(cardNumber).then(function (result) {
        if (result.error) {
            errorElement.textContent = result.error.message;
        } else {
            stripeTokenHandler(result.token);
        }
    });
});

function stripeTokenHandler(token) {
    var form = document.getElementById('card-form');
    var hiddenInput = document.createElement('input');
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', 'stripeToken');
    hiddenInput.setAttribute('value', token.id);
    form.appendChild(hiddenInput);
    form.submit();
}

ここまでで入力画面(form.php)のソースは完成です。ただ、現在は入力のみで送信した後の処理がありませんので、続いて完了画面(サーバー側のPHPの処理)を作成していきます。

PHPでサーバー側の処理を作成する

PHPでStripeを使用するためにライブラリをインストールします。

Stripeのライブラリをインストール

Composerでインストールする場合は下記のコマンドを実行してインストールします。

composer require stripe/stripe-php

Composerがない環境の場合は下記のURLからライブラリをダウンロードしてご利用ください。

https://github.com/stripe/stripe-php/releases

以上でライブラリの準備は完了です。

POSTで取得したトークンで支払いを作成する

前項で作成した入力画面で入力したクレジットカード情報を送信すると、Stripeによって生成されたトークンがサーバーに送信されます。PHP側ではPOSTで受け取ったトークンを使用し、APIでStripeの支払いを作成します。支払いの作成に成功するとStripeのダッシュ―ボードにある支払いに新しい支払いが作成されます。エラーが発生した場合は 開発者 のメニューからエラー内容を確認することができます。

PHP側ではダッシュボードから取得することができる開発用のシークレットキーを使用します。ダッシュボードから開発用のシークレットキーを取得し、setApiKeyに指定します。

//thanks.php

<?php

require 'vendor/autoload.php';

//シークレットキー
\Stripe\Stripe::setApiKey('sk_test_xxxxxx');

try {
    $stripeToken = $_POST['stripeToken'];

    $charge = \Stripe\Charge::create([
        'source' => $stripeToken,
        'amount' => 1000,
        'currency' => 'jpy',
    ]);
} catch (Error $e) {
    echo $e->getMessage();
}

Stripeにはテストで使用することができるクレジットカード番号が用意されています。下記を参考にクレジットカード番号を入力して、支払いを作成してみてください。

https://stripe.com/docs/testing#card

以上でトークンを使用した支払いの作成は完了です。入力画面と完了画面が作成できましたので、テストしてエラーがあればダッシュボードのエラーメッセージを参考に修正してみてください。

本記事で掲載したソースまとめ

全体のソースを分割した説明となってしまいましたので、最後に本記事で掲載したソースをまとめておきます。Stripe構築時のテンプレート的な感じで使用していただければ幸いです。

form.php

<!doctype html>
<html>
<head>
<script src="https://js.stripe.com/v3/"></script>
</head>
<body>
<form id="card-form" method="post" action="thanks.php">
    <table>
        <tbody>
            <tr>
                <th>カード番号</th>
                <td>
                    <label for="card-number"></label>
                    <div id="card-number"></div>
                </td>
            </tr>
            <tr>
                <th>有効期限</th>
                <td>
                    <label for="card-expiry"></label>
                    <div id="card-expiry"></div>
                    <input type="hidden" name="cardExpMonth" data-stripe="exp_month">
                </td>
            </tr>
            <tr>
                <th>セキュリティコード</th>
                <td>
                    <label for="card-cvc"></label>
                    <div id="card-cvc"></div>
                    <input type="hidden" name="cardExpYear" data-stripe="exp_year">
                </td>
            </tr>
        </tbody>
    </table>
    <div id="card-errors"></div>
    <button>支払いをする</button>
</form>
<script>
    var stripe = Stripe('pk_test_xxxxxx');
    var elements = stripe.elements();

    var cardNumber = elements.create('cardNumber');
    cardNumber.mount('#card-number');
    cardNumber.on('change', function (event) {
        var displayError = document.getElementById('card-errors');
        if (event.error) {
            displayError.textContent = event.error.message;
        } else {
            displayError.textContent = '';
        }
    });

    var cardExpiry = elements.create('cardExpiry');
    cardExpiry.mount('#card-expiry');
    cardExpiry.on('change', function (event) {
        var displayError = document.getElementById('card-errors');
        if (event.error) {
            displayError.textContent = event.error.message;
        } else {
            displayError.textContent = '';
        }
    });

    var cardCvc = elements.create('cardCvc');
    cardCvc.mount('#card-cvc');
    cardCvc.on('change', function (event) {
        var displayError = document.getElementById('card-errors');
        if (event.error) {
            displayError.textContent = event.error.message;
        } else {
            displayError.textContent = '';
        }
    });

    var form = document.getElementById('card-form');
    form.addEventListener('submit', function (event) {
        event.preventDefault();
        var errorElement = document.getElementById('card-errors');
        if (event.error) {
            errorElement.textContent = event.error.message;
        } else {
            errorElement.textContent = '';
        }

        stripe.createToken(cardNumber).then(function (result) {
            if (result.error) {
                errorElement.textContent = result.error.message;
            } else {
                stripeTokenHandler(result.token);
            }
        });
    });

    function stripeTokenHandler(token) {
        var form = document.getElementById('card-form');
        var hiddenInput = document.createElement('input');
        hiddenInput.setAttribute('type', 'hidden');
        hiddenInput.setAttribute('name', 'stripeToken');
        hiddenInput.setAttribute('value', token.id);
        form.appendChild(hiddenInput);
        form.submit();
    }
</script>
</body>
</html>

thanks.php

<?php

require 'vendor/autoload.php';


\Stripe\Stripe::setApiKey('sk_test_xxxxxx');

try {
    $stripeToken = $_POST['stripeToken'];

    $charge = \Stripe\Charge::create([
        'source' => $stripeToken,
        'amount' => 1000,
        'currency' => 'jpy',
    ]);
} catch (Error $e) {
    echo $e->getMessage();
}

最後に

Stripeはオンラインの決済を簡単に、安全にウェブサイトやアプリに導入することができるサービスです。クレジットカードをメインの決済方法として検討しているのであればStripeで始めるのも選択の一つかなと思います。Google PayやApple Payにも対応していて、決済方法も増えてきています。今後の展開に期待ですね!

以上、Stripe+PHPとStripe Elementsでシンプルな決済フォームを作成する方法をご紹介でした!