BackEnd

Laravel Cashier サブスクリプションに使用するテーブルを理解する

投稿日:

はじめに

以前、Laravel Cashierを使用してサブスクリプションを実装する方法について説明しました。しかし、Laravel Cashierは単純なStripeのラッパークラスではありません。そのため、例えばクレジットカードの決済に失敗したとき、どのようにハンドリングされるのか、しっかりと把握しておく必要があります。
そこで、今回はLaravel Cashierが実際にどのようなテーブルを持ち、またStripeでサブスクリプションの自動更新が失敗した場合の仕組みについて説明したいと思います。

Laravel Cashierのテーブル

Laravel CashierはStripeのラッパーではありますが、自分でテーブルも持っています。Laravel Cashierのインストール後に、 php artisan migrateを実行すると、vendor/larave/cashier/database/migrations配下にあるマイグレーションが実行されます。
Subscriptionの作成時はStripeのAPIをコールしますが、課金状況のチェックなどは、基本的にテーブルの内容を見にいきます。
そのため、Laravel Cashierで使用されるテーブルが、どのような動きをするのか、把握しておくことが大切です。

usersテーブル

ユーザテーブルには、次のように追加されます。

これらのカラムは、ユーザがSubscriptionに課金し、申し込んだときに作成されます。

  • stripe_id: string
    Stripeの顧客ID ( cus_**** )が入ります。
  • card_brand: string
    支払い方法に使用するカードブランドが入ります。
  • card_last_four: string
    支払い方法に使用するカードの下4桁がはいります。
  • trial_ends_at: timestamp
    支払い情報を登録せずに、試用させる場合に、試用終了時の日付が入ります。
    例えば、機能制限無しの期間限定試用版を実装する場合に使うことができます。

subscriptionsテーブル

subscriptionsテーブルは、ユーザがSubscriptionに課金し、申し込まれる度に作成されます。

  • user_id: unsigned big integer
    ユーザIDです。 ( Userクラスが、 Billableトレイトを使用すると、 $user->subscriptionsで取得できます。)
  • name: サブスクリプション名
    課金後に、サブスクリプションの状況などを取得するときに使用する名前です。サブスクリプション作成時に指定します。
    $user->subscribed('サブスクリプション名')といった形で使用します。(この場合は、サブスクリプション中であるかどうかをbooleanで返します。)
  • stripe_id: string
    StripeのサブスクリフションIDが入ります。( sub_***の形式です。)
  • stripe_status: string
    Stripeの課金状況が入ります。 $subscription->active()など、課金状況を確認するときに使用されるカラムです。
  • stripe_plan: string
    StripeのプランIDもしくは料金IDがあります。 ( plan_***もしくは price_***の形式です。)
  • quantity: integer
    サブスクリプションの数量です。
  • trial_ends_at: timestamp
    試用期間の終了日時です。
  • ends_at: timestamp
    課金の終了日時です。キャンセルすると、ここにサブスクリプションの最終日時が入ります。 cancelNow()メソッドでキャンセルした場合は、現在日時が入ります。

supscription_itemsテーブル

サブスクリプションに紐づく課金アイテムが入ります。

注意点としては、複数のアイテムがある場合は、 subscriptionsテーブルの、 stripe_planカラムと quantityプランはnullになります。

  • subscription_id: unsigned big integer
    subscriptionテーブルのidです。
  • stripe_id: string
    Stripeの定期支払いアイテムIDです。 ( si_***形式です。)
  • stripe_plan: string
    StripeのプランIDもしくは料金IDがあります。 ( plan_***もしくは price_***の形式です。)
  • quantity: integer
    数量が入ります。

課金情報の更新方法

実際には、利用者のクレジットカードのエラーにより、うまく自動更新できないことがあります。その場合は、Webhookを使用して、Stripe側からコールしてもらいます。
Laravel Cashierインストールすると、次のルーティングが追加されます。

このパスで、以下のWebhookを受け取ることができます。

  • customer.subscription.updated
  • customer.subscription.deleted
  • customer.updated
  • customer.deleted
  • invoice.payment_action_required

Stripeの管理画面で、これらのイベントを送信されるように設定します。
[Stripe管理画面]>[開発者]>[Webhook]>[アカウントからイベントを受信するイベント]>[+エンドポイントを追加] を開き、実際のアプリケーションのURLに、イベントが送信されるように設定します。

また、このWebhookはwebのルーティングに追加されるため、CSRF保護の対象外に設定する必要があります。 VerifyCsrfTokenクラスで、対象外に設定します。

これで完了です。Stripeから決済失敗のWebhookが3回連続で届くと、先ほどの subscriptionsテーブルが更新され、課金が無効になります。

さいごに

いかがでしたか。課金情報の問い合わせのために、何度もStripeにAPIリクエストすることなく、Laravel Cashierは動作しますが、Webhookをしっかり実装しないと、自動更新の失敗を検知することができません。
Laravel Cashierを使用するときは、必ずWebhookもセットで設定しましょう。

おすすめ書籍

PHPフレームワークLaravel入門 第2版 PHPフレームワーク Laravel実践開発 PHPフレームワーク Laravel Webアプリケーション開発 バージョン5.5 LTS対応 よくわかるPHPの教科書 【PHP7対応版】

blog-page_footer_336




blog-page_footer_336




-BackEnd
-, ,

執筆者:


comment

メールアドレスが公開されることはありません。

CAPTCHA


関連記事

[Dialogflow + CF] アクア様が罵倒してくれたり天気を教えてくれるSlackボットを作る

1 はじめに2 Dialogflowの準備2.1 プロジェクトを作る2.2 Intentを作る2.3 試してみる2.4 WELCOME Intentを作る3 Slackボットを作る4 名前を答える5 ...

rails

はじめてのrails、まずはローカル環境構築してみる

1 はじめに2 必要なライブラリ・ツールのインストール2.1 homebrew, rbenv2.2 rbenv-communal-gems3 最新安定版のrubyをインストール4 bundler, r ...

RubyのHanamiチュートリアルをやってみた

1 はじめに2 紹介2.1 Hanamiとは?2.2 Hanamiを選ぶ理由2.2.1 軽量2.2.2 アーキテクチャとして2.2.3 スレッドセーフ3 チュートリアルのための準備4 実践4.1 はじ ...

Go言語

Go言語の基礎〜基本構文その2〜

1 はじめに2 配列3 スライス3.1 スライスの宣言3.2 len3.3 append3.4 range3.5 値の切り出し3.6 可変長引数4 map4.1 宣言と初期化4.2 マップの操作4.3 ...

Go言語

Go言語でGinkgoを利用してBDDしてみた

1 はじめに2 BDDとは3 Ginkgoについて3.1 Ginkgoの概要3.1.1 Describe3.1.2 Context3.1.3 It3.1.4 JustBeforeEach3.1.5 B ...

フォロー

follow us in feedly

blog-page_side_responsive

2020年8月
 1
2345678
9101112131415
16171819202122
23242526272829
3031 

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。