插件管理更新

This commit is contained in:
技术老胡
2026-03-20 12:05:54 +08:00
parent f3919c9899
commit 0eee3b92c2
6 changed files with 98 additions and 38 deletions

View File

@@ -54,11 +54,11 @@ class PayPluginController extends BaseController
if ($className === '') { if ($className === '') {
// 默认约定类名 // 默认约定类名
$className = 'app\\common\\payment\\' . ucfirst($pluginCode) . 'Payment'; $className = ucfirst($pluginCode) . 'Payment';
} }
$this->pluginRepository->upsertByCode($pluginCode, [ $this->pluginRepository->upsertByCode($pluginCode, [
'plugin_name' => $pluginName, 'name' => $pluginName,
'class_name' => $className, 'class_name' => $className,
'status' => $status, 'status' => $status,
]); ]);

View File

@@ -7,28 +7,36 @@ use app\common\base\BaseModel;
/** /**
* 支付插件模型 * 支付插件模型
* *
* 对应表ma_pay_plugin主键 plugin_code * 对应表ma_pay_plugin主键 code
*/ */
class PaymentPlugin extends BaseModel class PaymentPlugin extends BaseModel
{ {
protected $table = 'ma_pay_plugin'; protected $table = 'ma_pay_plugin';
protected $primaryKey = 'plugin_code'; protected $primaryKey = 'code';
public $incrementing = false; public $incrementing = false;
protected $keyType = 'string'; protected $keyType = 'string';
protected $fillable = [ protected $fillable = [
'plugin_code', 'code',
'plugin_name', 'name',
'class_name', 'class_name',
'status', 'status',
'config_schema',
'pay_types',
'transfer_types',
'author',
'link',
]; ];
public $timestamps = true; public $timestamps = true;
protected $casts = [ protected $casts = [
'status' => 'integer', 'status' => 'integer',
'config_schema' => 'array',
'pay_types' => 'array',
'transfer_types' => 'array',
]; ];
} }

View File

@@ -19,13 +19,20 @@ class PaymentPluginRepository extends BaseRepository
{ {
return $this->model->newQuery() return $this->model->newQuery()
->where('status', 1) ->where('status', 1)
->get(['plugin_code', 'class_name']); ->get([
'code',
'name',
'class_name',
'pay_types',
'transfer_types',
'config_schema',
]);
} }
public function findActiveByCode(string $pluginCode): ?PaymentPlugin public function findActiveByCode(string $pluginCode): ?PaymentPlugin
{ {
return $this->model->newQuery() return $this->model->newQuery()
->where('plugin_code', $pluginCode) ->where('code', $pluginCode)
->where('status', 1) ->where('status', 1)
->first(); ->first();
} }
@@ -36,7 +43,7 @@ class PaymentPluginRepository extends BaseRepository
public function findByCode(string $pluginCode): ?PaymentPlugin public function findByCode(string $pluginCode): ?PaymentPlugin
{ {
return $this->model->newQuery() return $this->model->newQuery()
->where('plugin_code', $pluginCode) ->where('code', $pluginCode)
->first(); ->first();
} }
@@ -51,10 +58,10 @@ class PaymentPluginRepository extends BaseRepository
$query->where('status', (int)$filters['status']); $query->where('status', (int)$filters['status']);
} }
if (!empty($filters['plugin_code'])) { if (!empty($filters['plugin_code'])) {
$query->where('plugin_code', 'like', '%' . $filters['plugin_code'] . '%'); $query->where('code', 'like', '%' . $filters['plugin_code'] . '%');
} }
if (!empty($filters['plugin_name'])) { if (!empty($filters['plugin_name'])) {
$query->where('plugin_name', 'like', '%' . $filters['plugin_name'] . '%'); $query->where('name', 'like', '%' . $filters['plugin_name'] . '%');
} }
$query->orderByDesc('created_at'); $query->orderByDesc('created_at');
@@ -69,12 +76,12 @@ class PaymentPluginRepository extends BaseRepository
$row = $this->findByCode($pluginCode); $row = $this->findByCode($pluginCode);
if ($row) { if ($row) {
$this->model->newQuery() $this->model->newQuery()
->where('plugin_code', $pluginCode) ->where('code', $pluginCode)
->update($data); ->update($data);
return $this->findByCode($pluginCode) ?: $row; return $this->findByCode($pluginCode) ?: $row;
} }
$data['plugin_code'] = $pluginCode; $data['code'] = $pluginCode;
/** @var PaymentPlugin $created */ /** @var PaymentPlugin $created */
$created = $this->create($data); $created = $this->create($data);
return $created; return $created;
@@ -83,7 +90,7 @@ class PaymentPluginRepository extends BaseRepository
public function updateStatus(string $pluginCode, int $status): bool public function updateStatus(string $pluginCode, int $status): bool
{ {
return (bool)$this->model->newQuery() return (bool)$this->model->newQuery()
->where('plugin_code', $pluginCode) ->where('code', $pluginCode)
->update(['status' => $status]); ->update(['status' => $status]);
} }
} }

