はじめに
Laravel Cashierは Laravel公式のパッケージで、Stripe決済に必要なバックエンドの実装を肩代わりしてくれるパッケージです。
 今回は、支払い方法の登録、サブスクリプションの作成について紹介します。
Stripeの準備
はじめに、Stripeでアカウントを作成します。
 管理画面で、[開発者]>[APIキー]にある、「公開可能キー」と「シークレットキー」を控えておきます。
Laravel Cachierの初期設定
インストール
composerを使用してインストールします。
$ composer require laravel/cashier
インストール後、必要なマイグレーションファイルが追加されるため、マイグレーションを実施します。
$ php artisan migrate
APIキーの設定
envファイルに、控えておいたAPIキーを設定します。
|   1 2  |  STRIPE_KEY=公開可能キー STRIPE_SECRET=シークレットキー  |  
Userモデルへの実装
Userモデル、 
Billable
トレイトを使用するようにします。
 これにより、Webサイトの利用者が、課金・決済することができるようになります。
支払い方法の登録
支払い方法の登録
コントローラから実装していきます。
|   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26  |  <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class UserController extends Controller {     public function getPaymentMethod()     {         // クレジットカードの登録に必要なシークレットをStripeから取得する         return view('users.payment_method', [             'intent' => Auth::user()->createSetupIntent()         ]);     }     public function postPaymentMethod(Request $request)     {         // Stripe顧客を作成する         $stripeCustomer = Auth::user()->createAsStripeCustomer();         // トークンを受け取り、Stripeに検証した上で、usersテーブルに、支払い情報を登録する。         Auth::user()->updateDefaultPaymentMethod($request->payment_method);         return response()->redirectTo('/users/payment_method');     } }  |  
次に、ビューです。
|   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58  |  @extends('layouts.app') @section('content')     <div class="container">         <h3>支払い方法の登録</h3>         カード名義人 <input id="card-holder-name" type="text">         <!-- Stripe要素のプレースホルダ -->         <div id="card-element"></div>         <button id="card-button" data-secret="{{ $intent->client_secret }}">             登録する         </button>         <form method="post" action="/users/payment_method" id="updateForm">             @csrf             <input type="hidden" name="payment_method">         </form>         // StripeのJS SDKの読み込み         <script src="https://js.stripe.com/v3/"></script>         <script>             const stripe = Stripe('{{ env('STRIPE_KEY') }}');             const elements = stripe.elements();             const cardElement = elements.create('card');             cardElement.mount('#card-element');             const cardHolderName = document.getElementById('card-holder-name');             const cardButton = document.getElementById('card-button');             const clientSecret = cardButton.dataset.secret;             cardButton.addEventListener('click', async (e) => {                 // カード情報の登録 (Stripeとの通信)                 const { setupIntent, error } = await stripe.confirmCardSetup(                     clientSecret, {                         payment_method: {                             card: cardElement,                             billing_details: { name: cardHolderName.value }                         }                     }                 );                 if (error) {                     alert(error.message);                 } else {                     // クレジットカードの登録に成功したので、Laravel側にトークンをPostする                     const updateForm = document.getElementById('updateForm');                     updateForm.payment_method.value = setupIntent.payment_method;                     updateForm.submit();                 }             });         </script>     </div> @endsection  |  
Laravelの公式ドキュメントのソースコードをベースに作成しています。
 支払い情報を登録する際は、コントローラー側で、 
$user->createSetupIntent()
を呼び出し、結果をそのままビューに渡します。
 ビュー側の登録ボタンでは、 
<button id="card-button" data-secret="{{ $intent->client_secret }}">
となっており、シークレットを設定します。
ビュー側は、基本的にStripe JS SDKを使用します。カード情報はStripe側に登録させて、Laravel側にはトークンのみを受け取るようにします。
 支払い情報は、Stripe顧客を作成しないと登録できないため、先に作成した上で、カード情報を登録します。
サプスクリプション
サブスクリプションを作成するには、 
$user->newSubscription()
メソッドを使用して作成します。
 コントローラーのコードです。
|   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  |  <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class UserController extends Controller {     public function postSubscriptions(Request $request)     {         // 登録済みのデフォルト支払い方法を使用         $paymentMethod = Auth::user()->defaultPaymentMethod()->paymentMethod;         Auth::user()->newSubscription('default', 'プランID')->create($paymentMethod);         return response()->redirectTo('/users/subscriptions');     } }  |  
newSubscription()
メソッドの第一引数には、サブスクリプション の名前を付けます。この名前は、Laravelアプリ内のsubscriptionテーブルで管理されるもので、後からサブスクリプション の状況を確認するときにも使用します。
 プランIDは、Stripeに登録済みのプランIDを指定する必要があります。
 Stripe管理画面で商品を登録し、価格を登録すると表示される「API ID」を指定してください。
サブスクリプション状況を確認するには、 
$user->subscribed('default')
とすることで、確認することができます。
試用期間
試用期間を設定したい場合は、サプスクリプション作成時に設定します。
|   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  |  <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class UserController extends Controller {     public function postSubscriptions(Request $request)     {         $paymentMethod = Auth::user()->defaultPaymentMethod()->paymentMethod;         Auth::user()->newSubscription('default', 'price_id')             ->trialDays(7) // 7日間のトライアル             ->create($paymentMethod);         return response()->redirectTo('/users/subscriptions');     } }  |  
サブスクリプション作成時に、 
trialDays()
メソッドを使用することで、試用期間を設定できます。
 試用期間を設定すると、Stripe側で請求日が試用期間後の日付となり、その日以降は自動的に請求が発生します。
おまけ
Laravel Cashierには、Stripe PHP SDKがそのまま入っているため、直接使用することもできます。
 例えば、サブスクリプション作成時に必要となる、プランは、Stripe SDKを使用して動的に増やすこともできます。
 プランを作成し、そのプランIDを使用してサブスクリプションを作成するサンプルコードです。
|   1 2 3 4 5 6 7 8 9 10 11  |  // プランの作成 $plan = Plan::create([                 'amount' => 1000, // 1000円                 'currency' => 'jpy',  // 日本円決済                 'interval' => 'month', // サブスクリプション の周期                 'product' => ['name' => 'プレミアムプラン'] // 商品情報 ]); // 作成したプランのIDでサプスクリプションを作成する Auth::user()->newSubscription('default', $plan->id)             ->create($paymentMethod);  |  
さいごに
いかがでしたか。Laravel Cashierを使用すると、Stripeの実装に必要なバックエンドの実装が、かなり軽減されることが分かりました。次回は、Laravel CashierのWeb hookや、複数の支払い方法を管理する方法について紹介したいと思います。