更新时间:2021-09-18 GMT+08:00
分享

C#

环境要求

.NET Core 2.0及以上版本或.NET Framework 4.7.1及以上版本。

引用库

Newtonsoft.Json 11.0.2,请参考https://www.newtonsoft.com/json获取。

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

“语音通知API”代码样例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;

namespace voicecall_csharp_demo_x_wsse_
{
    class VoiceNotify
    {
        string base_url = "https://{domain}:{port}"; //APP接入地址,购买服务时下发,,请替换为实际值
        string appKey = "***appKey***"; //语音通知应用的appKey,购买服务时下发,请替换为实际值
        string appSecret = "***appSecret***"; //语音通知应用的appSecret,购买服务时下发,请替换为实际值

        static void Main(string[] args)
        {
            //构造放音列表,此处取值仅为样例,请替换为实际值
            ArrayList playInfoList = getPlayInfoList("notifyvoice.wav", "xxxxxx", ["3", "人民公园正门"]);
            //固话号码从控制台号码管理页获取,被叫号码请替换为实际号码.
            voiceNotifyAPI("+86531*******4", "+86135*******1", playInfoList);
        }

        static void voiceNotifyAPI(string displayNbr, string calleeNbr, ArrayList playInfoList)
        {
            if (String.IsNullOrEmpty(displayNbr) || String.IsNullOrEmpty(calleeNbr) || Count(playInfoList) < 1)
            {
                return;
            }

            string apiURI = "/rest/httpsessions/callnotify/v2.0"; //接口URI, v1.0 or v2.0
            string requestUrl = base_url + apiURI;

            try
            {
                //为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题
                //.NET Framework 4.7.1及以上版本,请采用如下代码
                var sslHandler = new HttpClientHandler()
                {
                    ServerCertificateCustomValidationCallback = (message, cert, chain, err) => { return true; }
                };
                HttpClient client = new HttpClient(sslHandler, true);
                //低于.NET Framework 4.7.1版本,请采用如下代码
                //HttpClient client = new HttpClient();
                //ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);

                //请求Headers
                client.DefaultRequestHeaders.Add("Authorization", "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
                client.DefaultRequestHeaders.Add("X-WSSE", buildWSSEHeader(appKey, appSecret));

                //请求Body
                var body = new Dictionary<string, object>() {
                    /*必填参数*/
                    {"displayNbr", displayNbr},//主叫用户手机终端的来电显示号码。
                    {"calleeNbr", calleeNbr},//发起呼叫时所拨打的被叫号码。
                    {"playInfoList", playInfoList}//播放信息列表,最大支持5个,每个播放信息携带的参数都可以不相同。
                    /*选填参数*/
                     
                    //{"statusUrl", ""}, //设置SP接收状态上报的URL,要求使用BASE64编码
                    //{"feeUrl", ""}, //设置SP接收话单上报的URL,要求使用BASE64编码
                    //{"returnIdlePort", "false"}, //指示是否需要返回平台空闲呼叫端口数量
                    //{"userData", "customerId123"} //设置用户的附属信息
                };

                HttpContent content = new StringContent(JsonConvert.SerializeObject(body));
                //请求Headers中的Content-Type参数
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

                var response = client.PostAsync(requestUrl, content).Result;
                Console.WriteLine(response.StatusCode);
                var res = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine(res); //打印响应结果
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
                Console.WriteLine(e.Message); //打印错误信息
            }
        }

        static string buildWSSEHeader(string appKey, string appSecret)
        {
            string now = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssZ"); //Created
            string nonce = Guid.NewGuid().ToString().Replace("-", ""); //Nonce

            byte[] material = Encoding.UTF8.GetBytes(nonce + now + appSecret);
            byte[] hashed = SHA256Managed.Create().ComputeHash(material);
            string hexdigest = BitConverter.ToString(hashed).Replace("-", "");
            string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(hexdigest)); //PasswordDigest

            return String.Format("UsernameToken Username=\"{0}\",PasswordDigest=\"{1}\",Nonce=\"{2}\",Created=\"{3}\"",
                            appKey, base64, nonce, now);
        }

