From af542c0f41988bdfe2e1596797ad2b50d1a978fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Thu, 26 Feb 2026 11:21:42 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20[esign]=20=EB=A1=9C=EC=BB=AC=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EB=B0=A9=EC=8B=9D=20=EB=B2=95=EC=9D=B8=EB=8F=84?= =?UTF-8?q?=EC=9E=A5=EC=9D=B4=20=EC=84=9C=EB=AA=85=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=EC=84=9C=20=EB=AF=B8=ED=91=9C=EC=8B=9C?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - store(): GCS뿐 아니라 local_path 도장도 signer에 자동 적용 - getContract(): signer에 도장 없어도 tenant_settings에서 확인하여 has_stamp 반환 - submitSignature(): 기존 계약 creator도 tenant_settings에서 도장 가져와 적용 --- .../Controllers/ESign/EsignApiController.php | 27 +++++--- .../ESign/EsignPublicController.php | 64 ++++++++++++++++++- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/ESign/EsignApiController.php b/app/Http/Controllers/ESign/EsignApiController.php index e0fe43df..45f20a7d 100644 --- a/app/Http/Controllers/ESign/EsignApiController.php +++ b/app/Http/Controllers/ESign/EsignApiController.php @@ -467,29 +467,36 @@ public function store(Request $request): JsonResponse ]); } - // 법인도장 자동 적용: GCS에서 다운로드 → 로컬 저장 → signer에 설정 + // 법인도장 자동 적용: 설정에서 도장 이미지를 읽어 signer에 복사 $stampSetting = TenantSetting::where('tenant_id', $tenantId) ->where('setting_group', 'esign') ->where('setting_key', 'company_stamp') ->first(); - if ($stampSetting && ! empty($stampSetting->setting_value['gcs_object'])) { + if ($stampSetting) { $creatorSigner = EsignSigner::withoutGlobalScopes() ->where('contract_id', $contract->id) ->where('role', 'creator') ->first(); if ($creatorSigner) { - $gcs = app(GoogleCloudStorageService::class); - $signedUrl = $gcs->getSignedUrl($stampSetting->setting_value['gcs_object'], 5); + $val = $stampSetting->setting_value; + $imageData = null; - if ($signedUrl) { - $imageData = @file_get_contents($signedUrl); - if ($imageData) { - $localPath = "esign/{$tenantId}/signatures/{$contract->id}_{$creatorSigner->id}_stamp.png"; - Storage::disk('local')->put($localPath, $imageData); - $creatorSigner->update(['signature_image_path' => $localPath]); + if (! empty($val['gcs_object'])) { + $gcs = app(GoogleCloudStorageService::class); + $signedUrl = $gcs->getSignedUrl($val['gcs_object'], 5); + if ($signedUrl) { + $imageData = @file_get_contents($signedUrl); } + } elseif (! empty($val['local_path']) && Storage::disk('local')->exists($val['local_path'])) { + $imageData = Storage::disk('local')->get($val['local_path']); + } + + if ($imageData) { + $localPath = "esign/{$tenantId}/signatures/{$contract->id}_{$creatorSigner->id}_stamp.png"; + Storage::disk('local')->put($localPath, $imageData); + $creatorSigner->update(['signature_image_path' => $localPath]); } } } diff --git a/app/Http/Controllers/ESign/EsignPublicController.php b/app/Http/Controllers/ESign/EsignPublicController.php index f5b803ba..877f8ac8 100644 --- a/app/Http/Controllers/ESign/EsignPublicController.php +++ b/app/Http/Controllers/ESign/EsignPublicController.php @@ -9,6 +9,7 @@ use App\Models\ESign\EsignAuditLog; use App\Models\ESign\EsignContract; use App\Models\ESign\EsignSigner; +use App\Models\Tenants\TenantSetting; use App\Services\Barobill\BarobillService; use App\Services\ESign\PdfSignatureService; use Illuminate\Http\JsonResponse; @@ -130,7 +131,7 @@ public function getContract(string $token): JsonResponse 'phone' => $signer->phone, 'role' => $signer->role, 'status' => $signer->status, - 'has_stamp' => (bool) $signer->signature_image_path, + 'has_stamp' => (bool) $signer->signature_image_path || ($signer->role === 'creator' && $this->hasCompanyStamp($contract->tenant_id)), 'signed_at' => $signer->signed_at, ], 'send_method' => $contract->tenant_id == 1 ? 'email' : ($contract->send_method ?? 'email'), @@ -295,7 +296,15 @@ public function submitSignature(Request $request, string $token): JsonResponse Storage::disk('local')->put($imagePath, $imageData); $signer->update(['signature_image_path' => $imagePath]); } elseif (! $signer->signature_image_path) { - return response()->json(['success' => false, 'message' => '등록된 도장 이미지가 없습니다.'], 422); + // 기존 계약: tenant_settings에서 법인도장 가져오기 + if ($signer->role === 'creator') { + $stampPath = $this->applyCompanyStamp($signer, $contract->tenant_id); + if (! $stampPath) { + return response()->json(['success' => false, 'message' => '등록된 도장 이미지가 없습니다.'], 422); + } + } else { + return response()->json(['success' => false, 'message' => '등록된 도장 이미지가 없습니다.'], 422); + } } } else { // 직접 서명: signature_image 필수 @@ -748,4 +757,55 @@ private function findSigner(string $token): ?EsignSigner return $signer; } + + private function hasCompanyStamp(int $tenantId): bool + { + $stamp = TenantSetting::where('tenant_id', $tenantId) + ->where('setting_group', 'esign') + ->where('setting_key', 'company_stamp') + ->first(); + + if (! $stamp) { + return false; + } + + $val = $stamp->setting_value; + + return ! empty($val['gcs_object']) || ! empty($val['local_path']); + } + + private function applyCompanyStamp(EsignSigner $signer, int $tenantId): ?string + { + $stamp = TenantSetting::where('tenant_id', $tenantId) + ->where('setting_group', 'esign') + ->where('setting_key', 'company_stamp') + ->first(); + + if (! $stamp) { + return null; + } + + $val = $stamp->setting_value; + $imageData = null; + + if (! empty($val['gcs_object'])) { + $gcs = app(\App\Services\GoogleCloudStorageService::class); + $signedUrl = $gcs->getSignedUrl($val['gcs_object'], 5); + if ($signedUrl) { + $imageData = @file_get_contents($signedUrl); + } + } elseif (! empty($val['local_path']) && Storage::disk('local')->exists($val['local_path'])) { + $imageData = Storage::disk('local')->get($val['local_path']); + } + + if (! $imageData) { + return null; + } + + $localPath = "esign/{$tenantId}/signatures/{$signer->contract_id}_{$signer->id}_stamp.png"; + Storage::disk('local')->put($localPath, $imageData); + $signer->update(['signature_image_path' => $localPath]); + + return $localPath; + } }