-- iXserverLoop 的闭环补丁:在 FeatureTest 种子(test_db_init_script.sql)之上执行。 -- loop.ps1 reset 里与建库、灌种子绑在一起执行,不提供「只建不补」的路径(方案 §8 #6): -- 种子里是真格式的 FB token 和真实的外部 webhook,不补就起 API,消息会漏到外面。 -- -- 端口与 config\loop.psd1 一致:第三方客户端 5056。改端口要同步改这里。 -- 需要 SQL Server 2016+(JSON_MODIFY)。winbox 上是 SQL Server 2022 Express。 SET NOCOUNT ON; SET XACT_ABORT ON; BEGIN TRANSACTION; DECLARE @fakeToken NVARCHAR(50) = N'loop-fake-token'; DECLARE @blackhole NVARCHAR(100) = N'http://127.0.0.1:9/loop-blackhole'; -- 9 = discard,本机没人听,立即拒绝连接 DECLARE @chatbot NVARCHAR(200) = N'http://localhost:5056/webhook?mode=ticket-with-source&service_code=epro_ig_demo'; ------------------------------------------------------------------------------------------------ -- 1. 所有服务号的真凭据换成假值(列 + all_setting 里的同名字段) ------------------------------------------------------------------------------------------------ UPDATE dbo.service_account_config SET fb_token = @fakeToken WHERE fb_token IS NOT NULL AND fb_token <> N''; UPDATE dbo.service_account_config SET wc_app_secret = @fakeToken WHERE wc_app_secret IS NOT NULL AND wc_app_secret <> N''; UPDATE dbo.service_account_config SET wc_account_token = @fakeToken WHERE wc_account_token IS NOT NULL AND wc_account_token <> N''; UPDATE dbo.service_account_config SET wc_api_token = @fakeToken WHERE wc_api_token IS NOT NULL AND wc_api_token <> N''; UPDATE dbo.service_account_config SET wc_AESKey = @fakeToken WHERE wc_AESKey IS NOT NULL AND wc_AESKey <> N''; UPDATE dbo.service_account_config SET line_channel_secret = @fakeToken WHERE line_channel_secret IS NOT NULL AND line_channel_secret <> N''; UPDATE dbo.service_account_config SET line_long_live_access_token = @fakeToken WHERE line_long_live_access_token IS NOT NULL AND line_long_live_access_token <> N''; UPDATE dbo.service_account_config SET emma_token = @fakeToken WHERE emma_token IS NOT NULL AND emma_token <> N''; -- JSON_MODIFY 在 lax 模式下会给不存在的路径新建键,所以每条都先判断路径存在 UPDATE dbo.service_account_config SET all_setting = JSON_MODIFY(all_setting, '$.InstagramSetting.FanPageToken', @fakeToken) WHERE ISJSON(all_setting) = 1 AND JSON_VALUE(all_setting, '$.InstagramSetting.FanPageToken') IS NOT NULL; UPDATE dbo.service_account_config SET all_setting = JSON_MODIFY(all_setting, '$.EmmaSetting.Token', @fakeToken) WHERE ISJSON(all_setting) = 1 AND JSON_VALUE(all_setting, '$.EmmaSetting.Token') IS NOT NULL; UPDATE dbo.service_account_config SET all_setting = JSON_MODIFY(all_setting, '$.LineSetting.ChannelSecret', @fakeToken) WHERE ISJSON(all_setting) = 1 AND JSON_VALUE(all_setting, '$.LineSetting.ChannelSecret') IS NOT NULL; UPDATE dbo.service_account_config SET all_setting = JSON_MODIFY(all_setting, '$.LineSetting.LongLiveAccessToken', @fakeToken) WHERE ISJSON(all_setting) = 1 AND JSON_VALUE(all_setting, '$.LineSetting.LongLiveAccessToken') IS NOT NULL; ------------------------------------------------------------------------------------------------ -- 2. 所有服务号指向外部的 chatbot 地址一律打进黑洞(api.commas.hk、hktbchatbot.com 等) ------------------------------------------------------------------------------------------------ UPDATE dbo.service_account_config SET all_setting = JSON_MODIFY(all_setting, '$.AISetting.AIProviderWebhook.Webhook', @blackhole) WHERE ISJSON(all_setting) = 1 AND JSON_VALUE(all_setting, '$.AISetting.AIProviderWebhook.Webhook') IS NOT NULL; UPDATE dbo.service_account_config SET all_setting = JSON_MODIFY(all_setting, '$.AutoResponeSetting.CustomChatbotWebhook', @blackhole) WHERE ISJSON(all_setting) = 1 AND JSON_VALUE(all_setting, '$.AutoResponeSetting.CustomChatbotWebhook') IS NOT NULL; UPDATE dbo.service_account_config SET all_setting = JSON_MODIFY(all_setting, '$.AutoResponeSetting.OfflineChatbotWebhook', @blackhole) WHERE ISJSON(all_setting) = 1 AND JSON_VALUE(all_setting, '$.AutoResponeSetting.OfflineChatbotWebhook') IS NOT NULL; UPDATE dbo.service_account_config SET ai_setting = JSON_MODIFY(ai_setting, '$.APIUrl', @blackhole) WHERE ISJSON(ai_setting) = 1 AND JSON_VALUE(ai_setting, '$.APIUrl') IS NOT NULL; -- 旧版 ai_setting.DataJson 是「字符串里套 JSON」,里面还有一份 AIProviderWebhook.Webhook。 -- DataJson 动辄超过 4000 字,JSON_VALUE 会返回 NULL,所以用 OPENJSON 取整段 UPDATE c SET ai_setting = JSON_MODIFY(c.ai_setting, '$.DataJson', JSON_MODIFY(j.DataJson, '$.AIProviderWebhook.Webhook', @blackhole)) FROM dbo.service_account_config c CROSS APPLY OPENJSON(c.ai_setting) WITH (DataJson NVARCHAR(MAX) '$.DataJson') j WHERE ISJSON(c.ai_setting) = 1 AND ISJSON(j.DataJson) = 1 AND JSON_VALUE(j.DataJson, '$.AIProviderWebhook.Webhook') IS NOT NULL; ------------------------------------------------------------------------------------------------ -- 3. 被测服务号 epro_ig_demo:chatbot 指向本地第三方客户端,模板走 ABP -- 切人工、客服在线、额度池不写在这里,由 SCRM 模拟调接口完成(方案 §4) ------------------------------------------------------------------------------------------------ IF NOT EXISTS (SELECT 1 FROM dbo.service_account_config WHERE code = N'epro_ig_demo' AND ISJSON(all_setting) = 1) THROW 50001, N'种子里找不到 epro_ig_demo 或它的 all_setting 不是 JSON', 1; UPDATE dbo.service_account_config SET all_setting = JSON_MODIFY(JSON_MODIFY(all_setting, '$.AISetting.AIProviderWebhook.Webhook', @chatbot), '$.ChatMessageSetting.CurrentProviderKey', N'AbpServiceAccountChatMessageProvider') WHERE code = N'epro_ig_demo'; ------------------------------------------------------------------------------------------------ -- 4. 第三方 client 登记:两张表都要有 setsail(方案 §2 链路 c)。ip_whitelist 留空 = 不限来源 ------------------------------------------------------------------------------------------------ DELETE FROM dbo.third_party_chatbot_client WHERE client_id = N'setsail'; DELETE FROM dbo.oauth_client WHERE client_id = N'setsail'; INSERT INTO dbo.oauth_client (id, client_id, name, allowed_scopes, ip_whitelist, enabled, create_datetime, update_datetime) VALUES (1001, N'setsail', N'setsail (loop)', N'ixserver_chatbot', NULL, 1, GETDATE(), GETDATE()); INSERT INTO dbo.third_party_chatbot_client (id, client_id, service_codes, create_datetime, update_datetime) VALUES (1001, N'setsail', N'epro_ig_demo', GETDATE(), GETDATE()); ------------------------------------------------------------------------------------------------ -- 5. 自检:补完之后库里不应再有任何真 token 或外部 chatbot 地址 ------------------------------------------------------------------------------------------------ DECLARE @leaks INT = ( SELECT COUNT(*) FROM dbo.service_account_config WHERE (fb_token IS NOT NULL AND fb_token NOT IN (N'', @fakeToken)) OR all_setting LIKE N'%commas.hk/%Webhook%' OR all_setting LIKE N'%hktbchatbot.com%' OR ai_setting LIKE N'%commas.hk/%Webhook%' OR ai_setting LIKE N'%hktbchatbot.com%'); IF @leaks > 0 THROW 50002, N'补丁后仍有服务号带着真 token 或外部 chatbot 地址,检查种子里是否出现了新字段', 1; COMMIT TRANSACTION; SELECT code, JSON_VALUE(all_setting, '$.AISetting.IsEnable') AS ai_enable, JSON_VALUE(all_setting, '$.AISetting.AIProviderWebhook.Webhook') AS webhook, JSON_VALUE(all_setting, '$.ChatMessageSetting.CurrentProviderKey') AS message_provider, JSON_VALUE(all_setting, '$.InstagramSetting.InstagramAccount') AS ig_account, JSON_VALUE(all_setting, '$.InstagramSetting.FanPageToken') AS ig_token FROM dbo.service_account_config WHERE code = N'epro_ig_demo';