IM SDK

Developer Documentation
v1.0.0
v2.0 可靠性增强 →
Online

SDK 下载

OrangeCloud IM SDK v1.0.0 各平台下载:

平台格式下载链接
Android AAR GitHub: OrangeCloud-SDK/orangecloud-im-android
iOS Swift Package GitHub: OrangeCloud-SDK/orangecloud-im-ios
Flutter Dart Package GitHub: OrangeCloud-SDK/orangecloud-im-flutter
Web npm (JS + TypeScript) GitHub: OrangeCloud-SDK/orangecloud-im-web

Demo 下载

各平台完整 Demo 源码,演示 SDK 所有功能(连接、群组、消息收发、礼物、弹幕等):

平台说明下载链接
Flutter Material Design 聊天室 Demo Flutter Demo
Android Activity 集成示例(含 AAR) Android Demo
iOS SwiftUI 聊天室 Demo iOS Demo
Web Vite + 原生 JS 聊天室 Demo Web Demo

快速入门

OrangeCloud IM SDK 提供跨平台的实时通信能力,支持 Flutter、iOS、Android、Web 四端。基于 SignalR 长连接,提供群组消息、在线状态、禁言等直播间核心功能。

API 命名风格与腾讯 IM SDK 保持一致,方便从腾讯 IM 迁移的开发者快速上手。

获取 AppId / SecretKey

每个租户拥有独立的 AppId 和 SecretKey,用于身份验证和数据隔离。

  1. 联系平台管理员创建 IM 应用
  2. 获取 8 位数字格式的 AppId(如 16000001)
  3. 获取 64 字符十六进制格式的 SecretKey
  4. 妥善保管 SecretKey,仅在服务端使用,切勿暴露给客户端
⚠️ SecretKey 是敏感信息,仅应存储在您的服务端,切勿在客户端代码中硬编码。

生成 UserSig

UserSig 是客户端连接 IM 服务的鉴权凭证,由您的服务端使用 SecretKey 通过 HMAC-SHA256 算法生成。

生成流程:

  1. 客户端向您的服务端请求 UserSig
  2. 您的服务端使用 SecretKey 对 AppId + userId + 过期时间 进行 HMAC-SHA256 签名
  3. 将签名内容打包为 JSON 并 Base64 编码,返回给客户端
  4. 客户端使用 UserSig 调用 login() 连接 IM 服务
💡 UserSig 默认有效期为 24 小时(86400 秒),可自定义过期时间(1~604800 秒)。

套餐与计费

OrangeCloud IM SDK 提供三种套餐,按月订阅,满足不同规模的业务需求。

功能免费版基础版 ¥399/月专业版 ¥999/月
DAU(日活用户数)10010,000100,000
房间数350无限
单房间人数上限505005,000
每日消息条数10,000500,000不限
包名/域名白名单1 个3 个5 个
消息存储不保存7 天30 天
敏感词过滤
禁言 / 踢人 / 全员禁言
自定义消息类型
消息回调 Webhook
数据统计报表基础详细
技术支持文档自助工单 (48h)专属群 (4h)

限额说明

当用量达到套餐上限时,SDK 会收到对应的错误回调:

限额项触发条件错误信息
DAU 上限当日活跃用户数达到上限时,新用户无法连接DAU 已达上限
房间数上限创建新房间时超出限额房间数已达上限
单房间人数加入房间时人数已满房间人数已达上限
每日消息数当日消息总量超出限额今日消息数已达上限
连接数上限同时在线连接数超出连接数已达上限
💡 所有限额按自然日(UTC+8)重置。DAU 以当日连接过的去重用户数计算。

域名白名单

为防止 AppId 被盗用,可配置包名/域名白名单。配置后,只有白名单内的来源才能连接。

