feat: [esign] 알림톡 템플릿 선택 기능 추가

- 바로빌 승인된 알림톡 템플릿 목록 조회 API 추가
- 서명 요청 발송 시 템플릿 선택 드롭다운 UI 추가
- 템플릿 미리보기 (본문 + 버튼) 표시
- send()에 template_name 파라미터 전달 지원
- 미선택 시 기존 하드코딩 폴백 유지
This commit is contained in:
김보곤
2026-02-25 22:42:29 +09:00
parent 8c24b0ae24
commit e9325ff74d
3 changed files with 192 additions and 5 deletions

View File

@@ -819,6 +819,7 @@ public function send(Request $request, int $id): JsonResponse
$sendMethod = $request->input('send_method', 'email');
$smsFallback = $request->boolean('sms_fallback', true);
$templateName = $request->input('template_name');
$contract->update([
'status' => 'pending',
@@ -838,7 +839,7 @@ public function send(Request $request, int $id): JsonResponse
$notificationResults = [];
foreach ($targetSigners as $signer) {
$signer->update(['status' => 'notified']);
$results = $this->dispatchNotification($contract, $signer, $sendMethod, $smsFallback);
$results = $this->dispatchNotification($contract, $signer, $sendMethod, $smsFallback, templateName: $templateName);
$notificationResults[] = [
'signer_id' => $signer->id,
'signer_name' => $signer->name,
@@ -966,13 +967,14 @@ private function dispatchNotification(
string $sendMethod,
bool $smsFallback,
bool $isReminder = false,
?string $templateName = null,
): array {
$results = [];
$alimtalkFailed = false;
// 알림톡 발송
if (in_array($sendMethod, ['alimtalk', 'both']) && $signer->phone) {
$alimtalkResult = $this->sendAlimtalk($contract, $signer, $smsFallback, $isReminder);
$alimtalkResult = $this->sendAlimtalk($contract, $signer, $smsFallback, $isReminder, $templateName);
$results[] = $alimtalkResult;
$alimtalkFailed = ! ($alimtalkResult['success'] ?? false);
}
@@ -1010,6 +1012,7 @@ private function sendAlimtalk(
EsignSigner $signer,
bool $smsFallback = true,
bool $isReminder = false,
?string $templateName = null,
): array {
try {
$member = BarobillMember::where('tenant_id', $contract->tenant_id)->first();
@@ -1033,7 +1036,9 @@ private function sendAlimtalk(
$signUrl = config('app.url').'/esign/sign/'.$signer->access_token;
$expires = $contract->expires_at?->format('Y-m-d H:i') ?? '없음';
$templateName = $isReminder ? '전자계약_리마인드' : '전자계약_서명요청';
if (! $templateName) {
$templateName = $isReminder ? '전자계약_리마인드' : '전자계약_서명요청';
}
// 등록된 템플릿 본문 + 버튼 정보 조회 (정확한 포맷 유지)
$tplData = $this->getTemplateData($barobill, $member->biz_no, $channelId, $templateName);
@@ -1228,6 +1233,99 @@ private function getTemplateData(BarobillService $barobill, string $bizNo, strin
return $empty;
}
/**
* 바로빌 등록 알림톡 템플릿 목록 조회 (승인 완료된 것만)
*/
public function getAlimtalkTemplates(): JsonResponse
{
try {
$tenantId = session('selected_tenant_id', 1);
$member = BarobillMember::where('tenant_id', $tenantId)->first();
if (! $member || ! $member->biz_no) {
return response()->json([
'success' => false,
'message' => '바로빌 회원 정보 또는 사업자번호가 설정되지 않았습니다.',
]);
}
$barobill = app(BarobillService::class);
$barobill->setServerMode($member->server_mode ?? 'production');
$channelId = $this->getKakaotalkChannelId($barobill, $member->biz_no);
if (! $channelId) {
return response()->json([
'success' => false,
'message' => '등록된 카카오톡 채널이 없습니다.',
]);
}
$result = $barobill->getKakaotalkTemplates($member->biz_no, $channelId);
if (! ($result['success'] ?? false) || empty($result['data'])) {
return response()->json([
'success' => false,
'message' => '템플릿 목록을 조회할 수 없습니다.',
]);
}
$data = $result['data'];
$items = [];
if (is_object($data) && isset($data->KakaotalkTemplate)) {
$items = is_array($data->KakaotalkTemplate)
? $data->KakaotalkTemplate
: [$data->KakaotalkTemplate];
}
// 승인(Status=3)된 템플릿만 필터링
$templates = [];
foreach ($items as $tpl) {
$status = $tpl->Status ?? null;
if ($status != 3) {
continue;
}
$buttons = [];
$btnData = $tpl->Buttons ?? null;
if ($btnData) {
$btnList = $btnData->KakaotalkButton ?? null;
if ($btnList) {
$btnList = is_array($btnList) ? $btnList : [$btnList];
foreach ($btnList as $btn) {
$buttons[] = [
'Name' => $btn->Name ?? '',
'ButtonType' => $btn->ButtonType ?? 'WL',
'Url1' => $btn->Url1 ?? '',
'Url2' => $btn->Url2 ?? '',
];
}
}
}
$templates[] = [
'name' => $tpl->TemplateName ?? '',
'content' => $tpl->TemplateContent ?? '',
'status' => $status,
'buttons' => $buttons,
];
}
return response()->json([
'success' => true,
'data' => [
'channel_id' => $channelId,
'templates' => $templates,
],
]);
} catch (\Throwable $e) {
\Log::error('알림톡 템플릿 목록 조회 실패', ['error' => $e->getMessage()]);
return response()->json([
'success' => false,
'message' => '템플릿 목록 조회 중 오류: '.$e->getMessage(),
]);
}
}
/**
* PDF 다운로드
*/