话单

更新时间: 2026/01/09 10:02:49

呼叫组件提供通话话单功能,在一通通话结束后,您会收到对应的通话话单。通话话单是一条事件通知消息,标记此次呼叫的状态。话单以 IM 会话类型消息抄送的形式发送,收到话单后,您可以解析消息体,获得通话时间等通话详情。

云信呼叫组件的话单消息共有 5 类,其中 4 类为 未接通时的话单(主叫方客户端发送),1 类为 带有通话时长的正常话单(服务端直接发送)。

由主叫方客户端发送的未接通话单包括 拒接话单占线话单超时未接听话单主叫取消话单

下图为常见话单示例,从上至下分别为主叫取消话单、被叫拒绝话单、超时未接听话单、被叫占线话单、正常通话带有时长的话单。

image-netease

多人通话默认未封装话单功能。若您需要使用话单,请通过其他方式自行实现。

使用话单功能

方式一:使用组件封装的话单

第一步:开通话单抄送

  1. 登录网易云信控制台。开通 IM 即时通讯、音视频通话以及信令(信令是 IM 即时通讯的子功能,需要单独开通)。具体请参考 开通或关闭功能

  2. 在抄送消息中开通呼叫组件的话单抄送。

    话单开通.png

第二步:发送话单

开通话单功能后,默认发送话单消息。

呼叫组件不包含话单接收及解析功能,用户需要参考示例项目源码自行实现。详细说明请参考 消息收发

第三步:接收并解析话单

话单消息同普通消息一样通过 NIM SDK 进行消息接收,示例代码如下:

Objective-C@interface NEMenuViewController ()<V2NIMMessageListener>
@end

@implementation NEMenuViewController

- (void)dealloc {
    [[[NIMSDK sharedSDK] v2MessageService] addMessageListener:self];
}

- (void)viewDidLoad {
    [[[NIMSDK sharedSDK] v2MessageService] removeMessageListener:self];
}

#pragma mark - IM delegate
- (void)onSendMessage:(V2NIMMessage *)message {
    if (message.sendingState == V2NIM_MESSAGE_SENDING_STATE_SENDING) {
        [self assmebleRecordWithV2Message:message withCaller:YES];
    }
}

- (void)onReceiveMessages:(NSArray<V2NIMMessage *> *)messages;
    for (V2NIMMessage *message in messages) {
        if ([message.senderId isEqualToString:[NEAccount shared].userModel.imAccid]) {
            [self assmebleRecordWithMessage:message withCaller:YES];
            return;
        }
        [self assmebleRecordWithV2Message:message withCaller:NO];
    }

}

@end

话单消息结构

话单类型 说明
NIMRtcCallStatusComplete 1 正常通话话单,通话双方都进入音视频通话后进行挂断。由服务器发送。
NIMRtcCallStatusCanceled 2 主叫取消话单,主叫呼叫后主动取消的话单。由客户端主叫方发送。
NIMRtcCallStatusRejected 3 被叫拒接话单,被叫拒接接听后的话单。客户端主叫方收到被叫拒接消息后进行发送。
NIMRtcCallStatusTimeout 4 超时话单,被叫收到通话邀请后不操作等待超时产生的话单。客户端主叫方发送。
NIMRtcCallStatusBusy 5 占线话单(用户忙),当主叫呼叫被叫时,被叫仍处于通话以及呼叫/被叫中,此时被叫会拒绝主叫的通话邀请。客户端主叫收到消息后会发送占线话单。

话单以 IM 消息抄送的形式发送,抄送类型为会话类型,即 eventType 为 1。会话类型的消息体中一般包含 eventTypeconvTypetofromAccountmsgTimestamp、msgTypemsgidClientmsgidServerattach 等字段,全量字段请参考 返回数据的 JSON 字段说明。其中:

  • 话单消息的 msgType 字段的值为 NRTC_NETCALL,表示音视频话单消息抄送。

  • 话单消息中 attach 字段中包含通话类型、呼叫状态等通话详情,请参考以下表格:

    字段 类型 示例 说明

    type

    Number

    1

    通话类型。

    • 1:音频通话。
    • 2:视频通话。
    channelId Number 123 房间 ID。

    status

    Number

    1

    呼叫状态。

    • 1:通话正常结束。
    • 2:主叫取消呼叫。
    • 3:被叫拒绝通话。
    • 4:被叫未接听呼叫,呼叫因超时被取消。
    • 5:被叫忙线,通话未接通。

    durations

    JsonArray

    通话过程详情,JSON 数组格式,其中包括:

    • accid:通话成员的 accid。
    • duration:对应成员的通话时长。

