更新时间: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代码样例