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


関連記事

rails

RailsでERBからJavaScriptにhashを渡す方法

1 はじめに2 カスタムデータ属性とは3 実装例3.1 コントローラの実装3.2 ビューの実装3.3 実行結果4 さいごに はじめに 以前、選択したプルダウンメニューに応じて別のプルダウンメニューの内 ...

rails

deviseを使ってユーザ登録フォームを作る

1 はじめに1.1 前提条件2 deviseについて2.1 deviseとは2.2 deviseでできること3 登録処理の実装3.1 Gemのインストール3.2 deviseのインストール3.3 デフ ...

rails

Ruby2.4でCookieを手動で復号する際に発生したエラーの対処

1 はじめに1.1 前提条件2 発生したエラー2.1 実際のコード2.2 エラー詳細2.3 原因3 どう対処したか3.1 修正後のコード はじめに こんにちは、onoです。 現在開発中のアプリケーショ ...

Kotlinでのnullの基本的な扱いかた

1 はじめに2 基本的にnullを許容しない3 nullを許容するNullable4 Nullableをnon-nullに変える4.1 nullチェックとスマートキャスト4.2 エルビス演算子4.3 ...

Rubyを使ってDialogflowのお勉強

1 はじめに1.1 環境2 とりあえずAPIで叩いてみる2.1 テスト用のIntentを作成2.2 Gemの設定3 Eventについて3.1 WELCOMEイベント3.2 パラメータ付きで叩く3.3 ...

フォロー

follow us in feedly

blog-page_side_responsive

2020年8月
 1
2345678
9101112131415
16171819202122
23242526272829
3031 

アプリ情報

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