        static ArrayList getPlayInfoList(string notifyVoice, string templateId, string[] templateParas)
        {
            ArrayList playInfoList = new ArrayList(); //播放信息列表,最大支持5个

            /*此处以构建一个playInfoDic,添加到playInfoList为例,请按需构建多个*/
            Dictionary<string, object> playInfoDic = new Dictionary<string, object>();
            playInfoDic.Add("notifyVoice", notifyVoice);
            playInfoDic.Add("templateId", templateId);
            playInfoDic.Add("templateParas", templateParas);
            //playInfoDic.Add("collectInd", 0); //是否进行收号
            //playInfoDic.Add("replayAfterCollection", "false"); //设置是否在收号后重新播放notifyVoice或templateId指定的放音
            //playInfoDic.Add("collectContentTriggerReplaying", "1"); //设置触发重新放音的收号内容
            playInfoList.Add(playInfoDic); //playInfoList添加元素

            return playInfoList;
        }

        //低于.NET Framework 4.7.1版本,启用如下方法
        //static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true;
        //}
    }
}

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

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;

namespace voicecall_csharp_demo_x_wsse_
{
    class CallEventImpl
    {
        static void Main(string[] args)
        {
            //呼叫事件通知样例
            string jsonBody = JsonConvert.SerializeObject(new Dictionary<string, object>(){
                {"eventType", "callout"},
                {"statusInfo", new Dictionary<string, object>(){
                        {"sessionId", "1201_612_4294967295_20190124030424@callenabler245.huaweicaas.com"},
                        {"timestamp", "2019-01-24 03:04:24"},
                        {"caller", "+86138*******2"},
                        {"called", "+86138*******1"},
                    }
                }
            });

            Console.WriteLine("jsonBody:" + jsonBody);

            OnCallEvent(jsonBody); //呼叫事件处理
        }

