diff --git a/app/Http/Controllers/ESign/EsignApiController.php b/app/Http/Controllers/ESign/EsignApiController.php index b44ab260..49b387fa 100644 --- a/app/Http/Controllers/ESign/EsignApiController.php +++ b/app/Http/Controllers/ESign/EsignApiController.php @@ -760,7 +760,7 @@ public function send(Request $request, int $id): JsonResponse return response()->json(['success' => false, 'message' => '초안 상태에서만 발송할 수 있습니다.'], 422); } - $sendMethod = $request->input('send_method', 'alimtalk'); + $sendMethod = $request->input('send_method', 'email'); $smsFallback = $request->boolean('sms_fallback', true); $contract->update([ @@ -848,7 +848,7 @@ public function remind(Request $request, int $id): JsonResponse $nextSigner->update(['status' => 'notified']); $results = $this->dispatchNotification( $contract, $nextSigner, - $contract->send_method ?? 'alimtalk', + $contract->send_method ?? 'email', $contract->sms_fallback ?? true, isReminder: true, ); @@ -908,26 +908,34 @@ private function dispatchNotification( bool $isReminder = false, ): array { $results = []; + $alimtalkFailed = false; // 알림톡 발송 if (in_array($sendMethod, ['alimtalk', 'both']) && $signer->phone) { - $results[] = $this->sendAlimtalk($contract, $signer, $smsFallback, $isReminder); + $alimtalkResult = $this->sendAlimtalk($contract, $signer, $smsFallback, $isReminder); + $results[] = $alimtalkResult; + $alimtalkFailed = !($alimtalkResult['success'] ?? false); } - // 이메일 발송 (email/both 선택 시, 또는 알림톡인데 번호 없으면 폴백) - if (in_array($sendMethod, ['email', 'both']) || ($sendMethod === 'alimtalk' && !$signer->phone)) { - if ($signer->email) { - try { - Mail::to($signer->email)->send(new EsignRequestMail($contract, $signer, $isReminder)); - $results[] = ['success' => true, 'channel' => 'email', 'error' => null]; - } catch (\Throwable $e) { - \Log::warning('E-Sign 이메일 발송 실패', [ - 'contract_id' => $contract->id, - 'signer_id' => $signer->id, - 'error' => $e->getMessage(), - ]); - $results[] = ['success' => false, 'channel' => 'email', 'error' => $e->getMessage()]; - } + // 이메일 발송 조건: + // 1) email/both 선택 시 + // 2) alimtalk인데 번호 없으면 폴백 + // 3) alimtalk 발송 실패 시 이메일 자동 폴백 + $shouldSendEmail = in_array($sendMethod, ['email', 'both']) + || ($sendMethod === 'alimtalk' && !$signer->phone) + || ($sendMethod === 'alimtalk' && $alimtalkFailed); + + if ($shouldSendEmail && $signer->email) { + try { + Mail::to($signer->email)->send(new EsignRequestMail($contract, $signer, $isReminder)); + $results[] = ['success' => true, 'channel' => 'email', 'error' => null]; + } catch (\Throwable $e) { + \Log::warning('E-Sign 이메일 발송 실패', [ + 'contract_id' => $contract->id, + 'signer_id' => $signer->id, + 'error' => $e->getMessage(), + ]); + $results[] = ['success' => false, 'channel' => 'email', 'error' => $e->getMessage()]; } } @@ -949,6 +957,10 @@ private function sendAlimtalk( return ['success' => false, 'channel' => 'alimtalk', 'error' => '바로빌 회원 미등록']; } + if (!$member->corp_num) { + return ['success' => false, 'channel' => 'alimtalk', 'error' => '사업자번호 미설정 (알림톡 발송 불가)']; + } + $barobill = app(BarobillService::class); $barobill->setServerMode($member->is_test_mode ? 'test' : 'production'); diff --git a/resources/views/esign/send.blade.php b/resources/views/esign/send.blade.php index 5269a2a7..5e258ffb 100644 --- a/resources/views/esign/send.blade.php +++ b/resources/views/esign/send.blade.php @@ -23,16 +23,16 @@ }); const SEND_METHODS = [ - { value: 'alimtalk', label: '카카오톡 알림톡', desc: '수신자 휴대폰으로 알림톡 발송 (카카오톡 미사용 시 SMS 자동 대체)', icon: '💬', recommended: true }, - { value: 'email', label: '이메일', desc: '수신자 이메일로 발송', icon: '✉' }, - { value: 'both', label: '알림톡 + 이메일 (동시)', desc: '두 채널 모두 발송하여 확인율 극대화', icon: '📡' }, + { value: 'email', label: '이메일', desc: '수신자 이메일로 서명 요청 링크 발송', icon: '✉', recommended: true }, + { value: 'alimtalk', label: '카카오톡 알림톡', desc: '수신자 휴대폰으로 알림톡 발송 (카카오 채널 개설 후 사용 가능)', icon: '💬', disabled: true }, + { value: 'both', label: '알림톡 + 이메일 (동시)', desc: '두 채널 모두 발송하여 확인율 극대화 (카카오 채널 개설 후 사용 가능)', icon: '📡', disabled: true }, ]; const App = () => { const [contract, setContract] = useState(null); const [loading, setLoading] = useState(true); const [sending, setSending] = useState(false); - const [sendMethod, setSendMethod] = useState('alimtalk'); + const [sendMethod, setSendMethod] = useState('email'); const [smsFallback, setSmsFallback] = useState(true); const fetchContract = useCallback(async () => { @@ -113,15 +113,17 @@
{SEND_METHODS.map(m => (