safeLoad(); $projectRoot = dirname(__DIR__, 2); $manifestPath = $projectRoot . '/user-app/src/manifest.json'; $litePosPluginProvider = 'wx7903bb295ac26ac7'; $litePosPluginExport = 'miniprogram_npm/lite-pos-plugin-mate/utils.js'; function replaceMpWeixinPlugin(string $content, string $version, string $provider, string $exportPath): string { if (!preg_match('/"mp-weixin"\s*:\s*\{/', $content, $matches, PREG_OFFSET_CAPTURE)) { throw new RuntimeException('未在 manifest.json 中找到 mp-weixin 配置块。'); } $blockStart = $matches[0][1] + strlen($matches[0][0]) - 1; $length = strlen($content); $depth = 0; $inString = false; $escaped = false; $blockEnd = -1; for ($i = $blockStart; $i < $length; $i++) { $char = $content[$i]; if ($inString) { if ($escaped) { $escaped = false; continue; } if ($char === '\\') { $escaped = true; continue; } if ($char === '"') { $inString = false; } continue; } if ($char === '"') { $inString = true; continue; } if ($char === '{') { $depth++; continue; } if ($char === '}') { $depth--; if ($depth === 0) { $blockEnd = $i; break; } } } if ($blockEnd < 0) { throw new RuntimeException('manifest.json 中 mp-weixin 配置块不完整。'); } $block = substr($content, $blockStart, $blockEnd - $blockStart + 1); $block = preg_replace('/,\s*"plugins"\s*:\s*\{\s*"lite-pos-plugin"\s*:\s*\{.*?\}\s*\}/s', '', $block, 1); if (!is_string($block)) { throw new RuntimeException('清理 manifest.json 小程序插件配置失败。'); } $pluginBlock = sprintf( ",\n \"plugins\" : {\n \"lite-pos-plugin\" : {\n \"version\" : \"%s\",\n \"provider\" : \"%s\",\n \"export\" : \"%s\"\n }\n }", addcslashes($version, "\\\""), addcslashes($provider, "\\\""), addcslashes($exportPath, "\\\"") ); $updatedBlock = rtrim(substr($block, 0, -1)) . $pluginBlock . "\n }"; return substr($content, 0, $blockStart) . $updatedBlock . substr($content, $blockEnd + 1); } $dsn = sprintf( 'mysql:host=%s;port=%s;dbname=%s;charset=%s', $_ENV['DB_HOST'] ?? '127.0.0.1', $_ENV['DB_PORT'] ?? '3306', $_ENV['DB_DATABASE'] ?? '', $_ENV['DB_CHARSET'] ?? 'utf8mb4' ); try { $pdo = new PDO( $dsn, $_ENV['DB_USERNAME'] ?? '', $_ENV['DB_PASSWORD'] ?? '', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); $configRows = $pdo->query("SELECT config_group, config_key, config_value FROM system_configs")->fetchAll(); $configMap = []; foreach ($configRows as $row) { $configMap[$row['config_group'] . '.' . $row['config_key']] = (string)($row['config_value'] ?? ''); } $miniProgramAppId = trim($configMap['mini_program.app_id'] ?? ''); if ($miniProgramAppId === '') { throw new RuntimeException('后台系统配置 mini_program.app_id 为空,无法同步到 user-app manifest。'); } $litePosPluginVersion = trim($configMap['payment.mini_program_plugin_version'] ?? ''); if ($litePosPluginVersion === '') { throw new RuntimeException('后台系统配置 payment.mini_program_plugin_version 为空,无法同步收钱吧小程序插件。'); } $manifestContent = @file_get_contents($manifestPath); if ($manifestContent === false) { throw new RuntimeException('无法读取 user-app/src/manifest.json。'); } $pattern = '/("mp-weixin"\s*:\s*\{.*?"appid"\s*:\s*")([^"]*)(")/s'; if (!preg_match($pattern, $manifestContent)) { throw new RuntimeException('未在 manifest.json 中找到 mp-weixin.appid 字段。'); } $updatedContent = preg_replace_callback( $pattern, static fn(array $matches): string => $matches[1] . $miniProgramAppId . $matches[3], $manifestContent, 1 ); if (!is_string($updatedContent) || $updatedContent === '') { throw new RuntimeException('同步 manifest.json 失败。'); } $updatedContent = replaceMpWeixinPlugin($updatedContent, $litePosPluginVersion, $litePosPluginProvider, $litePosPluginExport); if (@file_put_contents($manifestPath, $updatedContent) === false) { throw new RuntimeException('写入 user-app/src/manifest.json 失败。'); } echo "SYNC_CLIENT_CONFIG_OK\n"; echo "mini_program.app_id => {$miniProgramAppId}\n"; echo "payment.mini_program_plugin_version => {$litePosPluginVersion}\n"; } catch (Throwable $e) { fwrite(STDERR, "SYNC_CLIENT_CONFIG_FAIL: {$e->getMessage()}\n"); exit(1); }