##やりたいこと
・ 単品/定期購入をセレクトボックスで選択
・ クレカ情報を入力
・ Stripeで決済
##環境
・PHP
・Javascript
##参考
・Stripe Elements公式
##1. Stripe Elements読み込み##
<script src="https://js.stripe.com/v3/"></script>
公式ドキュメントではStripeによる不正検知の精度を上げるため
サイト内すべてのファイルで読み込むことを推奨しています。
##2. フォームを表示##
<form action="charge.php" method="post" id="payment-form">
<ul>
<li>
<select id="product" name="product" class="product">
<option value="定期購入">定期購入</option>
<option value="単品購入">単品購入</option>
</select>
</li>
<li><input type="email" name="email" class="email" placeholder="Email"></li>
<li><input type="text" name="name" class="name" placeholder="名前"></li>
<!-- Stripe Elements -->
<li><div id="card-number" class="stripe-input"></div></li>
<li><div id="card-expiry" class="stripe-input"></div></li>
<li><div id="card-cvc" class="stripe-input"></div></li>
<li><div id="stripe_err" role="alert"></div></li>
<li><button type="submit"> ご購入手続き </button></li>
</ul>
</form>
簡単なフォームと最低限のcssを追加しました。
Stripe Elementsの部分にカード情報入力フォームを表示することになります。
あとからcssで見た目の調整をするためそれぞれのdivにclass="stripe-input"を指定しています。
この状態で表示してもStripeElementsは表示されません。
##3. フォームにStripeElementsをマウント##
<script type="text/javascript">
// StripeのAPIキーを読み込み
var stripe = Stripe('pk_test_XXXXXXXX');
// Elementsインスタンスを作成
var elements = stripe.elements();
// Elementsのスタイルを指定(ここはお好みで)
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSize: '13px'
},
invalid: { //値が不正のときに文字色を変える
color: '#fa755a',
iconColor: '#fa755a'
}
};
// フォームのidを指定してElementsをマウント
const cardNumber = elements.create('cardNumber', {style: style,placeholder: 'カード番号 1111 1111 1111 1111'});
cardNumber.mount('#card-number');
const cardExpiry = elements.create('cardExpiry',{style: style,placeholder: '有効期限 MM/YY'});
cardExpiry.mount('#card-expiry');
const cardCvc = elements.create('cardCvc', {style: style,placeholder: 'セキュリティ番号'});
cardCvc.mount('#card-cvc');
// カード番号のリアルタイムバリデーション
cardNumber.addEventListener('change', function(event) {
var displayError = document.getElementById('stripe_err');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Submitボタンでエラーをチェック
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(cardNumber).then(function(result) {
if (result.error) {
var errorElement = document.getElementById('stripe_err');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
// フォーム送信処理 (stripeTokenをhiddenで送信)
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
</script>
StripeElementsを表示できました。
このままだとフォームの枠が無い状態なので、cssを追加します。
.stripe-input {
width: 200px;
padding:8px;
margin-bottom:5px;
border: 1px solid #BBBBBB;
border-radius:5px;
}
このように、他のフォームとスタイルを合わせて表示させることができました!
##4. 決済処理##
フォームから実行するphpを作成します。
Stripeをインストールしておきます。PHPならcomposerがおすすめ。
ルートディレクトリで composer require stripe/stripe-php
だけでOKです。
また、定期購入決済を利用する場合はプランをダッシュボードで作っておく必要があります。
require 'vendor/autoload.php';
// シークレットキーを設定
\Stripe\Stripe::setApiKey("sk_test_XXXXXXXXXX");
// トークンとプロダクト(定期/単品どちらか)を変数に格納
$token = $_POST['stripeToken'];
$product = $_POST['product'];
if($product == '単品購入'){
//単品購入なら単品チャージ
try {
$responce = \Stripe\Charge::create(array(
"amount" => 1000, //価格
"currency" => "jpy",
"source" => $token,
"description" => "単品購入",
));
}catch (\Stripe\Error\Card $e) {
// 決済できなかったときの処理
console.log($e);
die('決済が完了しませんでした');
}
}else{
//顧客情報を作成
try{
$customer = \Stripe\Customer::create(array(
'email' => $_POST['email'],
'source' => $token,
'metadata' =>['Name' =>$_POST['name']]
));
}catch (\Stripe\Error\Card $e) {
console.log($e);
die('顧客情報の登録が完了しませんでした');
}
//定期購入登録
try{
$responce = \Stripe\Subscription::create([
'customer' => $customer['id'],
'items' => [['plan' => 'plan_XXXXXX']],//予め作成した定期購入プランのIDを指定します
]);
}catch (\Stripe\Error\Card $e) {
console.log($e);
die('定期購入の登録が完了しませんでした');
}
}
エラー処理などは割愛して簡略化していますが、決済処理はたったこれだけでOKです。
実装がシンプルでデザインの自由度も高く、初心者でもとっつきやすいです。