.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> ...
随机推荐
- ASP.NET MVC编程——验证、授权与安全
1 验证 一般采用表单验证完成登陆验证,建议结合SSL使用.为限制控制器只能执行HTTPS,使用RequireHttpsAttribute 2 授权 对账户的权限的控制可以通过在控制器或控制器操作上 ...
- Liquibase的简单使用
LiquiBase是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态.它的目标是提供一种数据库类型无关的解决方案,通过执 ...
- OpenCascade Law Function
OpenCascade Law Function eryar@163.com 1.Introduction 在OpenCASCADE的TKGeomAlgo Toolkit中提供了一个Law Packa ...
- express+mongodb+socket.io
node后端代码 // Setup basic express server var express = require('express'); var app = express(); var pa ...
- 源码实现 --> itoa函数实现
itoa函数实现 itoa()函数的功能是将一个整数转换为一个字符串 例如12345,转换之后的字符串为"12345",-123转换之后为"-123",欢迎大家 ...
- 解决图片裁剪com.android.camera.action.CROP和intent.putExtra("return-data", true);
最近在做一个图片上传,在上传之前需要对照片进行裁剪,遇到一个坑,在别的手机上运行都正常,在小米手机上却遇见一个问题,选中图片无法裁剪,直接闪退,目前已解决!之前出过问题的地方会标红 //选择图片 pr ...
- centos7环境下mysql5.7的安装与配置
最近无事闲来折腾虚拟机,以前都是折腾云服务器,现在自己捣捣.看到mysql的教程蛮好的,准备做个笔记.原文来自mysql5.7的安装与配置(centos7环境) 第一步:下载mysql [root@M ...
- Java基础笔记(1)----语言基础
变量 变量:是内存中的一块存储空间,是存储数据的基本单元. 使用:先声明,后赋值,在使用. 声明:数据类型 + 变量名 = 值.(例:int a = 5:) 数据类型 分类:如图: 详解: Strin ...
- C#,一份超简单的数据库帮助类,SqlHelp
简单,实用,留存. using System; using System.Collections.Generic; using System.Configuration; using System.D ...
- Java基础学习笔记二十六 JDBC
什么是JDBC JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.原来我们操作数据库是在控制台使用SQL语句来操作数据库,J ...