平台校验方式传参方式
Android包名 (packageName)连接时 query 参数 packageName=com.example.app
iOSBundle ID连接时 query 参数 bundleId=com.example.app
Web域名 (Origin)浏览器自动携带 Origin 头
小程序小程序 AppID连接时 query 参数 miniAppId=wx1234567890
💡 未配置白名单时不做来源校验,所有来源均可连接。建议上线前配置白名单。

Flutter SDK

安装

pubspec.yaml 中添加依赖:

dependencies:
  orangecloud_im_client:
    path: ./packages/orangecloud_im_client

然后执行:

flutter pub get

初始化

import 'package:orangecloud_im_client/orangecloud_im_client.dart';

final client = OrangeCloudIMClient();

登录 / 登出

// 登录(建立连接)
await client.login(
  'https://your-server.com/hubs/live',
  '16000001',       // appId
  'user_001',       // userId
  'base64UserSig',  // userSig(由服务端生成)
);

// 登出(断开连接)
await client.logout();

加入 / 退出群组

// 加入群组(直播间)
await client.joinGroup('room_10001');

// 退出群组
await client.quitGroup('room_10001');

发送消息

// 发送群组消息
await client.sendGroupMsg('room_10001', jsonEncode({
  'type': 'chat',
  'content': 'Hello World!',
  'sender': 'user_001',
  'senderName': '张三',
}));

// 获取群组成员列表
await client.getGroupMemberList('room_10001');

事件监听

// 监听消息
client.onMessageReceived.listen((messageJson) {
  final msg = jsonDecode(messageJson);
  print('收到消息: ${msg['content']}');
});

// 监听用户加入
client.onUserJoined.listen((userInfoJson) {
  print('用户加入: $userInfoJson');
});

// 监听用户离开
client.onUserLeft.listen((userKey) {
  print('用户离开: $userKey');
});

// 监听在线人数变化
client.onOnlineCountChanged.listen((count) {
  print('在线人数: $count');
});

// 监听禁言
client.onMuted.listen((muteInfoJson) {
  print('被禁言: $muteInfoJson');
});

// 监听连接状态变化
client.onConnectionStateChanged.listen((state) {
  print('连接状态: $state');
});

完整示例

import 'dart:convert';
import 'package:orangecloud_im_client/orangecloud_im_client.dart';

void main() async {
  final client = OrangeCloudIMClient();

  // 监听事件
  client.onMessageReceived.listen((msg) {
    final data = jsonDecode(msg);
    print('[${data['senderName']}]: ${data['content']}');
  });

  client.onOnlineCountChanged.listen((count) {
    print('在线: $count 人');
  });

  // 登录
  await client.login(
    'https://your-server.com/hubs/live',
    '16000001',
    'user_001',
    'your_user_sig_here',
  );

  // 加入直播间
  await client.joinGroup('room_10001');

  // 发送消息
  await client.sendGroupMsg('room_10001', jsonEncode({
    'type': 'chat',
    'content': '大家好!',
    'sender': 'user_001',
    'senderName': '张三',
  }));
}

iOS SDK

安装

使用 Swift Package Manager,在 Package.swift 中添加:

dependencies: [
    .package(path: "./packages/OrangeCloudIMClient")
]

或在 Xcode 中:File → Add Package Dependencies → 添加本地包路径。

初始化

import OrangeCloudIMClient

let client = OCIMClient()

登录 / 登出

// 登录
try await client.login(
    hubUrl: "https://your-server.com/hubs/live",
    appId: "16000001",
    userId: "user_001",
    userSig: "base64UserSig"
)

// 登出
try await client.logout()

加入 / 退出群组

// 加入群组
try await client.joinGroup(groupId: "room_10001")

// 退出群组
try await client.quitGroup(groupId: "room_10001")

发送消息

// 发送群组消息
let message: [String: Any] = [
    "type": "chat",
    "content": "Hello World!",
    "sender": "user_001",
    "senderName": "张三"
]
let jsonData = try JSONSerialization.data(withJSONObject: message)
let jsonString = String(data: jsonData, encoding: .utf8)!
try await client.sendGroupMsg(groupId: "room_10001", messageJson: jsonString)

