# GoChat 企业功能分析文档 > 版本:v1.0 > 生成日期:2026-05-25 > 目标:Chatwoot 企业版功能深度分析 + GoChat 商业收费功能构思 + CaptainAI/SSO/语音通话等功能设计方案 --- ## 目录 1. [Chatwoot 企业版功能全景分析](#一chatwoot-企业版功能全景分析) 2. [GoChat 商业收费模式构思](#二gochat-商业收费模式构思) 3. [CaptainAI 功能设计](#三captainai-功能设计) 4. [SSO 单点登录设计](#四sso-单点登录设计) 5. [语音通话功能设计](#五语音通话功能设计) 6. [企业版功能实施路线图](#六企业版功能实施路线图) --- ## 一、Chatwoot 企业版功能全景分析 ### 1.1 Chatwoot 版本分层 Chatwoot 采取 **社区版(开源) + 企业版(付费)** 双轨模式: | 版本 | 定价 | 定位 | 核心差异 | |------|------|------|----------| | **Community (开源)** | 免费 / 自部署 | 小团队、初创企业 | 基础客服功能,无 SLA/SSO/AI/语音 | | **Cloud Pro** | $29/坐席/月 | 中型企业 | 云托管,含基础自动化 | | **Cloud Enterprise** | $69/坐席/月 | 大型企业 | 全功能 + SSO + SLA + CaptainAI + 语音 | | **Self-hosted Enterprise** | 按需报价 | 大型企业自部署 | 同 Cloud Enterprise,但自行部署 | ### 1.2 企业版独占功能清单 以下功能 **仅在 Enterprise 版本开放**,社区版无法使用: | # | 功能 | 模块 | Chatwoot 实现 | GoChat 状态 | |---|------|------|---------------|-------------| | 1 | **SLA 策略** | SlaPolicy + AppliedSla + SlaEvent | 完整实现 | Stub/未实现 | | 2 | **审计日志** | AuditLog | 完整实现 | Stub/未实现 | | 3 | **自定义角色权限** | CustomRole | 完整实现 | Stub/未实现 | | 4 | **公司/组织管理** | Company | 完整实现 | Stub/未实现 | | 5 | **坐席容量策略** | AgentCapacityPolicy + InboxCapacityLimit | 完整实现 | Stub/未实现 | | 6 | **语音通话** | Call + Voice 系列 Service | Twilio 集成 | Stub/未实现 | | 7 | **SAML SSO** | AccountSamlSettings | 完整实现 | 部分(仅 Enable) | | 8 | **Captain AI** | Captain::Assistant + Document + Scenario | 完整实现 | 已实现 | | 9 | **Copilot** | SuggestReplies/Summarize/Translate | 完整实现 | 已实现 | | 10 | **定时任务调度** | SidekiqCron | 完整实现 | 未实现 | | 11 | **自动分配策略** | AssignmentPolicy | 完整实现 | Stub/未实现 | | 12 | **Platform App / Partner API** | PlatformApp + Permissible | 完整实现 | Stub/未实现 | | 13 | **AgentBot 智能机器人** | AgentBot + AgentBotInbox | 完整实现 | Stub/未实现 | | 14 | **数据导入** | DataImport + DataImportJob | 完整实现 | 未实现 | | 15 | **多品牌 Help Center** | Portal + Category + Article | 完整实现 | Stub/未实现 | ### 1.3 Chatwoot 功能授权机制 Chatwoot 通过以下三层机制控制企业版功能: 1. **Feature Flag**(`features.yml`):全局功能开关 - `enterprise` flag → 企业版总开关 - `saml` flag → SAML SSO 子开关 - `voice` flag → 语音通话子开关 2. **Billing Subscription**(云版):`InstallationConfig` + `Subscription` 模型 - 超级管理员配置订阅状态 - API 中间件检查订阅 → 未订阅则 403 3. **Policy 授权**:Pundit Policy 类 - `CustomRole` → 精细化角色权限 - `AccountPolicy` → 账户级操作权限 ### 1.4 GoChat 当前差距总结 基于 `Gochat-vs-Chatwoot-Full-Comparison.md` 分析: | 维度 | Chatwoot | GoChat | 差距 | |------|----------|--------|------| | API 路由数 | 327+ | 106 | **缺 221+(仅 32% 覆盖)** | | Handler 方法数 | 150+ | 99 | **缺 51+** | | 真实实现率 | 100% | 57% | **差 43%** | | Stub/Placeholder | 0 | 37 | **全部需补实现** | | 501 Not Implemented | 0 | 6 | **全部需补实现** | | 消息队列调度 | Sidekiq 完整 | WorkerPool 全 stub | **不可用** | | 渠道扩展机制 | 11 渠道 | 仅 2 渠道 | **缺 9 渠道** | | 事件分发 | 9 Listener | 无真实 Listener | **事件驱动完全不可用** | --- ## 二、GoChat 商业收费模式构思 ### 2.1 定价策略定位 GoChat 作为 Chatwoot 的 Go 语言高性能重写,应借鉴但超越 Chatwoot 的定价模式: **核心差异化卖点:** - Go 语言带来的 **10x 性能优势**(并发处理、内存占用、延迟) - 更轻量的部署架构(单二进制 vs Ruby+Sidekiq+Redis 多进程) - 开源友好 + 自部署优先 - AI 能力原生集成(而非插件式) ### 2.2 版本分层设计 | 版本 | 定价 | 目标用户 | 功能范围 | |------|------|----------|----------| | **Community(开源)** | 免费 | 小团队/个人/初创 | 核心客服功能:对话、联系人、收件箱、基础渠道、基础报表 | | **Professional** | ¥99/坐席/月($15) | 中型企业 | +自动化规则 +高级报表 +批量操作 +Email渠道 +品牌定制 | | **Enterprise** | ¥299/坐席/月($45) | 大型企业 | +SLA +SSO +语音通话 +CaptainAI +审计日志 +自定义角色 +坐席容量 | | **Ultimate** | ¥599/坐席/月($90) | 超大型/政府 | +全功能 +私有部署支持 +定制开发 +专属SLA保障 | ### 2.3 功能-版本矩阵 | 功能 | Community | Professional | Enterprise | Ultimate | |------|-----------|-------------|------------|----------| | **对话管理** | ✅ | ✅ | ✅ | ✅ | | **联系人 CRM** | ✅ | ✅ | ✅ | ✅ | | **收件箱(5个)** | ✅ | ✅ 20个 | ✅ 无限 | ✅ 无限 | | **坐席数** | 5 | 20 | 无限 | 无限 | | **Telegram 渠道** | ✅ | ✅ | ✅ | ✅ | | **WebWidget 渠道** | ✅ | ✅ | ✅ | ✅ | | **API 渠道** | ✅ | ✅ | ✅ | ✅ | | **Email 渠道** | - | ✅ | ✅ | ✅ | | **WhatsApp 渠道** | - | ✅ | ✅ | ✅ | | **Facebook 渠道** | - | ✅ | ✅ | ✅ | | **Instagram 渠道** | - | ✅ | ✅ | ✅ | | **Slack 渠道** | - | - | ✅ | ✅ | | **Line 渠道** | - | - | ✅ | ✅ | | **语音通话** | - | - | ✅ | ✅ | | **SLA 策略** | - | - | ✅ | ✅ | | **SAML SSO** | - | - | ✅ | ✅ | | **Captain AI** | - | - | ✅ | ✅ | | **Copilot 副驾驶** | - | - | ✅ | ✅ | | **自定义角色权限** | - | - | ✅ | ✅ | | **审计日志** | - | - | ✅ | ✅ | | **坐席容量管理** | - | - | ✅ | ✅ | | **公司/组织管理** | - | ✅ 基础 | ✅ 高级 | ✅ 高级 | | **Help Center** | - | - | ✅ | ✅ | | **自动分配策略** | - | ✅ 基础 | ✅ 高级 | ✅ 高级 | | **自动化规则** | - | ✅ | ✅ | ✅ | | **批量操作** | - | ✅ | ✅ | ✅ | | **高级报表/洞察** | - | ✅ | ✅ | ✅ | | **实时报表** | - | ✅ | ✅ | ✅ | | **Platform API/Partner** | - | - | - | ✅ | | **私有部署支持** | - | - | ✅ 基础 | ✅ 专属 | | **定制开发** | - | - | - | ✅ | ### 2.4 计费模型设计 #### 计费维度 1. **坐席数(Agent)**:主计费单位,按月/年订阅 - 月付:标准价格 - 年付:8折优惠 2. **用量加价(Overage)**: - 对话量超限:每 1K 对话 ¥10 - AI 调用量超限:每 1K 次 ¥5 - 存储超限:每 GB ¥2/月 3. **附加功能包(Add-on)**: - CaptainAI 增强包:¥50/坐席/月(更高 AI 调用额度) - 语音通话包:¥30/坐席/月 + Twilio 话费 - SSO 增强包:¥20/坐席/月(支持 OIDC + LDAP + SAML) #### 数据模型设计 ```go // Subscription 订阅模型 type Subscription struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;index"` Plan string `gorm:"not null;type:varchar(20)"` // community/professional/enterprise/ultimate BillingCycle string `gorm:"not null;type:varchar(10)"` // monthly/yearly AgentCount int `gorm:"not null;default:5"` StartedAt time.Time `gorm:"not null"` ExpiresAt time.Time `gorm:"not null"` Status string `gorm:"not null;type:varchar(20)"` // active/expired/cancelled/suspended AutoRenew bool `gorm:"default:true"` Addons json.RawMessage `gorm:"type:jsonb"` // [{name, quantity, unit_price}] OverageAlert bool `gorm:"default:true"` // 用量超限是否告警 CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } // BillingUsage 计费用量 type BillingUsage struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;index"` Period string `gorm:"not null;type:varchar(7)"` // 2026-05 Conversations int `gorm:"default:0"` AICalls int `gorm:"default:0"` StorageGB float64 `gorm:"default:0"` VoiceMinutes float64 `gorm:"default:0"` CreatedAt time.Time UpdatedAt time.Time } // FeatureEntitlement 功能授权 type FeatureEntitlement struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;uniqueIndex"` Plan string `gorm:"not null"` Features json.RawMessage `gorm:"type:jsonb"` // {"sla": true, "sso": true, "voice": true, ...} MaxInboxes int `gorm:"default:5"` MaxAgents int `gorm:"default:5"` AICallLimit int `gorm:"default:0"` // 月度 AI 调用上限 StorageLimitGB float64 `gorm:"default:5"` CreatedAt time.Time UpdatedAt time.Time } ``` ### 2.5 功能开关中间件 ```go // FeatureGate 中间件:根据订阅计划控制功能访问 func FeatureGate(requiredFeature string) gin.HandlerFunc { return func(c *gin.Context) { accountID := getAccountID(c) entitlement := getFeatureEntitlement(accountID) features := parseFeatures(entitlement.Features) if !features[requiredFeature] { c.JSON(403, gin.H{ "error": "Feature not available in your plan", "feature": requiredFeature, "plan": entitlement.Plan, "upgrade_url": "/billing/upgrade", }) c.Abort() return } c.Next() } } // 路由注册示例 router.POST("/api/v1/accounts/:id/sla_policies", FeatureGate("sla"), // Enterprise 专属 authMiddleware(), slaHandler.Create(), ) router.POST("/api/v1/accounts/:id/captain/assistants", FeatureGate("captain_ai"), // Enterprise 专属 authMiddleware(), captainHandler.Create(), ) ``` ### 2.6 GoChat vs Chatwoot 商业模式差异 | 维度 | Chatwoot | GoChat 设计 | |------|----------|-------------| | **定价模型** | 按坐席/月(美元) | 按坐席/月(人民币优先,支持多币种) | | **自部署** | 免费社区版 + 企业版需购买 license | Community 免费 + Enterprise 自部署可购买 license 密钥 | | **功能授权** | features.yml + InstallationConfig | config.yaml + FeatureEntitlement DB + FeatureGate 中间件 | | **AI 计费** | 无独立计费(含在 Enterprise) | CaptainAI 独立 Add-on 包 + 用量计费 | | **语音计费** | 含在 Enterprise | 独立 Add-on + Twilio 话费透明 | | **开放策略** | 企业版源码闭源 | 全源码开放 + license 密钥解锁企业功能 | --- ## 三、CaptainAI 功能设计 ### 3.1 Captain AI 架构概览 Captain AI 是 GoChat 企业版的 AI 助手系统,提供两大核心能力: 1. **Captain(船长)**:AI 自动回复引擎,可绑定 Inbox 后自动处理客户咨询 2. **Copilot(副驾驶)**:AI 辅助工具,帮助坐席更快回复(建议回复、摘要、翻译) ### 3.2 功能模块拆解 | # | 子模块 | Chatwoot 对应 | 功能描述 | GoChat 实现状态 | |---|--------|--------------|----------|-----------------| | 1 | CaptainAssistant | Captain::Assistant | AI 助手 CRUD + Playground | ✅ 已实现 | | 2 | CaptainDocument | Captain::Document | 知识库文档管理 | ✅ 已实现 | | 3 | CaptainScenario | Captain::Scenario | 场景化对话流程 | ✅ 已实现 | | 4 | CaptainCustomTool | Captain::CustomTool | 自定义 AI 工具 | ✅ 已实现 | | 5 | CopilotSuggest | Copilot::SuggestReplies | 建议回复 | ✅ 已实现 | | 6 | CopilotSummarize | Copilot::Summarize | 对话摘要 | ✅ 已实现 | | 7 | CopilotTranslate | Copilot::Translate | 多语言翻译 | ✅ 已实现 | | 8 | CaptainInbox | CaptainInbox | 助手-Inbox 绑定 | ✅ 已实现 | | 9 | Playground | AssistantChatService/AgentRunnerService | 在线调试 | ✅ 已实现 | | 10 | DocumentSearch | pgvector 向量检索 | 知识库搜索 | ✅ 已实现 | ### 3.3 CaptainAI 增强设计(超越 Chatwoot) #### 3.3.1 多 LLM Provider 支持 Chatwoot 仅支持 OpenAI。GoChat 设计为多 Provider 架构: ```go // LLMProvider 接口 type LLMProvider interface { ChatCompletion(ctx context.Context, req ChatRequest) (ChatResponse, error) Embedding(ctx context.Context, text string) ([]float32, error) StreamChat(ctx context.Context, req ChatRequest) (<-chan ChatChunk, error) } // 支持的 Provider var Providers = map[string]LLMProvider{ "openai": &OpenAIProvider{}, "azure": &AzureOpenAIProvider{}, "anthropic": &AnthropicProvider{}, // Claude "deepseek": &DeepSeekProvider{}, // DeepSeek "qwen": &QwenProvider{}, // 通义千问 "glm": &GLMProvider{}, // 智谱 GLM "local": &LocalProvider{}, // llama.cpp 本地 "ollama": &OllamaProvider{}, // Ollama 本地 } ``` #### 3.3.2 RAG 知识库增强 | 特性 | Chatwoot | GoChat 增强 | |------|----------|-------------| | 向量存储 | pgvector 单一 | pgvector + Elasticsearch + Milvus 可选 | | 文档类型 | 知识库文档 | + 网页抓取 + PDF + FAQ 自动提取 | | 检索策略 | 简单向量相似度 | 混合检索(向量 + 关键词 + 重排序) | | 上下文窗口 | 固定 | 动态窗口 + MMR 去重 | | 多语言支持 | 英文为主 | 中英双语 + 自动检测 | #### 3.3.3 Agent Tool 框架 GoChat Agent Tool 设计超越 Chatwoot 的简单工具列表: ```go // AgentTool 接口 type AgentTool interface { Name() string Description() string Parameters() ToolParameters // JSON Schema Execute(ctx context.Context, args map[string]interface{}) (ToolResult, error) } // 内置工具 type FAQTool struct{} // FAQ 检索 type MemoryTool struct{} // 对话记忆 type ContactAttributesTool struct{} // 客户属性查询 type OrderStatusTool struct{} // 订单状态查询(需企业定制) type KnowledgeBaseTool struct{} // 知识库检索 // 自定义工具注册表 type ToolRegistry struct { builtin map[string]AgentTool custom map[string]AgentTool // 用户通过 API 注册 } // Agent Runner(v2 引擎) type AgentRunnerService struct { provider LLMProvider registry *ToolRegistry assistant *CaptainAssistant documents []CaptainDocument } func (s *AgentRunnerService) Run(ctx context.Context, message string) (*AgentResponse, error) { // 1. 构建系统 prompt(assistant config + response_guidelines + guardrails) // 2. 检索相关文档(RAG) // 3. 调用 LLM(带 tool_choice) // 4. LLM 返回 tool_call → 执行工具 → 回注结果 // 5. 循环直到 LLM 返回最终回复 // 6. 返回回复 + 引用来源 + 工具调用日志 } ``` #### 3.3.4 Copilot 增强功能 | 增强功能 | 描述 | 优先级 | |----------|------|--------| | **情绪分析** | 分析客户情绪(正面/负面/中性),帮助坐席判断应对策略 | P1 | | **意图识别** | 自动识别客户意图(投诉/咨询/退换/续费等) | P1 | | **智能摘要** | 不仅摘要对话,还提取关键决策点和承诺 | P0 | | **知识推荐** | 根据对话上下文推荐相关知识库文档 | P1 | | **多轮建议** | 不仅建议单条回复,还提供后续跟进建议 | P2 | | **质检辅助** | 对话结束后自动标注质检项(合规/违规) | P2 | ### 3.4 CaptainAI API 设计 ``` # Captain Assistant CRUD GET /api/v1/accounts/{id}/captain/assistants # 列表 POST /api/v1/accounts/{id}/captain/assistants # 创建 GET /api/v1/accounts/{id}/captain/assistants/{aid} # 详情 PATCH /api/v1/accounts/{id}/captain/assistants/{aid} # 更新 DELETE /api/v1/accounts/{id}/captain/assistants/{aid} # 删除 # Playground POST /api/v1/accounts/{id}/captain/assistants/{aid}/playground # 调试 # Tools GET /api/v1/accounts/{id}/captain/assistants/tools # 可用工具列表 # Inbox Binding POST /api/v1/accounts/{id}/captain/assistants/{aid}/inboxes # 绑定 DELETE /api/v1/accounts/{id}/captain/assistants/{aid}/inboxes/{inbox_id} # 解绑 # Captain Document CRUD GET /api/v1/accounts/{id}/captain/assistants/{aid}/documents POST /api/v1/accounts/{id}/captain/assistants/{aid}/documents DELETE /api/v1/accounts/{id}/captain/assistants/{aid}/documents/{did} # Captain Scenario CRUD GET /api/v1/accounts/{id}/captain/assistants/{aid}/scenarios POST /api/v1/accounts/{id}/captain/assistants/{aid}/scenarios PATCH /api/v1/accounts/{id}/captain/assistants/{aid}/scenarios/{sid} DELETE /api/v1/accounts/{id}/captain/assistants/{aid}/scenarios/{sid} # Copilot POST /api/v1/accounts/{id}/copilot/suggest_replies # 建议回复 POST /api/v1/accounts/{id}/copilot/summarize # 对话摘要 POST /api/v1/accounts/{id}/copilot/translate # 翻译 POST /api/v1/accounts/{id}/copilot/analyze_sentiment # 情绪分析(新增) POST /api/v1/accounts/{id}/copilot/detect_intent # 意图识别(新增) ``` ### 3.5 数据模型 ```go // CaptainAssistant — AI 助手 type CaptainAssistant struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;index"` Name string `gorm:"not null;type:varchar(255)"` Description string `gorm:"type:text"` Status AssistantStatus `gorm:"type:varchar(20);default:'draft'"` // active/draft/archived Config json.RawMessage `gorm:"type:jsonb"` // {temperature, feature_faq, feature_memory, ...} Guardrails json.RawMessage `gorm:"type:jsonb"` // 限制性规则 ResponseGuidelines json.RawMessage `gorm:"type:jsonb"` // 回复指导方针 LLMProvider string `gorm:"type:varchar(50);default:'openai'"` // 新增:LLM Provider LLMModel string `gorm:"type:varchar(100);default:'gpt-4'"` // 新增:具体模型 MaxTokens int `gorm:"default:2048"` // 新增:最大 token CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } // CaptainDocument — 知识库文档 type CaptainDocument struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;index"` AssistantID uint `gorm:"not null;index"` ExternalURL string `gorm:"type:varchar(500)"` // 外部链接 Content string `gorm:"type:text"` // 文档内容 Embedding []float32 `gorm:"type:vector(1536)"` // pgvector SourceType string `gorm:"type:varchar(20)"` // url/file/faq/api Status string `gorm:"type:varchar(20);default:'active'"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } // CaptainScenario — 对话场景 type CaptainScenario struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;index"` AssistantID uint `gorm:"not null;index"` Name string `gorm:"not null;type:varchar(255)"` Description string `gorm:"type:text"` TriggerRules json.RawMessage `gorm:"type:jsonb"` // 触发条件 FlowConfig json.RawMessage `gorm:"type:jsonb"` // 场景流程配置 Priority int `gorm:"default:0"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } // CaptainCustomTool — 自定义工具 type CaptainCustomTool struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;index"` AssistantID uint `gorm:"not null;index"` Name string `gorm:"not null;type:varchar(100)"` Description string `gorm:"type:text"` Parameters json.RawMessage `gorm:"type:jsonb"` // JSON Schema Endpoint string `gorm:"type:varchar(500)"` // API endpoint Method string `gorm:"type:varchar(10);default:'POST'"` Headers json.RawMessage `gorm:"type:jsonb"` AuthType string `gorm:"type:varchar(20)"` // none/bearer/basic/oauth2 AuthConfig json.RawMessage `gorm:"type:jsonb"` Status string `gorm:"type:varchar(20);default:'active'"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } // CaptainInbox — 助手-Inbox 绑定 type CaptainInbox struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;index"` AssistantID uint `gorm:"not null;index"` InboxID uint `gorm:"not null;index"` CreatedAt time.Time } ``` --- ## 四、SSO 单点登录设计 ### 4.1 SSO 架构概览 GoChat 企业版 SSO 支持 **三种协议**,超越 Chatwoot 仅支持 SAML: | 协议 | Chatwoot | GoChat | 适用场景 | |------|----------|--------|----------| | **SAML 2.0** | ✅ 仅此一种 | ✅ | Okta、Azure AD、OneLogin | | **OIDC (OAuth 2.0)** | ❌ | ✅ 新增 | Google Workspace、Auth0、Keycloak | | **LDAP** | ❌ | ✅ 新增 | 传统企业 AD/LDAP | ### 4.2 SAML 2.0 设计 #### 数据模型 ```go // AccountSamlSettings — SAML 配置 type AccountSamlSettings struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;uniqueIndex"` SsoURL string `gorm:"not null;type:varchar(500)"` // IdP SSO URL Certificate string `gorm:"not null;type:text"` // X509 证书 IdpEntityID string `gorm:"not null;type:varchar(500)"` // IdP Entity ID SpEntityID string `gorm:"type:varchar(500)"` // 自动生成 SP Entity ID RoleMappings json.RawMessage `gorm:"type:jsonb"` // SAML 属性 → GoChat 角色 SamlVersion string `gorm:"type:varchar(10);default:'2.0'"` NameIDFormat string `gorm:"type:varchar(50);default:'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'"` SignAssertions bool `gorm:"default:true"` SignRequests bool `gorm:"default:false"` EncryptAssertions bool `gorm:"default:false"` ForceAuthn bool `gorm:"default:false"` // 强制重新认证 CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } ``` #### SAML 认证流程 ``` 1. 用户点击 "SSO Login" → GoChat 生成 SAML AuthnRequest 2. 重定向到 IdP SsoURL(Okta/Azure AD 等) 3. 用户在 IdP 完成认证 4. IdP 返回 SAML Response → GoChat ACS URL (/api/v1/saml/callback) 5. GoChat 验证 SAML Response: a. 验证签名(使用 Certificate) b. 验证时间戳(NotOnOrAfter) c. 验证 Audience(SpEntityID) d. 提取 NameID(email) 6. SamlUserBuilder 处理: a. 按 email 查找已有用户 → 如属于账户直接登录 b. 新用户 → 创建 + 设置 provider='saml' + 自动确认邮箱 c. 角色映射 → 根据 RoleMappings 配置分配 AccountUser 角色 7. 返回 JWT token → 完成登录 ``` #### API 端点 ``` # SAML 配置管理 GET /api/v1/accounts/{id}/saml_settings # 获取配置 POST /api/v1/accounts/{id}/saml_settings # 创建配置 PUT /api/v1/accounts/{id}/saml_settings # 更新配置 DELETE /api/v1/accounts/{id}/saml_settings # 删除配置 # SAML 认证流程 GET /api/v1/accounts/{id}/saml/authn_request # 生成 AuthnRequest + 重定向 POST /api/v1/saml/callback # ACS 回调处理 GET /api/v1/accounts/{id}/saml/metadata # SP Metadata(供 IdP 配置) GET /api/v1/accounts/{id}/saml/certificate_fingerprint # 证书指纹 ``` ### 4.3 OIDC (OpenID Connect) 设计 ```go // AccountOIDCSettings — OIDC 配置(新增) type AccountOIDCSettings struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;uniqueIndex"` IssuerURL string `gorm:"not null;type:varchar(500)"` // OIDC Issuer URL ClientID string `gorm:"not null;type:varchar(200)"` ClientSecret string `gorm:"not null;type:varchar(200)"` Scopes string `gorm:"type:varchar(200);default:'openid,email,profile'"` AuthorizationURL string `gorm:"type:varchar(500)"` // 自动从 Issuer 发现 TokenURL string `gorm:"type:varchar(500)"` // 自动从 Issuer 发现 JWKSURL string `gorm:"type:varchar(500)"` // 自动从 Issuer 发现 UserInfoURL string `gorm:"type:varchar(500)"` RoleClaim string `gorm:"type:varchar(100);default:'roles'"` // 角色声明字段 GroupClaim string `gorm:"type:varchar(100);default:'groups'"` // 组声明字段 AutoProvision bool `gorm:"default:true"` // 自动创建新用户 CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } ``` #### OIDC 认证流程 ``` 1. 用户点击 "OIDC Login" → 重定向到 AuthorizationURL 2. IdP 认证 → 返回 authorization_code 3. GoChat 交换 code → TokenURL 获取 access_token + id_token 4. 验证 id_token(JWKS) → 提取 claims(email, name, roles) 5. OIDCUserBuilder 处理(类似 SamlUserBuilder) 6. 返回 JWT token → 完成登录 ``` #### API 端点 ``` GET /api/v1/accounts/{id}/oidc_settings # 获取配置 POST /api/v1/accounts/{id}/oidc_settings # 创建配置 PUT /api/v1/accounts/{id}/oidc_settings # 更新配置 DELETE /api/v1/accounts/{id}/oidc_settings # 删除配置 GET /api/v1/accounts/{id}/oidc/authorize # 发起 OIDC 认证 POST /api/v1/oidc/callback # OIDC 回调 ``` ### 4.4 LDAP 设计 ```go // AccountLDAPSettings — LDAP 配置(新增) type AccountLDAPSettings struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;uniqueIndex"` Host string `gorm:"not null;type:varchar(200)"` // LDAP 服务器 Port int `gorm:"not null;default:389"` UseTLS bool `gorm:"default:false"` BaseDN string `gorm:"not null;type:varchar(200)"` // 搜索基准 DN BindDN string `gorm:"type:varchar(200)"` // 绑定 DN BindPassword string `gorm:"type:varchar(200)"` // 绑定密码 UserFilter string `gorm:"type:varchar(200);default:'(objectClass=person)'"` EmailAttribute string `gorm:"type:varchar(50);default:'mail'"` NameAttribute string `gorm:"type:varchar(50);default:'cn'"` GroupAttribute string `gorm:"type:varchar(50);default:'memberOf'"` RoleMappings json.RawMessage `gorm:"type:jsonb"` // LDAP group → GoChat 角色 AutoProvision bool `gorm:"default:true"` SyncInterval int `gorm:"default:3600"` // 同步间隔(秒) CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } ``` #### LDAP 认证流程 ``` 1. 用户输入企业账号密码 → GoChat 发起 LDAP Bind 2. BindDN + BindPassword 连接 LDAP 服务器 3. 搜索 BaseDN + UserFilter → 获取用户 DN 4. 用户 DN + 密码验证(Bind 验证) 5. 提取 email/name/groups 属性 6. LDAPUserBuilder 处理(类似 SamlUserBuilder) 7. 返回 JWT token → 完成登录 8. 后台定时同步 LDAP 组 → GoChat 角色 ``` ### 4.5 SSO 中间件设计 ```go // SSOMiddleware — SSO 通用中间件 func SSOMiddleware() gin.HandlerFunc { return func(c *gin.Context) { accountID := getAccountID(c) // 检查账户是否配置了 SSO samlSettings := getSamlSettings(accountID) oidcSettings := getOIDCSettings(accountID) ldapSettings := getLDAPSettings(accountID) if samlSettings != nil || oidcSettings != nil || ldapSettings != nil { // 强制 SSO 登录(禁用普通邮箱登录) // 仅管理员可绕过 SSO(super_admin bypass) if !isSuperAdmin(c) { enforceSSO(c) } } c.Next() } } // SSOProviderRouter — 根据配置路由到不同 SSO Provider func SSOProviderRouter(accountID uint) string { if getSamlSettings(accountID) != nil { return "saml" } if getOIDCSettings(accountID) != nil { return "oidc" } if getLDAPSettings(accountID) != nil { return "ldap" } return "email" // 默认邮箱登录 } ``` --- ## 五、语音通话功能设计 ### 5.1 语音通话架构概览 GoChat 语音通话采用 **Conference 模式**(坐席 + 客户通过会议桥连接),与 Chatwoot 保持一致,但增加更多 Provider 支持: | Provider | Chatwoot | GoChat | 说明 | |----------|----------|--------|------| | **Twilio** | ✅ | ✅ | 主要语音 Provider | | **WhatsApp 通话** | ✅ | ✅ | WhatsApp Voice Call | | **Agora(声网)** | ❌ | ✅ 新增 | 国内音视频首选 | | **Tencent RTC** | ❌ | ✅ 新增 | 腾讯实时音视频 | ### 5.2 数据模型 ```go // Call — 通话记录 type Call struct { ID uint `gorm:"primaryKey"` AccountID uint `gorm:"not null;index"` InboxID uint `gorm:"not null;index"` ConversationID uint `gorm:"not null;index"` ContactID uint `gorm:"not null"` AgentID uint `gorm:"index"` // 接听坐席 CallSource string `gorm:"not null;type:varchar(20)"` // inbox/initiated CallDirection string `gorm:"not null;type:varchar(20)"` // inbound/outbound Status string `gorm:"not null;type:varchar(20)"` // ringing/in_progress/completed/no_answer/failed/busy Provider string `gorm:"type:varchar(20);default:'twilio'"` // twilio/agora/tencent/whatsapp CallSID string `gorm:"type:varchar(100)"` // Provider 侧通话 ID ConferenceSID string `gorm:"type:varchar(100)"` // Conference SID(Twilio) DurationSeconds int `gorm:"default:0"` // 通话时长 RecordingURL string `gorm:"type:varchar(500)"` // 录音 URL RecordingSID string `gorm:"type:varchar(100)"` // 录音 SID Transcript string `gorm:"type:text"` // 通话转录 VoipToken string `gorm:"type:varchar(500)"` // Twilio Access Token ClientIdentity string `gorm:"type:varchar(100)"` // Client 标识 AdditionalAttrs json.RawMessage `gorm:"type:jsonb"` // 附加属性 CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } // CallStatus 状态机 // ringing → in_progress → completed // ringing → no_answer // ringing → failed // ringing → busy // in_progress → completed(正常结束) ``` ### 5.3 通话流程设计 #### 5.3.1 呼出通话(Outbound) ``` 1. 坐席在对话页面点击 "Call" 按钮 2. GoChat 创建 Call 记录(status=ringing, direction=outbound) 3. 生成 VoipToken(Twilio Access Token + VoiceGrant) 4. 前端使用 Twilio Client SDK 发起通话 5. 同时通过 Twilio API 呼叫客户号码 6. Twilio Conference 模式:坐席 + 客户加入会议桥 7. 客户接听 → status=in_progress + 自动分配坐席到对话 8. 通话结束 → status=completed + 更新 duration_seconds 9. 对话中插入 voice_call 消息气泡(含通话详情) ``` #### 5.3.2 呼入通话(Inbound) ``` 1. 客户拨打企业号码 → Twilio 转发到 GoChat Webhook 2. GoChat Voice::IncomingCallService 处理: a. 查找关联 Inbox + Contact b. 创建/查找 Conversation c. 创建 Call(status=ringing, direction=inbound) d. 通知坐席(WebSocket 推送 + 呼叫响铃) 3. 坐席接听 → claim_call + auto_assign 4. 通话进行 → status=in_progress 5. 通话结束 → status=completed + 录音处理 ``` #### 5.3.3 WhatsApp 通话 ``` 1. WhatsApp 客户发起通话请求 → GoChat Webhook 接收 SDP offer 2. CallPermissionReplyService 处理权限判断 3. 呼入通话创建 → 通知坐席 4. 坐席 accept/reject → WhatsApp SDP answer/reject 5. 通话进行 → 状态更新 ``` ### 5.4 通话 Provider 抽象层 ```go // VoiceProvider 接口 type VoiceProvider interface { // 基础通话 MakeCall(ctx context.Context, params MakeCallParams) (*CallResult, error) HangupCall(ctx context.Context, callSID string) error // Conference CreateConference(ctx context.Context, params ConferenceParams) (*ConferenceResult, error) EndConference(ctx context.Context, conferenceSID string) error // Token GenerateToken(ctx context.Context, identity string) (string, error) // 录音 StartRecording(ctx context.Context, callSID string) error StopRecording(ctx context.Context, callSID string) error GetRecordingURL(ctx context.Context, recordingSID string) (string, error) // Webhook 处理 HandleIncomingCall(ctx context.Context, payload map[string]interface{}) (*IncomingCallResult, error) HandleConferenceEvent(ctx context.Context, event ConferenceEvent) error HandleRecordingStatus(ctx context.Context, payload map[string]interface{}) error } // Twilio Provider 实现 type TwilioProvider struct { AccountSID string AuthToken string AppSID string PhoneNumber string APIBase string // https://api.twilio.com } // Agora Provider 实现(新增) type AgoraProvider struct { AppID string AppCertificate string APIBase string } // TencentRTC Provider 实现(新增) type TencentRTCProvider struct { SDKAppID int SecretKey string APIBase string } ``` ### 5.5 通话 API 设计 ``` # 通话管理 POST /api/v1/accounts/{id}/calls # 创建通话(呼出) GET /api/v1/accounts/{id}/calls/{call_id} # 通话详情 PUT /api/v1/accounts/{id}/calls/{call_id} # 更新通话状态 DELETE /api/v1/accounts/{id}/calls/{call_id} # 结束通话 # 通话动作 POST /api/v1/accounts/{id}/calls/{call_id}/answer # 接听 POST /api/v1/accounts/{id}/calls/{call_id}/hangup # 挂断 POST /api/v1/accounts/{id}/calls/{call_id}/reject # 拒接 POST /api/v1/accounts/{id}/calls/{call_id}/mute # 静音 POST /api/v1/accounts/{id}/calls/{call_id}/unmute # 取消静音 # Twilio Token GET /api/v1/accounts/{id}/voice/token # 获取 VoIP Token # 录音 POST /api/v1/accounts/{id}/calls/{call_id}/record # 开始录音 GET /api/v1/accounts/{id}/calls/{call_id}/recording # 获取录音 # Webhook(Twilio 回调) POST /voice/twilio/incoming # Twilio 呼入回调 POST /voice/twilio/conference # Twilio 会议事件 POST /voice/twilio/recording_status # Twilio 录音状态 # WhatsApp 通话 POST /api/v1/accounts/{id}/whatsapp/call/accept # 接听 WhatsApp 通话 POST /api/v1/accounts/{id}/whatsapp/call/reject # 拒绝 WhatsApp 通话 ``` ### 5.6 录音与转录设计 ```go // VoiceRecordingService — 录音处理 type VoiceRecordingService struct { provider VoiceProvider storage StorageProvider // 本地/S3/OSS } func (s *VoiceRecordingService) ProcessRecording(ctx context.Context, callID uint) error { // 1. 从 Provider 获取录音文件 URL // 2. 下载录音文件 // 3. 存储到对象存储(S3/OSS) // 4. 创建 Attachment 关联到对话消息 // 5. 可选:调用转录服务(Whisper/阿里语音识别) // 6. 更新 Call.RecordingURL + Call.Transcript } // VoiceTranscriptionService — 通话转录 type VoiceTranscriptionService interface { Transcribe(ctx context.Context, audioURL string) (TranscriptionResult, error) } // 支持的转录 Provider var TranscriptionProviders = map[string]VoiceTranscriptionService{ "whisper": &WhisperProvider{}, // OpenAI Whisper "aliyun": &AliyunASRProvider{}, // 阿里云语音识别 "tencent": &TencentASRProvider{}, // 腾讯云语音识别 "azure": &AzureSpeechProvider{}, // Azure Speech } ``` --- ## 六、企业版功能实施路线图 ### 6.1 Phase 分期 | Phase | 功能 | 优先级 | 预估工时 | 前置条件 | |-------|------|--------|----------|----------| | **E1** | Feature Gate + Subscription 模型 | P0 | 3天 | 无 | | **E2** | SAML SSO 完整实现 | P0 | 5天 | E1 | | **E3** | OIDC SSO 实现 | P1 | 4天 | E2 | | **E4** | LDAP SSO 实现 | P2 | 4天 | E2 | | **E5** | SLA 策略完整实现 | P0 | 4天 | E1 | | **E6** | 审计日志实现 | P0 | 3天 | E1 | | **E7** | 自定义角色权限 | P0 | 5天 | E1 | | **E8** | 语音通话(Twilio) | P1 | 7天 | E1 | | **E9** | 语音通话(Agora/Tencent) | P2 | 4天 | E8 | | **E10** | CaptainAI 增强(多 LLM) | P1 | 5天 | E1 | | **E11** | Copilot 增强 | P2 | 3天 | E10 | | **E12** | 坐席容量策略 | P1 | 3天 | E7 | | **E13** | 公司/组织管理完善 | P1 | 3天 | E7 | | **E14** | 定时任务调度 | P2 | 2天 | Worker Pool 可用 | | **E15** | AgentBot 完善 | P1 | 4天 | E1 | ### 6.2 E1 Feature Gate 实现细节 ``` E1 是所有企业功能的基石,需要优先实现: 1. 数据模型:Subscription + BillingUsage + FeatureEntitlement 2. 中间件:FeatureGate(requiredFeature) → 403 if not entitled 3. 路由注册:所有企业版路由加 FeatureGate 中间件 4. 配置管理:config.yaml 增加 billing section 5. License 密钥验证(自部署场景) 6. API: - GET /api/v1/accounts/{id}/subscription # 查看订阅 - POST /api/v1/accounts/{id}/subscription # 创建/更新订阅 - GET /api/v1/accounts/{id}/entitlement # 查看功能授权 - GET /api/v1/accounts/{id}/billing_usage # 查看用量 ``` ### 6.3 关键技术决策 | 决策点 | 选项 | 推荐 | 原因 | |--------|------|------|------| | **向量存储** | pgvector vs Milvus vs ES | pgvector(默认) + Milvus(可选) | pgvector 与 PG 一体化,运维简单 | | **LLM 调用** | 直接 HTTP vs SDK | 直接 HTTP(resty/v2) | 减少依赖,多 Provider 更灵活 | | **SSO 协议** | 仅 SAML vs 三协议 | 三协议(SAML+OIDC+LDAP) | 国内企业 OIDC/LDAP 更常见 | | **语音 Provider** | 仅 Twilio vs 多 Provider | Twilio(海外) + Agora(国内) | 国内 Agaora 生态更成熟 | | **计费存储** | Stripe vs 本地 | Stripe(海外) + 支付宝/微信(国内) | 双币种双渠道 | | **功能授权** | config.yaml vs DB | DB(FeatureEntitlement) | 云版动态调整,自部署用 config.yaml + license | | **录音转录** | Whisper vs 云 ASR | Whisper(本地) + 阿里 ASR(云) | 灵活选择 | | **Conference 模式** | 保留 vs 简化 | 保留 Conference 模式 | 与 Chatwoot 一致,坐席可转接 | --- ## 附录A:Chatwoot 企业版 Feature Flag 对照表 | Flag | 功能 | GoChat 对应开关 | |------|------|-----------------| | `enterprise` | 企业版总开关 | `FeatureEntitlement.plan >= enterprise` | | `saml` | SAML SSO | `FeatureEntitlement.features.sso_saml` | | `voice` | 语音通话 | `FeatureEntitlement.features.voice` | | `captain_ai` | Captain AI | `FeatureEntitlement.features.captain_ai` | | `audit_log` | 审计日志 | `FeatureEntitlement.features.audit_log` | | `custom_roles` | 自定义角色 | `FeatureEntitlement.features.custom_roles` | | `sla` | SLA 策略 | `FeatureEntitlement.features.sla` | | `agent_capacity` | 坐席容量 | `FeatureEntitlement.features.agent_capacity` | ## 附录B:GoChat 新增企业版功能 Flag(超越 Chatwoot) | Flag | 功能 | 描述 | |------|------|------| | `oidc_sso` | OIDC SSO | OpenID Connect 单点登录(新增) | | `ldap_sso` | LDAP SSO | LDAP 认证(新增) | | `multi_llm` | 多 LLM Provider | 支持 Claude/DeepSeek/Qwen/GLM 等(新增) | | `voice_agora` | Agora 语音 | 声网语音通话(新增) | | `voice_tencent` | Tencent RTC | 腾讯实时音视频(新增) | | `sentiment_analysis` | 情绪分析 | Copilot 情绪分析(新增) | | `intent_detection` | 意图识别 | Copilot 意图识别(新增) | | `voice_transcription` | 通话转录 | 通话自动转录(新增) | | `hybrid_rag` | 混合 RAG | 向量+关键词混合检索(新增) | --- > **文档维护说明**:本文档随 GoChat 企业版功能迭代持续更新。每次 Phase 完成后更新实施状态和差距分析。