入社して半年になりました、田村です!
今回は、PHPとStripeでクレジットカード決済を実装する方法についてご紹介します。
Stripeのよいところ
UIのカスタマイズが簡単

Stripeのフォームは、自前のサイトに組み込む場合、初期状態では上のように非常にシンプルな見た目になっています。
このままだと、どこに入力すればよいのか少しわかりにくいですよね。
StripeにはStripe ElementsというUIコンポーネントライブラリが用意されており、フォームのカスタマイズが簡単に行えます。
フォームを安全に組み込める
Stripeでは、決済時に別ページに飛ぶことなく、自サイトで完結できます。
その際、カード情報をトークンに置き換えることで、カード情報を自身のサーバに通すことなく安全に処理できます。
作るもの

このようなカード情報入力フォームを、PHPとStripeで自前のページに設置してみたいと思います。
バージョン情報
- PHP:7.3.15
- stripe-php:7.64
Stripeアカウントの作成
まずはStripeのアカウントを作成します。
https://dashboard.stripe.com/register
アカウント作成後、テスト環境ですぐに利用を開始することができます。
導入が簡単なのもStripeの利点です。
実装方法
1. Composerでライブラリをインストール
$ composer require stripe/stripe-php
まずは環境にstripe-phpライブラリをインストールします。
PHP側
2. シークレットキーを設定
require 'vendor/autoload.php';
\Stripe\Stripe::setApiKey('sk_test_XXXXXXXXXXXXXXXXXX');
ComposerのオートロードでStripeライブラリを読み込み、シークレットキーを設定します。
キーはStripeのダッシュボードからコピーできます。
フロント側
3. 決済フォームの作成
PHP側の準備ができたら、次にHTML、JavaScriptで決済フォームを作成していきます。
3-1. HTMLの作成
<form id="form">
<div>
<label for="card_number">カード番号</label>
<div id="card_number"></div>
</div>
<div>
<label for="card_expiry">有効期限</label>
<div id="card_expiry"></div>
</div>
<div>
<label for="card_security">セキュリティコード</label>
<div id="card_security"></div>
</div>
<div id="card_errors"></div>
<button id="submit">支払い</button>
</form>
HTMLで、フォームを設置するための枠組みを作成します。
一見入力欄がないように見えますが、実際はStripe.jsによって<div id=”card_number”></div> などのdivの中にiframeが埋め込まれ、入力欄が表示される仕組みです。
3-2. Stripe.jsの読み込み
<script src="https://js.stripe.com/v3/"></script>
Stripe.jsは、入力されたカード情報をトークンとして処理してくれるJavaScriptライブラリです。
これにより、カード情報を自身のサーバで保持する必要がなくなるため、安全に処理を行うことができます。
3-3. フォームの作成
var stripe = Stripe('pk_test_XXXXXXXXXXXXXXXXXX');
var elements = stripe.elements();
JavaScriptでフォームの中身を作成していきます。
まずは、Stripe.jsを使うために、公開可能キーを設定し、Stripe Elementsのインスタンスを作成します。
公開可能キーもシークレットキー同様、ダッシュボードからコピーしてきます。
var cardNumber = elements.create('cardNumber');
cardNumber.mount('#card_number');
cardNumber.addEventListener('change', function(event) {
var displayError = document.getElementById('card_errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
次に、createメソッドでフォームを作成し、先ほど用意したHTMLの枠にマウントします。
フォームに入力された値が正しくなかった場合は、リアルタイムでエラー文が表示されるようになっています。
上のコードはカード番号の入力欄の例です。有効期限、セキュリティコードも同様に作成します。
var form = document.getElementById('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 {
stripeSubmit(result.token);
}
});
});
function stripeSubmit(token) {
var form = document.getElementById('form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
form.submit();
}
最後に、入力された情報からトークンを生成し、サーバに送信します。
PHP側(POST送信後)
4. 決済処理
if (!empty($_POST['stripeToken'])) {
$stripeToken = $_POST['stripeToken'];
}
try {
$charge = \Stripe\Charge::create([
'amount' => 1000,
'currency' => 'jpy',
'source' => $stripeToken,
]);
} catch (Error $e) {
echo $e->getMessage();
}
決済フォームからPOSTで受け取ったトークンで決済処理をします。
あとは、フォームのCSSを整えれば完成です。
Stripe決済の実装は以上になります。
ここまでご紹介したのは最低限の実装でしたが、続いて、これをベースにいくつかのカスタマイズをご紹介したいと思います。
カスタマイズ①:入力欄の詳細設定
フォーム作成時、createメソッドの第二引数にオプションを追加することで、フォームの詳細な設定ができます。
ここでは、フォームのスタイルと、フォームが特定の状態の時のクラス名を設定してみました。
【参考】createメソッドで設定できるオプション
https://stripe.com/docs/js/elements_object/create_element?type=card#elements_create-options
var elementStyles = {
base: {
fontSize: '14px',
},
invalid: {
color: '#eb1c26',
}
}
var elementClasses = {
focus: 'is-focused',
empty: 'is-empty',
invalid: 'is-invalid'
}
var cardNumber = elements.create('cardNumber', {
style: elementStyles,
classes: elementClasses,
});
カスタマイズ②:顧客情報を登録
Stripeでは、カード情報などを顧客情報として登録することができます。
この顧客情報のIDを元に決済することができるため、たとえば会員制のサイトなどで、ユーザーアカウントのテーブルに顧客IDを保存しておいて、決済時にそれを参照するようにすれば、毎回カード情報を入力しなくてもよくなります。
try {
if (!empty($_POST['stripeToken'])) {
$stripeToken = $_POST['stripeToken'];
}
if (!empty($_POST['email'])) {
$email = $_POST['email'];
}
if (!empty($_POST['name'])) {
$name = $_POST['name'];
}
$customer = \Stripe\Customer::create([
'source' => $stripeToken,
'email' => $email,
'name' => $name,
]);
$charge = \Stripe\Charge::create([
'amount' => 1000,
'currency' => 'jpy',
'customer' => $customer->id,
]);
} catch (Error $e) {
echo $e->getMessage();
}
POST送信後のコードを書き換えて、まずトークンを元に顧客情報を作成し、作成した顧客IDで決済を行うようにしました。
ここでは省略してしまいましたが、実際に実装する場合はそのユーザーアカウントが顧客登録されているかをチェックする必要があるので、DBからユーザーアカウントに紐づく顧客IDを取得して、空だったら顧客を作成して決済、存在したらそのIDで決済、という流れになるかと思います。
まとめ
今回初めてStripe決済を実装しましたが、ドキュメントもわかりやすく内容も豊富で、実装方法もシンプルなため比較的簡単に実装することができました!
デザインを損なうことなくサイトに組み込めて、カスタマイズ性も高いので、ユーザビリティの高い決済フォームが作成できると思います。
ぜひ導入してみてください。