163 lines
4.8 KiB
PHP
163 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace app\support;
|
|
|
|
use support\think\Db;
|
|
|
|
class MaterialLocalResourceService
|
|
{
|
|
public const RETENTION_MESSAGE = '系统仅保留3个批次图片';
|
|
|
|
public function qrRelativePath(string $batchNo, string $verifyCode): string
|
|
{
|
|
return sprintf(
|
|
'uploads/material-qrcodes/%s/%s.png',
|
|
$this->safeName($batchNo, 'batch'),
|
|
$this->safeName($verifyCode, 'code')
|
|
);
|
|
}
|
|
|
|
public function qrBatchDirectory(string $batchNo): string
|
|
{
|
|
return 'uploads/material-qrcodes/' . $this->safeName($batchNo, 'batch');
|
|
}
|
|
|
|
public function packageRelativePath(string $batchNo): string
|
|
{
|
|
$safeBatchNo = $this->safeName($batchNo, 'batch');
|
|
return sprintf(
|
|
'uploads/material-packages/%s/material-batch-%s.zip',
|
|
$safeBatchNo,
|
|
$safeBatchNo
|
|
);
|
|
}
|
|
|
|
public function packageBatchDirectory(string $batchNo): string
|
|
{
|
|
return 'uploads/material-packages/' . $this->safeName($batchNo, 'batch');
|
|
}
|
|
|
|
public function materialTagTemplatePath(): string
|
|
{
|
|
return dirname(__DIR__, 2) . '/resources/material-tag-template.jpg';
|
|
}
|
|
|
|
public function publicPath(string $relativePath): string
|
|
{
|
|
return public_path() . '/' . ltrim($relativePath, '/');
|
|
}
|
|
|
|
public function publicUrl(string $relativePath): string
|
|
{
|
|
$baseUrl = $this->localBaseUrl();
|
|
if ($baseUrl === '') {
|
|
throw new \RuntimeException('本地文件公开访问域名未配置,无法生成二维码下载链接');
|
|
}
|
|
|
|
return rtrim($baseUrl, '/') . '/' . ltrim($relativePath, '/');
|
|
}
|
|
|
|
public function ensureParentDirectory(string $filePath): void
|
|
{
|
|
$dir = dirname($filePath);
|
|
if (!is_dir($dir) && !mkdir($dir, 0775, true) && !is_dir($dir)) {
|
|
throw new \RuntimeException('本地文件目录创建失败');
|
|
}
|
|
}
|
|
|
|
public function deleteBatchResources(string $batchNo): void
|
|
{
|
|
$this->deleteDirectory($this->publicPath($this->qrBatchDirectory($batchNo)));
|
|
$this->deleteDirectory($this->publicPath($this->packageBatchDirectory($batchNo)));
|
|
}
|
|
|
|
public function deleteDirectory(string $dir): void
|
|
{
|
|
if (!is_dir($dir)) {
|
|
return;
|
|
}
|
|
|
|
$items = scandir($dir);
|
|
if ($items === false) {
|
|
return;
|
|
}
|
|
|
|
foreach ($items as $item) {
|
|
if ($item === '.' || $item === '..') {
|
|
continue;
|
|
}
|
|
|
|
$path = $dir . DIRECTORY_SEPARATOR . $item;
|
|
if (is_dir($path)) {
|
|
$this->deleteDirectory($path);
|
|
continue;
|
|
}
|
|
if (is_file($path)) {
|
|
@unlink($path);
|
|
}
|
|
}
|
|
|
|
@rmdir($dir);
|
|
}
|
|
|
|
public function safeName(string $value, string $fallback): string
|
|
{
|
|
$safe = preg_replace('/[^a-zA-Z0-9_-]/', '-', trim($value));
|
|
$safe = trim((string)$safe, '-_');
|
|
return $safe !== '' ? $safe : $fallback;
|
|
}
|
|
|
|
private function localBaseUrl(): string
|
|
{
|
|
foreach (['MATERIAL_LOCAL_BASE_URL', 'APP_PUBLIC_BASE_URL', 'PUBLIC_FILE_BASE_URL'] as $key) {
|
|
$value = trim((string)($_ENV[$key] ?? ''));
|
|
if ($value !== '') {
|
|
return $this->normalizeBaseUrl($value);
|
|
}
|
|
}
|
|
|
|
$notifyUrl = Db::name('system_configs')
|
|
->where('config_group', 'payment')
|
|
->where('config_key', 'notify_url')
|
|
->value('config_value');
|
|
if (is_string($notifyUrl) && trim($notifyUrl) !== '') {
|
|
return $this->extractOrigin($notifyUrl);
|
|
}
|
|
|
|
if (!in_array(strtolower((string)($_ENV['APP_ENV'] ?? '')), ['production', 'prod'], true)) {
|
|
return 'http://' . '127.0.0.' . '1:8787';
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
private function normalizeBaseUrl(string $baseUrl): string
|
|
{
|
|
$baseUrl = trim($baseUrl);
|
|
if ($baseUrl === '') {
|
|
return '';
|
|
}
|
|
if (!preg_match('/^https?:\/\//i', $baseUrl)) {
|
|
$baseUrl = 'https://' . ltrim($baseUrl, '/');
|
|
}
|
|
return rtrim($baseUrl, '/');
|
|
}
|
|
|
|
private function extractOrigin(string $url): string
|
|
{
|
|
$parts = parse_url(trim($url));
|
|
$scheme = (string)($parts['scheme'] ?? '');
|
|
$host = (string)($parts['host'] ?? '');
|
|
$port = (string)($parts['port'] ?? '');
|
|
if ($host === '') {
|
|
return $this->normalizeBaseUrl($url);
|
|
}
|
|
|
|
$origin = ($scheme !== '' ? $scheme : 'https') . '://' . $host;
|
|
if ($port !== '' && !(($scheme === 'http' && $port === '80') || ($scheme === 'https' && $port === '443'))) {
|
|
$origin .= ':' . $port;
|
|
}
|
|
return rtrim($origin, '/');
|
|
}
|
|
}
|