From b5da40c0517cfc3d48b3f46d1baec840d8667cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Thu, 26 Feb 2026 10:29:44 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[sms]=20SMS=20=EB=B0=9C=EC=86=A1=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=A9=94=EB=89=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SmsController (WEB): 카카오톡 패턴 동일한 HX-Redirect 처리 - BarobillSmsController (API): 발송, 발신번호 조회/확인, 전송상태 조회 - SMS 발송 테스트 블레이드 뷰: 발신번호 목록, 바이트 카운터, 발송 결과 표시 - web.php: barobill/sms/send 라우트 추가 - api.php: barobill/sms API 라우트 4개 추가 --- .../Admin/Barobill/BarobillSmsController.php | 137 ++++++++ .../Controllers/Barobill/SmsController.php | 29 ++ .../views/barobill/sms/send/index.blade.php | 304 ++++++++++++++++++ routes/api.php | 8 + routes/web.php | 5 + 5 files changed, 483 insertions(+) create mode 100644 app/Http/Controllers/Api/Admin/Barobill/BarobillSmsController.php create mode 100644 app/Http/Controllers/Barobill/SmsController.php create mode 100644 resources/views/barobill/sms/send/index.blade.php diff --git a/app/Http/Controllers/Api/Admin/Barobill/BarobillSmsController.php b/app/Http/Controllers/Api/Admin/Barobill/BarobillSmsController.php new file mode 100644 index 00000000..bf6ed06d --- /dev/null +++ b/app/Http/Controllers/Api/Admin/Barobill/BarobillSmsController.php @@ -0,0 +1,137 @@ +first(); + + if (! $member) { + return response()->json([ + 'success' => false, + 'message' => '바로빌 회원사가 등록되어 있지 않습니다.', + ], 404); + } + + $this->barobillService->setServerMode($member->server_mode ?? 'test'); + + return $member; + } + + /** + * SMS 발송 + */ + public function sendSms(Request $request): JsonResponse + { + $validated = $request->validate([ + 'from_number' => 'required|string', + 'to_name' => 'required|string', + 'to_number' => 'required|string', + 'contents' => 'required|string', + 'send_dt' => 'nullable|string', + 'ref_key' => 'nullable|string', + ]); + + $member = $this->resolveMember(); + if ($member instanceof JsonResponse) { + return $member; + } + + $result = $this->barobillService->sendSMSMessage( + corpNum: $member->biz_no, + senderId: $member->barobill_id, + fromNumber: $validated['from_number'], + toName: $validated['to_name'], + toNumber: $validated['to_number'], + contents: $validated['contents'], + sendDT: $validated['send_dt'] ?? '', + refKey: $validated['ref_key'] ?? '' + ); + + if (! $result['success']) { + return response()->json($result, 422); + } + + return response()->json($result); + } + + /** + * 등록된 발신번호 목록 조회 + */ + public function getFromNumbers(): JsonResponse + { + $member = $this->resolveMember(); + if ($member instanceof JsonResponse) { + return $member; + } + + $result = $this->barobillService->getSMSFromNumbers($member->biz_no); + + if (! $result['success']) { + return response()->json($result, 422); + } + + return response()->json($result); + } + + /** + * 발신번호 등록 여부 확인 + */ + public function checkFromNumber(Request $request): JsonResponse + { + $validated = $request->validate([ + 'from_number' => 'required|string', + ]); + + $member = $this->resolveMember(); + if ($member instanceof JsonResponse) { + return $member; + } + + $result = $this->barobillService->checkSMSFromNumber( + $member->biz_no, + $validated['from_number'] + ); + + if (! $result['success']) { + return response()->json($result, 422); + } + + return response()->json($result); + } + + /** + * SMS 전송 상태 조회 + */ + public function getSendState(string $sendKey): JsonResponse + { + $member = $this->resolveMember(); + if ($member instanceof JsonResponse) { + return $member; + } + + $result = $this->barobillService->getSMSSendState($member->biz_no, $sendKey); + + if (! $result['success']) { + return response()->json($result, 422); + } + + return response()->json($result); + } +} diff --git a/app/Http/Controllers/Barobill/SmsController.php b/app/Http/Controllers/Barobill/SmsController.php new file mode 100644 index 00000000..1f127767 --- /dev/null +++ b/app/Http/Controllers/Barobill/SmsController.php @@ -0,0 +1,29 @@ +header('HX-Request')) { + return response('', 200)->header('HX-Redirect', route('barobill.sms.send')); + } + + $tenantId = session('selected_tenant_id', 1); + $currentTenant = Tenant::find($tenantId); + $barobillMember = BarobillMember::where('tenant_id', $tenantId)->first(); + + return view('barobill.sms.send.index', compact('currentTenant', 'barobillMember')); + } +} diff --git a/resources/views/barobill/sms/send/index.blade.php b/resources/views/barobill/sms/send/index.blade.php new file mode 100644 index 00000000..3ba545bd --- /dev/null +++ b/resources/views/barobill/sms/send/index.blade.php @@ -0,0 +1,304 @@ +@extends('layouts.app') + +@section('title', 'SMS 발송 테스트') + +@section('content') +
+ +
+
+
+ 바로빌 + + SMS 발송 테스트 +
+

