Node.js SDK
Node.js 服務端 SDK 用應用憑據呼叫 OpenAPI,管理使用者、好友、群組、訊息和檔案,並接收事件回撥與同步回撥。它負責 App Token、重試、限流、分頁和回撥校驗。介面通用規則見呼叫介面,框架接入見接收回調,全部方法見服務與方法。
完整指令碼與框架示例的構建、配置、執行、回撥聯調和排查見 示例執行指南。當前沒有聊天 Web UI Demo。
首次接入可按快速開始在獨立 npm 工程中完成建立使用者、查詢和傳送訊息,無需先取得原始碼倉庫許可權。
| 要完成的工作 | 閱讀入口 |
|---|---|
| 安裝並跑通一次請求 | 快速開始 |
| 配置客戶端、Token、代理和共享儲存 | 本頁下方的客戶端配置 |
| 超時、重試、分頁、批次、檔案和頻道 | 呼叫介面 |
| 接入事件與同步回撥 | 接收回調 |
| 查方法簽名、引數和返回型別 | 服務與方法 |
| TypeScript 與後端框架示例 | 示例執行指南 |
| 安裝、鑑權、網路或回撥報錯 | 常見問題與排查 |
| 核對包版本及已驗證範圍 | 版本與驗證範圍 |
執行環境與安裝
- Node.js 22.17.0 以上,支援 Node.js 24;使用 Node.js 執行時,Next.js 中選擇
nodejs,不支援 Edge 執行時。 - 包名為
@deeprespond/im-server-sdk,沒有執行時依賴,使用內建fetch和 Node.js 模組。 - 同時提供 ES 模組和 CommonJS,帶 TypeScript 型別,只有具名匯出。
- Express、Koa、Fastify、Redis 等由應用按需安裝,SDK 不會自動引入它們。
在業務專案中安裝 npm 包:
npm install @deeprespond/im-server-sdk@1.0.7也可以使用 pnpm add @deeprespond/im-server-sdk@1.0.7。當前公共版本與安裝來源見 npm;JavaScript 可直接執行,TypeScript 專案安裝 typescript 與 @types/node@22,使用 moduleResolution: NodeNext、node16 或 bundler。
如需使用本地原始碼,在原始碼倉庫的 sdk/server/node 中構建安裝包:
pnpm install --frozen-lockfile
pnpm build
pnpm pack --pack-destination /tmp然後在你的業務專案中安裝生成的 .tgz 檔案:
npm install /tmp/deeprespond-im-server-sdk-1.0.7.tgz原始碼構建的安裝包不包含 examples,版本為 1.0.7;保留 UNLICENSED 授權標記,具體使用授權請聯絡深應智慧。本地原始碼更新後需重新打包並安裝。
ES 模組和 TypeScript:
import { DRClient, isDRError } from '@deeprespond/im-server-sdk';CommonJS:
const { DRClient, isDRError } = require('@deeprespond/im-server-sdk');| 匯入路徑 | 內容 |
|---|---|
@deeprespond/im-server-sdk | DRClient、DRError、BatchError、RawJSON、RAW、引數與響應型別 |
@deeprespond/im-server-sdk/callback | 回撥處理器、事件型別、同步回撥結果、記憶體儲存 |
@deeprespond/im-server-sdk/callback/node、/express、/koa、/fastify、/fetch | 回撥的框架適配 |
@deeprespond/im-server-sdk/redis | App Token、隨機數、事件去重的 Redis 儲存 |
@deeprespond/im-server-sdk/testing | 假 OpenAPI、帶簽名的回撥請求等測試輔助 |
建立客戶端
在控制台取得應用的 Client ID 和 Client Secret。orgName、appName 分別是 AppKey 中 # 前後的部分。
import { DRClient } from '@deeprespond/im-server-sdk';
export const im = new DRClient({
baseUrl: 'https://api.example.com',
orgName: process.env.IM_ORG_NAME!,
appName: process.env.IM_APP_NAME!,
clientId: process.env.IM_CLIENT_ID!,
clientSecret: process.env.IM_CLIENT_SECRET!,
});一個客戶端對應一個應用,在每個 Node.js 程序或 worker_threads 工作執行緒中建立並複用。構造時只校驗引數,第一次呼叫才換取 App Token;各方法返回 Promise,可以併發呼叫。baseUrl 必須是 HTTP 或 HTTPS 的絕對地址,不能帶查詢引數;HTTP 只允許本機、內網地址和不帶點的主機名,公網地址使用 HTTPS。傳入 API 根地址,不手動拼接 OpenAPI 的路徑字首。
Client Secret 和 App Token 等同應用管理員的密碼,客戶端 SDK 請使用 Web SDK 等,不要將服務端 SDK 打包進網頁、App 或小程式。
客戶端選項
時間選項使用毫秒。錯誤的 retryAfter 使用秒,見錯誤處理。
| 選項 | 預設值 | 說明 |
|---|---|---|
baseUrl | 必填 | IM 接入地址,末尾的 / 會去掉 |
orgName、appName | 必填 | 租戶標識、應用名稱 |
clientId、clientSecret | 必填 | 應用服務端憑據 |
timeoutMs | 30000 | 每次嘗試的總時限;完成上傳的預設時限為 150000 |
maxRetries | 3 | 網路錯誤、超時、5xx 的重試次數,不含第一次;只重試可安全重試的介面 |
maxRateLimitedRetries | 3 | rate_limited 後等待重發的次數 |
maxRetryAfterMs | 60000 | 自動等待 Retry-After 的上限;0 表示不等待 |
rateLimit | 關閉 | 本地限速 { perSecond, burst? };burst 預設 max(1, ceil(perSecond)) |
tokenStore | 程序內快取 | 共享 App Token 的儲存,見多程序共用令牌 |
fetch | 內建 fetch | 自己的請求實現,簽名為 (url, init) => Promise<Response> |
hooks | 無 | beforeRequest、afterResponse,見日誌與排查 |
logger | 不輸出 | { level?, sink? };設定 sink 後預設級別為 warn |
userAgentSuffix | 無 | 追加服務名和版本到 User-Agent |
im.withOptions({ timeoutMs: 3000, maxRetries: 0 }) 返回共用令牌、連線和限流狀態的檢視。可覆蓋 timeoutMs、maxRetries、maxRateLimitedRetries、maxRetryAfterMs,原客戶端的設定不變。
第一次呼叫
使用者登入你的業務系統後,為他簽發登入憑證,再交給客戶端 SDK:
const result = await im.users.issueLoginTicket('alice', { auto_create: true });
// 在业务接口的响应中将 result.ticket 交给当前已登录的用户。auto_create 為 true 時自動建立不存在的使用者。憑證有效期和使用規則見簽發登入憑證。
傳送單聊通知時,from 使用應用內已有的 IM 使用者:
await im.messages.send({
from: 'notice',
to_user: 'alice',
client_msg_id: 'order-20261008-paid',
type: 'text',
body: { text: '订单已支付' },
});to_user 和 to_group 恰好傳一個。使用穩定的業務 ID 作為 client_msg_id,業務層重試也能去重;不傳時 SDK 為本次呼叫生成 ID,自動重試沿用它。詳見傳送訊息。
App Token
SDK 自動換取、快取和重新整理 App Token,同一客戶端內併發請求共用一次換取。剩餘有效期不足總有效期的 10%(至少提前 5 分鐘)時後臺重新整理,已過期或剩餘不足 1 分鐘時等待新令牌。令牌失效後自動重新換取,具體鑑權語義見鑑權與 App Token。
輪換應用憑據後,可以呼叫 im.updateCredentials(newClientId, newClientSecret),後續請求使用新憑據。排查時可用 await im.token() 取得當前有效令牌,尚未換取時會自動獲取;不要將返回的令牌寫入日誌。im.appId 在首次換取前為 null,之後為應用 ID。
多程序共用令牌
import { Redis } from 'ioredis';
import { DRClient } from '@deeprespond/im-server-sdk';
import { ioredisStores } from '@deeprespond/im-server-sdk/redis';
const redis = new Redis(process.env.REDIS_URL!);
const { tokenStore } = ioredisStores(redis, { keyPrefix: 'my-service:im:' });
const im = new DRClient({
baseUrl: 'https://api.example.com',
orgName: process.env.IM_ORG_NAME!,
appName: process.env.IM_APP_NAME!,
clientId: process.env.IM_CLIENT_ID!,
clientSecret: process.env.IM_CLIENT_SECRET!,
tokenStore,
});使用 node-redis 時,先 await redis.connect(),再用 nodeRedisStores(redis)。SDK 不關閉呼叫方傳入的 Redis 客戶端。回撥隨機數和去重也可使用同一組儲存,見共享儲存。
代理與私有證書
需要代理時可以傳入自己的 fetch,例如使用 undici 的 ProxyAgent:
import { ProxyAgent } from 'undici';
import { DRClient } from '@deeprespond/im-server-sdk';
const dispatcher = new ProxyAgent('http://proxy.internal:3128');
const im = new DRClient({
baseUrl: 'https://api.example.com',
orgName: process.env.IM_ORG_NAME!,
appName: process.env.IM_APP_NAME!,
clientId: process.env.IM_CLIENT_ID!,
clientSecret: process.env.IM_CLIENT_SECRET!,
fetch: (url, init) => {
const options: RequestInit = { ...init };
Object.assign(options, { dispatcher });
return globalThis.fetch(url, options);
},
});
// 服务停止时先 await im.close(),再 await dispatcher.close()。內建 fetch 是否使用環境變數代理取決於 Node.js 的版本和啟動配置,SDK 不自行讀取 HTTPS_PROXY。私有化部署的 CA 證書可在啟動 Node.js 前配置 NODE_EXTRA_CA_CERTS。
服務停止時
await im.close();關閉原客戶端會處理正在進行的呼叫並停止令牌重新整理,之後不能再呼叫。檢視的 close() 不關閉原客戶端。自己的 Redis、代理連線池由應用關閉。
頻道版本
獨立 RTC 頻道的服務(im.channels)和 9 種頻道回撥的型別從 1.0.0 起提供。介面見頻道方法,用法見使用獨立頻道。