// 获取群组成员列表
try await client.getGroupMemberList(groupId: "room_10001")

事件监听

// 监听消息
client.onMessageReceived = { messageJson in
    print("收到消息: \(messageJson)")
}

// 监听用户加入
client.onUserJoined = { userInfoJson in
    print("用户加入: \(userInfoJson)")
}

// 监听用户离开
client.onUserLeft = { userKey in
    print("用户离开: \(userKey)")
}

// 监听在线人数变化
client.onOnlineCountChanged = { count in
    print("在线人数: \(count)")
}

// 监听禁言
client.onMuted = { muteInfoJson in
    print("被禁言: \(muteInfoJson)")
}

// 监听连接状态变化
client.onConnectionStateChanged = { state in
    print("连接状态: \(state)")
}

完整示例

import OrangeCloudIMClient
import Foundation

class LiveRoomViewController: UIViewController {
    let client = OCIMClient()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupListeners()
        connectToRoom()
    }

    func setupListeners() {
        client.onMessageReceived = { [weak self] messageJson in
            guard let data = messageJson.data(using: .utf8),
                  let msg = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return }
            print("[\(msg["senderName"] ?? "")]: \(msg["content"] ?? "")")
        }

        client.onOnlineCountChanged = { count in
            print("在线: \(count) 人")
        }
    }

    func connectToRoom() {
        Task {
            try await client.login(
                hubUrl: "https://your-server.com/hubs/live",
                appId: "16000001",
                userId: "user_001",
                userSig: "your_user_sig_here"
            )
            try await client.joinGroup(groupId: "room_10001")
        }
    }

    func sendMessage(_ text: String) {
        Task {
            let message: [String: Any] = [
                "type": "chat",
                "content": text,
                "sender": "user_001",
                "senderName": "张三"
            ]
            let jsonData = try JSONSerialization.data(withJSONObject: message)
            let jsonString = String(data: jsonData, encoding: .utf8)!
            try await client.sendGroupMsg(groupId: "room_10001", messageJson: jsonString)
        }
    }
}

Android SDK

安装

在模块级 build.gradle.kts 中添加依赖:

dependencies {
    implementation(project(":orangecloud-im-client"))
}

初始化

import com.orangecloud.im.OrangeCloudIMClient

val client = OrangeCloudIMClient()

登录 / 登出

// 登录
client.login(
    hubUrl = "https://your-server.com/hubs/live",
    appId = "16000001",
    userId = "user_001",
    userSig = "base64UserSig"
)

// 登出
client.logout()

加入 / 退出群组

// 加入群组
client.joinGroup("room_10001")

// 退出群组
client.quitGroup("room_10001")

发送消息

// 发送群组消息
val message = JSONObject().apply {
    put("type", "chat")
    put("content", "Hello World!")
    put("sender", "user_001")
    put("senderName", "张三")
}
client.sendGroupMsg("room_10001", message.toString())

// 获取群组成员列表
client.getGroupMemberList("room_10001")

事件监听

// 监听消息
client.onMessageReceived = { messageJson ->
    Log.d("IM", "收到消息: $messageJson")
}

// 监听用户加入
client.onUserJoined = { userInfoJson ->
    Log.d("IM", "用户加入: $userInfoJson")
}

// 监听用户离开
client.onUserLeft = { userKey ->
    Log.d("IM", "用户离开: $userKey")
}

// 监听在线人数变化
client.onOnlineCountChanged = { count ->
    Log.d("IM", "在线人数: $count")
}

// 监听禁言
client.onMuted = { muteInfoJson ->
    Log.d("IM", "被禁言: $muteInfoJson")
}

// 监听连接状态变化
client.onConnectionStateChanged = { state ->
    Log.d("IM", "连接状态: $state")
}

完整示例

