ポータルサイトブログLaravel でのサブスク決済には Cachier を使おう
ポータルサイトでもサブスクリプション制を導入するケースがありますが、Laravelでの手続きには「Cachier」が便利です。
Laravel Cashier とは
Laravel Cashier は Laravel が公式でリリースしている、決済用のライブラリです。
Cashier は「キャシア」と発音するようです。
基本的なサブスクリプション管理はもちろん、PDFでの請求書発行やクーポン、支払いプラン設定、キャンセル時の猶予期間を設けるなどの仕組みも作成可能です。
もちろんサブスクリプション(定期課金)ではない、単発の決済手続きにも使用できます。
基本的には決済サービス Stripe のラッパーライブラリですので、まずは Stripe への登録手続きが必要になります。
Stripe はプログラム開発者が使いやすいAPIが用意されており、決済に関する機能はほぼ網羅されています。
多くの国・言語に対応しており、クレジット決済はJCB、Apple Pay、Google Pay なども利用できます。
Laravel Cashier のインストール
Composerでインストール可能です。
composer require laravel/cashier
マイグレーション用設定が用意されているので、マイグレーションします。
php artisan migrate
もしマイグレーション設定をカスタマイズしたい場合はコピーします。
php artisan vendor:publish --tag="cashier-migrations"
Laravel Cashier の使い方
まずは支払う側となるユーザーモデルにトレイトを指定します。
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
...
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
...
}
対象モデルはデフォルトで App\User
ですが、 .env ファイルで指定できます。
CASHIER_MODEL=App\Models\User
加えて .env ファイルに Stripe のAPI情報も追記します。
STRIPE_KEY=StripeのAPIキー
STRIPE_SECRET=StripeのAPIシークレット
フロント側では Stripe の外部JavaScriptライブラリを使って入力・バリデーションを行います。
バリデーションが通れば、Laravel側での処理になります。
そのほか、具体的な決済処理方法は 公式マニュアル をご覧ください。
テストについて
決済の処理は念入りにテストした方が良いでしょう。
Stripe にはサンドボックスモードのようなものはなさそうですが、テスト用のクレジットカード番号などがあるので、各決済方式用のテスト方法のドキュメントを参考にしてください。
Laravel側のテストとしては、フロント側の入力テストも含まれるため Laravel Dusk(ダスク) を使いましょう。
Dusk は Chromeドライバを使ってブラウザテストする公式ライブラリです。
以下、 Dusk を使ったクレジットカード入力テストの例です。
<?php
namespace Tests\Feature;
use Tests\DuskTestCase;
use App\User;
class PaymentTest extends DuskTestCase
{
/**
* @test
* @throws \Throwable
*/
public function inputCreditCard()
{
$user = factory(User::class)->create();
$this->browse(function ($browser) use ($user) {
$browser
// 対象ユーザーでログイン
->loginAs($user)
// 決済ページへ移動
->visit('/payment')
// iframeのロードを待つ
// (<div id="card-element"></div> にStripeフォームを読み込む想定)
->waitFor('#card-element iframe')
->withinFrame('#card-element iframe', function ($browser) {
$browser
// カード番号入力欄の表示を待つ
->waitFor('input[name="cardnumber"]')
// フォーム入力
->keys('input[name="cardnumber"]', '4242 4242 4242 4242')
->keys('input[name="exp-date"]', '12 50')
->keys('input[name="cvc"]', '123')
// フォーム送信
->press('button[type="submit"]')
// iframeの表示が消えるのを待つ
->waitUntilMissing('#card-element iframe');
})
// ウインドウのリロードを待つ
->waitForReload()
// 決済後のURLに戻ってくるか検証
->assertPathIs('/home');
});
}
}
おわりに
決済まわりは複雑そうに思いますが、フレームワーク側が公式ライブラリを用意してくれているのは心強いです。
気軽に決済機能を付けられると良いですね。