View File

@@ -31,19 +31,29 @@ class PluginService extends BaseService
$plugins = []; $plugins = [];
foreach ($rows as $row) { foreach ($rows as $row) {
$pluginCode = $row->plugin_code; $pluginCode = $row->code;
try { $pluginName = (string)($row->name ?? '');
$plugin = $this->resolvePlugin($pluginCode, $row->class_name); $supportedMethods = is_array($row->pay_types ?? null) ? (array)$row->pay_types : [];
$plugins[] = [
'code' => $pluginCode, // 如果数据库里缺少元信息,则回退到实例化插件并写回数据库
'name' => $plugin->getName(), if ($pluginName === '' || $supportedMethods === []) {
'supported_methods'=> $plugin->getEnabledPayTypes(), try {
]; $plugin = $this->resolvePlugin($pluginCode, (string)($row->class_name ?? ''));
} catch (\Throwable $e) { $this->syncPluginMeta($pluginCode, $plugin);
// 忽略无法实例化的插件 $pluginName = $plugin->getName();
continue; $supportedMethods = (array)$plugin->getEnabledPayTypes();
} catch (\Throwable $e) {
// 忽略无法实例化的插件
continue;
}
} }
$plugins[] = [
'code' => $pluginCode,
'name' => $pluginName,
'supported_methods' => $supportedMethods,
];
} }
return $plugins; return $plugins;
@@ -54,8 +64,15 @@ class PluginService extends BaseService
*/ */
public function getConfigSchema(string $pluginCode, string $methodCode): array public function getConfigSchema(string $pluginCode, string $methodCode): array
{ {
$row = $this->pluginRepository->findActiveByCode($pluginCode);
if ($row && is_array($row->config_schema ?? null) && $row->config_schema !== []) {
return (array)$row->config_schema;
}
$plugin = $this->getPluginInstance($pluginCode); $plugin = $this->getPluginInstance($pluginCode);
return $plugin->getConfigSchema(); $schema = (array)$plugin->getConfigSchema();
$this->syncPluginMeta($pluginCode, $plugin);
return $schema;
} }
/** /**
@@ -76,8 +93,7 @@ class PluginService extends BaseService
*/ */
public function buildConfigFromForm(string $pluginCode, string $methodCode, array $formData): array public function buildConfigFromForm(string $pluginCode, string $methodCode, array $formData): array
{ {
$plugin = $this->getPluginInstance($pluginCode); $configSchema = $this->getConfigSchema($pluginCode, $methodCode);
$configSchema = $plugin->getConfigSchema();
$configJson = []; $configJson = [];
if (isset($configSchema['fields']) && is_array($configSchema['fields'])) { if (isset($configSchema['fields']) && is_array($configSchema['fields'])) {
@@ -110,7 +126,11 @@ class PluginService extends BaseService
*/ */
private function resolvePlugin(string $pluginCode, ?string $className = null): PaymentInterface&PayPluginInterface private function resolvePlugin(string $pluginCode, ?string $className = null): PaymentInterface&PayPluginInterface
{ {
$class = $className ?: 'app\\common\\payment\\' . ucfirst($pluginCode) . 'Payment'; $class = $className ?: (ucfirst($pluginCode) . 'Payment');
// 允许 DB 中只存短类名(如 AlipayPayment这里统一补全命名空间
if ($class !== '' && !str_contains($class, '\\')) {
$class = 'app\\common\\payment\\' . $class;
}
if (!class_exists($class)) { if (!class_exists($class)) {
throw new NotFoundException('支付插件类不存在:' . $class); throw new NotFoundException('支付插件类不存在:' . $class);
@@ -123,5 +143,27 @@ class PluginService extends BaseService
return $plugin; return $plugin;
} }
/**
* 把插件元信息写回数据库,供“列表/Schema 直接从DB读取”
*/
private function syncPluginMeta(string $pluginCode, PaymentInterface&PayPluginInterface $plugin): void
{
$payTypes = (array)$plugin->getEnabledPayTypes();
$transferTypes = method_exists($plugin, 'getEnabledTransferTypes') ? (array)$plugin->getEnabledTransferTypes() : [];
$configSchema = (array)$plugin->getConfigSchema();
$author = method_exists($plugin, 'getAuthorName') ? (string)$plugin->getAuthorName() : '';
$link = method_exists($plugin, 'getAuthorLink') ? (string)$plugin->getAuthorLink() : '';
$this->pluginRepository->upsertByCode($pluginCode, [
'name' => $plugin->getName(),
'pay_types' => $payTypes,
'transfer_types' => $transferTypes,
'config_schema' => $configSchema,
'author' => $author,
'link' => $link,
]);
}
} }

View File

@@ -40,13 +40,13 @@ ON DUPLICATE KEY UPDATE
`status` = VALUES(`status`), `status` = VALUES(`status`),
`updated_at` = NOW(); `updated_at` = NOW();
-- 5) 插件注册表(按项目约定:app\\common\\payment\\{Code}Payment -- 5) 插件注册表(按项目约定:类名短写,如 AlipayPayment
INSERT INTO `ma_pay_plugin` (`plugin_code`, `plugin_name`, `class_name`, `status`, `created_at`, `updated_at`) INSERT INTO `ma_pay_plugin` (`code`, `name`, `class_name`, `status`, `created_at`, `updated_at`)
VALUES VALUES
('lakala', '拉卡拉(示例)', 'app\\\\common\\\\payment\\\\LakalaPayment', 1, NOW(), NOW()), ('lakala', '拉卡拉(示例)', 'LakalaPayment', 1, NOW(), NOW()),
('alipay', '支付宝直连', 'app\\\\common\\\\payment\\\\AlipayPayment', 1, NOW(), NOW()) ('alipay', '支付宝直连', 'AlipayPayment', 1, NOW(), NOW())
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE
`plugin_name` = VALUES(`plugin_name`), `name` = VALUES(`name`),
`class_name` = VALUES(`class_name`), `class_name` = VALUES(`class_name`),
`status` = VALUES(`status`), `status` = VALUES(`status`),
`updated_at` = NOW(); `updated_at` = NOW();

View File

@@ -62,13 +62,16 @@ CREATE TABLE `ma_pay_method` (
-- ======================= -- =======================
DROP TABLE IF EXISTS `ma_pay_plugin`; DROP TABLE IF EXISTS `ma_pay_plugin`;
CREATE TABLE `ma_pay_plugin` ( CREATE TABLE `ma_pay_plugin` (
`plugin_code` varchar(32) NOT NULL DEFAULT '' COMMENT '插件编码(主键)', `code` varchar(32) NOT NULL DEFAULT '' COMMENT '插件编码(主键)',
`plugin_name` varchar(50) NOT NULL DEFAULT '' COMMENT '插件名称', `name` varchar(50) NOT NULL DEFAULT '' COMMENT '插件名称',
`class_name` varchar(255) NOT NULL DEFAULT '' COMMENT '插件类名(完整命名空间', `class_name` varchar(255) NOT NULL DEFAULT '' COMMENT '插件类名(短类名',
`config_schema` json DEFAULT NULL COMMENT '插件配置schema(JSON)',
`pay_types` json DEFAULT NULL COMMENT '插件支持支付类型(JSON)',
`transfer_types` json DEFAULT NULL COMMENT '插件支持转账类型(JSON)',
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态0-禁用, 1-启用', `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态0-禁用, 1-启用',
`created_at` datetime DEFAULT NULL COMMENT '创建时间', `created_at` datetime DEFAULT NULL COMMENT '创建时间',
`updated_at` datetime DEFAULT NULL COMMENT '更新时间', `updated_at` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`plugin_code`) PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付插件注册表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付插件注册表';
-- ======================= -- =======================