Files
Gnuboard7/plugins/_bundled/sirsoft-pay_nhnkcp/tests/Feature/Controllers/EscrowCommonNotifyControllerTest.php
T
thisgun 657f546efc chore(payment): NHN KCP와 NICE 결제 플러그인 개발 브랜치 분리
정식 develop에서는 기본 번들 정책에 따라 제거된 결제 플러그인을 별도 개발 브랜치에서 계속 유지보수할 수 있도록 복원한다.
2026-07-02 20:03:22 +09:00

154 lines
5.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Plugins\Sirsoft\PayNhnkcp\Tests\Feature\Controllers;
use App\Extension\HookManager;
use App\Models\User;
use Modules\Sirsoft\Ecommerce\Database\Factories\OrderFactory;
use Modules\Sirsoft\Ecommerce\Database\Factories\OrderPaymentFactory;
use Modules\Sirsoft\Ecommerce\Enums\OrderStatusEnum;
use Modules\Sirsoft\Ecommerce\Enums\PaymentMethodEnum;
use Modules\Sirsoft\Ecommerce\Enums\PaymentStatusEnum;
use Modules\Sirsoft\Ecommerce\Models\Order;
use Plugins\Sirsoft\PayNhnkcp\Tests\PluginTestCase;
class EscrowCommonNotifyControllerTest extends PluginTestCase
{
protected function tearDown(): void
{
HookManager::resetAll();
parent::tearDown();
}
private function createEscrowOrder(string $tno = 'KCP_ESCROW_TNO_REAL'): Order
{
$user = User::factory()->create();
$order = OrderFactory::new()->create([
'user_id' => $user->id,
'order_status' => OrderStatusEnum::PAYMENT_COMPLETE,
'subtotal_amount' => 30000,
'total_amount' => 30000,
'total_due_amount' => 0,
'total_paid_amount' => 30000,
'paid_at' => now(),
]);
OrderPaymentFactory::new()->create([
'order_id' => $order->id,
'payment_status' => PaymentStatusEnum::PAID,
'payment_method' => PaymentMethodEnum::CARD,
'pg_provider' => 'nhnkcp',
'transaction_id' => $tno,
'paid_amount_local' => 30000,
'paid_at' => now(),
'is_escrow' => true,
'payment_meta' => [
'site_cd' => 'T0000',
'is_test_mode' => true,
'escw_yn' => 'Y',
],
]);
return $order;
}
private function postEscrowNotify(array $payload): \Illuminate\Testing\TestResponse
{
return $this->withServerVariables(['REMOTE_ADDR' => '203.238.36.58'])
->post('/plugins/sirsoft-pay_nhnkcp/payment/escrow-common-notify', $payload);
}
private function assertKcpNotifyRetry(\Illuminate\Testing\TestResponse $response): void
{
$response->assertOk();
$this->assertStringContainsString('name="result"', $response->getContent());
$this->assertStringNotContainsString('value="0000"', $response->getContent());
}
private function assertKcpNotifyOk(\Illuminate\Testing\TestResponse $response): void
{
$response->assertOk();
$this->assertStringContainsString('name="result"', $response->getContent());
$this->assertStringContainsString('value="0000"', $response->getContent());
}
public function test_escrow_common_notify_retries_on_tno_mismatch_before_hooks(): void
{
$order = $this->createEscrowOrder('KCP_ESCROW_TNO_REAL');
$hookCalled = false;
HookManager::addAction(
'sirsoft-pay_nhnkcp.escrow.purchase_confirmed',
function () use (&$hookCalled): void {
$hookCalled = true;
}
);
$response = $this->postEscrowNotify([
'site_cd' => 'T0000',
'tno' => 'ATTACKER_ESCROW_TNO',
'order_no' => $order->order_number,
'tx_cd' => 'TX02',
'cl_status' => '2',
]);
$this->assertKcpNotifyRetry($response);
$this->assertFalse($hookCalled, '검증 실패한 에스크로 통보는 hook 을 발행하지 않아야 합니다.');
}
public function test_escrow_common_notify_processes_matching_tno(): void
{
$order = $this->createEscrowOrder('KCP_ESCROW_TNO_REAL');
$hookCalled = false;
HookManager::addAction(
'sirsoft-pay_nhnkcp.escrow.purchase_confirmed',
function () use (&$hookCalled): void {
$hookCalled = true;
}
);
$response = $this->postEscrowNotify([
'site_cd' => 'T0000',
'tno' => 'KCP_ESCROW_TNO_REAL',
'order_no' => $order->order_number,
'tx_cd' => 'TX02',
'cl_status' => '2',
]);
$this->assertKcpNotifyOk($response);
$this->assertTrue($hookCalled);
}
public function test_escrow_common_notify_does_not_dispatch_duplicate_payload_twice(): void
{
$order = $this->createEscrowOrder('KCP_ESCROW_TNO_REAL');
$hookCount = 0;
HookManager::addAction(
'sirsoft-pay_nhnkcp.escrow.purchase_confirmed',
function () use (&$hookCount): void {
$hookCount++;
}
);
$payload = [
'site_cd' => 'T0000',
'tno' => 'KCP_ESCROW_TNO_REAL',
'order_no' => $order->order_number,
'tx_cd' => 'TX02',
'tx_tm' => '20260624164000',
'cl_status' => '2',
];
$first = $this->postEscrowNotify($payload);
$second = $this->postEscrowNotify($payload);
$this->assertKcpNotifyOk($first);
$this->assertKcpNotifyOk($second);
$this->assertSame(1, $hookCount, '동일 에스크로 통보 replay 는 hook 을 한 번만 발행해야 합니다.');
}
}