Files
sam-api/app/Console/Commands/FcmTestCommand.php
권혁성 1c3cb48c7c feat(API): FCM 채널명 동기화 및 config 일원화 (7채널)
- push_urgent → push_vendor_register (거래처등록)
- push_payment → push_approval_request (결재요청)
- push_income 신규 추가 (입금)
- config/fcm.php에 전체 7개 채널 등록 (기존 2개→7개)
- 서비스 파일 하드코딩을 config() 참조로 전환

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 18:07:44 +09:00

135 lines
4.5 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Services\Fcm\FcmSender;
use Illuminate\Console\Command;
class FcmTestCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'fcm:test
{--token= : FCM 디바이스 토큰 (필수)}
{--channel=push_default : 알림 채널 ID (push_default, push_vendor_register, push_approval_request, push_income, push_sales_order, push_purchase_order, push_contract)}
{--title=테스트 알림 : 알림 제목}
{--body=FCM 테스트 메시지입니다. : 알림 내용}
{--data= : 추가 데이터 (JSON 형식)}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'FCM 푸시 알림 테스트 발송';
/**
* Execute the console command.
*/
public function handle(): int
{
$token = $this->option('token');
if (empty($token)) {
$this->error('--token 옵션은 필수입니다.');
$this->line('');
$this->line('사용법:');
$this->line(' php artisan fcm:test --token=YOUR_FCM_TOKEN');
$this->line(' php artisan fcm:test --token=YOUR_FCM_TOKEN --channel=push_vendor_register --title="신규업체 알림"');
return self::FAILURE;
}
$channel = $this->option('channel');
$title = $this->option('title');
$body = $this->option('body');
$dataJson = $this->option('data');
// 추가 데이터 파싱
$data = [];
if ($dataJson) {
$data = json_decode($dataJson, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$this->error('--data 옵션은 유효한 JSON이어야 합니다.');
return self::FAILURE;
}
}
// 설정 확인
$this->info('FCM 테스트 발송 시작...');
$this->line('');
$this->table(
['항목', '값'],
[
['Project ID', config('fcm.project_id') ?: '(미설정)'],
['Token', substr($token, 0, 30).'...'],
['Channel', $channel],
['Title', $title],
['Body', mb_substr($body, 0, 50).(mb_strlen($body) > 50 ? '...' : '')],
['Data', $data ? json_encode($data, JSON_UNESCAPED_UNICODE) : '(없음)'],
]
);
$this->line('');
// Project ID 확인
if (empty(config('fcm.project_id'))) {
$this->error('FCM_PROJECT_ID가 설정되지 않았습니다.');
$this->line('.env 파일에 FCM_PROJECT_ID를 설정해주세요.');
return self::FAILURE;
}
// Service Account 파일 확인
$saPath = config('fcm.service_account_path');
$fullPath = str_starts_with($saPath, '/') ? $saPath : storage_path($saPath);
if (! file_exists($fullPath)) {
$this->error("Service Account 파일을 찾을 수 없습니다: {$fullPath}");
$this->line('.env 파일에 FCM_SA_PATH를 확인해주세요.');
return self::FAILURE;
}
$this->info('Service Account 파일 확인됨: '.basename($fullPath));
// FCM 발송
try {
$sender = new FcmSender;
$response = $sender->sendToToken($token, $title, $body, $channel, $data);
$this->line('');
if ($response->success) {
$this->info('✅ FCM 발송 성공!');
$this->line("Message ID: {$response->messageId}");
$this->line("Status Code: {$response->statusCode}");
} else {
$this->error('❌ FCM 발송 실패');
$this->line("Error: {$response->error}");
$this->line("Status Code: {$response->statusCode}");
if ($response->isInvalidToken()) {
$this->warn('토큰이 유효하지 않습니다. 디바이스에서 새 토큰을 발급받아야 합니다.');
}
$this->line('');
$this->line('Response:');
$this->line(json_encode($response->rawResponse, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
return self::FAILURE;
}
} catch (\Exception $e) {
$this->error('FCM 발송 중 예외 발생: '.$e->getMessage());
return self::FAILURE;
}
return self::SUCCESS;
}
}