CaiWuXiTong/app/Support/CourierAgreementCredentials.php

106 lines
5.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Support;
use App\Models\Business\CourierAgreementSignature;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Intervention\Image\ImageManager;
use RuntimeException;
final class CourierAgreementCredentials
{
public const IMAGES = [
'license' => '营业执照', 'id_front' => '身份证人像面', 'id_back' => '身份证国徽面',
'bank_front' => '银行卡正面', 'bank_back' => '银行卡背面',
];
public static function definitions(string $type): array
{
$sheets = [
'identity' => ['name' => '身份证推送单', 'images' => ['id_front', 'id_back']],
'bank' => ['name' => '银行卡推送单', 'images' => ['bank_front', 'bank_back']],
];
return match ($type) {
'authorization' => $sheets,
'entity-change' => ['license' => ['name' => '营业执照盖章推送单', 'images' => ['license']]] + $sheets,
default => [],
};
}
public static function rules(string $type, bool $requested): array
{
$allowed = self::definitions($type);
$required = $requested ? array_merge(...array_column($allowed ?: [['images' => []]], 'images')) : [];
$rules = [
'credential_required' => ['nullable', 'boolean', Rule::prohibitedIf($allowed === [] && $requested)],
'credential_signer' => ['nullable', 'integer', 'in:0,1'],
'credential_images' => ['nullable', 'array:' . implode(',', array_keys(self::IMAGES))],
];
foreach (self::IMAGES as $key => $label) {
$active = in_array($key, $required, true);
$rules['credential_images.' . $key] = [Rule::requiredIf($active), Rule::prohibitedIf(! $active),
'nullable', 'image', 'mimes:jpg,jpeg,png', 'max:10240', 'dimensions:max_width=5000,max_height=5000'];
}
return $rules;
}
public function prepare(CourierAgreementSignature $signature, array $uploads): array
{
$definitions = self::definitions($signature->document_type);
if (! ($signature->payload['credential_required'] ?? false)) {
return [];
}
$disk = Storage::disk('uploads');
$base = "courier-agreements/{$signature->company_id}/{$signature->business_no}/credentials";
$result = [];
foreach ($definitions as $key => $definition) {
$pictures = [];
$originals = [];
foreach ($definition['images'] as $imageKey) {
$upload = $uploads[$imageKey] ?? null;
if (! $upload instanceof UploadedFile || ! $upload->isValid()) {
throw new RuntimeException('证件图片不完整,请重新上传。');
}
$extension = $upload->getMimeType() === 'image/png' ? 'png' : 'jpg';
$originalPath = "{$base}/{$imageKey}.{$extension}";
$original = file_get_contents($upload->getRealPath());
if (! $disk->put($originalPath, $original)) {
throw new RuntimeException('证件原始图片无法写入私有存储。');
}
$image = (new ImageManager(['driver' => 'gd']))->make($upload->getRealPath())->orientate();
$image->resize(2400, 2400, static function ($constraint): void {
$constraint->aspectRatio();
$constraint->upsize();
});
$maxHeight = $key === 'license' ? 470 : 180;
$scale = min(450 / $image->width(), $maxHeight / $image->height());
$pictures[] = ['label' => self::IMAGES[$imageKey],
'uri' => 'data:image/png;base64,' . base64_encode((string) $image->encode('png')),
'width' => round($image->width() * $scale, 2), 'height' => round($image->height() * $scale, 2)];
$originals[$imageKey] = ['path' => $originalPath, 'sha256' => hash('sha256', $original)];
$image->destroy();
}
$pdf = app('dompdf.wrapper');
$pdf->setPaper('a4', 'portrait');
$pdf->loadHTML(view('business.pdf.courier-credential', [
'title' => $definition['name'], 'pictures' => $pictures,
'stampOnly' => $key === 'license', 'signature' => $signature,
'fontPath' => str_replace('\\', '/', resource_path('fonts/DroidSansFallback.ttf')),
])->render(), 'UTF-8');
$bytes = $pdf->output();
if (! str_starts_with($bytes, '%PDF-') || $pdf->getDomPDF()->getCanvas()->get_page_count() !== 1) {
throw new RuntimeException('证件推送单必须为一页 PDF,请检查上传图片。');
}
$sourcePath = "{$base}/{$key}-source.pdf";
if (! $disk->put($sourcePath, $bytes)) {
throw new RuntimeException('证件推送单无法写入私有存储。');
}
$result[$key] = ['name' => $definition['name'], 'source_path' => $sourcePath,
'source_sha256' => hash('sha256', $bytes), 'originals' => $originals];
}
return $result;
}
}