更新时间:2024-09-24 GMT+08:00
分享

Java

注:使用前请务必先仔细阅读使用注意事项

将下列代码样例复制到新建java文件中即可运行。

  • 本文档所述Demo在提供服务的过程中,可能会涉及个人数据的使用,建议您遵从国家的相关法律采取足够的措施,以确保用户的个人数据受到充分的保护。
  • 本文档所述Demo仅用于功能演示,不允许客户直接进行商业使用。
  • 本文档信息仅供参考,不构成任何要约或承诺。

“语音通知场景API”代码样例

package com.huawei.demo;

import java.util.*;
import javax.net.ssl.HttpsURLConnection;

import com.huawei.utils.Constant;
import com.huawei.utils.HttpsUtil;
import com.huawei.utils.JsonUtil;
import com.huawei.utils.StreamClosedHttpResponse;
import com.huawei.utils.StringUtil;

public class VoiceNotifyMain {
    // 接口返回值
    private static String status = "";
    private static String resultcode = "";
    private static String resultdesc = "";
    // 语音通知接口返回值
    private static String sessionId = "";
    // 语音通知业务类实体
    public static VoiceNotify callNotifyAPI = new VoiceNotify();

    // 调用接口成功标识
    private static final String success = "200";

    public static void main(String args[]) throws Exception {

        // TODO 程序前端要求发起语音通知呼叫,首先使用getplayInfo构造构造playInfoList参数,然后调用doCallNotify方法.
        // 以下代码仅供调试使用,实际开发时请删除
        // 构造playInfoList参数
        List<Map<String, Object>> playInfoList = new ArrayList<Map<String, Object>>();
        // 使用音频文件作为第一段放音内容
        playInfoList.add(callNotifyAPI.getplayInfo("test.wav"));
        // 使用v2.0版本接口的语音通知模板作为第二段放音内容
        String templateId = "test";
        List<String> templateParas = new ArrayList<String>();
        templateParas.add("3");
        templateParas.add("1栋保安亭");
        playInfoList.add(callNotifyAPI.getplayInfo(templateId, templateParas));
        // 调用doCallNotify方法
        VoiceNotifyMain.doCallNotify("+8653159511234", "+8613800000001", playInfoList);
        if (status.indexOf(success) != -1) {
            System.out.println(status);
            System.out.println(resultcode + " " + resultdesc);
            System.out.println("The session id is: " + sessionId);
        }

        // TODO 需要接收状态和话单时,请参考"呼叫状态和话单通知API"接口实现状态通知和话单的接收和解析
        // HostingVoiceEventDemoImpl
    }

    /*
     * 前端需要发起语音通知呼叫时,调用此方法 该示例只仅体现必选参数,可选参数根据接口文档和实际情况配置.
     */
    public static void doCallNotify(String displayNbr, String calleeNbr, List<Map<String, Object>> playInfoList)
            throws Exception {

        Boolean retry = false;
        // 调用语音通知接口,直至成功
        do {
            status = callNotifyAPI.callNotifyAPI(displayNbr, calleeNbr, playInfoList);
            if (status.indexOf(success) != -1) {
                retry = false;
                // 调用成功,记录返回的信息.
                resultcode = callNotifyAPI.getResponsePara("resultcode");
                resultdesc = callNotifyAPI.getResponsePara("resultdesc");
                sessionId = callNotifyAPI.getResponsePara("sessionId");
            } else {
                retry = true;
                // 调用失败,获取错误码和错误描述.
                resultcode = callNotifyAPI.getResponsePara("resultcode");
                resultdesc = callNotifyAPI.getResponsePara("resultdesc");
                // 处理错误
                VoiceNotifyMain.processError();
            }
        } while (retry);
    }

    // 当API的返回值不是200时,处理错误.
    private static void processError() throws InterruptedException {

        // TODO 根据错误码和错误码描述处理问题
        // 以下代码仅供调试使用,实际开发时请删除
        System.out.println(status);
        System.out.println(resultcode + " " + resultdesc);
        System.exit(-1);
    }
}

class VoiceNotify {
    // 语音通知API的调用地址
    private String urlCallNotify;
    // 接口响应的消息体
    private Map<String, String> Responsebody;
    // Https实体
    private HttpsUtil httpsUtil;

    public VoiceNotify() {
        // 商用地址
        urlCallNotify = Constant.CALL_NOTIFY_COMERCIAL;
        Responsebody = new HashMap<>();
    }