        /// <summary>
        /// 呼叫事件通知,详细内容以接口文档为准
        /// </summary>
        /// <param name="jsonBody"></param>
        static void OnCallEvent(string jsonBody)
        {
            JObject jsonObj = (JObject)JsonConvert.DeserializeObject(jsonBody); //将通知消息解析为jsonObj
            string eventType = jsonObj["eventType"].ToString(); //通知事件类型

            if ("fee".Equals(eventType))
            {
                Console.WriteLine("EventType error:" + eventType);
                return;
            }

            if (!jsonObj.ContainsKey("statusInfo"))
            {
                Console.WriteLine("param error: no statusInfo.");
                return;
            }
            JObject statusInfo = (JObject)jsonObj["statusInfo"]; //呼叫状态事件信息

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

“话单通知API”代码样例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;

namespace voicecall_csharp_demo_x_wsse_
{
    class FeeImpl
    {
        static void Main(string[] args)
        {
            //话单通知样例
            string jsonBody = JsonConvert.SerializeObject(new Dictionary<string, object>(){
                {"eventType", "fee"},
                {"feeLst",  new object[] {
                    new Dictionary<string, object>(){
                            {"direction", 0}, //通话的呼叫方向,以语音通话平台为基准
                            {"spId", "CaaS_Test_01"}, //客户的云服务账号
                            {"appKey", "ka4k*****Em2"}, //应用的app_key,购买服务时下发,请替换为实际值
                            {"icid", "CAE-20190124110424-12019775"}, //呼叫记录的唯一标识
                            {"bindNum", "+8675512****78"}, //发起此次呼叫的CallEnabler业务号码,即绑定号码
                            {"sessionId", "1201_612_4294967295_20190124030424@callenabler245.huaweicaas.com"}, //通话链路的唯一标识
                            {"callerNum", "+86138****0022"}, //主叫号码
                            {"calleeNum", "+86138****0021"}, //被叫号码
                            {"fwdDisplayNum", "+86138****0022"}, //转接呼叫时的显示号码(仅语音回呼场景携带)
                            {"fwdDstNum", "+86138****7021"}, //转接呼叫时的转接号码(仅语音回呼场景携带)
                            
                            {"fwdStartTime", "2019-01-24 03:04:31"}, //转接呼叫操作的开始时间(仅语音回呼场景携带)
                            {"fwdAlertingTime", "2019-01-24 03:04:36"}, //转接呼叫操作后的振铃时间(仅语音回呼场景携带)
                            {"fwdAnswerTime", "2019-01-24 03:04:38"}, //转接呼叫操作后的应答时间(仅语音回呼场景携带)
                            {"callEndTime", "2019-01-24 03:04:49"}, //呼叫结束时间
                            {"fwdUnaswRsn", 0}, //转接呼叫操作失败的Q850原因值
                            {"failTime", ""}, //呼入,呼出的失败时间
                            {"ulFailReason", 0}, //通话失败的拆线点
                            {"sipStatusCode", 0}, //呼入,呼出的失败SIP状态码
                            {"callOutStartTime", "2019-01-24 03:04:24"}, //Initcall的呼出开始时间
                            {"callOutAlertingTime", "2019-01-24 03:04:27"}, //Initcall的呼出振铃时间
                            {"callOutAnswerTime", "2019-01-24 03:04:31"}, //Initcall的呼出应答时间
                            {"callOutUnaswRsn", 0}, //Initcall的呼出失败的Q850原因值
                            {"dynIVRStartTime", ""}, //自定义动态IVR开始时间(仅语音通知场景携带)
                            {"dynIVRPath", ""}, //自定义动态IVR按键路径(仅语音通知场景携带)
                            {"recordFlag", 0}, //录音标识
                            {"recordStartTime", ""}, //录音开始时间(仅语音回呼场景携带)
                            {"recordObjectName", ""}, //录音文件名(仅语音回呼场景携带)
                            {"recordBucketName", ""}, //录音文件所在的目录名(仅语音回呼场景携带)
                            {"recordDomain", ""}, //存放录音文件的域名(仅语音回呼场景携带)
                            {"recordFileDownloadUrl", ""}, //录音文件下载地址(仅语音回呼场景携带)
                            {"ttsPlayTimes", 0}, //应用TTS功能时,使用TTS的总次数
                            {"ttsTransDuration", 0}, //应用TTS功能时,TTS Server进行TTS转换的总时长(单位为秒)
                            {"serviceType", "002"}, //携带呼叫的业务类型信息
                            {"hostName", "callenabler245.huaweicaas.com"}, //话单生成的服务器设备对应的主机名
                            {"userData", "customerId123"} //用户附属信息
                        }
                    }
                }
            });

            Console.WriteLine(jsonBody);

            OnFeeEvent(jsonBody); //话单处理
        }

        /// <summary>
        /// 话单通知,详细内容以接口文档为准
        /// </summary>
        /// <param name="jsonBody"></param>
        static void OnFeeEvent(string jsonBody)
        {
            JObject jsonObj = (JObject)JsonConvert.DeserializeObject(jsonBody); //将通知消息解析为jsonObj
            string eventType = jsonObj["eventType"].ToString(); //通知事件类型

            if (!"fee".Equals(eventType))
            {
                Console.WriteLine("EventType error:" + eventType);
                return;
            }

            if (!jsonObj.ContainsKey("feeLst"))
            {
                Console.WriteLine("param error: no feeLst.");
                return;
            }
            JObject[] feeLst = jsonObj["feeLst"].ToObject<JObject[]>(); //呼叫话单事件信息

            //Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
            //短时间内有多个通话结束时语音通话平台会将话单合并推送,每条消息最多携带50个话单
            if (feeLst.Length > 1)
            {
                foreach (JObject loop in feeLst)
                {
                    if (loop.ContainsKey("sessionId"))
                    {
                        Console.WriteLine("sessionId:" + loop["sessionId"]);
                    }
                }
            }
            else if (feeLst.Length == 1)
            {
                if (feeLst[0].ContainsKey("sessionId"))
                {
                    Console.WriteLine("sessionId:" + feeLst[0]["sessionId"]);
                }
            }
            else
            {
                Console.WriteLine("feeLst error: no element.");
            }
        }
    }
}
分享:

    相关文档

    相关产品

close