LaravelとStripeでサブスクリプション決済を作成する

今回はLaravelとStripeを使用したクレジットカード決済システムを作成していきます!

cashierというパッケージを使用することによって簡単にクレジットカードのサブスクリプション決済を作成することができるのでサクッと作っていきましょう!

Laravelプロジェクトを作成する

まずはいつも通りcomposerでLaravelプロジェクトを作成していきます!

今回はsubscriptionというプロジェクト名で解説を進めていきます。

composer create-project --prefer-dist laravel/laravel subscription

プロジェクトが作成できたら次にcomposerで必要なパッケージをインストールしていきましょう!

composer require laravel/cashier

laravelの認証機能も作成しておきます。

php artisan make:auth

ここまできたら次にデータベースを作成していきます!

データベースを作成する

契約されているサブスクリプションを保存するためのサブスクリプションテーブルを作成します。

php artisan make:migrate create_subscriptions_table

これでdatabase/migrations/の中にcreate_subscriptions_table.phpというファイルが作成されます。

ユーザーテーブルは php artisan make:auth で作成された

database/migrations/2014_10_12_000000_create_users_table.php

を編集していきます。

それでは各マイグレーションファイルを編集していきましょう!

usersマイグレーションファイルの編集

まずはusersテーブルから作成していきましょう!

Schema::table('users', function ($table) {

  //省略...

  //追加
  $table->string('stripe_id')->nullable()->collation('utf8mb4_bin');
  $table->string('card_brand')->nullable();
  $table->string('card_last_four', 4)->nullable();
  $table->timestamp('trial_ends_at')->nullable();
});

subscriptionsマイグレーションファイルの編集

次にsubscriptionsテーブルです!

Schema::create('subscriptions', function ($table) {
   $table->increments('id');
   $table->unsignedInteger('user_id');
   $table->string('name');
   $table->string('stripe_id')->collation('utf8mb4_bin');
   $table->string('stripe_plan');
   $table->integer('quantity');
   $table->timestamp('trial_ends_at')->nullable();
   $table->timestamp('ends_at')->nullable();
   $table->timestamps();
});

ここまで作成できたら設定をDBに反映していきます。

php artisan migrate

User.phpの編集

各テーブルが作成できたら次にUser.php(ユーザーモデル)にBillableトレイトを追加します。

下記のコードをApp/User.phpに追記します

use Laravel\Cashier\Billable; //追加

class User extends Authenticatable
{
   use Billable;//追加
}

Stripe APIキーの登録

StripeのAPIキーをconfig/services.phpに追記していきます!

下記のコードをコピぺで追記してください!

デフォルトで書かれている場合はそのまま使用しても上書きしてもどちらでも大丈夫です。

//省略...

'stripe' => [
   'model'  => App\User::class,
   'key' => env('STRIPE_KEY'),
   'secret' => env('STRIPE_SECRET'),
],

次にstripeのアクセスキーをセットしていきます。

アクセスキーはStripeダッシュボードの左サイドバーの開発者をクリックすることでAPIキーというメニューが表示されます!

下記のコードを.envファイルの末尾に追記してあげてください。

//省略.....
STRIPE_KEY=Stripeのアクセスキー  //追記
STRIPE_SECRET=Stripeのシークレットキー  //追記

これで初期設定は完了です!

ルーティングの作成

カード決済に関係するルートを作成していきます。

web.phpに下記のコードを記入してルートを通してください。

//...省略

Route::get('/card', '[email protected]')->name('card');
Route::post('/create/subscription', '[email protected]')->name('create');

カード決済フォームの作成

まず決済フォーム用のviewを作成しましょう!

今回はviewsディレクトリの中にcard.blade.phpというのviewファイルを作成しました。

ここはコピぺで大丈夫なので作成したファイルに下記コードを記入してください!

<!DOCTYPE html>
<html lang="ja" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>サブスクリプション決済フォーム</title>
  <style>
  /**
  * The CSS shown here will not be introduced in the Quickstart guide, but shows
  * how you can use CSS to style your Element's container.
  */
  .StripeElement {
    background-color: white;
    height: 40px;
    padding: 10px 12px;
    border-radius: 4px;
    border: 1px solid transparent;
    box-shadow: 0 1px 3px 0 #e6ebf1;
    -webkit-transition: box-shadow 150ms ease;
    transition: box-shadow 150ms ease;
  }

  .StripeElement--focus {
    box-shadow: 0 1px 3px 0 #cfd7df;
  }

  .StripeElement--invalid {
    border-color: #fa755a;
  }

  .StripeElement--webkit-autofill {
    background-color: #fefde5 !important;
  }

  </style>
