7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

LaravelのCashierでusersテーブルではなく他のテーブルを使いたい

Last updated at Posted at 2022-03-07

Laravelで決済処理をするためにCashier(Stripe)を導入した際に、
Stripeの顧客をusersじゃないテーブルにしたかったのですが、
そのときのあれこれを備忘録として残します。

  • Laravelのバージョン:8.63.0
  • Cahierのバージョン:v13.8.0

■ まずLaravelにCashierを導入する

composerでCashierパッケージをインストールします。

composer require laravel/cashier

■ マイグレーションを実行する前に必要なこと

無事導入できたら、
デフォルトでは
ここでマイグレーションを実行すると、
既存のusersテーブルにStripeのためのカラムがいくつか追加されて、
新たにsubscriptionsというテーブルと、
subscription_itemsというテーブルが追加されます。

usersテーブルにStripeのためのカラムがいくつか追加されて、

usersテーブルに追加されたカラムのいくつかのうちのひとつに、
stripe_idというカラムがありまして、
そこにはStripeが顧客を判別するための顧客IDが保存されるようになります。
つまりLaravel上の顧客と、Stripe上の顧客は別物で、
それらを紐づけるためのカラムのようです。

subscriptionsテーブルとsubscription_itemsテーブルにおいても、
stripe_idという名前のカラムが生成されますが、
Stripeの顧客IDが入るのはusersテーブルのstripe_idカラムです。

...というのがCashier導入後に行うデフォルトのマイグレーション実行内容なわけなんですが、
usersテーブルじゃないテーブルをStripeの顧客テーブルにしたいときだってありますよね!

今回のわたしがそうでした。

Cashierさんが用意してくれてるマイグレーションファイルを編集したい!
となったとき、じゃぁどうしたら良いかというと

Laravel 8.x Laravel Cashier (Stripe)
Cashierに同梱されているマイグレーションを上書きする必要がある場合は、vendor:publish Artisanコマンドを使用してそれらをリソース公開できます。

とあり、

php artisan vendor:publish --tag="cashier-migrations"

このコマンドを実行すると、
Cashierさんが用意してくれてるマイグレーションファイルが
いつも見ているmigrationsフォルダに現れて、さわれるようになりました。
migration_files.png
現れたマイグレーションファイルのうち、
~create_customer_columns.phpという名前のファイルが
Stripeの顧客として扱いたいテーブルを指定するためのマイグレーションファイルになっていて
そのなかの、

~~create_customer_columns.php
 Schema::table('users', function (Blueprint $table) {

デフォルトではここでusersテーブルが指定されているので、
テーブル名を任意のテーブル名に変更。
この記事においては、仮にcompaniesテーブルに変更するとします。

- Schema::table('users', function (Blueprint $table) {
+ Schema::table('companies', function (Blueprint $table) {

なお、わたしはMysqlを使用していることから、

Laravel 8.x Laravel Cashier (Stripe)
Note: Stripeは、Stripe識別子の格納に使用される列では大文字と小文字を区別することを推奨しています。したがって、MySQLを使用する場合は、stripe_id列の列照合順序を確実にutf8_binへ設定する必要があります。これに関する詳細は、Stripeドキュメントにあります。

このようにする必要もあるようなので、
現れた3つのマイグレーションファイル内でstripe_id列を生成する行へ、
collationを追記しました。
例えば~create_customer_columns.phpにおいては、

- $table->string('stripe_id')->nullable()->index();
+ $table->string('stripe_id')->collation('utf8_bin')->nullable()->index();

このように追記。

これでマイグレーションのための準備が整いまして、ようやくマイグレーションを実行します。

php artisan migrate

(補足)
companiesテーブルよりも先に
~create_customer_columns.phpのマイグレーションが行われてしまうと
companiesテーブルは存在しませんが...というエラーで怒られてしまいましたので
順番が前後しないよう、それぞれのマイグレーションファイル名も要チェックでした。

■ マイグレーションの後はModelのお世話

無事マイグレーションが終わった後は、Modelのために必要な追記がいくつかありました。

Laravel 8.x Laravel Cashier (Stripe)
Cashierを使用する前に、Billableなモデルの定義へBillableトレイトを追加してください。通常、これはApp\Models\Userモデルになるでしょう。このトレイトはサブスクリプションの作成、クーポンの適用、支払い方法情報の更新など、一般的な請求タスクを実行できるようにするさまざまなメソッドを提供します。

デフォルトであればUserモデルにBillableトレイトを追加しなければならないようですが、
さきほどcompaniesテーブルを使うことにしたため、
Companyモデルへ

Company.php
use Laravel\Cashier\Billable;
class Company extends Model
{
    use Billable;
}

このように追加しました。

また、さらに

Laravel 8.x Laravel Cashier (Stripe)
CashierはLaravelに同梱されているApp\Models\UserクラスをBillableなモデルとして想定しています。これを変更したい場合は、useCustomerModelメソッドで別のモデルを指定します。このメソッドは通常、AppServiceProviderクラスのbootメソッドで呼び出します。

App\Models\Userクラス以外をBillableなモデルとして使いたい場合には
その旨をAppServiceProviderクラスのbootメソッドに書く必要があるとのこと。
いまわたしはApp\Models\Companyクラスを使いたいと思っているところなので、
指示に従って、

AppServiceProvider.php
use App\Models\Company;
use Laravel\Cashier\Cashier;

public function boot()
{
    Cashier::useCustomerModel(Company::class);
}

このように追記しました。

■ usersテーブルからcompaniesテーブルへの変更作業完了

以上の作業で、
Cashierで使う顧客テーブルをデフォルトのusersからcompaniesへ変更することができました!
このほかAPIキーの設定やwebhookなどもろもろ必要な作業については
usersテーブルを顧客テーブルとして実装する際と同様でした。
webhookについても備忘録を残しておきたいのですが、それはまた別記事にしたいと思います。
最後までお読みいただきありがとうございました🙌

■ 参考

Laravel 8.x Laravel Cashier (Stripe)

7
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?