【Laravel × Stripe】サブスクリプション処理を実装する手順１

## 概要
備忘録として、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ダッシュボードより、サブスク商品の登録
[商品カタログ]の[商品の追加]より、サブスク商品を追加する。
![スクリーンショット 2024-08-11 7.52.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1248327/83c9a1c7-16ba-465c-7b68-76aed8747ff4.png)


価格IDをコピーしておく。
![スクリーンショット 2024-08-11 8.57.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1248327/78b71fa7-37ea-091c-6b44-77579fd8e719.png)




### 2. Stripeの公開キー・シクレットキーを保存する

##### .envファイルに保存する
```
STRIPE_KEY=[公開キー]
STRIPE_SECRET=[シークレットキー]
STRIPE_PRICE_ID=[価格ID]
```
##### config/stripe.phpファイルを作成する。
`config/stripe.php`
```php
<?php
return [
    'public_key' => env('STRIPE_KEY'),
    'secret_key' => env('STRIPE_SECRET'),
    'price_id'   => env('STRIPE_PRICE_ID'),
];

```



### ３. Laravel Cashierをインストール
```
composer require laravel/cashier
php artisan migrate
```


![スクリーンショット 2024-08-11 5.16.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1248327/b3645c87-6f97-a663-97d0-563c241102f5.png)


### 4. userテーブルにカラムを追加
`database/migrations/2014_10_12_000000_create_users_table.php`
```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
<?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
<?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
<?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`
```php
<!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`
```php
<!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による決済フォームの表示について記述していきます。

https://qiita.com/takahiro-2020/items/b3473a2fb4f78c425ab9

<br>

https://qiita.com/takahiro-2020/items/b3473a2fb4f78c425ab9

https://qiita.com/takahiro-2020/items/3df331abc855537c246d

https://qiita.com/takahiro-2020/items/cf3be9352e1a1525a83c