收到的话单的 JSON 结构:

JSON{
   "type": 1,                       //1 表示音频,2 表示视频
   "channelId": 123,                //G2 的 channelId
   "status": 1,                     //1 表示正常结束通话话单,对应上表的话单类型
   "durations": [
           {
               "accid":"acc01",
               "duration":10
           },
           {
               "accid":"acc02",
               "duration":12
           }
   ]
}

接收到消息后进行消息解析。示例代码如下:

Objective-C- (void)assmebleRecordWithV2Message:(V2NIMMessage *)message withCaller:(BOOL)isCaller {
    V2NIMMessageCallAttachment *recordObject = (V2NIMMessageCallAttachment *)message.attachment;

    // 音频/视频 类型通话
    NIMRtcCallType type = (NIMRtcCallType)recordObject.type;

    // 话单类型
    NIMRtcCallStatus status = (NIMRtcCallStatus)recordObject.status;

    //// 时长列表
    NSArray<V2NIMMessageCallDuration *>*durations = recordObject.durations;

    switch (status) {
        case NIMRtcCallStatusComplete:
            // 成功接听
            break;
        case NIMRtcCallStatusCanceled:
            // 主叫用户取消
            break;
        case NIMRtcCallStatusRejected:
            // 被叫用户拒接
            break;
        case NIMRtcCallStatusTimeout:
            // 被叫接听超时
            break;
        case NIMRtcCallStatusBusy:
            // 被叫用户在通话中,占线
            break;
        default:
            break;
    }
}

方式二:自行实现话单

若组件自带的话单功能无法满足您的业务需求,可以参考以下步骤自行实现话单。

  1. 关闭 服务端 话单抄送。具体步骤请参考 开通话单功能

  2. 网易云信控制台 开通房间时长消息抄送(eventType=8)。详细步骤请参考 开通消息抄送

  3. 确定话单协议,通常用 JSON 表示。

    JSON{
      "type": 1   // 话单类型
      "data": ... // 话单消息内容,如通话时长等信息
    }
    
  4. 设置 setCallRecordProvider,实现开发者自己的话单逻辑(设置 setCallRecordProvider 后客户端本地不再发送组件内部话单),参考 自定义消息发送,将步骤 3 中确定的话单协议作为自定义内容进行发送。

    您可以通过设置自定义的回调来发送话单。

    此处仅回调未接通话单,接通话单需要您在通话结束后独立处理。

    Objective-C//设置自定义话单回调
    [[NECallEngine sharedInstance] setCallRecordProvider:self];
    
    // 接收话单回调,自定义发送内容,并发送话单
    - (void)onRecordSend:(NERecordConfig *)config{
    // 发送未成功通话话单
    }
    

    NERecordConfig 通话话单字段说明:

    字段 类型 示例
    accId NSString 通话对端的用户 ID。
    callType NECallType 通话类型,包括:
    • NECallType.AUDIO:音频通话
    • NECallType.VIDEO:视频通话
    callState NIMRtcCallStatus 通话话单类型(NERecordCallStatus),具体请参考 话单消息结构

关闭话单功能

若您不需要使用话单功能,可以参考以下步骤关闭:

  1. 关闭 服务端 话单抄送。具体步骤请参考 开通话单功能

  2. 关闭 客户端 话单发送。设置 setCallRecordProvider,然后空实现 onRecordSend 回调。

    Objective-C//设置自定义话单回调
    [[NECallEngine sharedInstance] setCallRecordProvider:self];
    
    // 接收话单回调,并空实现
    - (void)onRecordSend:(NERecordConfig *)config{
        //空实现即可
    }
    
此文档是否对你有帮助?
有帮助
去反馈
  • 使用话单功能
  • 方式一:使用组件封装的话单
  • 第一步:开通话单抄送
  • 第二步:发送话单
  • 第三步:接收并解析话单
  • 方式二:自行实现话单
  • 关闭话单功能