更新时间:2025-10-16 GMT+08:00
呼叫事件与话单通知
package com.huawei.hosting.service.voice; import org.apache.log4j.Logger; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; /** * 呼叫事件通知/话单通知/短信通知 * 客户平台收到隐私保护通话平台的呼叫事件通知/话单通知/短信通知,可按如下样例解析处理 */ public class HostingVoiceEventDemoImpl { private Logger logger = Logger.getLogger(HostingVoiceEventDemoImpl.class); /** * 呼叫事件 for AXB/AX/AXE * * @param jsonBody * @breif 详细内容以接口文档为准 */ public void onCallEvent(String jsonBody) { // 封装JOSN请求 JSONObject json = JSON.parseObject(jsonBody); String eventType = json.getString("eventType"); // 通知事件类型 if ("fee".equalsIgnoreCase(eventType)) { logger.info("EventType error: " + eventType); return; } JSONObject statusInfo = json.getJSONObject("statusInfo"); // 呼叫状态事件信息 logger.info("eventType: " + eventType); // 打印通知事件类型 //callin:呼入事件 if ("callin".equalsIgnoreCase(eventType)) { /** * Example: 此处以解析notifyMode为例,请按需解析所需参数并自行实现相关处理 * * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳 * 'sessionId': 通话链路的标识ID * 'caller': 主叫号码 * 'called': 被叫号码 * 'subscriptionId': 绑定关系ID,AXE模式不携带该参数 */ String sessionId = statusInfo.getString("sessionId"); logger.info("sessionId: " + sessionId); return; } //collectInfo:放音收号结果事件,仅AXE模式下的A被叫场景携带 if ("collectInfo".equalsIgnoreCase(eventType)) { /** * Example: 此处以解析digitInfo为例,请按需解析所需参数并自行实现相关处理 * * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳 * 'sessionId': 通话链路的标识ID * 'digitInfo': AXE场景中携带收号结果(即用户输入的数字) */ String digitInfo = statusInfo.getString("digitInfo"); logger.info("digitInfo: " + digitInfo); return; } //callout:呼出事件 if ("callout".equalsIgnoreCase(eventType)) { /** * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理 * * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳 * 'sessionId': 通话链路的标识ID * 'caller': 主叫号码 * 'called': 被叫号码 * 'subscriptionId': 绑定关系ID */ String sessionId = statusInfo.getString("sessionId"); logger.info("sessionId: " + sessionId); return; } //alerting:振铃事件 if ("alerting".equalsIgnoreCase(eventType)) { /** * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理 * * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳 * 'sessionId': 通话链路的标识ID * 'caller': 主叫号码 * 'called': 被叫号码 * 'subscriptionId': 绑定关系ID */ String sessionId = statusInfo.getString("sessionId"); logger.info("sessionId: " + sessionId); return; } //answer:应答事件 if ("answer".equalsIgnoreCase(eventType)) { /** * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理 * * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳 * 'sessionId': 通话链路的标识ID * 'caller': 主叫号码 * 'called': 被叫号码 * 'subscriptionId': 绑定关系ID */ String sessionId = statusInfo.getString("sessionId"); logger.info("sessionId: " + sessionId); return; } //disconnect:挂机事件 if ("disconnect".equalsIgnoreCase(eventType)) { /** * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理 * * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳 * 'sessionId': 通话链路的标识ID * 'caller': 主叫号码 * 'called': 被叫号码 * 'stateCode': 通话挂机的原因值 * 'stateDesc': 通话挂机的原因值的描述 * 'subscriptionId': 绑定关系ID */ String sessionId = statusInfo.getString("sessionId"); logger.info("sessionId: " + sessionId); return; } } /** * 话单通知 for AXB/AX/AXE/ * * @param jsonBody * @breif 详细内容以接口文档为准 */ public void onFeeEvent(String jsonBody) { // 封装JSON请求 JSONObject json = JSON.parseObject(jsonBody); String eventType = json.getString("eventType"); // 通知事件类型 if (!("fee".equalsIgnoreCase(eventType))) { logger.info("EventType error: " + eventType); return; } JSONArray feeLst = json.getJSONArray("feeLst"); // 呼叫话单事件信息 /** * Example: 此处以解析notifyMode为例,请按需解析所需参数并自行实现相关处理 * * 'direction': 通话的呼叫方向 * 'spId': 客户的云服务账号 * 'appKey': 商户应用的AppKey * 'icid': 呼叫记录的唯一标识 * 'bindNum': 隐私保护号码 * 'sessionId': 通话链路的唯一标识 * 'callerNum': 主叫号码 * 'calleeNum': 被叫号码 * 'fwdDisplayNum': 转接呼叫时的显示号码 * 'fwdDstNum': 转接呼叫时的转接号码 * 'callInTime': 呼入的开始时间 * 'fwdStartTime': 转接呼叫操作的开始时间 * 'fwdAlertingTime': 转接呼叫操作后的振铃时间 * 'fwdAnswerTime': 转接呼叫操作后的应答时间 * 'callEndTime': 呼叫结束时间 * 'fwdUnaswRsn': 转接呼叫操作失败的Q850原因值 * 'failTime': 呼入,呼出的失败时间 * 'ulFailReason': 通话失败的拆线点 * 'sipStatusCode': 呼入,呼出的失败SIP状态码 * 'recordFlag': 录音标识 * 'recordStartTime': 录音开始时间 * 'recordObjectName': 录音文件名 * 'recordBucketName': 录音文件所在的目录名 * 'recordDomain': 存放录音文件的域名 * 'serviceType': 携带呼叫的业务类型信息 * 'hostName': 话单生成的服务器设备对应的主机名 * 'subscriptionId': 绑定关系ID * 'extendNum': 分机号E,该参数仅在AXE模式场景携带 */ // 短时间内有多个通话结束时隐私保护通话平台会将话单合并推送,每条消息最多携带50个话单 if (feeLst.size() > 1) { for (Object loop : feeLst) { if (((JSONObject) loop).containsKey("sessionId")) { logger.info("sessionId: " + ((JSONObject) loop).getString("sessionId")); } } } else if (feeLst.size() == 1) { if (feeLst.getJSONObject(0).containsKey("sessionId")) { logger.info("sessionId: " + feeLst.getJSONObject(0).getString("sessionId")); } } else { logger.info("feeLst error: no element."); } } /** * 短信通知 for AXB/AX * * @param jsonBody * @breif 详细内容以接口文档为准 */ public void onSmsEvent(String jsonBody) { // 封装JOSN请求 JSONObject json = JSON.parseObject(jsonBody); // String appKey = json.getString("appKey"); // 商户应用的AppKey JSONObject smsEvent = json.getJSONObject("smsEvent"); // 短信通知信息 /** * Example: 此处以解析notificationMode为例,请按需解析所需参数并自行实现相关处理 * * 'smsIdentifier': 短信唯一标识 * 'notificationMode': 通知模式 * 'calling': 真实发送方号码 * 'called': 真实接收方号码 * 'virtualNumber': 隐私号码(X号码) * 'event': 短信状态事件 * 'timeStamp': 短信事件发生的系统时间戳,UTC时间 * 'subscriptionId': 绑定ID * 'smsContent': 用户发送的短信内容 */ String notificationMode = smsEvent.getString("notificationMode"); // 通知模式 // 如果是Block模式,则要按接口文档进行回复响应 if ("Block".equalsIgnoreCase(notificationMode)) { JSONObject resp = new JSONObject(); JSONArray actions = new JSONArray(); JSONObject action = new JSONObject(); action.put("operation", "vNumberRoute"); // 操作类型 actions.add(action); resp.put("actions", actions); // Block模式响应消息 logger.info(resp); } } }
父主题: Java代码样例