import com.orangecloud.im.OrangeCloudIMClient
import org.json.JSONObject
import kotlinx.coroutines.*

class LiveRoomActivity : AppCompatActivity() {
    private val client = OrangeCloudIMClient()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupListeners()
        connectToRoom()
    }

    private fun setupListeners() {
        client.onMessageReceived = { messageJson ->
            val msg = JSONObject(messageJson)
            runOnUiThread {
                appendMessage("[${msg.getString("senderName")}]: ${msg.getString("content")}")
            }
        }

        client.onOnlineCountChanged = { count ->
            runOnUiThread { updateOnlineCount(count) }
        }
    }

    private fun connectToRoom() {
        lifecycleScope.launch {
            client.login(
                hubUrl = "https://your-server.com/hubs/live",
                appId = "16000001",
                userId = "user_001",
                userSig = "your_user_sig_here"
            )
            client.joinGroup("room_10001")
        }
    }

    fun sendMessage(text: String) {
        lifecycleScope.launch {
            val message = JSONObject().apply {
                put("type", "chat")
                put("content", text)
                put("sender", "user_001")
                put("senderName", "张三")
            }
            client.sendGroupMsg("room_10001", message.toString())
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        lifecycleScope.launch {
            client.quitGroup("room_10001")
            client.logout()
        }
    }
}

Web SDK

安装

使用 npm 安装:

npm install orangecloud-im-client

或使用 yarn:

yarn add orangecloud-im-client

初始化

import { OrangeCloudIMClient } from 'orangecloud-im-client';

const client = new OrangeCloudIMClient();

登录 / 登出

// 登录
await client.login(
  'https://your-server.com/hubs/live',
  '16000001',       // appId
  'user_001',       // userId
  'base64UserSig'   // userSig
);

// 登出
await client.logout();

加入 / 退出群组

// 加入群组
await client.joinGroup('room_10001');

// 退出群组
await client.quitGroup('room_10001');

发送消息

// 发送群组消息
await client.sendGroupMsg('room_10001', JSON.stringify({
  type: 'chat',
  content: 'Hello World!',
  sender: 'user_001',
  senderName: '张三'
}));

// 获取群组成员列表
await client.getGroupMemberList('room_10001');

事件监听

// 监听消息
client.onMessageReceived((messageJson) => {
  const msg = JSON.parse(messageJson);
  console.log(`收到消息: ${msg.content}`);
});

// 监听用户加入
client.onUserJoined((userInfoJson) => {
  console.log('用户加入:', userInfoJson);
});

// 监听用户离开
client.onUserLeft((userKey) => {
  console.log('用户离开:', userKey);
});

// 监听在线人数变化
client.onOnlineCountChanged((count) => {
  console.log('在线人数:', count);
});

// 监听禁言
client.onMuted((muteInfoJson) => {
  console.log('被禁言:', muteInfoJson);
});

// 监听连接状态变化
client.onConnectionStateChanged((state) => {
  console.log('连接状态:', state);
});

完整示例

import { OrangeCloudIMClient } from 'orangecloud-im-client';

const client = new OrangeCloudIMClient();

// 设置事件监听
client.onMessageReceived((messageJson) => {
  const msg = JSON.parse(messageJson);
  const chatBox = document.getElementById('chat-box');
  chatBox.innerHTML += `<p>[${msg.senderName}]: ${msg.content}</p>`;
});

client.onOnlineCountChanged((count) => {
  document.getElementById('online-count').textContent = `在线: ${count} 人`;
});

client.onConnectionStateChanged((state) => {
  console.log('连接状态变化:', state);
});

// 连接并加入房间
async function init() {
  await client.login(
    'https://your-server.com/hubs/live',
    '16000001',
    'user_001',
    'your_user_sig_here'
  );
  await client.joinGroup('room_10001');
}

// 发送消息
async function sendMessage(text) {
  await client.sendGroupMsg('room_10001', JSON.stringify({
    type: 'chat',
    content: text,
    sender: 'user_001',
    senderName: '张三'
  }));
}

