C# 阿里云短信接口调用(不使用SDK,单文件完成)

虽然阿里云短信接口,提供了很多种语言的SKD,但是对应C#而言,如果使用阿里云SDK,你的项目中需要引入一大堆的dll,像这样:

我只需要发个短信,没必要引入这么多dll吧。于是,根据阿里云官方文档,接口SDK源码,自己整理封装了一个类,完成发短信的操作。闲话不多说,直接上代码:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;

namespace AliyunSMS
{
    /// <summary>
    /// 【相关文档】
    ///  RPC调用机制:https://help.aliyun.com/document_detail/315526.htm?spm=a2c4g.11186623.0.0.46b027b5vlfd0X
    ///  发送短信文档: https://help.aliyun.com/document_detail/419273.htm?spm=a2c4g.11186623.0.0.34374198G2b44u
    ///  短信接口文档:https://help.aliyun.com/document_detail/419298.html?spm=5176.25163407.help.dexternal.774dbb6eylDOx0
    /// </summary>
    public static class AliyunSmsHelper
    {
        /// <summary>
        ///     阿里云访问密钥
        /// </summary>
        public static string AccessKeyId = "***替换为自己的AccessKeyId***"; //用户标识
        public static string AccessKeySecret = "***替换为自己的AccessKeySecret***"; //用户密钥

        private static readonly string Separator = "&";
        public static string Url = "http://dysmsapi.aliyuncs.com?"; //短信接口地址

        /// <summary>
        ///     发送短信
        /// </summary>
        /// <param name="phone">手机号码</param>
        /// <param name="signName">短信签名</param>
        /// <param name="templateCode">模板编号</param>
        /// <param name="templateParam">模板变量</param>
        /// <returns></returns>
        public static string SendSms(string phone, string signName, string templateCode, string templateParam)
        {
            var dic = new Dictionary<string, string>();

            //公共请求参数
            dic.Add("Action", "SendSms");
            dic.Add("Version", "2017-05-25");
            dic.Add("Format", "JSON");
            dic.Add("AccessKeyId", AccessKeyId);
            dic.Add("SignatureNonce", Guid.NewGuid().ToString());
            dic.Add("Timestamp", DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss'Z'"));
            dic.Add("SignatureMethod", "HMAC-SHA1");
            dic.Add("SignatureVersion", "1.0");

            //请求参数
            dic.Add("PhoneNumbers", phone);
            dic.Add("SignName", signName);
            dic.Add("TemplateCode", templateCode);
            dic.Add("TemplateParam", templateParam);

            //接口签名
            var signature = GetSignature(dic, "GET", AccessKeySecret);
            dic.Add("Signature", signature);

            var parms = "";
            foreach (var pair in dic) parms += pair.Key + "=" + PercentEncode(pair.Value) + "&"; //参数值需用阿里云约定编码方式进行编码
            parms = parms.TrimEnd('&');

            return HttpGet(Url + parms);
        }

        /// <summary>
        ///     发起网络请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string HttpGet(string url)
        {
            var encode = Encoding.UTF8;
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.ContentType = "text/html, application/xhtml+xml, */*";

            var response = (HttpWebResponse)request.GetResponse();
            var rs = response.GetResponseStream();
            var sr = new StreamReader(rs, encode);
            var result = sr.ReadToEnd();
            sr.Close();
            rs.Close();
            return result;
        }

        /// <summary>
        ///     签名算法
        /// </summary>
        /// <param name="signedParams"></param>
        /// <param name="method"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static string GetSignature(
            Dictionary<string, string> signedParams,
            string method,
            string secret)
        {
            var list = signedParams.Keys.ToList();

            list.Sort(StringComparer.Ordinal); //排序

            var builder = new StringBuilder();
            foreach (var key in list)
                if (signedParams[key] != null)
                    builder.Append("&").Append(PercentEncode(key)).Append("=").Append(PercentEncode(signedParams[key]));

            var builder2 = new StringBuilder();
            builder2.Append(method);
            builder2.Append(Separator);
            builder2.Append(PercentEncode("/"));
            builder2.Append(Separator);
            builder2.Append(PercentEncode(builder.ToString().Substring(1)));

            byte[] hash = { };
            using (var fromName = CryptoConfig.CreateFromName("HMACSHA1") as KeyedHashAlgorithm)
            {
                if (fromName != null)
                {
                    fromName.Key = Encoding.UTF8.GetBytes(secret + Separator);
                    hash = fromName.ComputeHash(Encoding.UTF8.GetBytes(builder2.ToString().ToCharArray()));
                }
            }

            return Convert.ToBase64String(hash);
        }

