feat: [fcm] Admin FCM API 추가 - MNG에서 API 호출로 FCM 발송
- AdminFcmController, AdminFcmService 추가 - FormRequest 검증 (AdminFcmSendRequest 등) - Swagger 문서 추가 (AdminFcmApi.php) - ApiKeyMiddleware: admin/fcm/* 화이트리스트 추가 - FCM 에러 메시지 i18n 추가
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
use App\Models\FcmSendLog;
|
||||
use App\Models\PushDeviceToken;
|
||||
use App\Models\Tenants\Tenant;
|
||||
use App\Services\Fcm\FcmSender;
|
||||
use App\Services\FcmApiService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\View\View;
|
||||
@@ -13,7 +13,7 @@
|
||||
class FcmController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly FcmSender $fcmSender
|
||||
private readonly FcmApiService $fcmApiService
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -86,6 +86,8 @@ public function send(Request $request): View
|
||||
|
||||
/**
|
||||
* FCM 발송 실행 (HTMX)
|
||||
*
|
||||
* API 서버를 통해 FCM을 발송합니다.
|
||||
*/
|
||||
public function sendPush(Request $request): View
|
||||
{
|
||||
@@ -101,100 +103,34 @@ public function sendPush(Request $request): View
|
||||
'sound_key' => 'nullable|string|max:50',
|
||||
]);
|
||||
|
||||
// 대상 토큰 조회
|
||||
$query = PushDeviceToken::withoutGlobalScopes()->active();
|
||||
|
||||
if ($tenantId = $request->get('tenant_id')) {
|
||||
$query->forTenant($tenantId);
|
||||
}
|
||||
|
||||
if ($userId = $request->get('user_id')) {
|
||||
$query->forUser($userId);
|
||||
}
|
||||
|
||||
if ($platform = $request->get('platform')) {
|
||||
$query->platform($platform);
|
||||
}
|
||||
|
||||
$tokens = $query->pluck('token')->toArray();
|
||||
$tokenCount = count($tokens);
|
||||
|
||||
if ($tokenCount === 0) {
|
||||
return view('fcm.partials.send-result', [
|
||||
'success' => false,
|
||||
'message' => '발송 대상 토큰이 없습니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
// 발송 로그 생성
|
||||
$sendLog = FcmSendLog::create([
|
||||
'tenant_id' => $request->get('tenant_id'),
|
||||
'user_id' => $request->get('user_id'),
|
||||
'sender_id' => auth()->id(),
|
||||
'title' => $request->get('title'),
|
||||
'body' => $request->get('body'),
|
||||
'channel_id' => $request->get('channel_id', 'push_default'),
|
||||
'type' => $request->get('type'),
|
||||
'platform' => $request->get('platform'),
|
||||
'data' => array_filter([
|
||||
// API 서버로 발송 요청
|
||||
$result = $this->fcmApiService->send(
|
||||
array_filter([
|
||||
'title' => $request->get('title'),
|
||||
'body' => $request->get('body'),
|
||||
'tenant_id' => $request->get('tenant_id'),
|
||||
'user_id' => $request->get('user_id'),
|
||||
'platform' => $request->get('platform'),
|
||||
'channel_id' => $request->get('channel_id'),
|
||||
'type' => $request->get('type'),
|
||||
'url' => $request->get('url'),
|
||||
'sound_key' => $request->get('sound_key'),
|
||||
]),
|
||||
'status' => FcmSendLog::STATUS_SENDING,
|
||||
]);
|
||||
|
||||
try {
|
||||
// FCM 발송
|
||||
$data = array_filter([
|
||||
'type' => $request->get('type'),
|
||||
'url' => $request->get('url'),
|
||||
'sound_key' => $request->get('sound_key'),
|
||||
]);
|
||||
|
||||
$result = $this->fcmSender->sendToMany(
|
||||
$tokens,
|
||||
$request->get('title'),
|
||||
$request->get('body'),
|
||||
$request->get('channel_id', 'push_default'),
|
||||
$data
|
||||
);
|
||||
|
||||
// 무효 토큰 비활성화
|
||||
$invalidTokens = $result->getInvalidTokens();
|
||||
if (count($invalidTokens) > 0) {
|
||||
foreach ($invalidTokens as $token) {
|
||||
$response = $result->getResponse($token);
|
||||
$errorCode = $response?->getErrorCode();
|
||||
|
||||
PushDeviceToken::withoutGlobalScopes()
|
||||
->where('token', $token)
|
||||
->update([
|
||||
'is_active' => false,
|
||||
'last_error' => $errorCode,
|
||||
'last_error_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// 발송 로그 업데이트
|
||||
$summary = $result->toSummary();
|
||||
$sendLog->markAsCompleted($summary);
|
||||
|
||||
return view('fcm.partials.send-result', [
|
||||
'success' => true,
|
||||
'message' => '발송 완료',
|
||||
'data' => $summary,
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$sendLog->markAsFailed($e->getMessage());
|
||||
auth()->id()
|
||||
);
|
||||
|
||||
if (! $result['success']) {
|
||||
return view('fcm.partials.send-result', [
|
||||
'success' => false,
|
||||
'message' => '발송 중 오류 발생: '.$e->getMessage(),
|
||||
'message' => $result['message'] ?? 'FCM 발송에 실패했습니다.',
|
||||
]);
|
||||
}
|
||||
|
||||
return view('fcm.partials.send-result', [
|
||||
'success' => true,
|
||||
'message' => $result['message'] ?? '발송 완료',
|
||||
'data' => $result['data'] ?? [],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user