// 离开房间
async function leave() {
  await client.quitGroup('room_10001');
  await client.logout();
}

init();

UserSig 生成

UserSig 由您的服务端生成,客户端不应直接接触 SecretKey。以下提供四种语言的服务端生成代码示例。

💡 签名算法:HMAC-SHA256,签名内容格式为 {appId}\n{userId}\n{createTime}\n{expireTime},最终输出为 Base64 编码的 JSON 字符串。

C#

using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

public static class UserSigGenerator
{
    public static string Generate(string appId, string userId, string secretKey, int expireSeconds = 86400)
    {
        var createTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        var expireTime = createTime + expireSeconds;

        // 签名内容
        var signContent = $"{appId}\n{userId}\n{createTime}\n{expireTime}";

        // HMAC-SHA256 签名
        var keyBytes = Encoding.UTF8.GetBytes(secretKey);
        using var hmac = new HMACSHA256(keyBytes);
        var signBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(signContent));
        var signature = Convert.ToHexString(signBytes).ToLower();

        // 打包为 JSON 后 Base64 编码
        var payload = new
        {
            appId,
            userId,
            createTime,
            expireTime,
            signature
        };
        var json = JsonSerializer.Serialize(payload);
        return Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
    }
}

Java

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class UserSigGenerator {

    public static String generate(String appId, String userId, String secretKey, int expireSeconds) {
        long createTime = System.currentTimeMillis() / 1000;
        long expireTime = createTime + expireSeconds;

        // 签名内容
        String signContent = appId + "\n" + userId + "\n" + createTime + "\n" + expireTime;

        try {
            // HMAC-SHA256 签名
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec keySpec = new SecretKeySpec(
                secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            mac.init(keySpec);
            byte[] signBytes = mac.doFinal(signContent.getBytes(StandardCharsets.UTF_8));

            StringBuilder sb = new StringBuilder();
            for (byte b : signBytes) {
                sb.append(String.format("%02x", b));
            }
            String signature = sb.toString();

            // 打包为 JSON 后 Base64 编码
            String json = String.format(
                "{\"appId\":\"%s\",\"userId\":\"%s\",\"createTime\":%d,\"expireTime\":%d,\"signature\":\"%s\"}",
                appId, userId, createTime, expireTime, signature);

            return Base64.getEncoder().encodeToString(json.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            throw new RuntimeException("生成 UserSig 失败", e);
        }
    }

    public static String generate(String appId, String userId, String secretKey) {
        return generate(appId, userId, secretKey, 86400);
    }
}

Python

import hmac
import hashlib
import json
import base64
import time

def generate_user_sig(app_id: str, user_id: str, secret_key: str, expire_seconds: int = 86400) -> str:
    create_time = int(time.time())
    expire_time = create_time + expire_seconds

    # 签名内容
    sign_content = f"{app_id}\n{user_id}\n{create_time}\n{expire_time}"

    # HMAC-SHA256 签名
    signature = hmac.new(
        secret_key.encode('utf-8'),
        sign_content.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    # 打包为 JSON 后 Base64 编码
    payload = {
        "appId": app_id,
        "userId": user_id,
        "createTime": create_time,
        "expireTime": expire_time,
        "signature": signature
    }
    json_str = json.dumps(payload)
    return base64.b64encode(json_str.encode('utf-8')).decode('utf-8')


# 使用示例
user_sig = generate_user_sig("16000001", "user_001", "your_secret_key_here")
print(user_sig)

Node.js

const crypto = require('crypto');

function generateUserSig(appId, userId, secretKey, expireSeconds = 86400) {
    const createTime = Math.floor(Date.now() / 1000);
    const expireTime = createTime + expireSeconds;

    // 签名内容
    const signContent = `${appId}\n${userId}\n${createTime}\n${expireTime}`;

    // HMAC-SHA256 签名
    const signature = crypto
        .createHmac('sha256', secretKey)
        .update(signContent)
        .digest('hex');

    // 打包为 JSON 后 Base64 编码
    const payload = JSON.stringify({
        appId,
        userId,
        createTime,
        expireTime,
        signature
    });

    return Buffer.from(payload).toString('base64');
}

// 使用示例
const userSig = generateUserSig('16000001', 'user_001', 'your_secret_key_here');
console.log(userSig);

消息格式

所有消息通过 sendGroupMsg 发送,消息体为 JSON 字符串。以下是各类消息的标准格式。

聊天消息

普通文本聊天消息:

{
  "type": "chat",
  "content": "消息内容",
  "sender": "user_001",
  "senderName": "张三",
  "senderAvatar": "https://example.com/avatar.png",
  "timestamp": 1700000000
}
字段类型说明
typestring固定值 "chat"
contentstring消息文本内容
senderstring发送者 userId
senderNamestring发送者昵称
senderAvatarstring发送者头像 URL(可选)
timestampnumberUnix 时间戳(秒)

礼物消息

用户送礼时的消息格式:

{
  "type": "gift",
  "giftId": "gift_001",
  "giftName": "火箭",
  "giftIcon": "https://example.com/gifts/rocket.png",
  "giftCount": 1,
  "giftPrice": 100,
  "sender": "user_001",
  "senderName": "张三",
  "receiver": "anchor_001",
  "receiverName": "主播小美",
  "timestamp": 1700000000
}
字段类型说明
typestring固定值 "gift"
giftIdstring礼物 ID
giftNamestring礼物名称
giftIconstring礼物图标 URL
giftCountnumber礼物数量
giftPricenumber礼物单价(积分)
senderstring送礼者 userId
senderNamestring送礼者昵称
receiverstring收礼者 userId
receiverNamestring收礼者昵称
timestampnumberUnix 时间戳(秒)

系统公告

系统级别的公告消息:

{
  "type": "system",
  "content": "欢迎来到直播间!请遵守社区规范。",
  "level": "info",
  "timestamp": 1700000000
}
字段类型说明
typestring固定值 "system"
contentstring公告内容
levelstring级别:info / warning / error
timestampnumberUnix 时间戳(秒)

关播通知

主播关闭直播间时的通知:

{
  "type": "roomClosed",
  "groupId": "room_10001",
  "reason": "主播已结束直播",
  "timestamp": 1700000000
}
字段类型说明
typestring固定值 "roomClosed"
groupIdstring直播间 ID
reasonstring关播原因
timestampnumberUnix 时间戳(秒)

错误码

以下是 IM SDK 可能返回的错误码及其说明。

连接错误

错误码说明处理建议
10001网络连接失败检查网络状态,稍后重试
10002连接超时检查服务器地址是否正确,网络是否通畅
10003WebSocket 握手失败检查服务器是否支持 WebSocket
10004连接被服务端关闭可能是服务端重启,尝试重新连接
10005连接数已达上限当前应用连接数已满,请联系管理员扩容

鉴权错误

错误码说明处理建议
20001缺少鉴权参数检查 login 时是否传入了 appId、userId、userSig
20002AppId 无效确认 AppId 是否正确
20003UserSig 验证失败检查 SecretKey 是否正确,UserSig 是否被篡改
20004UserSig 已过期重新从服务端获取新的 UserSig
20005UserSig 格式无效检查 UserSig 生成逻辑是否正确
20006应用已禁用联系平台管理员确认应用状态
20007服务已到期联系平台管理员续费

业务错误

错误码说明处理建议
30001消息不能为空发送消息前检查内容是否为空
30002您已被禁言当前用户被禁言,等待禁言解除
30003群组不存在确认 groupId 是否正确
30004未加入群组先调用 joinGroup 加入群组
30005消息发送频率过高降低发送频率,建议间隔 1 秒以上
30006消息内容过长消息长度不超过 5000 字符