diff --git a/plans/esign-alimtalk-integration.md b/plans/esign-alimtalk-integration.md new file mode 100644 index 0000000..c37a6bb --- /dev/null +++ b/plans/esign-alimtalk-integration.md @@ -0,0 +1,363 @@ +# 전자계약(E-Sign) 알림톡 연동 계획서 + +> **문서 버전**: 1.0 +> **작성일**: 2026-02-14 +> **상태**: 계획 (카카오 채널 개설 후 착수) +> **전제 조건**: 바로빌 카카오톡 서비스 연동 완료 + +--- + +## 1. 현재 상태 (AS-IS) + +### 1.1 발송 흐름 + +``` +계약 생성 → 필드 설정 → [서명 요청 발송] → 이메일만 발송 + │ + └─ EsignApiController::send() + └─ Mail::to($signer->email)->send(new EsignRequestMail(...)) +``` + +### 1.2 관련 파일 + +| 구분 | 파일 | 역할 | +|------|------|------| +| 발송 화면 | `views/esign/send.blade.php` (129줄) | React 기반 발송 확인 UI | +| 발송 로직 | `EsignApiController::send()` (686~728줄) | 이메일 발송 실행 | +| 리마인드 | `EsignApiController::remind()` (734줄~) | 미서명자 재발송 | +| Mail 클래스 | `Mail/EsignRequestMail.php` (47줄) | 이메일 템플릿 | +| 이메일 뷰 | `views/emails/esign/request.blade.php` (79줄) | 이메일 HTML | +| 완료 Mail | `Mail/EsignCompletedMail.php` (46줄) | 완료 알림 이메일 | +| OTP Mail | `Mail/EsignOtpMail.php` (37줄) | OTP 인증 이메일 | +| 모델 | `Models/ESign/EsignSigner.php` | `email`, `phone` 필드 보유 | + +### 1.3 문제점 + +- 이메일 열람률 낮음 (20~30%), 스팸함 유입 가능 +- 서명 요청 확인까지 수시간~1일 소요 +- 모바일에서 이메일 확인 → 링크 클릭 동선이 불편 + +--- + +## 2. 목표 상태 (TO-BE) + +### 2.1 발송 흐름 + +``` +계약 생성 → 필드 설정 → [서명 요청 발송] + │ + ├─ 발송 방식 선택 (기본: 알림톡) + │ ├─ 알림톡 (기본값) + │ ├─ 이메일 + │ └─ 알림톡 + 이메일 (동시) + │ + └─ EsignApiController::send() + ├─ [알림톡] BarobillService::sendATKakaotalkEx() + │ └─ SMS 대체발송 (카톡 미사용자) + └─ [이메일] Mail::to()->send(new EsignRequestMail()) +``` + +### 2.2 핵심 변경 원칙 + +- **기본값은 알림톡** — 별도 선택 없이 발송하면 알림톡으로 전송 +- **이메일도 유지** — 알림톡 불가 시(채널 미연동 등) 이메일 폴백 +- **동시 발송 가능** — 중요 계약은 알림톡 + 이메일 동시 발송 옵션 +- **기존 코드 최소 변경** — 발송 로직만 분기, 나머지 흐름 동일 + +--- + +## 3. UI/UX 변경 + +### 3.1 발송 화면 (`send.blade.php`) 변경 + +**현재**: 서명자 확인 → [서명 요청 발송] 버튼만 존재 + +**변경 후**: + +``` +┌──────────────────────────────────────────┐ +│ 서명 요청 발송 │ +├──────────────────────────────────────────┤ +│ │ +│ [발송 전 확인] │ +│ ✓ 계약 제목: OO 공급계약서 │ +│ ✓ PDF 파일: contract_2026.pdf │ +│ ✓ 서명 필드: 4개 설정됨 │ +│ │ +│ [서명 순서] │ +│ ① 홍길동 (작성자) - hong@company.com │ +│ ② 김철수 (상대방) - kim@partner.com │ +│ │ +│ ┌─────────────────────────────────────┐ │ +│ │ 발송 방식 │ │ +│ │ │ │ +│ │ ● 카카오톡 알림톡 (권장) │ │ +│ │ 수신자 휴대폰으로 알림톡 발송 │ │ +│ │ 카카오톡 미사용 시 SMS 자동 대체 │ │ +│ │ │ │ +│ │ ○ 이메일 │ │ +│ │ 수신자 이메일로 발송 │ │ +│ │ │ │ +│ │ ○ 알림톡 + 이메일 (동시) │ │ +│ │ 두 채널 모두 발송 │ │ +│ │ │ │ +│ │ ☐ SMS 대체발송 사용 │ │ +│ │ (알림톡 선택 시 자동 체크) │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ [서명자별 연락처 확인] │ +│ ┌─────────────────────────────────────┐ │ +│ │ ① 홍길동 │ │ +│ │ 📱 010-1234-5678 ✓ │ │ +│ │ ✉ hong@company.com ✓ │ │ +│ │ │ │ +│ │ ② 김철수 │ │ +│ │ 📱 미입력 ⚠ (알림톡 발송 불가) │ │ +│ │ ✉ kim@partner.com ✓ │ │ +│ └─────────────────────────────────────┘ │ +│ │ +│ [돌아가기] [서명 요청 발송] │ +└──────────────────────────────────────────┘ +``` + +### 3.2 UI 동작 규칙 + +| 상황 | 기본 선택 | 동작 | +|------|----------|------| +| 모든 서명자에 휴대폰 번호 있음 | 알림톡 (기본) | 정상 발송 | +| 일부 서명자에 번호 없음 | 알림톡 선택 시 경고 표시 | "번호 미입력 서명자는 이메일로 발송됩니다" | +| 바로빌 카카오 미연동 | 이메일 (자동 전환) | 알림톡 옵션 비활성화 + 안내 문구 | +| 알림톡 + 이메일 선택 | 동시 발송 | 두 채널 모두 전송 | + +### 3.3 서명자 연락처 유효성 표시 + +| 아이콘 | 의미 | +|--------|------| +| ✓ (녹색) | 해당 채널로 발송 가능 | +| ⚠ (주황) | 정보 누락 — 다른 채널로 대체 가능 | +| ✗ (빨강) | 발송 불가 — 정보 입력 필요 | + +--- + +## 4. 백엔드 변경 + +### 4.1 EsignApiController::send() 수정 + +**현재** (이메일만): +```php +Mail::to($signer->email)->send(new EsignRequestMail($contract, $signer)); +``` + +**변경 후** (발송 방식 분기): +```php +// 요청에서 발송 방식 수신 +$sendMethod = $request->input('send_method', 'alimtalk'); // alimtalk | email | both + +foreach ($targetSigners as $signer) { + $signer->update(['status' => 'notified']); + + if (in_array($sendMethod, ['alimtalk', 'both']) && $signer->phone) { + // 알림톡 발송 + $this->sendAlimtalk($contract, $signer, $request->boolean('sms_fallback', true)); + } + + if (in_array($sendMethod, ['email', 'both']) || !$signer->phone) { + // 이메일 발송 (또는 번호 없으면 이메일 폴백) + Mail::to($signer->email)->send(new EsignRequestMail($contract, $signer)); + } +} +``` + +### 4.2 알림톡 발송 메서드 추가 + +```php +private function sendAlimtalk(EsignContract $contract, EsignSigner $signer, bool $smsFallback = true): void +{ + $signUrl = config('app.url') . '/esign/sign/' . $signer->access_token; + + $barobill = app(BarobillService::class); + $member = BarobillMember::where('tenant_id', $contract->tenant_id)->first(); + + if (!$member) return; // 바로빌 미연동 시 스킵 + + $barobill->setServerMode($member->is_test_mode ? 'test' : 'production'); + + $barobill->sendATKakaotalkEx( + corpNum: $member->corp_num, + certKey: $member->cert_key, + senderId: $member->kakaotalk_sender_id, // 발신 프로필 ID + templateName: '전자계약_서명요청', // 등록된 템플릿명 + receiverName: $signer->name, + receiverNum: $signer->phone, + title: '전자계약 서명 요청', + message: $this->buildAlimtalkMessage($contract, $signer), + buttons: [ + [ + 'Name' => '계약서 확인하기', + 'ButtonType' => 'WL', + 'Url1' => $signUrl, // 모바일 + 'Url2' => $signUrl, // PC + ], + ], + smsMessage: $smsFallback + ? "[SAM] {$signer->name}님, 전자계약 서명 요청이 도착했습니다. {$signUrl}" + : '', + ); +} +``` + +### 4.3 알림톡 메시지 템플릿 + +```php +private function buildAlimtalkMessage(EsignContract $contract, EsignSigner $signer): string +{ + $expires = $contract->expires_at?->format('Y-m-d H:i') ?? '없음'; + + return "안녕하세요, {$signer->name}님.\n" + . "전자계약 서명 요청이 도착했습니다.\n\n" + . "■ 계약명: {$contract->title}\n" + . "■ 서명 기한: {$expires}\n\n" + . "아래 버튼을 눌러 계약서를 확인하고 서명해 주세요."; +} +``` + +### 4.4 리마인드 발송도 동일 적용 + +`EsignApiController::remind()` 에도 동일한 발송 방식 분기 적용. + +### 4.5 계약 완료 알림도 알림톡 추가 + +`EsignPublicController::submitSignature()` → 모든 서명 완료 시 `EsignCompletedMail` 발송 부분에 알림톡 추가. + +--- + +## 5. 알림톡 템플릿 (카카오 검수용) + +카카오에 등록할 템플릿 3종: + +### 5.1 서명 요청 + +``` +템플릿명: 전자계약_서명요청 + +안녕하세요, #{수신자명}님. +전자계약 서명 요청이 도착했습니다. + +■ 계약명: #{계약명} +■ 서명 기한: #{마감일} + +아래 버튼을 눌러 계약서를 확인하고 서명해 주세요. + +[계약서 확인하기] (웹링크 버튼) +``` + +### 5.2 리마인드 + +``` +템플릿명: 전자계약_리마인드 + +안녕하세요, #{수신자명}님. +아직 서명이 완료되지 않은 전자계약이 있습니다. + +■ 계약명: #{계약명} +■ 서명 기한: #{마감일} + +기한 내에 서명을 완료해 주세요. + +[서명하기] (웹링크 버튼) +``` + +### 5.3 계약 완료 + +``` +템플릿명: 전자계약_완료 + +안녕하세요, #{수신자명}님. +전자계약이 모든 서명자의 서명 완료로 확정되었습니다. + +■ 계약명: #{계약명} +■ 완료일: #{완료일} + +아래 버튼에서 서명 완료된 계약서를 확인할 수 있습니다. + +[계약서 확인하기] (웹링크 버튼) +``` + +--- + +## 6. DB 변경 + +### 6.1 esign_contracts 테이블 (컬럼 추가) + +| 컬럼 | 타입 | 기본값 | 설명 | +|------|------|--------|------| +| `send_method` | `enum('alimtalk','email','both')` | `'alimtalk'` | 발송 방식 | +| `sms_fallback` | `boolean` | `true` | SMS 대체발송 사용 여부 | + +> 마이그레이션은 API 프로젝트에서 생성 + +### 6.2 esign_signers 테이블 (기존 컬럼 활용) + +- `phone` — 이미 존재. 알림톡 발송에 사용 +- `email` — 이미 존재. 이메일 발송에 사용 + +> 추가 컬럼 불필요. `phone`이 nullable이므로, 없으면 이메일 폴백. + +--- + +## 7. 구현 순서 + +| 단계 | 작업 | 파일 | 우선순위 | +|------|------|------|---------| +| **0** | **카카오 채널 개설 + 바로빌 연동 + 템플릿 검수** | (비개발) | 선행 필수 | +| 1 | API 마이그레이션 — `send_method`, `sms_fallback` 컬럼 추가 | `api/database/migrations/` | 높음 | +| 2 | `EsignApiController::send()` 발송 방식 분기 로직 | `EsignApiController.php` | 높음 | +| 3 | `sendAlimtalk()` 메서드 + 메시지 빌더 추가 | `EsignApiController.php` | 높음 | +| 4 | `send.blade.php` 발송 방식 선택 UI 추가 | `send.blade.php` | 높음 | +| 5 | 서명자 연락처 유효성 표시 UI | `send.blade.php` | 중간 | +| 6 | `remind()` 알림톡 분기 추가 | `EsignApiController.php` | 중간 | +| 7 | 계약 완료 알림톡 추가 | `EsignPublicController.php` | 중간 | +| 8 | 바로빌 카카오 미연동 시 알림톡 옵션 비활성화 처리 | `send.blade.php` + 컨트롤러 | 중간 | +| 9 | 테스트 발송 검증 | - | 높음 | +| 10 | 운영 전환 (`testws` → `ws`) | `config/services.php` | 최종 | + +--- + +## 8. 영향 범위 + +### 8.1 변경 파일 (예상) + +| 프로젝트 | 파일 | 변경 내용 | +|---------|------|----------| +| **API** | `database/migrations/xxx_add_send_method_to_esign_contracts.php` | 컬럼 추가 | +| **MNG** | `app/Http/Controllers/ESign/EsignApiController.php` | 발송 분기 로직 | +| **MNG** | `app/Http/Controllers/ESign/EsignPublicController.php` | 완료 알림톡 | +| **MNG** | `resources/views/esign/send.blade.php` | 발송 방식 선택 UI | +| **MNG** | `resources/views/esign/detail.blade.php` | 발송 방식 표시 (선택사항) | + +### 8.2 변경하지 않는 파일 + +- `EsignController.php` — 페이지 라우팅만 담당, 변경 불필요 +- `EsignRequestMail.php` — 이메일 발송은 그대로 유지 +- `views/emails/esign/*` — 이메일 템플릿 유지 +- `views/esign/sign/*` — 서명 화면은 발송 방식과 무관 +- `Models/ESign/*` — `send_method` 컬럼만 fillable 추가 + +--- + +## 9. 리스크 및 대응 + +| 리스크 | 영향 | 대응 | +|--------|------|------| +| 카카오 템플릿 검수 반려 | 알림톡 발송 불가 | 템플릿 문구 수정 후 재신청 (반복 가능) | +| 서명자 휴대폰 번호 미입력 | 알림톡 발송 실패 | 이메일 자동 폴백 | +| 바로빌 API 장애 | 알림톡 발송 실패 | try-catch → 이메일 폴백 + 에러 로그 | +| SMS 대체발송 비용 | 예상 외 비용 발생 | SMS 대체발송 on/off 옵션 제공 | + +--- + +## 변경 이력 + +| 날짜 | 버전 | 변경 내용 | +|------|------|----------| +| 2026-02-14 | 1.0 | 계획서 초안 작성 |