payjpの導入
以前の記事を参照
ユーザーがこれまで決済したカード一覧を取得する
- PaymentController.php
public function index()
{
$user = auth()->user();
$cardList = [];
// 既にpayjpに登録済みの場合
if (!empty($user->payjp_customer_id)) {
// カード一覧を取得
\Payjp\Payjp::setApiKey(config('payjp.secret_key'));
$cardDatas = \Payjp\Customer::retrieve($user->payjp_customer_id)->cards->data;
foreach ($cardDatas as $cardData) {
$cardList[] = [
'cardNumber' => "**** **** **** {$cardData->last4}",
'brand' => $cardData->brand,
'exp_year' => $cardData->exp_year,
'exp_month' => $cardData->exp_month,
'name' => $cardData->name,
];
}
}
return view('payment', compact('cardList'));
}
上記により、
既に顧客&カード登録済みの場合、$cardList
にはこんなデータが入ってくる
array:1 [▼
0 => array:5 [▼
"cardNumber" => "**** **** **** 4242"
"brand" => "Visa"
"exp_year" => 2024
"exp_month" => 12
"name" => "TEST USER"
]
]
支払いフォームで登録済みのカード一覧を表示
- payment.blade.php
@if (session('error-message'))
<p>{{ session('error-message') }}</p>
@endif
<form action="{{ route('payment') }}" method="post">
@csrf
<script
src="https://checkout.pay.jp/"
class="payjp-button"
data-key="{{ config('payjp.public_key') }}"
data-text="カード情報を入力"
data-submit-text="カードを登録する"
></script>
</form>
@if (!empty($cardList))
<p>もしくは登録済みのカードで支払い</p>
<form action="{{ route('payment') }}" method="post">
@csrf
@foreach ($cardList as $card)
<div class="card-item">
<label>
<input type="radio" name="payjp_card_id" value="{{ $card['id'] }}" />
<span class="brand">{{ $card['brand'] }}</span>
<span class="number">{{ $card['number'] }}</span>
</label>
<div>
<p>名義: {{ $card['name'] }}</p>
<p>期限: {{ $card['exp_year'] }}/{{ $card['exp_month'] }}</p>
</div>
</div>
@endforeach
<button type="submit">選択したカードで決済する</button>
</form>
@endif
cssは省略してるけど画面はこんな感じ
Controller側で登録・決済処理実装
- PaymentController.php
public function payment(Request $request)
{
if (empty($request->get('payjp-token')) && !$request->get('payjp_card_id')) {
abort(404);
}
DB::beginTransaction();
try {
// ログインユーザー取得
$user = auth()->user();
// シークレットキーを設定
\Payjp\Payjp::setApiKey(config('payjp.secret_key'));
// ⭐️ 以前使用したカードを使う場合
if (!empty($request->get('payjp_card_id'))) {
$customer = \Payjp\Customer::retrieve($user['payjp_customer_id']);
// 使用するカードを設定
$customer->default_card = $request->get('payjp_card_id');
$customer->save();
// ⭐️ 既にpayjpに登録済みの場合
} elseif (!empty($user['payjp_customer_id'])) {
// カード情報を追加
$customer = \Payjp\Customer::retrieve($user['payjp_customer_id']);
$card = $customer->cards->create([
'card' => $request->get('payjp-token'),
]);
// 使用するカードを設定
$customer->default_card = $card->id;
$customer->save();
// ⭐️ payjp未登録の場合
} else {
// payjpで顧客新規登録 & カード登録
$customer = \Payjp\Customer::create([
'card' => $request->get('payjp-token'),
]);
// DBにcustomer_idを登録
$user->payjp_customer_id = $customer->id;
$user->save();
}
// ⭐️ 支払い処理
// 新規支払い情報作成
\Payjp\Charge::create([
"customer" => $customer->id,
"amount" => 100,
"currency" => 'jpy',
]);
DB::commit();
return redirect(route('payment'))->with('message', '支払いが完了しました');
} catch (\Exception $e) {
Log::error($e);
DB::rollback();
if(strpos($e,'has already been used') !== false) {
return redirect()->back()->with('error-message', '既に登録されているカード情報です');
}
return redirect()->back();
}
}
ざっくり解説
- 以前使用したカードIDを渡された場合
→ 自分に紐づく$customer
を取得して、デフォルトカード(=支払うカード)としてそのカードIDを設定する - カード情報入力 & 既にpayjpには登録済みの場合
→ 自分に紐づく$customer
を取得して、新しいカードを追加 & デフォルトカード(=支払うカード)としてそのカードIDを設定する - 新規の場合
→$customer
及びカードを新規作成 - 同じカード番号かつ同じ期限のカードはエラーが出るので
catch
して支払いフォームに表示してあげる
Laravelのプロジェクトでpayjpで決済する際に
以前使用したカード情報を再利用できるようにして
カード入力を省略化させてあげる