#はじめに stripeとは
stripeは、クレジットカードなどの決算処理を代行してくれるサービスです。
シンプルな実装で決済処理を実現でき、カード情報を自社サーバで持たなくても良いなどの特徴があります。
大まかな流れとして、
- サービスの請求モデルを作成
- フロントサイドでカード情報を取得
- バックエンドで顧客登録、決済処理
と進んでいきます。
#サービスの請求モデルを作成する
##1. stripeに登録する
###1-1.はじめに、stripeの公式ページにて、今すぐ始めるをクリック。
###1-2メールアドレス、名前、パスワードを入力登録。
なお、テスト用に登録する際には、メールアドレスの存在確認は求められません。
この時点で、登録が完了いたしました。
###1-3.ダッシュボードが表示される
登録が完了したら、いくつかの質問がされるので答えていきます。
質問が完了したら、次のようなダッシュボードが表示されます。
##2.テストAPIキーを取得する
ダッシュボードが表示されたら、まずはAPIキーを取得してみましょう。
今回はテスト用のAPIキーを取得します。
ダッシュボードのテストAPIキーの取得をクリックしてください。
###公開可能キー
公開可能キーは、不特定多数に表示されてもかまわないキーです。
JavaScriptなど、フロントサイドで使用されるキーです。
###シークレットキー
一方シークレットキーは秘密にしなければなりません。
PHPなど、サーバーサイドで使用されます。
##3.商品(Product)を登録する
###3-1.Billing->商品をクリック
はじめに、提供するサービスである、**商品(Product)**を登録します。
画面左側のBilling
をクリックしてから、商品
が表示されるのでもう一度クリックしてください。
###3-2.商品を作成
商品名
を入力して、商品を作成
をクリックします。
なお、ここでは商品の価格などの情報は入力しません。
商品の配下に、プラン(Plan)
を作成して個別に料金体系(価格、通貨、支払い間隔など)を設定します。
一つの商品に対して、複数のプランが設定できます。
例えば、有料会員
という製品には以下のプランが紐付けられていると考えられます。
- 有料会員
- ブロンズ会員 月額500円
- シルバー会員 月額1,000円
- ゴールド会員 月額3,000円
#4.プランを作成する
###4-1.プランの作成
それでは実際にプランを作成してみます。
商品を作成したら、そのままプランを作成するページへ遷移します。
必要な項目を入力して、料金プランを追加
をクリックすると、プランが追加されます。
###4-2.プランIDの取得
後ほど会員をプランに追加する際に、プランIDが必要になるのでここで取得します。
prod_から始まる商品IDではないことに注意してください
先程作成したプランクリックして詳細を表示します。
#コードを実装する。
##5.ライブラリをインストールする
いよいよコードの実装にはいります。
はじめに、Composer
を利用して、PHPのライブラリを入手します。
composer require stripe/stripe-php
##6.フロントサイドの実装(JavaScript)
###6-1.カード情報を入手する
カード情報を入手するための入力フォームを、JavaScritpで実装します。
カード情報といっても、実際に得られるのはAPI通信によって得られたトークンの情報です。
<form id="form_payment" action="/add.php" method="post">
Name:<input id="name" type="text" name="name">
Email:<input id="email" type="text" name="email">
<!-- ここのdivタブがカード入力フォームに置き換わります。 -->
<div id="card-element" class="MyCardElement"></div>
<!-- ここにエラーメッセージが表示されます。 -->
<div id="card-errors" role="alert"></div>
<button id="button">Submit</button>
</form>
<!-- stripAPIを読み込みます -->
<script src="https://js.stripe.com/v3/"></script>
<script>
// 公開可能なAPIキーです。
const stripe = Stripe('pk_test_aGucPIXrlDAHQuflip6RqErD00CqmOnlKK');
// 入力フォームを生成します。スタイルを指定することもできます。
const elements = stripe.elements();
const cardElement = elements.create("card");
// 先程のdivタブにマウントします。
cardElement.mount("#card-element");
// クレジットカード番号や有効期限の入力に合わせてエラーメッセージを出力します。
cardElement.addEventListener('change', ({error}) => {
const displayError = document.getElementById('card-errors');
if (error) {
displayError.textContent = error.message;
} else {
displayError.textContent = '';
}
});
const submit = document.getElementById('button');
const name = document.getElementById('name');
const email = document.getElementById('email');
// 登録ボタンがクリックされたら、API通信をおこなう
submit.addEventListener('click', async(e) => {
e.preventDefault();
const {paymentMethod, error} = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
// 顧客名emailアドレスはなくてもOK
name: name.value,
email: email.value,
},
});
// 通信エラー時
if (error) {
console.error(error)
} else {
// 成功したらトークンが返されるので、hiddenに埋め込む
const form = document.getElementById('form_payment');
const hiddenToken = document.createElement('input');
hiddenToken.setAttribute('type', 'hidden');
hiddenToken.setAttribute('value', paymentMethod.id);
hiddenToken.setAttribute('name', 'token');
form.appendChild(hiddenToken);
form.submit();
}
});
</script>
下記画像のように、カード番号・有効期限・確認番号・郵便番号を入力するフォームが生成されました。
これらの項目はすべて必須項目です。
もし、郵便番号の入力をなくしたいなら、入力フォーム生成時にhidePostalCode
をtrue
にします。
const cardElement = elements.create('card', {hidePostalCode: true});
テスト用として、4242 4242 4242 4242
の番号が用意されているので、そちらを利用します。
その他の値はなんでもかまわないようです。
##7.サーバーサイド(PHP)
###7-1.顧客情報を登録する。
フロントサイドから受け取ったトークンをもとに、顧客情報を登録します。
<?php
require '/vendor/autoload.php';
// シークレットキーをセットする
\Stripe\Stripe::setApiKey(YOUR_SECRET_KEY);
if($_SERVER['REQUEST_METHOD'] == 'POST') {
// ここではバリデーションは省略しています
$name = $_POST['name'];
$email = $_POST['email'];
$token = $_POST['token'];
// 顧客情報を登録
$customer = \Stripe\Customer::create([
'payment_method' => $token, // 登録する支払い方法
'name' => $name,
'email' => $email,
'invoice_settings' => [
'default_payment_method' => $token, // デフォルトで使用する支払い方法。必須。
],
]);
###7-2.顧客をプランに登録する
さらに、先程登録した顧客情報をもとに、プランへの登録処理を行います。
// 顧客をプランに登録する
$subscription = \Stripe\Subscription::create([
// 先程登録した顧客情報のID
'customer' => $customer->id,
'items' => [
[
// 4-2で取得したプランID
'plan' => 'plan_GYHnkoAjA7PFtG',
],
],
'trial_end' => strtotime('+3 month'),
// トライアル(無料)期間。UNIX秒で指定する。
]);
// subsctiprionIDは、解約時に必要
$sub_id = $subscription->id; // sub_GYJXuOff81PbZy
// DBを準備
try {
$db = new PDO('mysql:dbname=php;host=localhost', 'root', '');
} catch (PDOException $e) {
print "Coudn't connet to the database: " . $e->getMessage();
exit();
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 顧客情報を登録
try {
$stmt = $db->prepare('INSERT INTO Users (name, email, sub_id)
VAlUES (?,?,?)');
$stmt->execute($name, $email, $sub_id);
} catch (PDOException $e) {
print "Coudn't connet to the database: " . $e->getMessage();
exit();
}
}
trial_end
を指定すると、トライアル(無料期間)を定めることができます。
音楽ストリーミングサイトによくある初回3ヶ月無料!みたいなやつです。
UNIX秒で指定するので、strtotimeを使用すればある程度簡単に指定することができます。
プラン登録時の返却値のSubscription
オブジェクトのIDは、解約時に必要になります。
なので、顧客情報とともにDBに登録します。
##8.登録を確認する
ダッシュボードに戻り、左側の顧客
をクリックすると、先程登録した顧客情報が表示されているかと思います。
無事顧客が登録されていましたね。
さらに、詳細情報をみると顧客の定期支払を確認することができます。
トライアル期間を設定したので、請求書をみると初回の支払いは0円で、次回請求日は3ヶ月後に設定されていることが確認できます。(今回登録した日付は01/15)
###9.プランを解約する
最後に、顧客が有料会員プランを解約する流れを説明します。
<?php
// 契約を解除するためにログインしている想定
session_start();
require 'vendor/autoload.php';
$name = $_SESSION['name'];
// DBを準備
try {
$db = new PDO('mysql:dbname=php;host=localhost', 'root', '');
} catch (PDOException $e) {
print "Coudn't connet to the database: " . $e->getMessage();
exit();
}
// ログインユーザーからsub_idを取得
$stmt = $db->prepare('SELECT sub_id FROM Users WHERE name = ?');
$stmt->execute($name);
$row = $stmt->fetch('assoc');
if ($row) {
$sub_id = $row->sub_id;
} else {
exit();
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// シークレットキーをセットする
\Stripe\Stripe::setApiKey(YOUR_API_KEY);
// 解約したあとも有効期限までは、プランに入会したまま
\Stripe\Subscription::update(
$sub_id,
[
'cancel_at_period_end' => true,
]
);
上記の例のようにcancel_at_period_end
をtrue
にしてプランをSubscription::update
で更新することで、解約後も有効期限内まではプランが有効になります。
もし、解約後はすぐにプランを終了したいときには、以下のようなコードを書きます。
// 解約後はすぐにプランが終了する。
$subscription = \Stripe\Subscription::retrieve('sub_49ty4767H20z6a');
$subscription->cancel();
###8-2.解約を確認
ダッシュボードを確認すると、先程の会員が有効期限である04/15
にプランがキャンセルされることが確認できました。
#おわりに
定額課金の決済の簡単な流れを説明しました。
他にも期間中のアップグレード、ダウングレードや途中解約に対する比例配分、更新時にカードが利用できなかった場合など複雑な状況にも対応できます。
ぜひ、ドキュメントも参照してみてください。
#参考サイト
公式ドキュメント
API リファレンス
Stripe Billing 101
Stripe.js & Elements を利用して決済フローを理解する