聊天室登录
更新时间: 2024/07/01 15:44:15
用户在聊天室收发消息前需要先创建聊天室实例并调用 SDK 的聊天室登录接口进入聊天室。登录成功后,用户才能正常在聊天室收发消息并使用其他聊天室相关功能。
本文介绍创建聊天室实例与实现聊天室登录的流程以及相关常见问题。
支持平台
Android | iOS | Windows/macOS | Web/uni-app/小程序 | Harmony |
---|---|---|---|---|
✓ | ✓ | ✓ | ✓ | ✓ |
技术原理
聊天室的登录过程包括以下三阶段:
- 获取聊天室 Link 地址
- 登录鉴权(建立聊天室长连接)
- 进入聊天室
上述任一过程失败,都会触发进入聊天室失败回调。
本地端或多端同步进入聊天室成功后,会收到 onChatroomEntered
回调。如果已在云信控制台开启了聊天室用户进出消息系统下发功能,聊天室内所有其他成员会收到回调 onChatroomMemberEnter
。如未开启,可参见开通和配置聊天室功能。
根据鉴权方式,登录方式分为静态 Token 登录、动态 Token 登录和通过第三方回调登录。
您可按需实现一种或多种登录方式。
登录方式 |
鉴权方式 | 描述 |
---|---|---|
静态 Token 登录 | 静态 Token 鉴权 | 静态 Token 默认永久有效,且恒定不变,除非主动调用服务端接口刷新。 |
动态 Token 登录 | 动态 Token 鉴权 | 动态 Token 具备时效性,适用于对于用户信息安全有较高要求的业务场景。 |
通过第三方回调登录 | 通过第三方回调鉴权 | 用户登录聊天室时的鉴权工作由指定的第三方服务器(可以是应用服务器)进行,云信服务端不做聊天室登录鉴权。 |
前提条件
实现登录聊天室前,请确保:
- 已开通和配置聊天室功能。
- 已创建聊天室,目前只能通过新版服务端 API 创建聊天室。
配置聊天室登录策略
登录策略指您的应用需要采用的一种或多种聊天室登录方式。登录聊天室前,您需要在云信控制台配置应用的聊天室登录策略。如未配置相应的登录策略,后续调用登录接口时可能因无登录权限而报错(状态码:403)。
-
在控制台首页应用管理中选择应用,然后单击 IM 即时通讯下的功能配置按钮进入功能配置页。
-
在顶部选择聊天室页签,开启聊天室功能,然后单击子功能配置
-
在子功能配置页选择配置聊天室登录策略。
- 静态 token:用户登录聊天室时需传入静态 token。静态 token 默认永久有效,且恒定不变,除非主动调用新版服务端 API刷新 Token。
- 动态 token:用户登录聊天室时需传入动态 token。动态 token 具备时效性,适用于对于用户信息安全有较高要求的业务场景。
- 第三方回调:用户登录聊天室时的鉴权工作由指定的第三方服务器(可以是应用服务器)进行,云信服务端不做聊天室登录鉴权。选择第三方回调后,请至第三方回调配置进行相关设置。
实现流程
步骤1:准备 Token
根据以上配置的登录策略,您需要获取对应的 Token 以供后续鉴权。
-
静态 Token:默认永久有效。如有需要,可通过云信新版服务端 API 主动刷新 Token。
您可以通过以下两种方式获取静态 Token,用于静态 Token 登录的鉴权。
-
如果您只需要进行简单的体验或者快速测试,那么可以在云信控制台创建测试用的 IM 账号,并获取与该 IM 账号相应的静态 token,获取方式详见注册 IM 账号。
-
如果您在正式的生产环境,为了保障用户的信息安全,那么需要通过云信新版服务端 API 注册 IM 账号,并获取与之相对应的静态 token。获取方式详见注册云信 IM 账号。
-
-
动态 Token:具备时效性,可在生成时设置 token 的有效期。
注册云信 IM 账号,获取 IM 账号(
accountId
)和静态 token。基于 App Key、App Secret 和accountId
,通过约定算法在应用服务端生成动态 token。后续客户端可通过在登录聊天室时实现
V2NIMChatroomLoginOption#tokenProvider
方法,从回调中获取聊天室动态 token。具体实现方式详见下文动态 Token 登录。 -
动态登录扩展数据(LoginExtension):适用于所有登录模式。如果在第三方回调登录模式中设置动态登录扩展数据,第三方服务器可使用该值来进行鉴权。
后续客户端可通过在登录聊天室时实现
V2NIMChatroomLoginOption#loginExtensionProvider
方法,从回调中获取聊天室动态扩展数据loginExtension
。具体实现方式详见下文通过第三方回调登录。
步骤2:创建聊天室实例
调用 newInstance
方法创建聊天室实例。调用成功后,返回聊天室实例(instanceId
),聊天室实例与聊天室(roomId
)形成一一绑定关系。
Android/iOS/macOS/Windows
javaV2NIMChatroomClient chatroomClient = V2NIMChatroomClient.newInstance();
objective-cV2NIMChatroomClient *chatroomClient = [V2NIMChatroomClient newInstance];
cppauto chatroomClient = V2NIMChatroomClient::newInstance();
if (!chatroomClient) {
// create instance failed
// ...
return;
}
auto instanceId = chatroomClient->getInstanceId();
// save instanceId to cache
// ...
Web/uni-app/小程序/Harmony
需要在创建实例时传入聊天室初始化参数。
参数名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
initParams | V2NIMChatroomInitParams |
是 | 聊天室初始化参数,包括应用 AppKey 和自定义的设备类型。 |
typescriptconst chatroom = V2NIMChatroomClient.newInstance(
{
appkey: 'YOUR_APPKEY'
}
)
typescriptconst context: common.Context = getContext(this).getApplicationContext()
const chatroom = V2NIMChatroomClient.newInstance(context,
{
appkey: 'YOUR_APPKEY'
}
)
步骤3:注册聊天室登录相关事件监听
聊天室实例相关回调:
-
onChatroomStatus
:聊天室连接状态变更回调。聊天室内所有成员均会收到该回调。 -
onChatroomEntered
:进入聊天室回调。 -
onChatroomKicked
:被踢出聊天室回调。被踢出聊天室后,会同时触发onChatroomExited
回调。 -
onChatroomExited
:退出聊天室回调。退出聊天室后,不会继续重连。退出聊天室包括以下场景:
- 账号变更后登录失败导致退出聊天室。
- 被加入聊天室黑名单导致退出聊天室。
- 由于账号被封禁导致退出聊天室。
- 由于聊天室被关闭导致退出聊天室。
Android/iOS/macOS/Windows
调用 addChatroomClientListener
方法注册聊天室实例监听器,包括聊天室连接状态变更、进出聊天室、被踢出聊天室。示例代码如下:
javachatroomClient.addChatroomClientListener(new V2NIMChatroomClientListener() {
@Override
public void onChatroomStatus(V2NIMChatroomStatus status, V2NIMError error) {
}
@Override
public void onChatroomEntered() {
}
@Override
public void onChatroomExited(V2NIMError error) {
}
@Override
public void onChatroomKicked(V2NIMChatroomKickedInfo kickedInfo) {
}
});
objective-c@interface ClientListener : NSObject <V2NIMChatroomClientListener>
- (void)addToClient:(NSInteger)clientId;
@end
@implementation ClientListener
- (void)addToClient:(NSInteger)clientId
{
V2NIMChatroomClient *instance = [V2NIMChatroomClient getInstance:clientId];
[instance addChatroomClientListener:self];
}
- (void)onChatroomStatus:(V2NIMChatroomStatus)status
error:(nullable V2NIMError *)error
{
}
- (void)onChatroomEntered
{
}
- (void)onChatroomExited:(nullable V2NIMError *)error
{
}
- (void)onChatroomKicked:(V2NIMChatroomKickedInfo *)kickedInfo
{
}
@end
cppV2NIMChatroomClientListener listener;
listener.onChatroomStatus = [](V2NIMChatroomStatus status, nstd::optional<V2NIMError> error) {
// handle chatroom status
};
listener.onChatroomEntered = []() {
// handle chatroom entered
};
listener.onChatroomExited = [](nstd::optional<V2NIMError> error) {
// handle chatroom exited
};
listener.onChatroomKicked = [](V2NIMChatroomKickedInfo kickedInfo) {
// handle chatroom kicked
};
chatroomClient.addChatroomClientListener(listener);
如需移除聊天室实例相关监听器,可调用 removeChatroomClientListener
。
javachatroomClient.removeChatroomClientListener(chatroomClientListener);
objective-c@interface ClientListener : NSObject <V2NIMChatroomClientListener>
- (void)addToClient:(NSInteger)clientId;
- (void)removeFromClient:(NSInteger)clientId;
@end
@implementation ClientListener
- (void)addToClient:(NSInteger)clientId
{
V2NIMChatroomClient *instance = [V2NIMChatroomClient getInstance:clientId];
[instance addChatroomClientListener:self];
}
- (void)removeFromClient:(NSInteger)clientId
{
V2NIMChatroomClient *instance = [V2NIMChatroomClient getInstance:clientId];
[instance removeChatroomClientListener:self];
}
- (void)onChatroomStatus:(V2NIMChatroomStatus)status
error:(nullable V2NIMError *)error
{
}
- (void)onChatroomEntered
{
}
- (void)onChatroomExited:(nullable V2NIMError *)error
{
}
- (void)onChatroomKicked:(V2NIMChatroomKickedInfo *)kickedInfo
{
}
@end
cppV2NIMChatroomClientListener listener;
// ...
chatroomClient.addChatroomClientListener(listener);
// ...
chatroomClient.removeChatroomClientListener(listener);
Web/uni-app/小程序/Harmony
调用 on("EventName")
方法注册聊天室实例监听器,包括聊天室连接状态变更、进出聊天室、被踢出聊天室。
typescriptchatroom.on("onChatroomStatus", function (status: V2NIMChatroomStatus, err?: V2NIMError) {})
chatroom.on("onChatroomEntered", function () {})
chatroom.on("onChatroomExited", function (err?: V2NIMError) {})
chatroom.on("onChatroomKicked", function (kickedInfo: V2NIMChatroomKickedInfo) {})
typescriptconst chatroom = this.getInstance(instanceId)
chatroom.on("onChatroomStatus", (status: V2NIMChatroomStatus, err?: V2NIMError) => {
})
chatroom.on("onChatroomEntered", ()=> {
})
chatroom.on("onChatroomExited", (err?: V2NIMError) => {
})
chatroom.on("onChatroomKicked", (kickedInfo: V2NIMChatroomKickedInfo)=> {
})
如需移除登录相关监听器,可调用 off("EventName")
。
typescriptchatroom.off("onChatroomStatus", function (status: V2NIMChatroomStatus, err?: V2NIMError) {})
chatroom.off("onChatroomEntered", function () {})
chatroom.off("onChatroomExited", function (err?: V2NIMError) {})
chatroom.off("onChatroomKicked", function (kickedInfo: V2NIMChatroomKickedInfo) {})
typescriptchatroom.off("onChatroomStatus", function (status: V2NIMChatroomStatus, err?: V2NIMError) {})
chatroom.off("onChatroomEntered", function () {})
chatroom.off("onChatroomExited", function (err?: V2NIMError) {})
chatroom.off("onChatroomKicked", function (kickedInfo: V2NIMChatroomKickedInfo) {})
步骤4:获取聊天室地址
Harmony 可跳过此步骤。
在登录聊天室之前,需要先提前获取聊天室地址。可以通过以下两种方式获取:
-
若当前客户端已登录 IM,那么可以通过
getChatroomLinkAddress
方法获取指定聊天室的地址。Androidjava
NIMClient.getService(V2NIMLoginService.class).getChatroomLinkAddress("123", new V2NIMSuccessCallback<List<String>>() { @Override public void onSuccess(List<String> result) { // get success } }, new V2NIMFailureCallback() { @Override public void onFailure(V2NIMError error) { // get failed } });
iOSobjective-c
NSString *roomId = @"36"; [NIMSDK.sharedSDK.v2LoginService getChatroomLinkAddress:roomId success:^(NSArray<NSString *> *links) { // get success } failure:^(V2NIMError *error) { // get failed }];
macOS/Windowscpp
loginService.getChatroomLinkAddress( "roomId", [](nstd::vector<nstd::string> linkAddresses) { // handle link addresses }, [](V2NIMError error) { // handle error });
Web/uni-app/小程序typescript
const addressArray = await nim.V2NIMLoginService.getChatroomLinkAddress('36', isMiniApp)
-
若当前客户端未登录 IM,那么 SDK 无法获取聊天室服务器的地址,需要客户端向开发者应用服务器请求该地址,而应用服务器需要向网易云信服务器请求,然后将请求结果原路返回给客户端。具体请 参考获取聊天室地址 服务端 API。
步骤5:登录聊天室
通过调用 enter
方法建立聊天室长连接,登录聊天室,对应用户手动输入登录账号密码的场景。
调用后,SDK 会自动连接聊天室,传递用户信息并返回登录结果。登录过程中用户可主动取消登录。如果因为网络或其他原因导致服务端长时间未响应,用户未主动取消登录,SDK 将在 45 秒后自动重连 ,并返回错误码,详情请参见错误码。
javapublic void enter(String roomId, V2NIMChatroomEnterParams enterParams, V2NIMSuccessCallback<V2NIMChatroomEnterResult> success, V2NIMFailureCallback failure)
参数名称 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
roomId |
String | 是 | - | 聊天室 ID。如果为空、不合法、不存在则返回 191004 参数错误。 |
enterParams |
V2NIMChatroomEnterParams |
是 | - | 进入聊天室相关参数。 |
success |
V2NIMSuccessCallback |
是 | - | 进入聊天室成功回调,返回 V2NIMChatroomEnterResult 。 |
failure |
V2NIMFailureCallback |
是 | - | 进入聊天室失败回调,返回错误码。 |
objective-c- (void)enter:(NSString *)roomId
enterParams:(V2NIMChatroomEnterParams *)enterParams
success:(nullable V2NIMChatroomEnterResultCallback)success
failure:(nullable V2NIMFailureCallback)failure;
参数名称 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
roomId |
NSString * | 是 | - | 聊天室 ID。如果为空、不合法、不存在则返回 191004 参数错误。 |
enterParams |
V2NIMChatroomEnterParams |
是 | - | 进入聊天室相关参数。 |
success |
V2NIMChatroomEnterResultCallback |
是 | - | 进入聊天室成功回调,可自定义。 |
failure |
V2NIMFailureCallback |
是 | - | 进入聊天室失败回调,返回错误码。 |
cppvirtual void enter(std::string roomId,
V2NIMChatroomEnterParams enterParams,
V2NIMSuccessCallback<V2NIMChatroomEnterResult> success,
V2NIMFailureCallback failure) = 0;
参数名称 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
roomId |
std::string | 是 | - | 聊天室 ID。如果为空、不合法、不存在则返回 191004 参数错误。 |
enterParams |
V2NIMChatroomEnterParams |
是 | - | 进入聊天室相关参数。 |
success |
V2NIMSuccessCallback |
是 | - | 进入聊天室成功回调,返回 V2NIMChatroomEnterResult 。 |
failure |
V2NIMFailureCallback |
是 | - | 进入聊天室失败回调,返回错误码。 |
typescriptenter(roomId: string, enterParams: V2NIMChatroomEnterParams): Promise<V2NIMChatroomEnterResult>
参数名称 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
roomId |
string | 是 | - | 聊天室 ID。如果为空、不合法、不存在则返回 191004 参数错误。 |
enterParams |
V2NIMChatroomEnterParams |
是 | - | 进入聊天室相关参数。 |
typescriptenter(roomId: string, enterParams: V2NIMChatroomEnterParams): Promise<V2NIMChatroomEnterResult>
参数名称 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
roomId |
string | 是 | - | 聊天室 ID。如果为空、不合法、不存在则返回 191004 参数错误。 |
enterParams |
V2NIMChatroomEnterParams |
是 | - | 进入聊天室相关参数。 |
V2NIMChatroomEnterParams
的参数说明:
参数名称 | 类型 | 是否必填 | 默认值 | 描述 |
---|---|---|---|---|
anonymousMode |
Boolean | 否 | false | 是否为匿名模式进入聊天室。 在匿名模式下不能发消息,只能收消息。 |
accountId |
String | 否 | null | 用户账号。 |
token |
String | 否 | null | 静态 token,静态 Token 鉴权(V2NIMChatroomLoginOption.authType=0)时必填,否则可以不填。 |
roomNick |
String | 否 | 账号对应信息 | 进入聊天室后显示的昵称。 可以不填,默认显示账号对应相关信息,例如:匿名模式则默认昵称为账号名称。 |
roomAvatar |
String | 否 | 账号对应信息 | 进入聊天室后显示的头像,可通过 V2NIMStorageService.uploadFile 方法上传头像。可以不填,默认显示账号对应相关信息,例如:匿名模式则默认头像为空。 |
timeout |
Integer | 否 | 60 | 调用 enter 方法进入聊天室的超时时间。若超过该时间未成功进入聊天室,则返回失败回调。 |
loginOption |
V2NIMChatroomLoginOption |
否 | null | 聊天室登录配置。包括:authType (V2NIMLoginAuthType ),包括静态 Token 鉴权(默认)、动态 Token 鉴权、通过第三方回调鉴权。tokenProvider (V2NIMChatroomTokenProvider ),若使用动态 Token 鉴权(authType=1)则为必填。该回调在登录连接完成、登录鉴权校验前触发。若函数执行有异常或返回非预期内容(非法字符串),则登录中止并报错。loginExtensionProvider (V2NIMChatroomLoginExtensionProvider ),若使用第三方回调鉴权(authType=2)则为必填。该回调在登录连接完成、登录鉴权校验前触发。若函数执行有异常或返回非预期内容(非法字符串),则登录中止并报错。 |
linkProvider |
V2NIMChatroomLinkProvider |
是 | - | 聊天室连接地址回调,SDK 通过两种方式获取:V2NIMLoginService.getChatroomLinkAddress 方法获取聊天室连接地址。 |
serverExtension |
String | 否 | null | 服务端扩展字段,建议使用 JSON 格式,多端同步。长度上限为 4096 字符。 |
notificationExtension |
String | 否 | null | 进入聊天室通知的扩展字段,长度上限为 2048 字符。 |
tagConfig |
V2NIMChatroomTagConfig |
否 | null | 进入聊天室的标签信息配置。 |
locationConfig |
V2NIMChatroomLocationConfig |
否 | null | 进入聊天室的空间位置信息配置。 |
antispamConfig |
V2NIMAntispamConfig |
否 | null | 易盾反垃圾检测。 |
静态 Token 登录
使用静态 Token 登录时,V2NIMChatroomEnterParams.token
必填,V2NIMChatroomLoginOption.authType
设置为 0(默认)。
java//创建V2NIMChatroomClient(注意:不要每次都newInstance,用完不再使用需要destroyInstance)
V2NIMChatroomClient chatroomClient = V2NIMChatroomClient.newInstance();
//获取chatroomClient的实例ID,可以缓存起来,后面通过instanceId可以得到V2NIMChatroomClient
int instanceId = chatroomClient.getInstanceId()
……
V2NIMChatroomLinkProvider chatroomLinkProvider = new V2NIMChatroomLinkProvider() {
@Override
public List<String> getLinkAddress(String roomId, String accountId) {
return "聊天室Link地址";
}
};
V2NIMChatroomEnterParams enterParams = V2NIMChatroomEnterParams.V2NIMChatroomEnterParamsBuilder.builder(chatroomLinkProvider)
.withAccountId("账号名")
.withToken("静态token")
// 按需设置
//.withRoomNick("进入聊天室后显示的昵称")
//.withRoomAvatar("进入聊天室后显示的头像")
//.withTimeout("进入方法超时时间")
//.withServerExtension("用户扩展字段")
//.withNotificationExtension("通知扩展字段,进入聊天室通知开发者扩展字段")
//.withTagConfig("进入聊天室标签信息配置")
//.withLocationConfig("进入聊天室空间位置信息配置")
//.withAntispamConfig("用户资料反垃圾检测配置");
.build();
V2NIMChatroomClient chatroomClient = V2NIMChatroomClient.getInstance(instanceId);
if(chatroomClient != null){
chatroomClient.enter(roomId, enterParams,
new V2NIMSuccessCallback<V2NIMChatroomEnterResult>() {
@Override
public void onSuccess(V2NIMChatroomEnterResult result) {
//进入成功
}
},
new V2NIMFailureCallback() {
@Override
public void onFailure(V2NIMError error) {
//进入失败
}
});
}
使用静态 Token 登录时,V2NIMChatroomEnterParams.token
必填,V2NIMChatroomLoginOption.authType
设置为 0(默认)。
objective-c@interface V2NIMEnterChatroom: NSObject <V2NIMChatroomLinkProvider>
@end
@implementation V2NIMEnterChatroom
- (void)enter
{
NSString *roomId = @"36";
//创建V2NIMChatroomClient(注意:不要每次都newInstance,用完不再使用需要destroyInstance)
V2NIMChatroomClient *client = [V2NIMChatroomClient newInstance];
//获取chatroomClient的实例ID,可以缓存起来,后面通过instanceId可以得到V2NIMChatroomClient
NSInteger instanceId = client.getInstanceId;
V2NIMChatroomEnterParams *enterParams = [[V2NIMChatroomEnterParams alloc] init];
enterParams.linkProvider = self;
enterParams.accountId = @"账号名";
enterParams.token = @"静态token";
// 按需设置
// enterParams.roomNick: 进入聊天室后显示的昵称
// enterParams.roomAvatar: 进入聊天室后显示的头像
// enterParams.timeout: 进入方法超时时间
// enterParams.serverExtension: 用户扩展字段
// enterParams.notificationExtension: 通知扩展字段,进入聊天室通知开发者扩展字段
// enterParams.tagConfig: 进入聊天室标签信息配置
// enterParams.locationConfig: 进入聊天室空间位置信息配置
// enterParams.antispamConfig: 用户资料反垃圾检测配置
V2NIMChatroomClient *chatroomClient = [V2NIMChatroomClient getInstance:instanceId];
[chatroomClient enter:roomId
enterParams:enterParams
success:^(V2NIMChatroomEnterResult *result)
{
//进入成功
}
failure:^(V2NIMError *error)
{
//进入失败
}];
}
- (nullable NSArray<NSString *> *)getLinkAddress:(NSString *)roomId
accountId:(NSString *)accountId
{
return @[@"聊天室Link地址"];
}
@end
使用静态 Token 登录时,V2NIMChatroomEnterParams.token
必填,V2NIMChatroomLoginOption.authType
设置为 0(默认)。
cppV2NIMChatroomEnterParams enterParams;
enterParams.accountId = "accountId";
enterParams.token = "token";
enterParams.roomNick = "nick";
enterParams.roomAvatar = "avatar";
enterParams.linkProvider = [](nstd::string roomId, nstd::string account) {
nstd::vector<nstd::string> linkAddresses;
// get link addresses
// ...
return linkAddresses;
};
enterParams.serverExtension = "server extension";
enterParams.notificationExtension = "notification extension";
chatroomClient.enter(
"roomId",
enterParams,
[](V2NIMChatroomEnterResult result) {
// enter succeeded
},
[](V2NIMError error) {
// enter failed, handle error
});
使用静态 Token 登录时,V2NIMChatroomEnterParams.token
必填,V2NIMChatroomLoginOption.authType
设置为 0(默认)。
typescripttry {
const chatroom = V2NIMChatroomClient.newInstance({
appkey: 'YOUR_APPKEY',
debugLevel: 'debug'
})
await chatroom.enter('YOUR_ROOM_ID', {
accountId: 'YOUR_ACCOUNT_ID',
token: 'YOUR_TOKEN'
})
} catch (err) {
// TODO failed, check code
// console.log(err.code)
}
使用静态 Token 登录时,V2NIMChatroomEnterParams.token
必填,V2NIMChatroomLoginOption.authType
设置为 0(默认)。
typescripttry {
const chatroom = V2NIMChatroomClient.newInstance({
appkey: 'YOUR_APPKEY',
debugLevel: 'debug'
})
await chatroom.enter('YOUR_ROOM_ID', {
accountId: 'YOUR_ACCOUNT_ID',
token: 'YOUR_TOKEN'
})
} catch (err) {
// TODO failed, check code
// console.log(err.code)
}
动态 Token 登录
使用动态 Token 登录时,V2NIMChatroomLoginOption.authType
设置为 1,并设置获取动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
。
java//创建V2NIMChatroomClient(注意:不要每次都newInstance,用完不再使用需要destroyInstance)
V2NIMChatroomClient chatroomClient = V2NIMChatroomClient.newInstance();
//获取chatroomClient的实例ID,可以缓存起来,后面通过instanceId可以得到V2NIMChatroomClient
int instanceId = chatroomClient.getInstanceId()
……
V2NIMChatroomLinkProvider chatroomLinkProvider = new V2NIMChatroomLinkProvider() {
@Override
public List<String> getLinkAddress(String roomId, String accountId) {
return "聊天室Link地址";
}
};
V2NIMChatroomLoginOption loginOption = V2NIMChatroomLoginOption.V2NIMChatroomLoginOptionBuilder.builder()
.withAuthType(V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN)
.withTokenProvider(new V2NIMChatroomTokenProvider() {
@Override
public String getToken(String roomId, String account) {
return "动态登录Token"
}
})
.build();
V2NIMChatroomEnterParams enterParams = V2NIMChatroomEnterParams.V2NIMChatroomEnterParamsBuilder.builder(chatroomLinkProvider)
.withAccountId("账号名")
.withLoginOption(loginOption)
// 按需设置
//.withRoomNick("进入聊天室后显示的昵称")
//.withRoomAvatar("进入聊天室后显示的头像")
//.withTimeout("进入方法超时时间")
//.withServerExtension("用户扩展字段")
//.withNotificationExtension("通知扩展字段,进入聊天室通知开发者扩展字段")
//.withTagConfig("进入聊天室标签信息配置")
//.withLocationConfig("进入聊天室空间位置信息配置")
//.withAntispamConfig("用户资料反垃圾检测配置");
.build();
V2NIMChatroomClient chatroomClient = V2NIMChatroomClient.getInstance(instanceId);
if(chatroomClient != null){
chatroomClient.enter(roomId, enterParams,
new V2NIMSuccessCallback<V2NIMChatroomEnterResult>() {
@Override
public void onSuccess(V2NIMChatroomEnterResult result) {
//进入成功
}
},
new V2NIMFailureCallback() {
@Override
public void onFailure(V2NIMError error) {
//进入失败
}
});
}
使用动态 Token 登录时,V2NIMChatroomLoginOption.authType
设置为 1,并设置获取动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
。
objective-c@interface V2NIMEnterChatroom: NSObject <V2NIMChatroomLinkProvider, V2NIMChatroomTokenProvider>
@end
@implementation V2NIMEnterChatroom
- (void)enter
{
NSString *roomId = @"36";
//创建V2NIMChatroomClient(注意:不要每次都newInstance,用完不再使用需要destroyInstance)
V2NIMChatroomClient *client = [V2NIMChatroomClient newInstance];
//获取chatroomClient的实例ID,可以缓存起来,后面通过instanceId可以得到V2NIMChatroomClient
NSInteger instanceId = client.getInstanceId;
……
V2NIMChatroomLoginOption *option = [[V2NIMChatroomLoginOption alloc] init];
option.authType = V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN;
option.tokenProvider = self;
V2NIMChatroomEnterParams *enterParams = [[V2NIMChatroomEnterParams alloc] init];
enterParams.linkProvider = self;
enterParams.accountId = @"账号名";
enterParams.loginOption = option;
// 按需设置
// enterParams.roomNick: 进入聊天室后显示的昵称
// enterParams.roomAvatar: 进入聊天室后显示的头像
// enterParams.timeout: 进入方法超时时间
// enterParams.serverExtension: 用户扩展字段
// enterParams.notificationExtension: 通知扩展字段,进入聊天室通知开发者扩展字段
// enterParams.tagConfig: 进入聊天室标签信息配置
// enterParams.locationConfig: 进入聊天室空间位置信息配置
// enterParams.antispamConfig: 用户资料反垃圾检测配置
V2NIMChatroomClient *chatroomClient = [V2NIMChatroomClient getInstance:instanceId];
[chatroomClient enter:roomId
enterParams:enterParams
success:^(V2NIMChatroomEnterResult *result)
{
//进入成功
}
failure:^(V2NIMError *error)
{
//进入失败
}];
}
- (nullable NSArray<NSString *> *)getLinkAddress:(NSString *)roomId
accountId:(NSString *)accountId
{
return @[@"聊天室Link地址"];
}
- (nullable NSString *)getToken:(NSString *)roomId accountId:(NSString *)accountId {
return @"动态登录Token";
}
@end
使用动态 Token 登录时,V2NIMChatroomLoginOption.authType
设置为 1,并设置获取动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
。
cppV2NIMChatroomEnterParams enterParams;
enterParams.accountId = "accountId";
enterParams.roomNick = "nick";
enterParams.roomAvatar = "avatar";
enterParams.linkProvider = [](nstd::string roomId, nstd::string account) {
nstd::vector<nstd::string> linkAddresses;
// get link addresses
// ...
return linkAddresses;
};
enterParams.loginOption.authType = V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN;
enterParams.loginOption.tokenProvider = [](nstd::string roomId, nstd::string account) {
nstd::string dynamicToken;
// get dynamic token
// ...
// return null on fail
return dynamicToken;
};
enterParams.serverExtension = "server extension";
enterParams.notificationExtension = "notification extension";
chatroomClient.enter(
"roomId",
enterParams,
[](V2NIMChatroomEnterResult result) {
// enter succeeded
},
[](V2NIMError error) {
// enter failed, handle error
});
使用动态 Token 登录时,V2NIMChatroomLoginOption.authType
设置为 1,并设置获取动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
。
typescripttry {
const chatroom = V2NIMChatroomClient.newInstance({
appkey: 'YOUR_APPKEY',
debugLevel: 'debug'
})
await chatroom.enter('YOUR_ROOM_ID', {
accountId: 'YOUR_ACCOUNT_ID',
loginOption: {
// authType == 1时,登录方式为动态 token
authType: 1,
// 服务器动态签算动态token
tokenProvider: async function(appkey, roomId, account) {
return await fetch('YOUR_SERVER_URL', {
body: JSON.stringify({
appkey, roomId, account
})
})
}
}
})
} catch (err) {
// TODO failed, check code
// console.log(err.code)
}
使用动态 Token 登录时,V2NIMChatroomLoginOption.authType
设置为 1,并设置获取动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
。
typescripttry {
const chatroom = V2NIMChatroomClient.newInstance({
appkey: 'YOUR_APPKEY',
debugLevel: 'debug'
})
await chatroom.enter('YOUR_ROOM_ID', {
accountId: 'YOUR_ACCOUNT_ID',
loginOption: {
// authType == 1时,登录方式为动态 token
authType: 1,
// 服务器动态签算动态token
tokenProvider: async function(appkey, roomId, account) {
return await fetch('YOUR_SERVER_URL', {
body: JSON.stringify({
appkey, roomId, account
})
})
}
}
})
} catch (err) {
// TODO failed, check code
// console.log(err.code)
}
第三方回调登录
如采用该登录方式,云信聊天室不做登录鉴权,鉴权工作需由指定的第三方服务器(可以是应用服务器)进行。
-
需要先在云信控制台开通和配置第三方服务。
-
调用
enter
登录聊天室。 -
在服务端发起登录相关回调请求,由第三方服务器进行鉴权并判定聊天室登录事件是否放行通过。若不通过,云信服务端将返回 302 错误码。
需要采用第三方服务器的动态登录扩展数据或动态 Token 进行鉴权,那么需要将 V2NIMChatroomLoginOption.authType
设置为 2,并设置获取动态登录扩展数据 V2NIMChatroomLoginOption.loginExtensionProvider
回调和动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
,SDK 会在登录过程中获取第三方回调的动态扩展数据和动态 Token。
java//创建V2NIMChatroomClient(注意:不要每次都newInstance,用完不再使用需要destroyInstance)
V2NIMChatroomClient chatroomClient = V2NIMChatroomClient.newInstance();
//获取chatroomClient的实例ID,可以缓存起来,后面通过instanceId可以得到V2NIMChatroomClient
int instanceId = chatroomClient.getInstanceId()
……
V2NIMChatroomLinkProvider chatroomLinkProvider = new V2NIMChatroomLinkProvider() {
@Override
public List<String> getLinkAddress(String roomId, String accountId) {
return "聊天室Link地址";
}
};
V2NIMChatroomLoginOption loginOption = V2NIMChatroomLoginOption.V2NIMChatroomLoginOptionBuilder.builder()
.withAuthType(V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN)
.withTokenProvider(new V2NIMChatroomTokenProvider() {
@Override
public String getToken(String roomId, String account) {
return "第三方登录Token"
}
})
.withLoginExtensionProvider(new V2NIMChatroomLoginExtensionProvider() {
@Override
public String getLoginExtension(String roomId, String accountId) {
return "聊天室登录扩展"
}
});
.build();
V2NIMChatroomEnterParams enterParams = V2NIMChatroomEnterParams.V2NIMChatroomEnterParamsBuilder.builder(chatroomLinkProvider)
.withAccountId("账号名")
.withLoginOption(loginOption)
// 按需设置
//.withRoomNick("进入聊天室后显示的昵称")
//.withRoomAvatar("进入聊天室后显示的头像")
//.withTimeout("进入方法超时时间")
//.withServerExtension("用户扩展字段")
//.withNotificationExtension("通知扩展字段,进入聊天室通知开发者扩展字段")
//.withTagConfig("进入聊天室标签信息配置")
//.withLocationConfig("进入聊天室空间位置信息配置")
//.withAntispamConfig("用户资料反垃圾检测配置");
.build();
V2NIMChatroomClient chatroomClient = V2NIMChatroomClient.getInstance(instanceId);
if(chatroomClient != null){
chatroomClient.enter(roomId, enterParams,
new V2NIMSuccessCallback<V2NIMChatroomEnterResult>() {
@Override
public void onSuccess(V2NIMChatroomEnterResult result) {
//进入成功
}
},
new V2NIMFailureCallback() {
@Override
public void onFailure(V2NIMError error) {
//进入失败
}
});
}
需要采用第三方服务器的动态登录扩展数据或动态 Token 进行鉴权,那么需要将 V2NIMChatroomLoginOption.authType
设置为 2,并设置获取动态登录扩展数据 V2NIMChatroomLoginOption.loginExtensionProvider
回调和动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
,SDK 会在登录过程中获取第三方回调的动态扩展数据和动态 Token。
objective-c@interface V2NIMEnterChatroom: NSObject <V2NIMChatroomLinkProvider, V2NIMChatroomTokenProvider, V2NIMChatroomLoginExtensionProvider>
@end
@implementation V2NIMEnterChatroom
- (void)enter
{
NSString *roomId = @"36";
//创建V2NIMChatroomClient(注意:不要每次都newInstance,用完不再使用需要destroyInstance)
V2NIMChatroomClient *client = [V2NIMChatroomClient newInstance];
//获取chatroomClient的实例ID,可以缓存起来,后面通过instanceId可以得到V2NIMChatroomClient
NSInteger instanceId = client.getInstanceId;
V2NIMChatroomLoginOption *option = [[V2NIMChatroomLoginOption alloc] init];
option.authType = V2NIM_LOGIN_AUTH_TYPE_THIRD_PARTY;
option.tokenProvider = self;
option.loginExtensionProvider = self;
V2NIMChatroomEnterParams *enterParams = [[V2NIMChatroomEnterParams alloc] init];
enterParams.linkProvider = self;
enterParams.accountId = @"账号名";
enterParams.loginOption = option;
// 按需设置
// enterParams.roomNick: 进入聊天室后显示的昵称
// enterParams.roomAvatar: 进入聊天室后显示的头像
// enterParams.timeout: 进入方法超时时间
// enterParams.serverExtension: 用户扩展字段
// enterParams.notificationExtension: 通知扩展字段,进入聊天室通知开发者扩展字段
// enterParams.tagConfig: 进入聊天室标签信息配置
// enterParams.locationConfig: 进入聊天室空间位置信息配置
// enterParams.antispamConfig: 用户资料反垃圾检测配置
V2NIMChatroomClient *chatroomClient = [V2NIMChatroomClient getInstance:instanceId];
[chatroomClient enter:roomId
enterParams:enterParams
success:^(V2NIMChatroomEnterResult *result)
{
//进入成功
}
failure:^(V2NIMError *error)
{
//进入失败
}];
}
- (nullable NSArray<NSString *> *)getLinkAddress:(NSString *)roomId
accountId:(NSString *)accountId
{
return @[@"聊天室Link地址"];
}
- (nullable NSString *)getToken:(NSString *)roomId accountId:(NSString *)accountId {
return @"动态登录Token";
}
- (nullable NSString *)getLoginExtension:(NSString *)roomId accountId:(NSString *)accountId {
return @"聊天室登录扩展";
}
@end
需要采用第三方服务器的动态登录扩展数据或动态 Token 进行鉴权,那么需要将 V2NIMChatroomLoginOption.authType
设置为 2,并设置获取动态登录扩展数据 V2NIMChatroomLoginOption.loginExtensionProvider
回调和动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
,SDK 会在登录过程中获取第三方回调的动态扩展数据和动态 Token。
cppV2NIMChatroomEnterParams enterParams;
enterParams.accountId = "accountId";
enterParams.roomNick = "nick";
enterParams.roomAvatar = "avatar";
enterParams.linkProvider = [](nstd::string roomId, nstd::string account) {
nstd::vector<nstd::string> linkAddresses;
// get link addresses
// ...
return linkAddresses;
};
enterParams.loginOption.authType = V2NIM_LOGIN_AUTH_TYPE_THIRD_PARTY;
enterParams.loginOption.loginExtensionProvider = [](nstd::string roomId, nstd::string account) {
nstd::string loginExtension;
// get login extension
// ...
// return null on fail
return loginExtension;
};
enterParams.serverExtension = "server extension";
enterParams.notificationExtension = "notification extension";
chatroomClient.enter(
"roomId",
enterParams,
[](V2NIMChatroomEnterResult result) {
// enter succeeded
},
[](V2NIMError error) {
// enter failed, handle error
});
需要采用第三方服务器的动态登录扩展数据或动态 Token 进行鉴权,那么需要将 V2NIMChatroomLoginOption.authType
设置为 2,并设置获取动态登录扩展数据 V2NIMChatroomLoginOption.loginExtensionProvider
回调和动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
,SDK 会在登录过程中获取第三方回调的动态扩展数据和动态 Token。
typescripttry {
const chatroom = V2NIMChatroomClient.newInstance({
appkey: 'YOUR_APPKEY',
debugLevel: 'debug'
})
await chatroom.enter('YOUR_ROOM_ID', {
accountId: 'YOUR_ACCOUNT_ID',
loginOption: {
// authType == 2时,登录方式为通过第三方回调鉴权
authType: 2,
// 服务器动态签算动态token
loginExtensionProvider: async function(account) {
return await fetch('YOUR_SERVER_URL', {
body: JSON.stringify({
account
})
})
}
}
})
} catch (err) {
// TODO failed, check code
// console.log(err.code)
}
需要采用第三方服务器的动态登录扩展数据或动态 Token 进行鉴权,那么需要将 V2NIMChatroomLoginOption.authType
设置为 2,并设置获取动态登录扩展数据 V2NIMChatroomLoginOption.loginExtensionProvider
回调和动态 Token 回调 V2NIMChatroomLoginOption.tokenProvider
,SDK 会在登录过程中获取第三方回调的动态扩展数据和动态 Token。
typescripttry {
const chatroom = V2NIMChatroomClient.newInstance({
appkey: 'YOUR_APPKEY',
debugLevel: 'debug'
})
await chatroom.enter('YOUR_ROOM_ID', {
accountId: 'YOUR_ACCOUNT_ID',
loginOption: {
// authType == 2时,登录方式为通过第三方回调鉴权
authType: 2,
// 服务器动态签算动态token
loginExtensionProvider: async function(account) {
return await fetch('YOUR_SERVER_URL', {
body: JSON.stringify({
account
})
})
}
}
})
} catch (err) {
// TODO failed, check code
// console.log(err.code)
}
步骤6:获取聊天室服务
登录聊天室成功后,调用getChatroomService
方法获取聊天室服务。后续聊天室相关操作(聊天室成员、消息等)均在返回的 V2NIMChatroomService
类中实现。
Web/uni-app/小程序可跳过此步骤。
javaV2NIMChatroomService chatroomService = chatroomClient.getChatroomService()
objective-c[[V2NIMChatroomClient getInstance:instanceId] getChatroomService];
cppauto& chatroomService = client.getChatroomService();
typescriptconst client: V2NIMChatroomClient = this.getInstance(instanceId)
const ret = client.chatroomService
步骤7:登出聊天室
注销聊天室登录(即退出聊天室)后,会断开聊天室对应的连接,不再接收关于此聊天室的任何消息。如果应用退出时聊天室仍处于登录状态,请手动调用 exit
方法退出聊天室。
调用 exit
方法退出聊天室成功后,会收到 onChatroomExited
回调。如果已在云信控制台开启了聊天室用户进出消息系统下发功能,聊天室内所有其他成员会收到回调onChatroomMemberExit
。如未开启,可参见开通和配置聊天室功能。
退出聊天室后,聊天室实例(instanceId)将与聊天室(roomId)解除绑定关系。
javachatroomCore.exit();
objective-c[[V2NIMChatroomClient getInstance:instanceId] exit];
cppchatroomClient.exit();
typescriptchatroom.exit()
typescriptconst client = this.getInstance(instanceId)
client.exit()
步骤8:销毁聊天室实例
调用 destroyInstance
方法销毁聊天室实例。
javaV2NIMChatroomClient.destroyInstance(instanceId);
objective-c[V2NIMChatroomClient destroyInstance:instanceId];
cppuint32_t instanceId{0};
// get instanceId from cache
// ...
V2NIMChatroomClient::destroyInstance(instanceId);
typescriptV2NIMChatroomClient.destroyInstance(this.instanceId)
typescriptV2NIMChatroomClient.destroyInstance(this.instanceId)
相关信息
断网重连
SDK 提供了自动重连机制(自动重新建立与网易云信服务器的连接并重新登录)。
当成功登录聊天室后,若因为网络状态差或其他问题导致网络超时时,SDK 会持续有策略地进行自动重连,此时不需要上层开发者去做额外的重登逻辑。
多端登录与互踢
当前 NIM SDK 支持配置两种不同的聊天室多端登录与互踢策略:只允许一端登录、各端均可以同时登录在线。
您可通过两种方式实现聊天室的多端登录与互踢。
方式一:通过云信控制台配置
当前 NIM SDK 支持通过云信控制台配置两种不同的聊天室多端登录策略:
- 只允许一端登录,Windows、Web、Android、iOS 彼此互踢。同一账号仅允许在一台设备上登录。当该账号在另一台设备上成功登录时,新设备会将旧设备踢下线。
- 各端均可以同时登录在线。最多可支持 10 个设备同时在线,在设备数上限内,所有的新设备再次登录,均不会将在线的旧设备踢下线。
通过该方式的配置,可实现自动管控聊天室的多端登录。具体如何配置,请参见开通和配置聊天室功能。
- 控制台修改多端互踢的逻辑之后,下次新的设备登录时才会基于新的多端互踢策略进行校验,已经建立连接的设备不会因为策略的修改被强制踢出。
- 如果某台设备重复登录同一个聊天室,后登录的会将前面的长连接断开,此时会再触发一次进入聊天室的抄送,但是不会触发退出聊天室的抄送。关于进出聊天室(eventType=9)的抄送请参见聊天室成员进出聊天室事件抄送。
方式二:主动将其他端踢下线
-
本端(踢人方)登录聊天室。
-
同一账号的其他客户端(被踢方)注册
onChatroomExited
事件回调并登录聊天室。 -
本端(踢人方)调用
V2NIMChatroomService#kickMember
方法将其他同时登录的客户端踢下线。
javaV2NIMChatroomClient v2ChatroomClient = V2NIMChatroomClient.getInstance(instanceId);
V2NIMChatroomService v2ChatroomService = v2ChatroomClient.getChatroomService();
// 被踢的成员ID
String accountId = "test";
// 设置通知扩展字段,可不传
String notificationExtension = "xxx";
v2ChatroomService.kickMember(accountId, notificationExtension, new V2NIMSuccessCallback<Void>() {
@Override
public void onSuccess(Void unused) {
// 踢出成功
}
}, new V2NIMFailureCallback() {
@Override
public void onFailure(V2NIMError error) {
// 踢出失败
}
});
objective-c// 通过实例 ID 获取聊天室实例
id <V2NIMChatroomService> service = [[V2NIMChatroomClient getInstance:1] getChatroomService];
// 被踢的成员 ID
NSString *accountId = @"accountId";
// 设置通知扩展字段,可不传
NSString *notificationExtension = @"xxx";
[service kickMember:accountId
notificationExtension:notificationExtension
success:^() {
// 踢出成功
}
failure:^(V2NIMError *error) {
// 踢出失败
}];
cppchatroomService.kickMember(
"accountId",
"notificationExtension",
[]() {
// kick member succeeded
},
[](V2NIMError error) {
// kick member failed, handle error
});
typescriptawait chatroom.V2NIMChatroomService.kickMember('account', 'notificationExtension')
typescriptawait this.chatroomClient.chatroomService.kickMember('account', 'notificationExtension')
-
其他客户端(被踢方)被踢下线后,会收到被踢回调信息(
V2NIMChatroomKickedInfo
),包含被踢原因(kickedReason
)和被踢的扩展字段(serverExtension
)。收到被踢回调后,建议进行注销并切换到登录界面。
常见问题
如何处理登录请求被拒绝问题
若您开启了应用标识安全验证,需要在将列表中写入允许的客户端应用标识。当请求登录的客户端应用标识不在列表中时,登录请求将被拒绝。
在控制台首页应用管理选择应用进入应用配置页面,顶部选择标识管理页签,添加对应的客户端应用标识。
日活计算
- 非匿名登录,同一个账号同一天无论进入多少个聊天室,进入多少次,都只计算一个日活。
- 匿名登录,每进入一次聊天室,就计算一个日活。