158 lines
4.8 KiB
PHP
158 lines
4.8 KiB
PHP
<?php
|
||
|
||
namespace App\Service;
|
||
|
||
use App\BaseApp\BaseService;
|
||
use App\Models\WxAppModel;
|
||
use App\Service\common\FieldEncryptService;
|
||
|
||
/**
|
||
* 小程序应用配置管理(后台)
|
||
*
|
||
* 密钥列只写不读:列表与详情一律返回掩码,前端留空表示不修改。
|
||
* 这么做的原因是老项目把 AppSecret 明文放源码里、还进了 git 历史。
|
||
*/
|
||
class WxAppConfigService extends BaseService
|
||
{
|
||
/**
|
||
* @var array<int, string> 密文列
|
||
*/
|
||
private const SECRET_FIELDS = ['app_secret', 'mch_key', 'mch_private_key'];
|
||
|
||
public function __construct()
|
||
{
|
||
parent::__construct();
|
||
$this->model = WxAppModel::class;
|
||
$this->selectField = [
|
||
'id', 'code', 'name', 'app_id', 'mch_id', 'mch_serial_no', 'notify_url',
|
||
'template_code', 'status', 'remark', 'created_at', 'updated_at',
|
||
];
|
||
$this->queryField = ['code' => '=', 'name' => 'like', 'status' => '='];
|
||
$this->orderBy = ['name' => 'id', 'sort' => 'asc'];
|
||
}
|
||
|
||
public function list(): array
|
||
{
|
||
$result = $this->getPageList();
|
||
foreach ($result['items'] as &$item) {
|
||
$item = $this->withSecretFlags($item);
|
||
}
|
||
unset($item);
|
||
return $result;
|
||
}
|
||
|
||
public function option(): mixed
|
||
{
|
||
$this->optionField = ['id', 'name', 'code'];
|
||
return $this->getOption();
|
||
}
|
||
|
||
public function detail($id): mixed
|
||
{
|
||
$info = $this->getDetail($id);
|
||
return $this->withSecretFlags(is_array($info) ? $info : $info->toArray());
|
||
}
|
||
|
||
public function create($params): mixed
|
||
{
|
||
return $this->insert($this->encryptSecrets($params));
|
||
}
|
||
|
||
public function update($id, $params): mixed
|
||
{
|
||
return $this->save($id, $this->encryptSecrets($params));
|
||
}
|
||
|
||
public function delete($ids): mixed
|
||
{
|
||
return $this->del($ids);
|
||
}
|
||
|
||
public function status($id, $status): mixed
|
||
{
|
||
return $this->save($id, ['status' => (int) $status]);
|
||
}
|
||
|
||
/**
|
||
* 按 .env 的 WX_DEFAULT_APP_CODE / WX_APP_ID 引导落库一条空密钥记录
|
||
* 方便首次部署:先建壳子,再进后台填 AppSecret(密钥仍不进 .env)
|
||
*/
|
||
public function initFromEnv(): array
|
||
{
|
||
$code = trim((string) config('nl.wx.default_app_code', ''));
|
||
$appId = trim((string) config('nl.wx.env_app_id', ''));
|
||
$name = trim((string) config('nl.wx.env_app_name', ''));
|
||
if ($code === '' || $appId === '') {
|
||
$this->utils->errorThrow('请先在 .env 配置 WX_DEFAULT_APP_CODE 与 WX_APP_ID,再点初始化');
|
||
}
|
||
$row = WxAppModel::where('code', $code)->where('deleted_at', 0)->first();
|
||
if (!empty($row)) {
|
||
$row->update([
|
||
'app_id' => $appId,
|
||
'name' => $name !== '' ? $name : $row->name,
|
||
'updated_at' => time(),
|
||
]);
|
||
return [
|
||
'created' => false,
|
||
'id' => (int) $row->id,
|
||
'code' => $code,
|
||
'app_id' => $appId,
|
||
'app_secret_set' => trim((string) ($row->app_secret ?? '')) !== '',
|
||
'message' => '已更新 AppID/名称,请编辑该行填写 AppSecret',
|
||
];
|
||
}
|
||
$id = WxAppModel::insertGetId([
|
||
'code' => $code,
|
||
'name' => $name !== '' ? $name : $code,
|
||
'app_id' => $appId,
|
||
'status' => 0,
|
||
'created_at' => time(),
|
||
'updated_at' => time(),
|
||
]);
|
||
return [
|
||
'created' => true,
|
||
'id' => (int) $id,
|
||
'code' => $code,
|
||
'app_id' => $appId,
|
||
'app_secret_set' => false,
|
||
'message' => '已创建应用记录,请编辑填写 AppSecret',
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 加密要落库的密钥;留空表示不改动
|
||
*/
|
||
private function encryptSecrets(array $params): array
|
||
{
|
||
$encrypt = FieldEncryptService::getInstance();
|
||
foreach (self::SECRET_FIELDS as $field) {
|
||
if (!array_key_exists($field, $params)) {
|
||
continue;
|
||
}
|
||
$value = trim((string) $params[$field]);
|
||
if ($value === '') {
|
||
unset($params[$field]);
|
||
continue;
|
||
}
|
||
if ($encrypt->isEncrypted($value)) {
|
||
continue;
|
||
}
|
||
$params[$field] = $encrypt->encryptForStorage($value);
|
||
}
|
||
return $params;
|
||
}
|
||
|
||
/**
|
||
* 只告诉前端「配没配」,不回显密文也不回显明文
|
||
*/
|
||
private function withSecretFlags(array $row): array
|
||
{
|
||
$raw = WxAppModel::where('id', $row['id'] ?? 0)->first(self::SECRET_FIELDS);
|
||
foreach (self::SECRET_FIELDS as $field) {
|
||
$row[$field . '_set'] = !empty($raw[$field] ?? '');
|
||
unset($row[$field]);
|
||
}
|
||
return $row;
|
||
}
|
||
}
|