        /// <summary>
        ///     编码
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string PercentEncode(string value)
        {
            if (value == null)
                return null;
            var stringBuilder = new StringBuilder();
            var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
            foreach (char ch in Encoding.UTF8.GetBytes(value))
                if (str.IndexOf(ch) >= 0)
                    stringBuilder.Append(ch);
                else
                    stringBuilder.Append("%").Append(string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)ch));
            return stringBuilder.ToString().Replace("+", "%20").Replace("*", "%2A").Replace("%7E", "~");
        }

        public static string ToForm(IDictionary filter)
        {
            if (filter == null)
                return string.Empty;
            var dictionary = filter.Keys.Cast<string>().ToDictionary(key => key, key => filter[key]);
            var dicOut = new Dictionary<string, string>();
            TileDict(dicOut, dictionary);
            var values = new List<string>();
            foreach (var keyValuePair in dicOut)
                if (!string.IsNullOrEmpty(keyValuePair.Value))
                    values.Add(PercentEncode(keyValuePair.Key) + "=" + PercentEncode(keyValuePair.Value));
            return string.Join("&", values.ToArray());
        }

        internal static void TileDict(Dictionary<string, string> dicOut, object obj, string parentKey = "")
        {
            if (obj == null)
                return;
            if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
            {
                foreach (var keyValuePair in ((IDictionary)obj).Keys.Cast<string>()
                         .ToDictionary(key => key, key => ((IDictionary)obj)[key]))
                {
                    var parentKey1 = parentKey + "." + keyValuePair.Key;
                    if (keyValuePair.Value != null)
                        TileDict(dicOut, keyValuePair.Value, parentKey1);
                }
            }
            else if (typeof(IList).IsAssignableFrom(obj.GetType()))
            {
                var num = 1;
                foreach (var obj1 in (IEnumerable)obj)
                {
                    TileDict(dicOut, obj1, parentKey + "." + num.ToSafeString());
                    ++num;
                }
            }
            else if (obj.GetType() == typeof(byte[]))
            {
                dicOut.Add(parentKey.TrimStart('.'), Encoding.UTF8.GetString((byte[])obj));
            }
            else
            {
                dicOut.Add(parentKey.TrimStart('.'), obj.ToSafeString(""));
            }
        }

        public static string ToSafeString(this object obj, string defaultStr = null)
        {
            if (obj == null)
                return defaultStr;
            try
            {
                return obj.ToString();
            }
            catch
            {
                return defaultStr;
            }
        }
    }
}

调用方式如下:(以发送短信验证码短信为例)

var random = new Random().Next(100000, 999999).ToString();
AliyunSmsHelper.SendSms("1******4902", "短信签名", "SMS_262******", "{"code":"" + random + ""}");
       

 参考文档:

1.RPC调用机制:https://help.aliyun.com/document_detail/315526.htm?spm=a2c4g.11186623.0.0.46b027b5vlfd0X

2.发送短信文档: https://help.aliyun.com/document_detail/419273.htm?spm=a2c4g.11186623.0.0.34374198G2b44u

3.短信接口文档:https://help.aliyun.com/document_detail/419298.html?spm=5176.25163407.help.dexternal.774dbb6eylDOx0

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>