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,用于身份验证和数据隔离。
- 联系平台管理员创建 IM 应用
- 获取 8 位数字格式的
AppId(如 16000001) - 获取 64 字符十六进制格式的
SecretKey - 妥善保管 SecretKey,仅在服务端使用,切勿暴露给客户端
生成 UserSig
UserSig 是客户端连接 IM 服务的鉴权凭证,由您的服务端使用 SecretKey 通过 HMAC-SHA256 算法生成。
生成流程:
- 客户端向您的服务端请求 UserSig
- 您的服务端使用 SecretKey 对
AppId + userId + 过期时间进行 HMAC-SHA256 签名 - 将签名内容打包为 JSON 并 Base64 编码,返回给客户端
- 客户端使用 UserSig 调用
login()连接 IM 服务
套餐与计费
OrangeCloud IM SDK 提供三种套餐,按月订阅,满足不同规模的业务需求。
| 功能 | 免费版 | 基础版 ¥399/月 | 专业版 ¥999/月 |
|---|---|---|---|
| DAU(日活用户数) | 100 | 10,000 | 100,000 |
| 房间数 | 3 | 50 | 无限 |
| 单房间人数上限 | 50 | 500 | 5,000 |
| 每日消息条数 | 10,000 | 500,000 | 不限 |
| 包名/域名白名单 | 1 个 | 3 个 | 5 个 |
| 消息存储 | 不保存 | 7 天 | 30 天 |
| 敏感词过滤 | ❌ | ✅ | ✅ |
| 禁言 / 踢人 / 全员禁言 | ❌ | ✅ | ✅ |
| 自定义消息类型 | ❌ | ✅ | ✅ |
| 消息回调 Webhook | ❌ | ❌ | ✅ |
| 数据统计报表 | ❌ | 基础 | 详细 |
| 技术支持 | 文档自助 | 工单 (48h) | 专属群 (4h) |
限额说明
当用量达到套餐上限时,SDK 会收到对应的错误回调:
| 限额项 | 触发条件 | 错误信息 |
|---|---|---|
| DAU 上限 | 当日活跃用户数达到上限时,新用户无法连接 | DAU 已达上限 |
| 房间数上限 | 创建新房间时超出限额 | 房间数已达上限 |
| 单房间人数 | 加入房间时人数已满 | 房间人数已达上限 |
| 每日消息数 | 当日消息总量超出限额 | 今日消息数已达上限 |
| 连接数上限 | 同时在线连接数超出 | 连接数已达上限 |
域名白名单
为防止 AppId 被盗用,可配置包名/域名白名单。配置后,只有白名单内的来源才能连接。
| 平台 | 校验方式 | 传参方式 |
|---|---|---|
| Android | 包名 (packageName) | 连接时 query 参数 packageName=com.example.app |
| iOS | Bundle 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。以下提供四种语言的服务端生成代码示例。
{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
}
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | 固定值 "chat" |
| content | string | 消息文本内容 |
| sender | string | 发送者 userId |
| senderName | string | 发送者昵称 |
| senderAvatar | string | 发送者头像 URL(可选) |
| timestamp | number | Unix 时间戳(秒) |
礼物消息
用户送礼时的消息格式:
{
"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
}
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | 固定值 "gift" |
| giftId | string | 礼物 ID |
| giftName | string | 礼物名称 |
| giftIcon | string | 礼物图标 URL |
| giftCount | number | 礼物数量 |
| giftPrice | number | 礼物单价(积分) |
| sender | string | 送礼者 userId |
| senderName | string | 送礼者昵称 |
| receiver | string | 收礼者 userId |
| receiverName | string | 收礼者昵称 |
| timestamp | number | Unix 时间戳(秒) |
系统公告
系统级别的公告消息:
{
"type": "system",
"content": "欢迎来到直播间!请遵守社区规范。",
"level": "info",
"timestamp": 1700000000
}
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | 固定值 "system" |
| content | string | 公告内容 |
| level | string | 级别:info / warning / error |
| timestamp | number | Unix 时间戳(秒) |
关播通知
主播关闭直播间时的通知:
{
"type": "roomClosed",
"groupId": "room_10001",
"reason": "主播已结束直播",
"timestamp": 1700000000
}
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | 固定值 "roomClosed" |
| groupId | string | 直播间 ID |
| reason | string | 关播原因 |
| timestamp | number | Unix 时间戳(秒) |
错误码
以下是 IM SDK 可能返回的错误码及其说明。
连接错误
| 错误码 | 说明 | 处理建议 |
|---|---|---|
| 10001 | 网络连接失败 | 检查网络状态,稍后重试 |
| 10002 | 连接超时 | 检查服务器地址是否正确,网络是否通畅 |
| 10003 | WebSocket 握手失败 | 检查服务器是否支持 WebSocket |
| 10004 | 连接被服务端关闭 | 可能是服务端重启,尝试重新连接 |
| 10005 | 连接数已达上限 | 当前应用连接数已满,请联系管理员扩容 |
鉴权错误
| 错误码 | 说明 | 处理建议 |
|---|---|---|
| 20001 | 缺少鉴权参数 | 检查 login 时是否传入了 appId、userId、userSig |
| 20002 | AppId 无效 | 确认 AppId 是否正确 |
| 20003 | UserSig 验证失败 | 检查 SecretKey 是否正确,UserSig 是否被篡改 |
| 20004 | UserSig 已过期 | 重新从服务端获取新的 UserSig |
| 20005 | UserSig 格式无效 | 检查 UserSig 生成逻辑是否正确 |
| 20006 | 应用已禁用 | 联系平台管理员确认应用状态 |
| 20007 | 服务已到期 | 联系平台管理员续费 |
业务错误
| 错误码 | 说明 | 处理建议 |
|---|---|---|
| 30001 | 消息不能为空 | 发送消息前检查内容是否为空 |
| 30002 | 您已被禁言 | 当前用户被禁言,等待禁言解除 |
| 30003 | 群组不存在 | 确认 groupId 是否正确 |
| 30004 | 未加入群组 | 先调用 joinGroup 加入群组 |
| 30005 | 消息发送频率过高 | 降低发送频率,建议间隔 1 秒以上 |
| 30006 | 消息内容过长 | 消息长度不超过 5000 字符 |