</head>
<body>
  <script src="https://js.stripe.com/v3/"></script>
  <form action="{{ route("create") }}" method="post" id="payment-form">
    @csrf
    <div class="form-row">
      <label for="card-element">
        カード決済フォーム
      </label>
      <div id="card-element">
        <!-- A Stripe Element will be inserted here. -->
      </div>

      <!-- Used to display form errors. -->
      <div id="card-errors" role="alert"></div>
    </div>

    <button>Submit Payment</button>
  </form>
  <script type="text/javascript">
  // Create a Stripe client.
  var stripe = Stripe('{{ env("STRIPE_KEY") }}');

  // Create an instance of Elements.
  var elements = stripe.elements();

  // Custom styling can be passed to options when creating an Element.
  // (Note that this demo uses a wider set of styles than the guide below.)
  var style = {
    base: {
      color: '#32325d',
      lineHeight: '18px',
      fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
      fontSmoothing: 'antialiased',
      fontSize: '16px',
      '::placeholder': {
        color: '#aab7c4'
      }
    },
    invalid: {
      color: '#fa755a',
      iconColor: '#fa755a'
    }
  };

  // Create an instance of the card Element.
  var card = elements.create('card', {style: style});

  // Add an instance of the card Element into the `card-element` <div>.
  card.mount('#card-element');

  // Handle real-time validation errors from the card Element.
  card.addEventListener('change', function(event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
      displayError.textContent = event.error.message;
    } else {
      displayError.textContent = '';
    }
  });

  // Handle form submission.
  var form = document.getElementById('payment-form');
  form.addEventListener('submit', function(event) {
    event.preventDefault();

    stripe.createToken(card).then(function(result) {
      if (result.error) {
        // Inform the user if there was an error.
        var errorElement = document.getElementById('card-errors');
        errorElement.textContent = result.error.message;
      } else {
        // Send the token to your server.
        stripeTokenHandler(result.token);
      }
    });
  });

  // Submit the form with the token ID.
  function stripeTokenHandler(token) {
    // Insert the token ID into the form so it gets submitted to the server
    var form = document.getElementById('payment-form');
    var hiddenInput = document.createElement('input');
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', 'stripeToken');
    hiddenInput.setAttribute('value', token.id);
    form.appendChild(hiddenInput);

    // Submit the form
    form.submit();
  }
  </script>

</body>
</html>

次にStripeを処理したりカード決済フォームのviewを表示するためのコントローラーを作成していきましょう。

php artisan make:controller StripeController

作成したコントローラーの中にページを表示するためのコードを記入していきます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Auth;

class StripeController extends Controller
{
  //

  public function index () {
    return view("card");
  }

  public function createSubscription (Request $request) {
    $user = Auth::user();
    $stripeToken = $request -> stripeToken;
    $user->newSubscription('main', '作成したプランのID')->create($stripeToken);
  }
}

ここまできたら一度サーバーを立ち上げてページにアクセスしてみましょう!

簡易的ではありますがこのようにクレジットカードの決済フォームが作成されていますね!

クレジットカード決済処理

決済フォームページまで作成できたらいよいよ決済処理の実装に入ります。

といっても特に難しいことはないので気楽に実装していきましょう!

まずは先ほど作成したStripeCpntrollerにサブスクリプションを登録するためのコードを記入していきます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Auth;

class StripeController extends Controller
{
  //

  public function index () {
    return view("card");
  }

  public function createSubscription (Request $request) {
    $user = Auth::user();
    $stripeToken = $request -> stripeToken;
    $user->newSubscription('main', '作成したプランのID')->create($stripeToken);
  }
}

たったのこれだけでサブスクリプションのカード決済が実装できます。

これに対応したルートは先ほど作成済みなので実際にデモ決済を行ってみましょう!

デモのカード決済を行う

まずはユーザー新規作成ページから新規ユーザーを作成しましょう。

そしたらweb.phpで設定したカード決済フォームのURLにアクセスして、デモ用のクレジットカード番号

4242424242424242  それ以降は自由に入力していただいて大丈夫です!

ただしカードの有効期限だけ過去の日付にしないようにしてください!

カード情報を入力して送信してしばらくすると、真っ白な画面が表示されたかと思います。その状態になったらStripeのダッシュボードにいって売上を確認してみてください!

ちゃんと売上金が反映されているかと思います。

処理の最後にreturn redirectでリダイレクト先を指定することで決済処理後にページを移動することができます。

まとめ

たったこれだけでサブスクリプションの決済を実装することができました。

この処理以外にもサブスクリプションのキャンセルや、プランの移行など様々な処理が行えるのでさらに詳しく知りたい方はリクエストしてください!


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です