SMS 발송 테스트

+

바로빌 SMS 서비스 연동 테스트 (단문 16.5원/건)

+
+
+ + @if(!$barobillMember) +
+

바로빌 회원사 연동 필요

+

SMS 발송을 위해 먼저 바로빌 회원사를 등록해주세요.

+
+ @else +
+ +
+
+

등록된 발신번호

+ +
+
+
+ + 발신번호 목록 로딩 중... +
+
+
+ + +
+

SMS 발송

+
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + 0 / 90 바이트 +
+ + +
+ +
+ + +

비워두면 즉시 발송됩니다.

+
+
+ +
+
+
+ + + +
+ @endif +
+@endsection + +@push('scripts') + +@endpush diff --git a/routes/api.php b/routes/api.php index 10e09ba9..06ad8be2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -225,6 +225,14 @@ Route::delete('/send/{sendKey}/cancel', [\App\Http\Controllers\Api\Admin\Barobill\BarobillKakaotalkController::class, 'cancelReserved'])->name('send.cancel'); }); + // 바로빌 SMS API + Route::prefix('barobill/sms')->name('barobill.sms.')->group(function () { + Route::post('/send', [\App\Http\Controllers\Api\Admin\Barobill\BarobillSmsController::class, 'sendSms'])->name('send'); + Route::get('/from-numbers', [\App\Http\Controllers\Api\Admin\Barobill\BarobillSmsController::class, 'getFromNumbers'])->name('from-numbers'); + Route::post('/check-from-number', [\App\Http\Controllers\Api\Admin\Barobill\BarobillSmsController::class, 'checkFromNumber'])->name('check-from-number'); + Route::get('/send-state/{sendKey}', [\App\Http\Controllers\Api\Admin\Barobill\BarobillSmsController::class, 'getSendState'])->name('send-state'); + }); + // 테넌트 관리 API Route::prefix('tenants')->name('tenants.')->group(function () { // 고정 경로는 먼저 정의 diff --git a/routes/web.php b/routes/web.php index fdeb3ebe..f8e538d1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -631,6 +631,11 @@ Route::get('/history', [\App\Http\Controllers\Barobill\KakaotalkController::class, 'history'])->name('history'); Route::get('/guide', [\App\Http\Controllers\Barobill\KakaotalkController::class, 'guide'])->name('guide'); }); + + // SMS 발송 테스트 + Route::prefix('sms')->name('sms.')->group(function () { + Route::get('/send', [\App\Http\Controllers\Barobill\SmsController::class, 'send'])->name('send'); + }); }); /*