
# AX模式
|    样例    | [AX模式绑定接口] [AX模式解绑接口] [AX模式绑定信息修改接口] [AX模式绑定信息查询接口] [AX模式设置临时被叫接口] [获取录音文件下载地址接口] [呼叫事件通知接口] [话单通知接口] [短信通知接口] |
|---|---|
| **环境要求** | 基于.NET Core SDK 2.1.401版本，要求.NET Core 2.0及以上版本或.NET Framework 4.7.1及以上版本。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| **引用库**  | Newtonsoft.Json 11.0.2，请参考<https://www.newtonsoft.com/json>获取。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
   
![](https://support.huaweicloud.com/devg-PrivateNumber/public_sys-resources/notice_3.0-zh-cn.png)
- 本文档所述Demo在提供服务的过程中，可能会涉及个人数据的使用，建议您遵从国家的相关法律采取足够的措施，以确保用户的个人数据受到充分的保护。
- 本文档所述Demo仅用于功能演示，不允许客户直接进行商业使用。
- 本文档信息仅供参考，不构成任何要约或承诺。
- 本文档接口携带参数只是用作参考，不可以直接复制使用，填写参数需要替换为实际值，请参考"[开发准备](https://support.huaweicloud.com/devg-PrivateNumber/privatenumber_01_0005.html)"获取所需数据。
 
 #### AX模式绑定接口
```
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
namespace privatenumber_ax_csharp_demo
{
    class axBind
    {
        static void Main(string[] args)
        {
            //必填,请参考"开发准备"获取如下数据,替换为实际值
            string apiAddress = "https://rtcpns.cn-north-1.myhuaweicloud.com/rest/provision/caas/privatenumber/v1.0"; //APP接入地址+接口访问URI
            string appKey = "a1********"; //APP_Key
            string appSecret = "cfc8********"; //APP_Secret
            string origNum = "+86186****5678"; //A号码
            string privateNum = "+86180****0001"; //X号码(隐私号码)
            /*
             * 选填,各参数要求请参考"AX模式绑定接口"
             */
            string privateNumType = "mobile-virtual"; //固定为mobile-virtual
            //string areaCode = "0755"; //需要绑定的X号码对应的城市码
            //string recordFlag = "true"; //是否需要针对该绑定关系产生的所有通话录音
            //string recordHintTone = "recordHintTone.wav"; //设置录音提示音
            string calleeNumDisplay = "0"; //设置非A用户呼叫X时,A接到呼叫时的主显号码
            //string privateSms = "true"; //设置该绑定关系是否支持短信功能
            //string callerHintTone = "callerHintTone.wav"; //设置A拨打X号码时的通话前等待音
            //string calleeHintTone = "calleeHintTone.wav"; //设置非A用户拨打X号码时的通话前等待音
            //var preVoice = new Dictionary<string, object>(){
            //    { "callerHintTone", callerHintTone},
            //    { "calleeHintTone", calleeHintTone}
            //};
            FileStream fs = File.Open("bind_data.txt", FileMode.Append); //打开文件
            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", "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
                client.DefaultRequestHeaders.Add("X-AKSK", buildAKSKHeader(appKey, appSecret));
                //请求Body
                var body = new Dictionary<string, object>() {
                    {"origNum", origNum},
                    {"privateNum", privateNum},
                    {"privateNumType", privateNumType},
                    //{"areaCode", areaCode},
                    //{"recordFlag", recordFlag},
                    //{"recordHintTone", recordHintTone},
                    {"calleeNumDisplay", calleeNumDisplay},
                    //{"privateSms", privateSms},
                    //{"preVoice", preVoice}
                };
                HttpContent content = new StringContent(JsonConvert.SerializeObject(body));
                //请求Headers中的Content-Type参数
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                byte[] bbody = Encoding.Default.GetBytes("绑定请求数据：" + JsonConvert.SerializeObject(body) + "\r\n");
                fs.Write(bbody, 0, bbody.Length); //绑定请求参数记录到本地文件,方便定位问题
                var response = client.PostAsync(apiAddress, content).Result; //POST请求
                Console.WriteLine(response.StatusCode);
                var res = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine(res); //打印响应数据
                byte[] bres = Encoding.Default.GetBytes("绑定结果：" + res + "\r\n");
                fs.Write(bres, 0, bres.Length); //绑定ID很重要,请记录到本地文件,方便后续修改绑定关系及解绑
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
                Console.WriteLine(e.Message); //打印错误信息
            }
            finally
            {
                fs.Close(); //关闭文件
            }
        }
        static string buildAKSKHeader(string appKey, string appSecret)
        {
            string now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); //Created
            string nonce = Guid.NewGuid().ToString().Replace("-", ""); //Nonce
            String str = nonce + now;
            byte[] keyByte = Encoding.UTF8.GetBytes(appSecret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(str);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                string base64 = Convert.ToBase64String(hashmessage);
                return String.Format("UsernameToken Username=\"{0}\",PasswordDigest=\"{1}\",Nonce=\"{2}\",Created=\"{3}\"",
                    appKey, base64, nonce, now);
            }
        }
        //低于.NET Framework 4.7.1版本,启用如下方法
        //static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true;
        //}
    }
}
```
 #### AX模式解绑接口
```
using System;
using System.Collections.Specialized;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
namespace privatenumber_ax_csharp_demo
{
    class axUnbind
    {
        static void Main(string[] args)
        {
            //必填,请参考"开发准备"获取如下数据,替换为实际值
            string apiAddress = "https://rtcpns.cn-north-1.myhuaweicloud.com/rest/provision/caas/privatenumber/v1.0"; //APP接入地址+接口访问URI
            string appKey = "a1d1f50cad21415fbdd13d8f53d36d60"; //APP_Key
            string appSecret = "cfc8********"; //APP_Secret
            /*
             * 选填,各参数要求请参考"AX模式解绑接口"
             * subscriptionId和(origNum+privateNum)为二选一关系,都携带时以subscriptionId为准
             */
            //string origNum = "+86186****5678"; //A号码
            //string privateNum = "+86180****0001"; //X号码(隐私号码)
            string subscriptionId = "****"; //指定"AX模式绑定接口"返回的绑定ID进行解绑
            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", "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
                client.DefaultRequestHeaders.Add("X-AKSK", buildAKSKHeader(appKey, appSecret));
                //请求url参数
                var keyValues = new NameValueCollection();
                keyValues.Add("subscriptionId", subscriptionId);
                //keyValues.Add("origNum", origNum);
                //keyValues.Add("privateNum", privateNum);
                //完整请求地址
                var url = apiAddress + "?" + buildQueryString(keyValues);
                Console.WriteLine(buildQueryString(keyValues)); //打印请求数据
                var response = client.DeleteAsync(url).Result; //DELETE请求
                Console.WriteLine(response.StatusCode);
                var res = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine(res); //打印响应结果
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
                Console.WriteLine(e.Message); //打印错误信息
            }
        }
        /// <summary>
        /// 构造请求url参数
        /// </summary>
        /// <param name="keyValues"></param>
        /// <returns></returns>
        static string buildQueryString(NameValueCollection keyValues)
        {
            StringBuilder temp = new StringBuilder();
            foreach (string item in keyValues.Keys)
            {
                temp.Append(item).Append("=").Append(WebUtility.UrlEncode(keyValues.Get(item))).Append("&");
            }
            return temp.Remove(temp.Length - 1, 1).ToString();
        }
        static string buildAKSKHeader(string appKey, string appSecret)
        {
            string now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); //Created
            string nonce = Guid.NewGuid().ToString().Replace("-", ""); //Nonce
            String str = nonce + now;
            byte[] keyByte = Encoding.UTF8.GetBytes(appSecret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(str);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                string base64 = Convert.ToBase64String(hashmessage);
                return String.Format("UsernameToken Username=\"{0}\",PasswordDigest=\"{1}\",Nonce=\"{2}\",Created=\"{3}\"",
                    appKey, base64, nonce, now);
            }
        }
        //低于.NET Framework 4.7.1版本,启用如下方法
        //static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true;
        //}
    }
}
```
 #### AX模式绑定信息修改接口
```
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
namespace privatenumber_ax_csharp_demo
{
    class axModify
    {
        static void Main(string[] args)
        {
            //必填,请参考"开发准备"获取如下数据,替换为实际值
            string apiAddress = "https://rtcpns.cn-north-1.myhuaweicloud.com/rest/provision/caas/privatenumber/v1.0"; //APP接入地址+接口访问URI
            string appKey = "a1********"; //APP_Key
            string appSecret = "cfc8********"; //APP_Secret
            /*
             * 选填,各参数要求请参考"AX模式绑定信息修改接口"
             * subscriptionId和(origNum+privateNum)为二选一关系,都携带时以subscriptionId为准
             */
            string origNum = "+86186****5678"; //A号码
            string privateNum = "+86180****0001"; //X号码(隐私号码)
            //string subscriptionId = "****"; //指定"AX模式绑定接口"返回的绑定ID进行解绑
            string privateSms = "true"; //必填,修改该绑定关系是否支持短信功能
            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", "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
                client.DefaultRequestHeaders.Add("X-AKSK", buildAKSKHeader(appKey, appSecret));
                //请求Body
                var body = new Dictionary<string, object>() {
                    {"origNum", origNum},
                    {"privateNum", privateNum},
                    //{"subscriptionId", subscriptionId},
                    {"privateSms", privateSms}
                };
                HttpContent content = new StringContent(JsonConvert.SerializeObject(body));
                //请求Headers中的Content-Type参数
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                Console.WriteLine(JsonConvert.SerializeObject(body)); //打印请求数据
                var response = client.PutAsync(apiAddress, content).Result; //PUT请求
                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 buildAKSKHeader(string appKey, string appSecret)
        {
            string now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); //Created
            string nonce = Guid.NewGuid().ToString().Replace("-", ""); //Nonce
            String str = nonce + now;
            byte[] keyByte = Encoding.UTF8.GetBytes(appSecret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(str);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                string base64 = Convert.ToBase64String(hashmessage);
                return String.Format("UsernameToken Username=\"{0}\",PasswordDigest=\"{1}\",Nonce=\"{2}\",Created=\"{3}\"",
                    appKey, base64, nonce, now);
            }
        }
        //低于.NET Framework 4.7.1版本,启用如下方法
        //static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true;
        //}
    }
}
```
 #### AX模式绑定信息查询接口
```
using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
namespace privatenumber_ax_csharp_demo
{
    class axQueryBind
    {
        static void Main(string[] args)
        {
            //必填,请参考"开发准备"获取如下数据,替换为实际值
            string apiAddress = "https://rtcpns.cn-north-1.myhuaweicloud.com/rest/provision/caas/privatenumber/v1.0"; //APP接入地址+接口访问URI
            string appKey = "a1********"; //APP_Key
            string appSecret = "cfc8********"; //APP_Secret
            /*
             * 选填,各参数要求请参考"AX模式绑定信息查询接口"
             * subscriptionId和origNum为二选一关系,两者都携带时以subscriptionId为准
             */
            string origNum = "+86186****5678"; //指定A号码进行查询
            string subscriptionId = "****"; //指定"AX模式绑定接口"返回的绑定ID进行查询
            FileStream fs = File.Open("bind_data.txt", FileMode.Append); //打开文件
            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", "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
                client.DefaultRequestHeaders.Add("X-AKSK", buildAKSKHeader(appKey, appSecret));
                //请求url参数
                var keyValues = new NameValueCollection();
                keyValues.Add("subscriptionId", subscriptionId);
                keyValues.Add("origNum", origNum);
                //完整请求地址
                var url = apiAddress + "?" + buildQueryString(keyValues);
                var response = client.GetAsync(url).Result; //GET请求
                Console.WriteLine(response.StatusCode);
                var res = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine(res); //打印响应结果
                byte[] bres = Encoding.Default.GetBytes("绑定查询结果：" + res + "\r\n");
                fs.Write(bres, 0, bres.Length); //查询结果,记录到本地文件
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
                Console.WriteLine(e.Message); //打印错误信息
            }
            finally
            {
                fs.Close(); //关闭文件
            }
        }
        /// <summary>
        /// 构造请求url参数
        /// </summary>
        /// <param name="keyValues"></param>
        /// <returns></returns>
        static string buildQueryString(NameValueCollection keyValues)
        {
            StringBuilder temp = new StringBuilder();
            foreach (string item in keyValues.Keys)
            {
                temp.Append(item).Append("=").Append(WebUtility.UrlEncode(keyValues.Get(item))).Append("&");
            }
            return temp.Remove(temp.Length - 1, 1).ToString();
        }
        static string buildAKSKHeader(string appKey, string appSecret)
        {
            string now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); //Created
            string nonce = Guid.NewGuid().ToString().Replace("-", ""); //Nonce
            String str = nonce + now;
            byte[] keyByte = Encoding.UTF8.GetBytes(appSecret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(str);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                string base64 = Convert.ToBase64String(hashmessage);
                return String.Format("UsernameToken Username=\"{0}\",PasswordDigest=\"{1}\",Nonce=\"{2}\",Created=\"{3}\"",
                    appKey, base64, nonce, now);
            }
        }
        //低于.NET Framework 4.7.1版本,启用如下方法
        //static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true;
        //}
    }
}
```
 #### AX模式设置临时被叫接口
```
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
namespace privatenumber_ax_csharp_demo
{
    class axSetCalleeNum
    {
        static void Main(string[] args)
        {
            //必填,请参考"开发准备"获取如下数据,替换为实际值
            string apiAddress = "https://rtcpns.cn-north-1.myhuaweicloud.com/rest/caas/privatenumber/calleenumber/v1.0"; //APP接入地址+接口访问URI
            string appKey = "a1********"; //APP_Key
            string appSecret = "cfc8********"; //APP_Secret
            /*
             * 选填,各参数要求请参考"AX模式设置临时被叫接口"
             * subscriptionId和(origNum+privateNum)为二选一关系,都携带时以subscriptionId为准
             */
            string origNum = "+86186****5678"; //A号码
            string privateNum = "+86180****0001"; //X号码(隐私号码)
            //string subscriptionId = "****"; //指定“AX模式绑定接口”返回的绑定ID设置临时被叫
            string calleeNum = "+86186****5679"; //必填,本次呼叫的真实被叫号码
            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", "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
                client.DefaultRequestHeaders.Add("X-AKSK", buildAKSKHeader(appKey, appSecret));
                //请求Body
                var body = new Dictionary<string, object>() {
                    {"origNum", origNum},
                    {"privateNum", privateNum},
                    //{"subscriptionId", subscriptionId},
                    {"calleeNum", calleeNum}
                };
                HttpContent content = new StringContent(JsonConvert.SerializeObject(body));
                //请求Headers中的Content-Type参数
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                Console.WriteLine(JsonConvert.SerializeObject(body)); //打印请求数据
                var response = client.PutAsync(apiAddress, content).Result; //PUT请求
                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 buildAKSKHeader(string appKey, string appSecret)
        {
            string now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); //Created
            string nonce = Guid.NewGuid().ToString().Replace("-", ""); //Nonce
            String str = nonce + now;
            byte[] keyByte = Encoding.UTF8.GetBytes(appSecret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(str);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                string base64 = Convert.ToBase64String(hashmessage);
                return String.Format("UsernameToken Username=\"{0}\",PasswordDigest=\"{1}\",Nonce=\"{2}\",Created=\"{3}\"",
                    appKey, base64, nonce, now);
            }
        }
        //低于.NET Framework 4.7.1版本,启用如下方法
        //static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true;
        //}
    }
}
```
 #### 获取录音文件下载地址接口
```
using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
namespace privatenumber_ax_csharp_demo
{
    class axGetRecordLink
    {
        static void Main(string[] args)
        {
            //必填,请参考"开发准备"获取如下数据,替换为实际值
            string apiAddress = "https://rtcpns.cn-north-1.myhuaweicloud.com/rest/provision/voice/record/v1.0"; //APP接入地址+接口访问URI
            string appKey = "a1********"; //APP_Key
            string appSecret = "cfc8********"; //APP_Secret
            //必填,通过"话单通知接口"获取
            string fileName = "****.wav"; //录音文件名
            string recordDomain = "****.com"; //录音文件存储的服务器域名
            FileStream fs = File.Open("bind_data.txt", FileMode.Append); //打开文件
            try
            {
                //为防止因HTTPS证书认证失败造成API调用失败,需要先忽略证书信任问题
                //.NET Framework 4.7.1及以上版本,请采用如下代码
                var sslHandler = new HttpClientHandler()
                {
                    ServerCertificateCustomValidationCallback = (message, cert, chain, err) => { return true; }
                };
                sslHandler.AllowAutoRedirect = false; //关闭重定向
                HttpClient client = new HttpClient(sslHandler, true);
                //低于.NET Framework 4.7.1版本,请采用如下代码
                //var sslHandler = new HttpClientHandler();
                //sslHandler.AllowAutoRedirect = false;
                //HttpClient client = new HttpClient(sslHandler);
                //ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                //请求Headers
                client.DefaultRequestHeaders.Add("Authorization", "AKSK realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
                client.DefaultRequestHeaders.Add("X-AKSK", buildAKSKHeader(appKey, appSecret));
                //请求url参数
                var keyValues = new NameValueCollection();
                keyValues.Add("fileName", fileName);
                keyValues.Add("recordDomain", recordDomain);
                //完整请求地址
                var url = apiAddress + "?" + buildQueryString(keyValues);
                var response = client.GetAsync(url).Result; //GET请求
                if (response.StatusCode.Equals(301))
                {
                    var slink = Convert.ToString(response.Headers.GetValues("Location"));
                    Console.WriteLine(slink);
                    byte[] blink = Encoding.Default.GetBytes("获取录音文件下载地址：" + slink + "\r\n");
                    fs.Write(blink, 0, blink.Length); //查询结果,记录到本地文件
                }
                else
                {
                    var res = response.Content.ReadAsStringAsync().Result;
                    Console.WriteLine(response.StatusCode);
                    Console.WriteLine(res); //打印响应结果
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
                Console.WriteLine(e.Message); //打印错误信息
            }
            finally
            {
                fs.Close(); //关闭文件
            }
        }
        /// <summary>
        /// 构造请求url参数
        /// </summary>
        /// <param name="keyValues"></param>
        /// <returns></returns>
        static string buildQueryString(NameValueCollection keyValues)
        {
            StringBuilder temp = new StringBuilder();
            foreach (string item in keyValues.Keys)
            {
                temp.Append(item).Append("=").Append(WebUtility.UrlEncode(keyValues.Get(item))).Append("&");
            }
            return temp.Remove(temp.Length - 1, 1).ToString();
        }
        static string buildAKSKHeader(string appKey, string appSecret)
        {
            string now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); //Created
            string nonce = Guid.NewGuid().ToString().Replace("-", ""); //Nonce
            String str = nonce + now;
            byte[] keyByte = Encoding.UTF8.GetBytes(appSecret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(str);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                string base64 = Convert.ToBase64String(hashmessage);
                return String.Format("UsernameToken Username=\"{0}\",PasswordDigest=\"{1}\",Nonce=\"{2}\",Created=\"{3}\"",
                    appKey, base64, nonce, now);
            }
        }
        //低于.NET Framework 4.7.1版本,启用如下方法
        //static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        //{
        //    return true;
        //}
    }
}
```
 #### 呼叫事件通知接口
```
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
namespace privatenumber_ax_csharp_demo
{
    class callEventImpl
    {
        static void Main(string[] args)
        {
            //呼叫事件通知样例
            string jsonBody = JsonConvert.SerializeObject(new Dictionary<string, object>(){
                {"eventType", "disconnect"},
                {"statusInfo", new Dictionary<string, object>(){
                        {"sessionId", "1200_1827_4294967295_20190124023003@callenabler246.huaweicaas.com"},
                        {"timestamp", "2019-01-24 02:30:22"},
                        {"caller", "+86138****0022"},
                        {"called", "+86138****7021"},
                        {"stateCode", 0},
                        {"stateDesc", "The user releases the call."},
                        {"subscriptionId", "****"}
                    }
                }
            });
            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); //打印通知事件类型
            //callin：呼入事件
            if ("callin".Equals(eventType))
            {
                /**
                 * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
                 *
                 * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳
                 * 'sessionId': 通话链路的标识ID
                 * 'caller': 主叫号码
                 * 'called': 被叫号码
                 * 'subscriptionId': 绑定关系ID
                 */
                if (statusInfo.ContainsKey("sessionId"))
                {
                    Console.WriteLine("sessionId:" + statusInfo["sessionId"]);
                }
                return;
            }
            //callout：呼出事件
            if ("callout".Equals(eventType))
            {
                /**
                 * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
                 *
                 * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳
                 * 'sessionId': 通话链路的标识ID
                 * 'caller': 主叫号码
                 * 'called': 被叫号码
                 * 'subscriptionId': 绑定关系ID
                 */
                if (statusInfo.ContainsKey("sessionId"))
                {
                    Console.WriteLine("sessionId:" + statusInfo["sessionId"]);
                }
                return;
            }
            //alerting：振铃事件
            if ("alerting".Equals(eventType))
            {
                /**
                 * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
                 *
                 * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳
                 * 'sessionId': 通话链路的标识ID
                 * 'caller': 主叫号码
                 * 'called': 被叫号码
                 * 'subscriptionId': 绑定关系ID
                 */
                if (statusInfo.ContainsKey("sessionId"))
                {
                    Console.WriteLine("sessionId:" + statusInfo["sessionId"]);
                }
                return;
            }
            //answer：应答事件
            if ("answer".Equals(eventType))
            {
                /**
                 * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
                 *
                 * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳
                 * 'sessionId': 通话链路的标识ID
                 * 'caller': 主叫号码
                 * 'called': 被叫号码
                 * 'subscriptionId': 绑定关系ID
                 */
                if (statusInfo.ContainsKey("sessionId"))
                {
                    Console.WriteLine("sessionId:" + statusInfo["sessionId"]);
                }
                return;
            }
            //disconnect：挂机事件
            if ("disconnect".Equals(eventType))
            {
                /**
                 * Example: 此处以解析sessionId为例,请按需解析所需参数并自行实现相关处理
                 *
                 * 'timestamp': 呼叫事件发生时隐私保护通话平台的UNIX时间戳
                 * 'sessionId': 通话链路的标识ID
                 * 'caller': 主叫号码
                 * 'called': 被叫号码
                 * 'stateCode': 通话挂机的原因值
                 * 'stateDesc': 通话挂机的原因值的描述
                 * 'subscriptionId': 绑定关系ID
                 */
                if (statusInfo.ContainsKey("sessionId"))
                {
                    Console.WriteLine("sessionId:" + statusInfo["sessionId"]);
                }
                return;
            }
        }
    }
}
```
 #### 话单通知接口
```
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
namespace privatenumber_ax_csharp_demo
{
    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", 1},
                            {"spId", "****"},
                            {"appKey", "****"},
                            {"icid", "ba171f34e6953fcd751edc77127748f4.3757285803.338666679.5"},
                            {"bindNum", "+86138****0022"},
                            {"sessionId", "1200_1827_4294967295_20190124023003@callenabler246.huaweicaas.com"},
                            {"subscriptionId", "****"},
                            {"callerNum", "+86138****0021"},
                            {"calleeNum", "+86138****0022"},
                            {"fwdDisplayNum", "+86138****0022"},
                            {"fwdDstNum", "+86138****7021"},
                            {"callInTime", "2019-01-24 02:30:03"},
                            {"fwdStartTime", "2019-01-24 02:30:03"},
                            {"fwdAlertingTime", "2019-01-24 02:30:04"},
                            {"fwdAnswerTime", "2019-01-24 02:30:06"},
                            {"callEndTime", "2019-01-24 02:30:22"},
                            {"fwdUnaswRsn", 0},
                            {"ulFailReason", 0},
                            {"sipStatusCode", 0},
                            {"callOutUnaswRsn", 0},
                            {"recordFlag", 1},
                            {"recordStartTime", "2019-01-24 02:30:06"},
                            {"recordDomain", "****.com"},
                            {"recordBucketName", "****"},
                            {"recordObjectName", "****.wav"},
                            {"ttsPlayTimes", 0},
                            {"ttsTransDuration", 0},
                            {"mptyId", "****"},
                            {"serviceType", "003"},
                            {"hostName", "callenabler246.huaweicaas.com"}
                        }
                    }
                }
            });
            Console.WriteLine("jsonBody:" + 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为例,请按需解析所需参数并自行实现相关处理
             *
             * '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
             */
            //短时间内有多个通话结束时隐私保护通话平台会将话单合并推送,每条消息最多携带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.");
            }
        }
    }
}
```
 #### 短信通知接口
```
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
namespace privatenumber_ax_csharp_demo
{
    class smsNotifyImpl
    {
        static void Main(string[] args)
        {
            //短信通知样例
            string jsonBody = JsonConvert.SerializeObject(new Dictionary<string, object>(){
                {"appKey", "****"},
                {"smsEvent", new Dictionary<string, object>(){
                        {"smsIdentifier", "****"},
                        {"notificationMode", "Block"},
                        {"calling", "+86138****0001"},
                        {"virtualNumber", "+86138****0000"},
                        {"event", "TextSMS"},
                        {"timeStamp", "2018-09-13T09:46:16.023Z"}
                    }
                }
            });
            Console.WriteLine("jsonBody:" + jsonBody);
            //短信通知处理
            OnSmsEvent(jsonBody);
        }
        /// <summary>
        /// 短信通知,详细内容以接口文档为准
        /// </summary>
        /// <param name="jsonBody"></param>
        static void OnSmsEvent(string jsonBody)
        {
            JObject jsonObj = (JObject)JsonConvert.DeserializeObject(jsonBody); //将通知消息解析为jsonObj
            if (!jsonObj.ContainsKey("smsEvent"))
            {
                Console.WriteLine("param error: no smsEvent.");
                return;
            }
            //Console.WriteLine("appKey:" + jsonObj["appKey"]); //商户应用的AppKey
            JObject smsEvent = (JObject)jsonObj["smsEvent"]; //短信通知信息
            /**
             * Example: 此处以解析notificationMode为例,请按需解析所需参数并自行实现相关处理
             * 
             * 'smsIdentifier': 短信唯一标识
             * 'notificationMode': 通知模式
             * 'calling': 真实发送方号码
             * 'called': 真实接收方号码
             * 'virtualNumber': 隐私号码(X号码)
             * 'event': 短信状态事件
             * 'timeStamp': 短信事件发生的系统时间戳,UTC时间
             * 'subscriptionId': 绑定ID
             * 'smsContent': 用户发送的短信内容
             */
            if (smsEvent.ContainsKey("notificationMode"))
            {
                if ("Block".Equals(smsEvent["notificationMode"].ToString()))
                {
                    //收到隐私保护通话平台的短信通知,若为Block模式,请参考接口文档回消息指示下一步操作
                    IDictionary actions = new Dictionary<string, object>(){
                        {"operation", "vNumberRoute"}, //操作类型,转发短信/丢弃短信
                        {"message", new Dictionary<string, object>(){
                                {"called", "+86138****7022"}, //真实接收方号码
                                {"calling", "+86138****7021"} //真实发送方号码
                            }
                        }
                    };
                string resp = JsonConvert.SerializeObject(new Dictionary<string, object>(){{ "actions", new object[]{ actions }}}); //Block模式响应消息
                Console.WriteLine("resp:" + resp);
                }
                else if ("Notify".Equals(smsEvent["notificationMode"].ToString()))
                {
                    //收到隐私保护通话平台的短信通知,若为Notify模式,请回HTTP状态码为200的空消息
                    //string statusCode = 200;
                    Console.WriteLine("This is AX sms Notify mode.");
                }
                else
                {
                    Console.WriteLine("notificationMode param error.");
                }
            }
        }
    }
}
```