    @SuppressWarnings("unchecked")
    /*
     * 该示例只仅体现必选参数,可选参数根据接口文档和实际情况配置. 该示例不体现参数校验,请根据各参数的格式要求自行实现校验功能.
     * playInfoList为最大个数为5的放音内容参数列表,每个放音内容参数以Map<String,Object>格式存储,
     * 放音内容参数的构造方法请参考getplayInfo方法.
     */
    public String callNotifyAPI(String displayNbr, String calleeNbr, List<Map<String, Object>> playInfoList)
        throws Exception {

        httpsUtil = new HttpsUtil();

        // 忽略证书信任问题
        httpsUtil.trustAllHttpsCertificates();
        HttpsURLConnection.setDefaultHostnameVerifier(httpsUtil.hv);



        // 请求Headers
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put(Constant.HEADER_APP_AUTH, Constant.AUTH_HEADER_VALUE);
        headerMap.put(Constant.HEADER_APP_AKSK,
            StringUtil.buildAKSKHeader(Constant.CALLNOTIFY_APPID, Constant.CALLNOTIFY_SECRET));

        // 构造消息体
        Map<String, Object> bodys = new HashMap<>();
        bodys.put("displayNbr", displayNbr);//主叫用户手机终端的来电显示号码。
        bodys.put("calleeNbr", calleeNbr);//发起呼叫时所拨打的被叫号码。
        bodys.put("playInfoList", playInfoList);//播放信息列表,最大支持5个,每个播放信息携带的参数都可以不相同。
        String jsonRequest = JsonUtil.jsonObj2Sting(bodys);

        /*
         * Content-Type为application/json且请求方法为post时, 使用doPostJsonGetStatusLine方法构造http
         * request并获取响应.
         */
        StreamClosedHttpResponse responseCallNotify = httpsUtil.doPostJsonGetStatusLine(urlCallNotify, headerMap,
            jsonRequest);

        // 响应的消息体写入Responsebody.
        Responsebody = JsonUtil.jsonString2SimpleObj(responseCallNotify.getContent(), Responsebody.getClass());

        // 返回响应的status.
        return responseCallNotify.getStatusLine().toString();
    }

    /*
     * 构造playInfoList中携带的放音内容参数 使用语音文件或者v1.0版本接口的TTS文本作为放音内容
     */
    public Map<String, Object> getplayInfo(String fileorTTS) {
        Map<String, Object> body = new HashMap<String, Object>();
        // 音频文件只支持wave格式,文件名以.wav结尾
        if (fileorTTS.endsWith(".wav")) {
            body.put("notifyVoice", fileorTTS);
        } else {
            System.out.println("Only .wav file is supported.");
        }
        return body;
    }

    /*
     * 构造playInfoList中携带的放音内容参数 使用v2.0版本接口的TTS模板作为放音内容 重构getplayInfo方法
     */
    public Map<String, Object> getplayInfo(String templateId, List<String> templateParas) {
        Map<String, Object> bodys = new HashMap<String, Object>();
        bodys.put("templateId", templateId);
        bodys.put("templateParas", templateParas);
        return bodys;
    }

    // 获取整个响应消息体
    public Map<String, String> getResponsebody() {
        return this.Responsebody;
    }

    // 获取响应消息体中的单个参数
    public String getResponsePara(String ParaName) {
        return this.Responsebody.get(ParaName);
    }
}

“获取录音文件下载地址API”代码样例

package com.huawei.demo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import com.huawei.utils.Constant;
import com.huawei.utils.HttpsUtil;
import com.huawei.utils.JsonUtil;
import com.huawei.utils.StreamClosedHttpResponse;

public class GetRecordLink {
    // 获取录音文件下载地址API的URL
    private String urlRecordFile;
    // Https实体
    private HttpsUtil httpsUtil;
    // 接口响应的消息体
    private Map<String, String> Responsebody;
    // 录音文件下载地址
    private String Location;

    public GetRecordLink() {
        // 商用地址
        urlRecordFile = Constant.VOICE_FILE_DOWNLOAD;

        Responsebody = new HashMap<>();
    }

