更新时间:2024-11-14 GMT+08:00
分享

C#

样例

发送短信示例发送分批短信示例接收状态报告示例接收上行短信示例

环境要求

.net 7.0Visual Studio Code 1.75.1(插件C# v1.25.7, Code Runner v0.12.0(非必选))

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

参考API签名SDK与demo,点击下载其中的SDK与Demo。以Visual Studio Code为例,在本地资源管理器选择一个目录,比如D:/sms,使用终端进入。

  1. 执行dotnet new console命令,产生一个工程。
  2. 将Signer.cs、HttpEncoder.cs复制到D:/sms文件夹;然后在sms文件夹内新建SendSms.cs空文件,再将下列样例(比如“发送短信示例”)的内容复制到SendSms.cs中。
  3. 用Visual Studio Code打开该工程,即可运行SendSms.cs。

发送短信示例

 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
using System;
using System.Net;
using System.IO;
using APIGATEWAY_SDK;
using System.Text;

namespace DEMO
{
    class Program
    {
        static void Main(string[] args)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

           //必填,请参考"开发准备"获取如下数据,替换为实际值
            string apiAddress = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1"; //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
            // 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;
            string appKey = "c8RWg3ggEcyd4D3p94bf3Y7x1Ile"; //APP_Key
            string appSecret = "q4Ii87Bh************80SfD7Al"; //APP_Secret
            string sender = "csms12345678"; //国内短信签名通道号
            string templateId = "8ff55eac1d0b478ab3c06c3c6a492300"; //模板ID

            //条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
           
            //string signature = "华为云短信测试"; //签名名称

            //必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔
            string receiver = "+86137****6781,+86137****6782"; //短信接收人号码

            //选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
            string statusCallBack = "";

            /*
             * 选填,使用无变量模板时请赋空值 string templateParas = "";
             * 单变量模板示例:模板内容为"您的验证码是${1}"时,templateParas可填写为"[\"369751\"]"
             * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,templateParas可填写为"[\"3\",\"人民公园正门\"]"
             * 模板中的每个变量都必须赋值,且取值不能为空
             * 查看更多模板规范和变量规范:产品介绍>短信模板须知和短信变量须知
             */
            string templateParas = "[\"369751\"]"; //模板变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。

            Signer signer = new Signer();
            signer.Key = appKey;
            signer.Secret = appSecret;

            HttpRequest r = new HttpRequest("POST", new Uri(apiAddress)); //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI

            //请求Body
            var body = new Dictionary<string, string>() {
                {"from", sender},
                {"to", receiver},
                {"templateId", templateId},
                {"templateParas", templateParas},
                {"statusCallback", statusCallBack},
                //{"signature", signature} //使用国内短信通用模板时,必须填写签名名称
            };

            r.body =new FormUrlEncodedContent(body).ReadAsStringAsync().Result;
            r.headers.Add("Content-Type", "application/x-www-form-urlencoded");

            HttpWebRequest req = signer.Sign(r);
            Console.WriteLine(req.Headers.GetValues("x-sdk-date")[0]);
            Console.WriteLine(string.Join(", ", req.Headers.GetValues("authorization")));
            Console.WriteLine("body: " + r.body);

            // 不校验证书
            ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
            try
            {
                var writer = new StreamWriter(req.GetRequestStream());
                writer.Write(r.body);
                writer.Flush();
                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                var reader = new StreamReader(resp.GetResponseStream());
                Console.WriteLine(reader.ReadToEnd());
            }
            catch (WebException e)
            {
                HttpWebResponse resp = (HttpWebResponse)e.Response;
                if (resp != null)
                {
                    Console.WriteLine((int)resp.StatusCode + " " + resp.StatusDescription);
                    var reader = new StreamReader(resp.GetResponseStream());
                    Console.WriteLine(reader.ReadToEnd());
                }
                else
                {
                    Console.WriteLine(e.Message);
                }

            }
        }

    }
}

发送分批短信示例

引用库:Newtonsoft.Json 11.0.2及以上版本,请参考https://www.newtonsoft.com/json获取。

  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
using System;
using System.Net;
using System.IO;
using APIGATEWAY_SDK;
using System.Text;
using System.Collections;
using System.Collections.Generic;

using Newtonsoft.Json;

namespace DEMODiffSMS
{
    class Program
    {
        static void Main(string[] args)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

            //必填,请参考"开发准备"获取如下数据,替换为实际值
            string apiAddress = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendDiffSms/v1"; //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
            // 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;
            string appKey = "c8RWg3ggEcyd4D3p94bf3Y7x1Ile"; //APP_Key
            string appSecret = "q4Ii87Bh************80SfD7Al"; //APP_Secret
            string sender = "csms12345678"; //国内短信签名通道号
            string templateId_1 = "8ff55eac1d0b478ab3c06c3c6a492300"; //模板ID1
            string templateId_2 = "8ff55eac1d0b478ab3c06c3c6a492301"; //模板ID2

            //条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
           
            string signature_1 = "华为云短信测试1"; //签名名称1
            string signature_2 = "华为云短信测试2"; //签名名称2

            //必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔
            string[] receiver_1 = { "+86151****6781", "+86151****6783" }; //模板1的接收号码
            string[] receiver_2 = { "+86151****6782", "+86151****6784" }; //模板2的接收号码

            //选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
            string statusCallBack = "https://your.server.com/rest/callback/statusReport";

