feat:E-Sign 서명 요청/리마인더 메일 발송 구현
- EsignRequestMail Mailable 클래스 추가 (리마인더 구분 지원) - 이메일 HTML 템플릿 추가 (서명하기 버튼 + 계약 정보) - send()에서 첫 번째 서명자에게 메일 발송 - remind()에서 다음 서명 대상자에게 리마인더 메일 발송 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,12 +3,14 @@
|
||||
namespace App\Http\Controllers\ESign;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Mail\EsignRequestMail;
|
||||
use App\Models\ESign\EsignContract;
|
||||
use App\Models\ESign\EsignSigner;
|
||||
use App\Models\ESign\EsignSignField;
|
||||
use App\Models\ESign\EsignAuditLog;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class EsignApiController extends Controller
|
||||
@@ -256,10 +258,11 @@ public function send(Request $request, int $id): JsonResponse
|
||||
'updated_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
// 첫 번째 서명자 상태 변경
|
||||
// 첫 번째 서명자 상태 변경 + 메일 발송
|
||||
$nextSigner = $contract->signers()->orderBy('sign_order')->first();
|
||||
if ($nextSigner) {
|
||||
$nextSigner->update(['status' => 'notified']);
|
||||
Mail::to($nextSigner->email)->send(new EsignRequestMail($contract, $nextSigner));
|
||||
}
|
||||
|
||||
EsignAuditLog::create([
|
||||
@@ -295,6 +298,7 @@ public function remind(Request $request, int $id): JsonResponse
|
||||
|
||||
if ($nextSigner) {
|
||||
$nextSigner->update(['status' => 'notified']);
|
||||
Mail::to($nextSigner->email)->send(new EsignRequestMail($contract, $nextSigner, isReminder: true));
|
||||
}
|
||||
|
||||
EsignAuditLog::create([
|
||||
|
||||
47
app/Mail/EsignRequestMail.php
Normal file
47
app/Mail/EsignRequestMail.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\ESign\EsignContract;
|
||||
use App\Models\ESign\EsignSigner;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class EsignRequestMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public function __construct(
|
||||
public EsignContract $contract,
|
||||
public EsignSigner $signer,
|
||||
public bool $isReminder = false,
|
||||
) {}
|
||||
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
$prefix = $this->isReminder ? '[리마인더] ' : '';
|
||||
|
||||
return new Envelope(
|
||||
subject: "{$prefix}[SAM] 전자계약 서명 요청 - {$this->contract->title}",
|
||||
);
|
||||
}
|
||||
|
||||
public function content(): Content
|
||||
{
|
||||
$signUrl = config('app.url') . '/esign/sign/' . $this->signer->access_token;
|
||||
|
||||
return new Content(
|
||||
html: 'emails.esign.request',
|
||||
with: [
|
||||
'contractTitle' => $this->contract->title,
|
||||
'signerName' => $this->signer->name,
|
||||
'signUrl' => $signUrl,
|
||||
'expiresAt' => $this->contract->expires_at?->format('Y-m-d H:i'),
|
||||
'isReminder' => $this->isReminder,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
79
resources/views/emails/esign/request.blade.php
Normal file
79
resources/views/emails/esign/request.blade.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>전자계약 서명 요청</title>
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0; background-color: #f5f5f5; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="padding: 40px 20px;">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
|
||||
<!-- Header -->
|
||||
<tr>
|
||||
<td style="background-color: #2563eb; padding: 32px 40px; text-align: center;">
|
||||
<h1 style="margin: 0; color: #ffffff; font-size: 24px; font-weight: 600;">
|
||||
@if($isReminder ?? false)
|
||||
[리마인더] 전자계약 서명 요청
|
||||
@else
|
||||
전자계약 서명 요청
|
||||
@endif
|
||||
</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Body -->
|
||||
<tr>
|
||||
<td style="padding: 40px;">
|
||||
<p style="margin: 0 0 16px; font-size: 16px; color: #333;">안녕하세요, <strong>{{ $signerName }}</strong>님.</p>
|
||||
<p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
|
||||
@if($isReminder ?? false)
|
||||
아래 전자계약에 대한 서명이 아직 완료되지 않았습니다.<br>
|
||||
서명 기한 내에 서명을 완료해 주세요.
|
||||
@else
|
||||
아래 전자계약에 대한 서명이 요청되었습니다.<br>
|
||||
링크를 클릭하여 서명을 진행해 주세요.
|
||||
@endif
|
||||
</p>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f8fafc; border-radius: 6px; margin-bottom: 24px;">
|
||||
<tr>
|
||||
<td style="padding: 20px;">
|
||||
<p style="margin: 0 0 8px; font-size: 13px; color: #888;">계약 제목</p>
|
||||
<p style="margin: 0 0 16px; font-size: 16px; color: #333; font-weight: 600;">{{ $contractTitle }}</p>
|
||||
<p style="margin: 0 0 8px; font-size: 13px; color: #888;">서명 기한</p>
|
||||
<p style="margin: 0; font-size: 15px; color: #ef4444;">{{ $expiresAt }}</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="100%" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td align="center" style="padding: 8px 0;">
|
||||
<a href="{{ $signUrl }}" style="display: inline-block; background-color: #2563eb; color: #ffffff; text-decoration: none; padding: 14px 40px; border-radius: 6px; font-size: 16px; font-weight: 600;">
|
||||
서명하기
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p style="margin: 24px 0 0; font-size: 13px; color: #999; line-height: 1.6;">
|
||||
위 버튼이 동작하지 않으면 아래 링크를 브라우저에 직접 입력해 주세요:<br>
|
||||
<a href="{{ $signUrl }}" style="color: #2563eb; word-break: break-all;">{{ $signUrl }}</a>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td style="background-color: #f8fafc; padding: 24px 40px; text-align: center; border-top: 1px solid #e5e7eb;">
|
||||
<p style="margin: 0; font-size: 12px; color: #999;">
|
||||
본 메일은 SAM 전자계약 시스템에서 자동 발송되었습니다.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user