    @SuppressWarnings("unchecked")
    public String getRecordLinkAPI(String fileName, String recordDomain, String aksk) throws Exception {

        httpsUtil = new HttpsUtil();

        // 忽略证书信任问题
        httpsUtil.trustAllHttpsCertificates();
        HttpsURLConnection.setDefaultHostnameVerifier(httpsUtil.hv);

        // 构造URL
        List<NameValuePair> keyValues = new ArrayList<NameValuePair>();
        keyValues.add(new BasicNameValuePair("fileName", fileName));
        keyValues.add(new BasicNameValuePair("recordDomain", recordDomain));

        // 请求Headers
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put(Constant.HEADER_APP_AUTH, Constant.AUTH_HEADER_VALUE);
        headerMap.put(Constant.HEADER_APP_AKSK, aksk);

        /*
         * Content-Type为application/json且请求方法为get时, 使用doGetWithParasGetStatusLine方法构造http
         * request并获取响应.
         */
        StreamClosedHttpResponse respRecordLink = httpsUtil.doGetWithParasGetStatusLine(urlRecordFile, keyValues,
                headerMap);

        // 响应的消息体写入Responsebody.
        Responsebody = JsonUtil.jsonString2SimpleObj(respRecordLink.getContent(), Responsebody.getClass());

        // 从响应头域中获取location.
        String code = respRecordLink.getStatusLine().toString();
        if (code.indexOf("301") != -1) {
            Location = respRecordLink.getFirstHeader("Location").getValue();
        } else {
            Location = "";
        }

        // 返回响应的status.
        return code;
    }

    // 获取整个响应消息体
    public Map<String, String> getResponsebody() {
        return this.Responsebody;
    }

    // 获取响应消息体中的单个参数
    public String getResponsePara(String ParaName) {
        return this.Responsebody.get(ParaName);
    }

    // 获取location
    public String getLocation() {
        return this.Location;
    }
}

“呼叫状态通知API”与“话单通知API”代码样例

package com.huawei.demo;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 呼叫事件通知/话单通知
 * 客户平台收到RTC业务平台的呼叫事件通知/话单通知的接口通知
 */
public class HostingVoiceEventDemoImpl {
    private static Logger logger = Logger.getLogger(HostingVoiceEventDemoImpl.class);

