$root . '/server/app/api/controller/QywxExternalContactCallbackController.php', 'logic' => $root . '/server/app/adminapi/logic/firstvisit/WecomPromotionLogic.php', 'initialMigration' => $root . '/server/sql/1.9.20260831/add_wecom_promotion_automation.sql', 'upgradeMigration' => $root . '/server/sql/1.9.20260901/upgrade_qywx_promotion_automation_runtime.sql', 'compose' => $root . '/docker/docker-compose.yml', ]; $sources = []; foreach ($paths as $name => $path) { $source = file_get_contents($path); if (!is_string($source)) { throw new RuntimeException("无法读取 {$name}: {$path}"); } $sources[$name] = $source; } if (!str_contains($sources['callback'], 'enqueueVerifiedEvent($event, true)')) { throw new RuntimeException('企微回调未启用欢迎语和标签即时通道'); } if (!str_contains($sources['logic'], "'automation_saved' => \$automation !== null")) { throw new RuntimeException('保存接口未向前端确认自动化配置已落库'); } foreach (['initialMigration', 'upgradeMigration'] as $name) { foreach (['qywx:retry-promotion-automation', 'qywx:refresh-promotion-media'] as $command) { if (!str_contains($sources[$name], $command)) { throw new RuntimeException("{$name} 缺少 {$command}"); } } } if (!str_contains($sources['compose'], 'qywx:work-promotion-automation')) { throw new RuntimeException('Docker 部署未启动企微欢迎语常驻进程'); } echo "QYWX_PROMOTION_AUTOMATION_RUNTIME_CONTRACT_OK\n";