Skip to content

二次开发扩展点

1. 自定义消息

业务消息使用稳定四元组:

text
contentType + contentVersion + payload + fallbackText

推荐命名:

text
com.customer.product.order-card
com.customer.product.live-invite
com.customer.product.workflow-approval

不要使用 custom1、页面类名或会随重构变化的字符串。版本只属于一个 contentType;兼容增加字段时升版本,改变业务含义时创建新类型。

swift
let outgoing = XHIMOutgoingMessage(
    contentType: "com.example.shop.order-card",
    contentVersion: 1,
    payload: encodedOrder,
    fallbackText: "[订单] ¥199.00"
)

_ = try await client.sendMessage(
    conversationID: conversationID,
    message: outgoing
)

1.1 用户资料公开业务扩展

UserProfile.application_extension_json 与自定义消息不同:它是与用户 资料一起同步的小型、应用拥有、对陌生人也公开的 JSON object,不是私密 存储、凭证保险箱或通用文档库。推荐 key 采用业务命名空间,例如:

json
{
  "crm.label": "gold",
  "workflow.enabled": true
}

规则:非空值必须是 UTF-8 JSON object,服务端规范化后最大 16 KiB、 嵌套最大 64 层;省略更新字段表示不改,空 bytes 表示清除。严禁写入 手机、邮箱、实名、密码、Token、会话/认证状态、加密密钥或任何其他 个人敏感和认证数据。需要当前账号私有数据时,使用专用私有业务存储, 不要依赖 private_profile_visible 隐藏该字段。

2. Message Plugin

XHIMMessagePlugin / Windows IXHIMMessagePlugin 定义:

成员用途
contentType插件唯一负责的稳定类型
supportedVersions当前 SDK 可以解释的版本范围
validate发送前和展示前验证 payload
presentation生成会话预览、通知预览和 renderer key

XHIMMessagePluginRegistry 公开:

api-idiOS / macOS / Android / HarmonyOSWindows说明
extension.plugin_registerregisterRegister注册;重复 contentType 失败
extension.plugin_unregisterunregisterUnregister删除注册并返回是否存在
extension.plugin_validatevalidateValidate校验 outgoing message
extension.plugin_presentpresentationPresent把收到的消息转为展示描述

Registry 放在 App 的 IM 组合根中只创建一次。不要让每个 Cell 注册插件,也不要 在 Plugin 中发网络请求。

未知类型或未知版本的规则固定:

  1. 保留完整 XHIMMessage
  2. 展示 fallbackText
  3. 不执行未知 payload;
  4. 升级后可重新渲染已有历史消息。

3. 内置标准消息工厂

XHIMStandardMessageFactory

api-id / 工厂内容
extension.standard_stickersticker / Sticker表情包 ID、资源 URL 和描述
extension.standard_locationlocation / Location纬度、经度、标题和地址
extension.standard_contact_cardcontactCard / ContactCard用户 ID、展示名、头像
extension.standard_red_packetredPacket红包业务单据引用、祝福语、状态和业务路由
extension.standard_transfertransfer转账业务单据引用、最小货币单位金额、币种、状态和业务路由
extension.standard_enterprise_cardenterpriseCard审批、任务、公告、日程等企业业务卡片
extension.standard_markdownmarkdown / Markdown受限 Markdown 源文本和纯文本降级内容
extension.standard_quotequote / Quote被引用消息身份、发送者和摘要
extension.standard_mentionmention / Mention文本、用户 ID 列表、是否 @所有人
extension.standard_merged_forwardmergedForward / MergedForward标题和不可变 XHIMForwardItem 列表

XHIMMentionContent.decode(Windows Decode)可以从收到的 Message 解码 @ 信息,并用 mentions(userID) 判断是否命中当前用户。 Apple 端使用 XHIMQuoteContent.decodeXHIMMergedForwardContent.decode 读取收到的引用与合并转发内容;不要在 App 中重复实现 Protobuf 解析。

这些工厂只负责消息 envelope,不授予位置、通讯录或相册权限;系统权限由宿主 App 明确请求。

Markdown 使用稳定的 text/markdown@1 信封。SDK 只校验、编码和传输源文本, 不会执行 HTML,也不会把 Markdown 直接转换成富文本。宿主 Renderer 必须关闭 原始 HTML、脚本 URL 和不受信任的远程资源;不能安全渲染时始终显示 plainTextFallback。工厂收到空 fallback 时会把 Markdown 源文本作为字面纯文本 降级,保证旧端仍能阅读且不会执行标记。

红包、转账和企业卡片都是“业务单据引用消息”,不是资金或审批执行引擎。IM 服务只保证消息可靠投递、版本兼容、会话预览和历史保存;余额、支付密码、实名、 风控、审批权限和最终业务状态必须由购买方的业务服务校验。客户端点击卡片时, 先校验允许的 actionURL scheme/host,再向已登录业务模块请求最新状态,不能 相信历史消息中的 state 就直接付款、领款或通过审批。

Apple 示例:

swift
let transfer = try XHIMStandardMessageFactory.transfer(
    transferID: order.id,
    amountMinor: order.amountFen,
    currency: "CNY",
    note: "项目报销",
    state: .pending,
    actionURL: "myapp://wallet/transfers/\(order.id)"
)
_ = try await client.sendMessage(
    conversationID: conversationID,
    message: transfer
)

let approval = try XHIMStandardMessageFactory.enterpriseCard(
    businessID: approvalID,
    category: "审批",
    title: "采购申请待处理",
    summary: "申请人:王晓晨",
    state: "pending",
    actionURL: "myapp://oa/approvals/\(approvalID)",
    participantUserIDs: approverUserIDs
)