    /**
     * 呼叫事件 for 语音回呼/语音通知/语音验证码
     * 
     * @param jsonBody
     * @breif 详细内容以接口文档为准
     */
    public static 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;
        }

        if (!(json.containsKey("statusInfo"))) {
            logger.info("param error: no statusInfo.");
            return;
        }
        JSONObject statusInfo = json.getJSONObject("statusInfo"); // 呼叫状态事件信息

        logger.info("eventType: " + eventType); // 打印通知事件类型

        //callout:呼出事件
        if ("callout".equalsIgnoreCase(eventType)) {
            /**
             * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
             *
             * 'timestamp': 该呼叫事件发生时RTC业务平台的UNIX时间戳
             * 'userData': 用户附属信息
             * 'sessionId': 通话链路的标识ID
             * 'caller': 主叫号码
             * 'called': 被叫号码
             */
            if (statusInfo.containsKey("sessionId")) {
                logger.info("sessionId: " + statusInfo.getString("sessionId"));
            }
            return;
        }
        //alerting:振铃事件
        if ("alerting".equalsIgnoreCase(eventType)) {
            /**
             * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
             *
             * 'timestamp': 该呼叫事件发生时RTC业务平台的UNIX时间戳
             * 'userData': 用户附属信息
             * 'sessionId': 通话链路的标识ID
             * 'caller': 主叫号码
             * 'called': 被叫号码
             */
            if (statusInfo.containsKey("sessionId")) {
                logger.info("sessionId: " + statusInfo.getString("sessionId"));
            }
            return;
        }
        //answer:应答事件
        if ("answer".equalsIgnoreCase(eventType)) {
            /**
             * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
             *
             * 'timestamp': 该呼叫事件发生时RTC业务平台的UNIX时间戳
             * 'userData': 用户附属信息
             * 'sessionId': 通话链路的标识ID
             * 'caller': 主叫号码
             * 'called': 被叫号码
             */
            if (statusInfo.containsKey("sessionId")) {
                logger.info("sessionId: " + statusInfo.getString("sessionId"));
            }
            return;
        }
        //collectInfo:放音收号结果事件,仅应用于语音通知场景
        if ("collectInfo".equalsIgnoreCase(eventType)) {
            /**
             * Example: 此处以解析digitInfo为例,请按需解析所需参数并自行实现相关处理
             *
             * 'timestamp': 该呼叫事件发生时RTC业务平台的UNIX时间戳
             * 'sessionId': 通话链路的标识ID
             * 'digitInfo': 放音收号场景中,RTC业务平台对开发者进行放音收号操作的结果描述
             */
            if (statusInfo.containsKey("digitInfo")) {
                logger.info("digitInfo: " + statusInfo.getString("digitInfo"));
            }
            return;
        }
        //disconnect:挂机事件
        if ("disconnect".equalsIgnoreCase(eventType)) {
            /**
             * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
             *
             * 'timestamp': 该呼叫事件发生时RTC业务平台的UNIX时间戳
             * 'userData': 用户附属信息
             * 'sessionId': 通话链路的标识ID
             * 'caller': 主叫号码
             * 'called': 被叫号码
             * 'partyType': 挂机的用户类型,仅在语音回呼场景携带
             * 'stateCode': 通话挂机的原因值
             * 'stateDesc': 通话挂机的原因值的描述
             */
            if (statusInfo.containsKey("sessionId")) {
                logger.info("sessionId: " + statusInfo.getString("sessionId"));
            }
            return;
        }
    }

    /**
     * 话单通知 for 语音回呼/语音通知/语音验证码
     * 
     * @param jsonBody
     * @breif 详细内容以接口文档为准
     */
    public static 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;
        }

        if (!(json.containsKey("feeLst"))) {
            logger.info("param error: no feeLst.");
            return;
        }
        JSONArray feeLst = json.getJSONArray("feeLst"); // 呼叫话单事件信息
        /**
         * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
         *
         * 'direction': 通话的呼叫方向,以RTC业务平台为基准
         * 'spId': 客户的云服务账号
         * 'appKey': 应用的app_key
         * 'icid': 呼叫记录的唯一标识
         * 'bindNum': 发起此次呼叫的CallEnabler业务号码
         * 'sessionId': 通话链路的唯一标识
         * 'callerNum': 主叫号码
         * 'calleeNum': 被叫号码
         * 'fwdDisplayNum': 转接呼叫时的显示号码(仅语音回呼场景携带)
         * 'fwdDstNum': 转接呼叫时的转接号码(仅语音回呼场景携带)
         * 'fwdStartTime': 转接呼叫操作的开始时间(仅语音回呼场景携带)
         * 'fwdAlertingTime': 转接呼叫操作后的振铃时间(仅语音回呼场景携带)
         * 'fwdAnswerTime': 转接呼叫操作后的应答时间(仅语音回呼场景携带)
         * 'callEndTime': 呼叫结束时间
         * 'fwdUnaswRsn': 转接呼叫操作失败的Q850原因值
         * 'failTime': 呼入,呼出的失败时间
         * 'ulFailReason': 通话失败的拆线点
         * 'sipStatusCode': 呼入,呼出的失败SIP状态码
         * 'callOutStartTime': Initcall的呼出开始时间
         * 'callOutAlertingTime': Initcall的呼出振铃时间
         * 'callOutAnswerTime': Initcall的呼出应答时间
         * 'callOutUnaswRsn': Initcall的呼出失败的Q850原因值
         * 'dynIVRStartTime': 自定义动态IVR开始时间(仅语音通知场景携带)
         * 'dynIVRPath': 自定义动态IVR按键路径(仅语音通知场景携带)
         * 'recordFlag': 录音标识
         * 'recordStartTime': 录音开始时间(仅语音回呼场景携带)
         * 'recordObjectName': 录音文件名(仅语音回呼场景携带)
         * 'recordBucketName': 录音文件所在的目录名(仅语音回呼场景携带)
         * 'recordDomain': 存放录音文件的域名(仅语音回呼场景携带)
         * 'recordFileDownloadUrl': 录音文件下载地址(仅语音回呼场景携带)
         * 'ttsPlayTimes': 应用TTS功能时,使用TTS的总次数
         * 'ttsTransDuration': 应用TTS功能时,TTS Server进行TTS转换的总时长(单位为秒)
         * 'serviceType': 携带呼叫的业务类型信息
         * 'hostName': 话单生成的服务器设备对应的主机名
         * 'userData': 用户附属信息
         */
        //短时间内有多个通话结束时RTC业务平台会将话单合并推送,每条消息最多携带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.");
        }
    }
}

相关文档