概要
備忘録として、LaravelとStripeを使ってサブスクリプション処理を実装する手順について記録します。
この記事では、「Check Out」を開いてサブスクリプションの契約を行う処理、・「カスタマーポータル」を開いて契約キャンセルをするための処理までまとめます。
Stripeの決済ページには、「Checkout (リダイレクト型)」と「埋め込み型」があります。
Checkoutは、ホスティング済みの支払いページを提供し、簡単かつ安全にオンライン決済を実装できるツールです。事前デザインされたUIで、クレジットカードやApple Payなどに対応し、セキュリティもStripe側で管理します。サブスクリプションや多言語対応、モバイルフレンドリーな設計が特徴です。
一方、埋め込み型の決済では、自サイトに直接決済フォームを組み込みます。デザインや機能のカスタマイズが自由ですが、セキュリティ管理やPCI準拠の責任が発生します。
前提
- Laravelの基本的な知識があること
- Stripeのアカウントが作成済みであること
- Stripeダッシュボードで価格(price)IDが設定済みであること
準備
流れ
1.Stripeダッシュボードより、サブスク商品の登録
2. Stripeの公開キー・シクレットキーを保存する
3. Laravel Cashierをインストール
4. userテーブルにカラムを追加
5. Userモデルの編集する
6. ルーティングの作成
7. コントローラーの作成
8. viewの作成
1.Stripeダッシュボードより、サブスク商品の登録
[商品カタログ]の[商品の追加]より、サブスク商品を追加する。
2. Stripeの公開キー・シクレットキーを保存する
.envファイルに保存する
STRIPE_KEY=[公開キー]
STRIPE_SECRET=[シークレットキー]
STRIPE_PRICE_ID=[価格ID]
config/stripe.phpファイルを作成する。
config/stripe.php
<?php
return [
'public_key' => env('STRIPE_KEY'),
'secret_key' => env('STRIPE_SECRET'),
'price_id' => env('STRIPE_PRICE_ID'),
];
3. Laravel Cashierをインストール
composer require laravel/cashier
php artisan migrate
4. userテーブルにカラムを追加
database/migrations/2014_10_12_000000_create_users_table.php
/* ~ */
$table->string('stripe_id')->nullable()->default(null);//顧客ID
$table->string('subscription_id')->nullable()->default(null);//契約中のサブスクID
5. UserモデルにBillableトレイトをuserする
- Billableトレイトをuserします
- 追加カラムを登録
app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Laravel\Cashier\Billable; //追加
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
use Billable; //追加
protected $fillable = [
/* ~ */
'stripe_id',//追加
'subscription_id',//追加
];
}
6. ルーティングの作成
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\StripSubscriptionController;
# サブスク申請ページ(チェックアウトに進む前のページ)
Route::get('stripe/subscription',
[StripSubscriptionController::class, 'index'])
->name('stripe.subscription');
# チェックアウトページ
Route::get('stripe/subscription/checkout',
[StripSubscriptionController::class, 'checkout'])
->name('stripe.subscription.checkout');
# 決済完了ウェブホック
Route::post('stripe/subscription/webhook',
[StripSubscriptionController::class, 'webhook']);
# 支払い完了
Route::get('stripe/subscription/comp',
[StripSubscriptionController::class, 'comp'])
->name('stripe.subscription.comp');
# カスタマーポータル
Route::get('stripe/subscription/customer_portal',
[StripSubscriptionController::class, 'customer_portal'])
->name('stripe.subscription.customer_portal');
7. コントローラーの作成
php artisan make:controller StripSubscriptionController;
StripSubscriptionController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Stripe\Stripe;
use Stripe\Customer;
use Stripe\Charge;
use Stripe\Event;
use Stripe\Checkout\Session;
use Stripe\StripeClient;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
/**
* =========================================
* Stripe サブスク コントローラー
* =========================================
*/
class StripSubscriptionController extends Controller
{
/**
* サブスク申請ページ(チェックアウトに進む前のページ)
*
* @return \Illuminate\View\View
*/
public function index()
{
return view('stripe.subscription.index');
}
/**
* 支払い完了
*
* @return \Illuminate\View\View
*/
public function comp()
{
return view('stripe.subscription.comp');
}
/**
* チェックアウトページ
*
* @return \Illuminate\Http\Response
*/
public function checkout(){ /* 次回 */}
/**
* カスタマーポータル
*
* @return \Illuminate\Http\Response
*/
public function customer_portal() { /* 次回 */}
/**
* サブスク決済完了ウェブホック
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function webhook(){ /* 次回 */}
}
8. viewの作成
サブスク申請ページ(チェックアウトに進む前のページ)
resources/view/stripe/subscription/index
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>サブスク申請ページ</title>
</head>
<body>
<a href="{{route('stripe.subscription.checkout')}}">チェックアウトページに進む</a>
</body>
</html>
サブスク完了ページ
resources/view/stripe/subscription/index
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>支払い完了ページ</title>
</head>
<body>
サブスクの支払いが完了しました。
</body>
</html>
長くなったので、次回はCheck Outによる決済フォームの表示について記述していきます。