Files
Gnuboard7/plugins/_bundled/sirsoft-pay_nhnkcp/src/Controllers/PaymentRetryController.php
T
2026-07-13 11:10:50 +09:00

94 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Plugins\Sirsoft\PayNhnkcp\Controllers;
use App\Helpers\ResponseHelper;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\RateLimiter;
use Modules\Sirsoft\Ecommerce\Services\OrderProcessingService;
use Plugins\Sirsoft\PayNhnkcp\Concerns\RecordsPaymentWindowClosure;
use Plugins\Sirsoft\PayNhnkcp\Http\Requests\PaymentRetryRequest;
class PaymentRetryController
{
use RecordsPaymentWindowClosure;
public function __construct(
private readonly OrderProcessingService $orderService,
) {}
/**
* 같은 주문번호로 NHN KCP 결제를 다시 열기 전 실패 주문을 결제대기 상태로 복구합니다.
*
* @param PaymentRetryRequest $request 결제 재시도 준비 요청
* @return JsonResponse 재시도 준비 처리 결과
*/
public function store(PaymentRetryRequest $request): JsonResponse
{
$validated = $request->validated();
$oid = $validated['oid'];
$price = (int) $validated['price'];
$rateLimitKey = $this->rateLimitKey($request, $oid);
if (RateLimiter::tooManyAttempts($rateLimitKey, 20)) {
return ResponseHelper::error('messages.failed', 429, [
'message' => ['Too many NHN KCP payment retry requests. Please try again later.'],
]);
}
RateLimiter::hit($rateLimitKey, 60);
$order = $this->orderService->findByOrderNumber($oid);
if (! $order) {
return ResponseHelper::error('messages.failed', 404, [
'message' => ['Order not found.'],
]);
}
if (! $this->requestMatchesOrderBuyer($request, $order)) {
return ResponseHelper::error('messages.failed', 403, [
'message' => ['Order buyer verification failed.'],
]);
}
$expectedPrice = $this->resolveExpectedPaymentPriceOrNull($order, 'payment_retry', [
'oid' => $oid,
'received_price' => $price,
'ip' => $request->ip(),
]);
if ($expectedPrice === null) {
return ResponseHelper::error('messages.failed', 422, [
'message' => ['Payment currency is not chargeable.'],
]);
}
if ($price !== $expectedPrice) {
return ResponseHelper::error('messages.failed', 422, [
'message' => ['Payment amount does not match the order amount.'],
]);
}
if ($order->order_status->isBeforePayment()) {
return ResponseHelper::success('messages.success', [
'status' => 'ready',
]);
}
if ($this->restoreRetryableKcpOrder($order, $price)) {
return ResponseHelper::success('messages.success', [
'status' => 'restored',
]);
}
return ResponseHelper::error('messages.failed', 409, [
'message' => ['Order is not retryable for NHN KCP payment.'],
]);
}
private function rateLimitKey(PaymentRetryRequest $request, string $oid): string
{
return 'sirsoft-pay_nhnkcp:payment-retry:' . sha1($request->ip() . '|' . $oid);
}
}