C++ Core 和 C ABI 已经把消息 envelope 当作不透明、可版本化载荷可靠保存,因此 其他端可以立即使用相同 contentType@1xhim_content_v1.proto 编码收发, 无需改动 Core。各端便利工厂和 Renderer 应以协议文件为唯一字段来源。

4. Renderer

UI Kit 的 Renderer Registry 以 rendererKeycontentType 选择消息 Cell / Composable / WPF DataTemplate / ArkUI Component。

Renderer 输入只依赖:

  • XHIMMessage
  • Plugin 给出的 XHIMMessagePresentation
  • 主题与宿主路由闭包

Renderer 不直接调用 C ABI、不读取 SQLite、不持有 Token。点击订单卡片、名片 或位置时,通过宿主注入的路由闭包回到购买方业务模块。

各端入口:

平台UI/Renderer 入口
iOSXHIMSwiftUI 的 message renderer registry 和 SwiftUI View
macOSXHIMSwiftUI Renderer;AppKit 可使用 NSHostingView
Androidxhim-ui-compose 的 message renderer registry / Composable
WindowsXHIM.UI.Wpf.XHIMMessageRendererRegistry
HarmonyOSXHIMMessageRendererRegistry / XHIMMessageItemRenderer

5. UI Kit 可替换边界

text
App Navigation / Theme / Business Screens
└── XHIM UI Kit(可选)
    ├── Conversation List
    ├── Chat Timeline + Composer
    ├── Attachment Picker
    └── Message Renderer Registry
        └── Headless XHIMClient

购买方可以:

  • 替换导航、主题、字体、颜色和本地化;
  • 只使用会话列表或聊天页的一部分;
  • 完全不用 UI Kit,自己用 Facade 构建 MVVM/VIP 页面;
  • 注册业务消息 Renderer;
  • 替换相机、相册、文件和录音入口;
  • 注入用户头像、业务页面路由和权限提示。

购买方不需要、也不应修改:

  • XHIM Core 二进制;
  • xhim_v1 C ABI;
  • SDK 数据库 schema;
  • Outbox、同步和媒体 durable task 状态机;
  • Endpoint 验签和凭证轮换逻辑。

6. Attachment Picker

UI 包提供的 Picker 是薄适配层:

能力iOSmacOSAndroidWindowsHarmonyOS
拍照/视频AVFoundation / UIImagePickerAVFoundationActivity Result / Camera宿主相机服务系统 Picker
相册PhotosPickerPhotosPicker / NSOpenPanelPhoto PickerFileOpenPickerPhotoViewPicker
文件UIDocumentPickerNSOpenPanel + 安全作用域Storage Access FrameworkFileOpenPickerDocumentViewPicker
录音AVAudioRecorderAVAudioRecorderMediaRecorder宿主录音服务AVRecorder

Picker 返回本地受权资源后,统一交给 durable media API,而不是把路径塞入消息。

7. Repository 与 ViewModel

推荐每个登录账号创建一个组合根:

text
XHIMService
├── XHIMClient
├── MessagePluginRegistry
├── ConversationRepository
├── MessageRepository
├── SocialRepository
└── MediaRepository

Repository 的读模型来自 SDK Query API;事件只触发重新查询。ViewModel 只消费 Repository 状态并调用业务动作。这样二次开发可以替换 UI,而不会把连接、同步、 事件和 Token 逻辑散落在页面里。

8. 扩展兼容清单

发布新的自定义消息前至少验证:

  • 当前版本正常收发和渲染;
  • 旧版本只显示 fallback,不崩溃;
  • iOS/macOS/Android/Windows/HarmonyOS payload 字节一致;
  • Push 通知预览不泄露敏感字段;
  • 合并转发和引用只保存必要快照;
  • 内容审核能根据 contentType 路由;
  • Renderer 失败时回退到普通未知消息气泡;
  • 消息复制、搜索、清空、撤回和离线 Reader 不破坏未知 payload。

9. 语音转文字与翻译 Provider

XHIM::Enrichment 提供供应商中立的 C++17 MessageEnrichmentProvider SPI。购买方可以适配阿里云、腾讯云或 已审核的本地模型;XHIM 不内置云凭证,也不会用 Fake Provider 伪装生产能力。

api-id能力说明
extension.enricher_create创建 Provider 隔离的 Enricher创建时复制配置与 vtable;旧 Core 明确 unsupported
extension.enricher_transcribe提交语音转文字音频字节或安全本地句柄二选一;有界进度与终态
extension.enricher_translate提交消息翻译明文边界和远端处理同意都必须显式填写
extension.enricher_cancel幂等取消一个 Request ID迟到 Provider 回调由 epoch fence 丢弃
extension.enricher_close停止 Provider 并释放 Enricher支持从 progress/completion 回调中安全重入

Enricher 不属于 XHIMClient 的消息可靠传输状态机:它不能读取数据库、Token 或 E2EE 密钥,也不会自动把结果写回消息。宿主只把用户明确选择的输入交给 Provider,并自行决定如何展示结果。Provider 回调可能同步发生,因此各平台 Facade 都先复制借用内存,再切换到语言自己的 Task/Coroutine/Promise 机制。

完整输入上限、请求/观察者 epoch fence、超时、取消、错误分类、 Provider 适配和 E2EE 明文边界见 Message Enricher 接入与安全边界

XHIM 客户端 SDK 与服务端文档