.net core 使用阿里云短信发送SMS
阿里云官方的skd(aliyun-net-sdk-core,aliyun-net-sdk-dysmsapi)在dnc中发送短信会出错,nuget上的包貌似也一样不管用。直接改下sdk当然也可以,但就发个短信,官方的sdk实在是有点繁杂,其实可以简单化,一个类就搞定。
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web; namespace Vino.Core.Communication.SMS
{
public class AliyunSmsSender : ISmsSender
{
private string RegionId = "cn-hangzhou";
private string Version = "2017-05-25";
private string Action = "SendSms";
private string Format = "JSON";
private string Domain = "dysmsapi.aliyuncs.com"; private int MaxRetryNumber = ;
private bool AutoRetry = true;
private const string SEPARATOR = "&";
private int TimeoutInMilliSeconds = ; private string AccessKeyId;
private string AccessKeySecret; public AliyunSmsSender(string accessKeyId, string accessKeySecret)
{
this.AccessKeyId = accessKeyId;
this.AccessKeySecret = accessKeySecret;
} /// <summary>
/// 发送短信
/// </summary>
public async Task<(bool success, string response)> Send(SmsObject sms)
{
var paramers = new Dictionary<string, string>();
paramers.Add("PhoneNumbers", sms.Mobile);
paramers.Add("SignName", sms.Signature);
paramers.Add("TemplateCode", sms.TempletKey);
paramers.Add("TemplateParam", JsonConvert.SerializeObject(sms.Data));
paramers.Add("OutId", sms.OutId);
paramers.Add("AccessKeyId", AccessKeyId); try
{
string url = GetSignUrl(paramers, AccessKeySecret); int retryTimes = ;
var reply = await HttpGetAsync(url);
while ( <= reply.StatusCode && AutoRetry && retryTimes < MaxRetryNumber)
{
url = GetSignUrl(paramers, AccessKeySecret);
reply = await HttpGetAsync(url);
retryTimes++;
} if (!string.IsNullOrEmpty(reply.response))
{
var res = JsonConvert.DeserializeObject<Dictionary<string, string>>(reply.response);
if (res != null && res.ContainsKey("Code") && "OK".Equals(res["Code"]))
{
return (true, response: reply.response);
}
} return (false, response: reply.response);
}
catch (Exception ex)
{
return (false, response: ex.Message);
}
} private string GetSignUrl(Dictionary<string, string> parameters, string accessSecret)
{
var imutableMap = new Dictionary<string, string>(parameters);
imutableMap.Add("Timestamp", FormatIso8601Date(DateTime.Now));
imutableMap.Add("SignatureMethod", "HMAC-SHA1");
imutableMap.Add("SignatureVersion", "1.0");
imutableMap.Add("SignatureNonce", Guid.NewGuid().ToString());
imutableMap.Add("Action", Action);
imutableMap.Add("Version", Version);
imutableMap.Add("Format", Format);
imutableMap.Add("RegionId", RegionId); IDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(imutableMap, StringComparer.Ordinal);
StringBuilder canonicalizedQueryString = new StringBuilder();
foreach (var p in sortedDictionary)
{
canonicalizedQueryString.Append("&")
.Append(PercentEncode(p.Key)).Append("=")
.Append(PercentEncode(p.Value));
} StringBuilder stringToSign = new StringBuilder();
stringToSign.Append("GET");
stringToSign.Append(SEPARATOR);
stringToSign.Append(PercentEncode("/"));
stringToSign.Append(SEPARATOR);
stringToSign.Append(PercentEncode(canonicalizedQueryString.ToString().Substring())); string signature = SignString(stringToSign.ToString(), accessSecret + "&"); imutableMap.Add("Signature", signature); return ComposeUrl(Domain, imutableMap);
} private static string FormatIso8601Date(DateTime date)
{
return date.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.CreateSpecificCulture("en-US"));
} /// <summary>
/// 签名
/// </summary>
public static string SignString(string source, string accessSecret)
{
using (var algorithm = new HMACSHA1(Encoding.UTF8.GetBytes(accessSecret.ToCharArray())))
{
return Convert.ToBase64String(algorithm.ComputeHash(Encoding.UTF8.GetBytes(source.ToCharArray())));
}
} private static string ComposeUrl(string endpoint, Dictionary<String, String> parameters)
{
StringBuilder urlBuilder = new StringBuilder("");
urlBuilder.Append("http://").Append(endpoint);
if (- == urlBuilder.ToString().IndexOf("?"))
{
urlBuilder.Append("/?");
}
string query = ConcatQueryString(parameters);
return urlBuilder.Append(query).ToString();
} private static string ConcatQueryString(Dictionary<string, string> parameters)
{
if (null == parameters)
{
return null;
}
StringBuilder sb = new StringBuilder(); foreach (var entry in parameters)
{
String key = entry.Key;
String val = entry.Value; sb.Append(HttpUtility.UrlEncode(key, Encoding.UTF8));
if (val != null)
{
sb.Append("=").Append(HttpUtility.UrlEncode(val, Encoding.UTF8));
}
sb.Append("&");
} int strIndex = sb.Length;
if (parameters.Count > )
sb.Remove(strIndex - , ); return sb.ToString();
} public static string PercentEncode(string value)
{
StringBuilder stringBuilder = new StringBuilder();
string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
byte[] bytes = Encoding.GetEncoding("UTF-8").GetBytes(value);
foreach (char c in bytes)
{
if (text.IndexOf(c) >= )
{
stringBuilder.Append(c);
}
else
{
stringBuilder.Append("%").Append(
string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)c));
}
}
return stringBuilder.ToString();
} private async Task<(int StatusCode, string response)> HttpGetAsync(string url)
{
HttpClientHandler handler = new HttpClientHandler();
handler.Proxy = null;
handler.AutomaticDecompression = DecompressionMethods.GZip; using (var http = new HttpClient(handler))
{
http.Timeout = new TimeSpan(TimeSpan.TicksPerMillisecond * TimeoutInMilliSeconds);
HttpResponseMessage response = await http.GetAsync(url);
return ((int)response.StatusCode, await response.Content.ReadAsStringAsync());
}
}
}
}
SmsObject.cs
using System;
using System.Collections.Generic;
using System.Text; namespace Vino.Core.Communication.SMS
{
public class SmsObject
{
/// <summary>
/// 手机号
/// </summary>
public string Mobile { set; get; } /// <summary>
/// 签名
/// </summary>
public string Signature { get; set; } /// <summary>
/// 模板Key
/// </summary>
public string TempletKey { set; get; } /// <summary>
/// 短信数据
/// </summary>
public IDictionary<string, string> Data { set; get; } /// <summary>
/// 业务ID
/// </summary>
public string OutId { set; get; }
}
}
调用方法
IDictionary<string, string> data = new Dictionary<string, string>();
data.Add("code", "");
var sms = new SmsObject
{
Mobile = "",
Signature = "我的签名",
TempletKey = "模板ID",
Data = data,
OutId = "OutId"
}; var res = await new AliyunSmsSender(accessKeyId, accessKeySecret).Send(sms);
Debug.WriteLine($"发送结果:{res.success}");
Debug.WriteLine($"Response:{res.response}");
.net core 使用阿里云短信发送SMS的更多相关文章
- Abp 添加阿里云短信发送
ABP中有短信发送接口ISmsSender public interface ISmsSender { Task<string> SendAsync(string number, stri ...
- 2018阿里云短信发送DEMO接入简单实例
以下更新2018-04-2309:57:54 后续不再更新, 基本类: app/SignatureHelper.php <?php namespace aliyun_mns; /** * 签名助 ...
- 阿里云短信发送服务SDK-Python3
本文提供阿里云的短信发送服务SDK,使用Python3实现. # -*- coding: utf-8 -*- # pip install requests import requests import ...
- spring boot集成阿里云短信发送接收短信回复功能
1.集成阿里云通信发送短信: 在pom.xml文件里添加依赖 <!--阿里短信服务--> <dependency> <groupId>com.aliyun</ ...
- tp5阿里云短信发送
到阿里云下载php版demo,下完整版的,不是轻量级的; 框架 :TP5 把下载下来的文件放到extend里面 文件名:alimsg 里面的文件 import('alimsg.api_demo.Sm ...
- java 阿里云短信发送
记录自己的足迹,学习的路很长,一直在走着呢~ 第一步登录阿里云的控制台,找到此处: 点击之后就到此页面,如果发现账号有异常或者泄露什么,可以禁用或者删除 AccessKey: 此处方便测试,所以就新 ...
- ABP框架中短信发送处理,包括阿里云短信和普通短信商的短信发送集成
在一般的系统中,往往也有短信模块的需求,如动态密码的登录,系统密码的找回,以及为了获取用户手机号码的短信确认等等,在ABP框架中,本身提供了对邮件.短信的基础支持,那么只需要根据自己的情况实现对应的接 ...
- 阿里云短信服务开发报错Java.lang.NoClassDefFoundError:com/aliyuncs/exceptions/ClientException
手机app获取短信验证码功能时候,遇到的问题.使用的是阿里云的短信服务,下载平台demo时运行不报错,但是在service层调用的时候报错 Java.lang.NoClassDefFoundError ...
- 阿里云短信验证解决方案(java版)(redis存储)
最近搞了一个互联网项目的注册,需要写一个手机号验证(由于之前没有轮子,只能自己摸索了); 1:基本思路: 1>购买了阿里云短信服务->下载阿里云短信发送demo(java版); 2> ...
随机推荐
- 关于IM的一些思考与实践
上一篇简单的实现了一个聊天网页,但这个太简单,消息全广播,没有用户认证和已读未读处理,主要的意义是走通了websocket-sharp做服务端的可能性.那么一个完整的IM还需要实现哪些部分? 一.发消 ...
- Mycat 分片规则详解--日期范围 hash 分片
实现方式:其思想和范围取模分片一样,由于日期取模会出现数据热点问题,所以先根据日期分组,再根据时间 hash 使得短期数据分布跟均匀. 优点:避免扩容时的数据迁移,可以在一定程度上避免范围分片的热点问 ...
- poj-1012-约瑟夫问题
Description The Joseph's problem is notoriously known. For those who are not familiar with the origi ...
- ELK学习笔记(四)SpringBoot+Logback+Redis+ELK实例
废话不多说,直接上干货,首先看下整体应用的大致结构.(整个过程我用到了两台虚拟机 应用和Shipper 部署在192.168.25.128 上 Redis和ELK 部署在192.168.25.129 ...
- Laravel 模型事件入门
Laravel 模型事件允许你监听模型生命周期内的多个关键点,甚至可以在阻止一个模型的保存或者删除. Laravel 模型事件文档 概述了如何使用钩子将对应事件与相关的事件类型关联起来,但是本文的主旨 ...
- mysql新手入门随笔2
17.创建表 CREATE TABLE tbname(columnname1 类型 约束条件, columnname2 类型 约束条件,-); 三大类型:数值型,时间日期型,字符串类型 六大约束条件: ...
- zip详解
http://www.360doc.com/content/06/0915/14/10610_208147.shtml
- JavaWeb学习笔记六 JSP
JSP技术 JSP全称Java Server Pages,是一种动态网页开发技术.它使用JSP标签在HTML网页中插入Java代码.标签通常以<%开头以%>结束. JSP是一种Java s ...
- 十个 PHP 开发者最容易犯的错误
PHP 语言让 WEB 端程序设计变得简单,这也是它能流行起来的原因.但也是因为它的简单,PHP 也慢慢发展成一个相对复杂的语言,层出不穷的框架,各种语言特性和版本差异都时常让搞的我们头大,不得不浪费 ...
- Spring MVC之适配器的获取及执行(RequestMappingHandlerAdapter)
首先看下doDispatch()方法如何找到适合的适配器来执行方法的: protected HandlerAdapter getHandlerAdapter(Object handler) throw ...