            /*
             * 选填,使用无变量模板时请赋空值 string[] templateParas = {};
             * 单变量模板示例:模板内容为"您的验证码是${1}"时,templateParas可填写为{"369751"}
             * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,templateParas可填写为{"3","人民公园正门"}
             * 模板中的每个变量都必须赋值,且取值不能为空
             * 查看更多模板规范和变量规范:产品介绍>短信模板须知和短信变量须知
             */
            string[] templateParas_1 = {"123456"}; //模板1变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。
            string[] templateParas_2 = {"234567"}; //模板2变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。

            ArrayList smsContent = new ArrayList
            {
                //smsContent,不携带签名名称时,signature请填null
                InitDiffSms(receiver_1, templateId_1, templateParas_1, signature_1),
                InitDiffSms(receiver_2, templateId_2, templateParas_2, signature_2)
            };

            //请求Body
            var body = new Dictionary<string, object>{
                {"from", sender},
                {"statusCallback", statusCallBack},
                {"smsContent", smsContent}
            };

            Signer signer = new Signer();
            signer.Key = appKey;
            signer.Secret = appSecret;

            HttpRequest r = new HttpRequest("POST", new Uri(apiAddress));
            r.body = JsonConvert.SerializeObject(body);
            r.headers.Add("Content-Type", "application/json");

            HttpWebRequest req = signer.Sign(r);
            Console.WriteLine(req.Headers.GetValues("x-sdk-date")[0]);
            Console.WriteLine(string.Join(", ", req.Headers.GetValues("authorization")));
            Console.WriteLine("body: " + r.body);

            // 不校验证书
            ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
            try
            {
                var writer = new StreamWriter(req.GetRequestStream());
                writer.Write(r.body);
                writer.Flush();
                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                var reader = new StreamReader(resp.GetResponseStream());
                Console.WriteLine(reader.ReadToEnd());
            }
            catch (WebException e)
            {
                HttpWebResponse resp = (HttpWebResponse)e.Response;
                if (resp != null)
                {
                    Console.WriteLine((int)resp.StatusCode + " " + resp.StatusDescription);
                    var reader = new StreamReader(resp.GetResponseStream());
                    Console.WriteLine(reader.ReadToEnd());
                }
                else
                {
                    Console.WriteLine(e.Message);
                }

            }
        }

        static Dictionary<string, object> InitDiffSms(string[] receiver, string templateId, string[] templateParas, string signature)
        {
            Dictionary<string, object> dic = new Dictionary<string, object>
            {
                {"to", receiver},
                {"templateId", templateId},
                {"templateParas", templateParas}
            };
            if (!signature.Equals(null) && signature.Length > 0)
            {
                dic.Add("signature", signature);
            }

            return dic;
        }
    }
}

接收状态报告

 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
using System;
using System.Web;

namespace msgsms_csharp_demo
{
    class Report
    {
        static void Main(string[] args)
        {
            //string success_body = "sequence=1&total=1&updateTime=2018-10-31T08%3A43%3A41Z&source=2&smsMsgId=2ea20735-f856-4376-afbf-570bd70a46ee_11840135&status=DELIVRD";
            string failed_body = "sequence=1&total=1&updateTime=2018-10-31T08%3A43%3A41Z&source=2&smsMsgId=2ea20735-f856-4376-afbf-570bd70a46ee_11840135&status=E200027";

            //OnSmsStatusReport(success_body);
            OnSmsStatusReport(failed_body);
        }

        /// <summary>
        /// 解析状态报告数据
        /// </summary>
        /// <param name="data">短信平台上报的状态报告数据</param>
        static void OnSmsStatusReport(string data)
        {
            var keyValues = HttpUtility.ParseQueryString(data); //解析状态报告数据

            /**
             * Example: 此处已解析status为例,请按需解析所需参数并自行实现相关处理
             * 
             * 'smsMsgId': 短信唯一标识
             * 'total': 长短信拆分条数
             * 'sequence': 拆分后短信序号
             * 'source': 状态报告来源
             * 'updateTime': 资源更新时间
             * 'status': 状态码
             */
            string status = keyValues.Get("status"); // 状态报告枚举值
            // 通过status判断短信是否发送成功
            if ("DELIVRD".Equals(status.ToUpper()))
            {
                Console.WriteLine("Send sms success. smsMsgId: " + keyValues.Get("smsMsgId"));
            }
            else
            {
                // 发送失败,打印status和orgCode
                Console.WriteLine("Send sms failed. smsMsgId: " + keyValues.Get("smsMsgId"));
                Console.WriteLine("Failed status: " + status);
            }
        }
    }
}

接收上行短信

 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
using System;
using System.Web;

namespace msgsms_csharp_demo
{
    class UpData
    {
        static void Main(string[] args)
        {
            string updata = "from=%2B86151****6789&to=1069****019&body=********&smsMsgId=9692b5be-c427-4525-8e73-cf4a6ac5b3f7";

            onSmsUpData(updata);
        }

        /// <summary>
        /// 解析上行短信通知数据
        /// </summary>
        /// <param name="data">短信平台推送的上行短信通知数据</param>
        static void onSmsUpData(string data)
        {
            var keyValues = HttpUtility.ParseQueryString(data); //解析上行短信通知数据

            /**
             * Example: 此处已解析body为例,请按需解析所需参数并自行实现相关处理
             * 
             * 'smsMsgId': 上行短信唯一标识
             * 'from': 上行短信发送方的号码
             * 'to': 上行短信接收方的号码
             * 'body': 上行短信发送的内容
             */
            string body = keyValues.Get("body"); // 上行短信发送的内容
            Console.WriteLine("Sms up data. Body: " + body);
        }
    }
}

相关文档