決済といえば、そう!Stripeですよね!!
ついにStripeが記事になる時が来ました!

決済シリーズ第3弾!今回はLaravelでStripe決済を簡易的に実装してみたいと思います。

Stripeアカウントの作成

まずはStripeのアカウントを作成しましょう。

アカウントを作成すると質問を受けるかもしれませんが、実際に運用するわけではない場合は適当に情報を入力して登録しましょう。

下図のようなダッシュボードが表示されればOKです。

.env情報の設定

テスト時は実際に決済が実行されないようにテスト環境に設定しましょう。

また、アクセスキーを.envに設定しましょう。

STRIPE_PUBLIC_KEY=pk_test_51xxxxxxxxxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_test_51xxxxxxxxxxxxxxxxxxx

続いて、env呼び出し用のconfigファイルを作成します。

config/stripe.phpを作成して下記のコードをコピペしてください。

<?php
return [
    'stripe_public_key' => env('STRIPE_PUBLIC_KEY'),
    'stripe_secret_key' => env('STRIPE_SECRET_KEY'),
];

念のため、php artisan config:clear && php artisan cache:clearしておきます。

これでアクセスキーの設定は完了です。

SDKの導入

ターミナルで以下のコマンドを実行してください。

$ composer require stripe/stripe-php

これでStripeライブラリが使用できます。

決済フォームの作成

まずコントローラーを作成します。

ここではPaymentController.phpとします。

<?php

namespace App\Http\Controllers;

class PaymentController extends Controller
{
    /**
     * 決済フォーム表示
     */
    public function create()
    {
        return view('payment.create');
    }
}

routeを記述しておきましょう。画面表示と決済実行のルートを記述しておきます。

Route::prefix('payment')->name('payment.')->group(function () {
    Route::get('/create', [PaymentController::class, 'create'])->name('create');
    Route::post('/store', [PaymentController::class, 'store'])->name('store');
});

続いて、viewを作成します。

create.blade.phpを作成し、以下のコードをコピペしてください。

※CSSはbootstrapを利用しています。

<x-app-layout>
    <div class="container">
        @if (session('flash_alert'))
            <div class="alert alert-danger">{{ session('flash_alert') }}</div>
        @elseif(session('status'))
            <div class="alert alert-success">
                {{ session('status') }}
            </div>
        @endif
        <div class="p-5">
            <div class="col-6 card">
                <div class="card-header">Stripe決済</div>
                <div class="card-body">
                    <form id="card-form" action="{{ route('payment.store') }}" method="POST">
                        @csrf
                        <div>
                            <label for="card_number">カード番号</label>
                            <div id="card-number" class="form-control"></div>
                        </div>

                        <div>
                            <label for="card_expiry">有効期限</label>
                            <div id="card-expiry" class="form-control"></div>
                        </div>

                        <div>
                            <label for="card-cvc">セキュリティコード</label>
                            <div id="card-cvc" class="form-control"></div>
                        </div>

                        <div id="card-errors" class="text-danger"></div>

                        <button class="mt-3 btn btn-primary">支払い</button>
                    </form>
                </div>
            </div>
        </div>
    </div>

    <script src="https://js.stripe.com/v3/"></script>
    <script>
        /* 基本設定*/
        const stripe_public_key = "{{ config('stripe.stripe_public_key') }}"
        const stripe = Stripe(stripe_public_key);
        const elements = stripe.elements();

        var cardNumber = elements.create('cardNumber');
        cardNumber.mount('#card-number');
        cardNumber.on('change', function(event) {
            var displayError = document.getElementById('card-errors');
            if (event.error) {
                displayError.textContent = event.error.message;
            } else {
                displayError.textContent = '';
            }
        });

        var cardExpiry = elements.create('cardExpiry');
        cardExpiry.mount('#card-expiry');
        cardExpiry.on('change', function(event) {
            var displayError = document.getElementById('card-errors');
            if (event.error) {
                displayError.textContent = event.error.message;
            } else {
                displayError.textContent = '';
            }
        });

        var cardCvc = elements.create('cardCvc');
        cardCvc.mount('#card-cvc');
        cardCvc.on('change', function(event) {
            var displayError = document.getElementById('card-errors');
            if (event.error) {
                displayError.textContent = event.error.message;
            } else {
                displayError.textContent = '';
            }
        });

        var form = document.getElementById('card-form');
        form.addEventListener('submit', function(event) {
            event.preventDefault();
            var errorElement = document.getElementById('card-errors');
            if (event.error) {
                errorElement.textContent = event.error.message;
            } else {
                errorElement.textContent = '';
            }

            stripe.createToken(cardNumber).then(function(result) {
                if (result.error) {
                    errorElement.textContent = result.error.message;
                } else {
                    stripeTokenHandler(result.token);
                }
            });
        });

        function stripeTokenHandler(token) {
            var form = document.getElementById('card-form');
            var hiddenInput = document.createElement('input');
            hiddenInput.setAttribute('type', 'hidden');
            hiddenInput.setAttribute('name', 'stripeToken');
            hiddenInput.setAttribute('value', token.id);
            form.appendChild(hiddenInput);
            form.submit();
        }
    </script>
</x-app-layout>

画面を開いてみると以下のようなフォームが表示されます。

これで決済フォームは完成です。

決済処理の実装

では決済処理を実装します。PaymentController.phpにstoreアクションを追加してください。

<?php

namespace App\Http\Controllers;

use App\Http\Requests\StorePaymentRequest;
use Exception;

class PaymentController extends Controller
{
    /**
     * 決済フォーム表示
     */
    public function create()
    {
        return view('payment.create');
    }

    /**
     * 決済実行
     */
    public function store(StorePaymentRequest $request)
    {
        \Stripe\Stripe::setApiKey(config('stripe.stripe_secret_key'));

        try {
            \Stripe\Charge::create([
                'source' => $request->stripeToken,
                'amount' => 1000,
                'currency' => 'jpy',
            ]);
        } catch (Exception $e) {
            return back()->with('flash_alert', '決済に失敗しました!('. $e->getMessage() . ')');
        }
        return back()->with('status', '決済が完了しました!');
    }
}

FormRequestのStorePaymentRequestが不要な場合はいつも通りRequestクラスに置き換えてください。

setApiKeyにシークレットキーを設定し、Charge::createで決済が実行されます。

sourceにはフォームから受け取ったクレカのトークン、amountには金額を指定します。

実際に支払いボタンを押して決済が成功するか確認してみてください。

「決済が完了しました!」が表示されたらOKです。Stripeの管理画面を開いて支払いが適切にされているか確認してみましょう。

「成功」という表示がされていればしっかり決済が実行されています。

おわりに

今回はStripeについて紹介しました。

Stripeは他の決済サービスと比較して、本番運用ですぐに使える点が魅力的です。

クレカ決済のみならず、コンビニ決済、銀行振り込みにも対応しています。

よく使う決済サービスのため、実装できるようになっておくと何かと便利です。

決済シリーズ

Pay.jp

Square

参考

Stripe API Reference

この記事をシェアする