商城配置 -> 汇付支付配置'); self::log($output, '分账设置: 系统管理 -> 商城配置 -> 支付分账 -> 分账设置'); self::log($output, '直达: /admin/shopro_huifu/config | /admin/shopro/split/config'); } } /** * 直接写入 info.ini 的 state,不依赖 get_addon_instance(CLI 下类可能尚未加载) */ public static function setAddonState($name, $state, $output = null) { $file = ADDON_PATH . $name . DS . 'info.ini'; if (!is_file($file)) { self::log($output, ' [warn] info.ini 不存在,跳过 state 写入'); return false; } $content = file_get_contents($file); $state = intval($state); if (preg_match('/^state\s*=\s*\d+/m', $content)) { $content = preg_replace('/^state\s*=\s*\d+/m', 'state = ' . $state, $content); } else { $content = rtrim($content) . "\nstate = " . $state . "\n"; } if (file_put_contents($file, $content, LOCK_EX) === false) { throw new \RuntimeException('无法写入 ' . $file . ',请检查文件权限'); } \think\Config::set($name, null, 'addoninfo'); \think\Config::set('addon-info-' . $name, null); self::log($output, '已设置 info.ini state=' . $state); if ($state === 1) { try { Service::refresh(); self::log($output, '已刷新 application/extra/addons.php 插件缓存'); } catch (\Exception $e) { self::log($output, ' [warn] Service::refresh 失败: ' . $e->getMessage()); self::log($output, ' [warn] 请在后台插件中心重新启用一次 Shopro汇付支付'); } } return true; } public static function installMenu($output = null) { $menuFile = ADDON_PATH . 'shopro_huifu' . DS . 'config' . DS . 'menu.php'; if (!is_file($menuFile)) { return false; } $menu = include $menuFile; if (!$menu) { return false; } $parent = self::resolveMenuParent(); self::log($output, '菜单父节点: ' . $parent); self::recreateMenu($menu, $parent, 'shopro_huifu/config', ['shopro_huifu']); $configMenu = AuthRule::getByName('shopro_huifu/config'); if ($configMenu) { AuthRule::update([ 'ismenu' => 1, 'status' => 'normal', 'weigh' => 5, ], ['id' => $configMenu['id']]); } \app\common\library\Menu::refresh('shopro_huifu', $menu); return $parent; } public static function installSplitMenu($output = null) { $menuFile = ADDON_PATH . 'shopro_huifu' . DS . 'config' . DS . 'split_menu.php'; if (!is_file($menuFile)) { return false; } $menu = include $menuFile; if (!$menu) { return false; } $parent = self::resolveConfigParent(); self::log($output, '分账菜单父节点: ' . $parent); self::recreateMenu($menu, $parent, 'shopro/split'); $splitMenu = AuthRule::getByName('shopro/split'); if ($splitMenu) { AuthRule::update([ 'ismenu' => 1, 'status' => 'normal', 'weigh' => 4, ], ['id' => $splitMenu['id']]); } return $parent; } /** * FastAdmin Menu::create 不会检测库中已存在同名节点,repair 时需先删后建 */ protected static function recreateMenu(array $menu, $parent, $rootName, array $legacyNames = []) { $toDelete = array_unique(array_filter(array_merge( $legacyNames, [$rootName], array_column($menu, 'name') ))); foreach ($toDelete as $name) { \app\common\library\Menu::delete($name); } \app\common\library\Menu::create($menu, $parent); } /** * 补跑升级 SQL(repair-menu / 导入联行号前可单独调用,忽略已存在字段/表) */ public static function upgradeSchema($output = null) { $addonDir = ADDON_PATH . 'shopro_huifu' . DS; self::log($output, '检查/升级汇付数据表 ...'); self::importSqlFile($addonDir . 'upgrade_huifu_split.sql', $output, true); self::importSqlFile($addonDir . 'upgrade_huifu_onboard.sql', $output, true); self::importSqlFile($addonDir . 'upgrade_huifu_onboard_account.sql', $output, true); self::importSqlFile($addonDir . 'upgrade_huifu_split_bind.sql', $output, true); self::upgradePayTypeColumn($output); } public static function ensureBankBranchTable($output = null) { self::upgradeSchema($output); } /** * 汇付/分账菜单统一挂到「商城配置」 */ public static function resolveConfigParent() { foreach (['shopro/config', 'shopro'] as $name) { $rule = AuthRule::getByName($name); if ($rule && $rule['status'] === 'normal') { return $name; } } return 0; } /** * 优先挂到侧栏可见的「商城配置」,其次 Shopro 根节点 */ public static function resolveMenuParent() { return self::resolveConfigParent(); } /** * 给已拥有 Shopro 权限的管理组追加汇付/分账菜单节点 */ public static function grantRulesToShoproGroups($output = null) { $ruleIds = array_unique(array_merge( \app\common\library\Menu::getAuthRuleIdsByName('shopro_huifu/config'), \app\common\library\Menu::getAuthRuleIdsByName('shopro/split') )); if (!$ruleIds) { self::log($output, ' [warn] 未找到汇付/分账菜单规则,跳过权限分配'); return false; } $groups = Db::name('auth_group')->where('status', 'normal')->select(); $granted = 0; foreach ($groups as $group) { if ($group['rules'] === '*') { continue; } $owned = array_filter(array_map('intval', explode(',', (string) $group['rules']))); if (!$owned) { continue; } $hasShopro = Db::name('auth_rule') ->where('id', 'in', $owned) ->where('name', 'like', 'shopro%') ->count(); if (!$hasShopro) { continue; } $merged = array_unique(array_merge($owned, $ruleIds)); Db::name('auth_group')->where('id', $group['id'])->update([ 'rules' => implode(',', $merged), ]); $granted++; } self::log($output, '已为 ' . $granted . ' 个 Shopro 权限组追加汇付/分账菜单'); return true; } public static function clearMenuCache() { Cache::rm('__menu__'); } /** * 扩展 shopro_order.pay_type,支持 huifu_wechat / group */ public static function upgradePayTypeColumn($output = null) { $file = ADDON_PATH . 'shopro_huifu' . DS . 'upgrade_huifu_pay_type.sql'; self::importSqlFile($file, $output, true); self::log($output, '已检查/升级 shopro_order.pay_type 字段'); } protected static function log($output, $message) { if ($output) { $output->writeln($message); } } /** * 使用 Db::execute 导入 SQL(CLI 下 Service::importsql 的 Db::getPdo() 可能未连接) */ protected static function importSqlFile($file, $output = null, $ignoreErrors = false) { if (!is_file($file)) { return; } $prefix = config('database.prefix'); $lines = file($file); $templine = ''; foreach ($lines as $line) { if (substr($line, 0, 2) === '--' || $line === '' || substr($line, 0, 2) === '/*') { continue; } $templine .= $line; if (substr(trim($line), -1, 1) === ';') { $templine = str_ireplace('__PREFIX__', $prefix, $templine); $templine = preg_replace('/^INSERT INTO /i', 'INSERT IGNORE INTO ', $templine); try { Db::execute($templine); } catch (\Exception $e) { if (!$ignoreErrors) { throw $e; } self::log($output, ' [skip] ' . basename($file) . ': ' . $e->getMessage()); } $templine = ''; } } } }