@@ -138,6 +138,10 @@ | |||
#endregion | |||
#region 8号库 | |||
/// <summary> | |||
/// sms | |||
/// </summary> | |||
public static int sms { get { return 8; } } | |||
#endregion | |||
#region 9号库 | |||
@@ -91,6 +91,24 @@ namespace Learun.Util | |||
return sb.ToString(); | |||
} | |||
/// <summary> | |||
/// 数字随机数 | |||
/// </summary> | |||
/// <param name="n">生成长度</param> | |||
/// <returns></returns> | |||
public static string RandNum(int n) | |||
{ | |||
char[] arrChar = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; | |||
StringBuilder num = new StringBuilder(); | |||
Random rnd = new Random(DateTime.Now.Millisecond); | |||
for (int i = 0; i < n; i++) | |||
{ | |||
num.Append(arrChar[rnd.Next(0, 9)].ToString()); | |||
} | |||
return num.ToString(); | |||
} | |||
#endregion | |||
#region 删除最后一个字符之后的字符 | |||
@@ -148,7 +148,33 @@ namespace Learun.Util | |||
} | |||
return result; | |||
} | |||
public static string HttpPost(string url, string json, Encoding encoding) | |||
{ | |||
string result = ""; | |||
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); | |||
req.Method = "POST"; | |||
req.ContentType = "application/x-www-form-urlencoded"; | |||
byte[] data = encoding.GetBytes(json);//把字符串转换为字节 | |||
req.ContentLength = data.Length; //请求长度 | |||
using (Stream reqStream = req.GetRequestStream()) //获取 | |||
{ | |||
reqStream.Write(data, 0, data.Length);//向当前流中写入字节 | |||
reqStream.Close(); //关闭当前流 | |||
} | |||
HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); //响应结果 | |||
Stream stream = resp.GetResponseStream(); | |||
//获取响应内容 | |||
using (StreamReader reader = new StreamReader(stream, encoding)) | |||
{ | |||
result = reader.ReadToEnd(); | |||
} | |||
return result; | |||
} | |||
public static string HttpPosts(string url, string json, WebHeaderCollection header) | |||
{ | |||
string result = ""; | |||
@@ -0,0 +1,85 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Threading.Tasks; | |||
using Aliyun.Acs.Core; | |||
using Aliyun.Acs.Core.Exceptions; | |||
using Aliyun.Acs.Core.Profile; | |||
using Aliyun.Acs.Dysmsapi.Model.V20170525; | |||
using Learun.Util; | |||
using Newtonsoft.Json; | |||
namespace Quanjiang.DigitalScholl.SendSms | |||
{ | |||
public class AliyunSms : ISms | |||
{ | |||
private static readonly string RegionIdForPop = ConfigManager.AppSettings["regionIdForPop"].Value; | |||
private static readonly string AccessId = ConfigManager.AppSettings["accessId"].Value; | |||
private static readonly string AccessSecret = ConfigManager.AppSettings["accessSecret"].Value; | |||
private static readonly string Product = ConfigManager.AppSettings["product"].Value; | |||
private static readonly string Domain = ConfigManager.AppSettings["domain"].Value; | |||
private static readonly string SignName = ConfigManager.AppSettings["SignName"].Value; | |||
/// <summary> | |||
/// 发送短信 | |||
/// </summary> | |||
/// <param name="phoneNumber">手机号</param> | |||
/// <param name="st">短信通知类型</param> | |||
/// <returns>发送结果</returns> | |||
public async Task<(string code, string randomNum, string message, string errorType)> SendSmsToSingle(string phoneNumber, SmsType st, List<string> sendParams = null) | |||
{ | |||
(string code, string randomNum, string message, string errorType) result; | |||
IClientProfile profile = DefaultProfile.GetProfile(RegionIdForPop, AccessId, AccessSecret); | |||
DefaultProfile.AddEndpoint(RegionIdForPop, RegionIdForPop, Product, Domain); | |||
IAcsClient acsClient = new DefaultAcsClient(profile); | |||
var request = new SendSmsRequest(); | |||
try | |||
{ | |||
request.PhoneNumbers = phoneNumber; | |||
request.SignName = SignName; | |||
var (templatecode, templateparam, randomNum) = GetSmsTemplateBySmsType(st); | |||
request.TemplateCode = templatecode; | |||
request.TemplateParam = templateparam; | |||
var sendSmsResponse = await Task.FromResult(acsClient.GetAcsResponse(request)); | |||
result = (sendSmsResponse.Code, randomNum, sendSmsResponse.Message, ""); | |||
} | |||
catch (ServerException e) | |||
{ | |||
result = (e.ErrorCode, "", e.ErrorMessage, Enum.GetName(typeof(ErrorType), e.ErrorType)); | |||
} | |||
catch (ClientException e) | |||
{ | |||
result = (e.ErrorCode, "", e.ErrorMessage, Enum.GetName(typeof(ErrorType), e.ErrorType)); | |||
} | |||
return result; | |||
} | |||
public Task<(string code, string randomNum, string message, string errorType)> SendSmsToMulti(List<string> phoneNumbers, SmsType st, List<string> sendParams = null) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
/// <summary> | |||
/// 根据短信通知类型获取短信模板 | |||
/// </summary> | |||
/// <param name="st"></param> | |||
/// <returns></returns> | |||
private (string templateCode, string templateParam, string randomNum) GetSmsTemplateBySmsType(SmsType st) | |||
{ | |||
(string templateCode, string templateParam, string randomNum) result; | |||
var randomNum = CommonHelper.RandNum(6); | |||
switch (st) | |||
{ | |||
case SmsType.LoginBind: | |||
result = ("SMS_468910589", JsonConvert.SerializeObject(new { code = randomNum }), randomNum); | |||
break; | |||
case SmsType.ForgetPassWord: | |||
result = ("SMS_468910589", JsonConvert.SerializeObject(new { code = randomNum }), randomNum); | |||
break; | |||
default: | |||
throw new ArgumentOutOfRangeException(nameof(st), st, null); | |||
} | |||
return result; | |||
} | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<configuration> | |||
<appSettings> | |||
<!--阿里云短信平台参数--> | |||
<add key="product" value="Dysmsapi" /> | |||
<add key="domain" value="dysmsapi.aliyuncs.com" /> | |||
<add key="accessId" value="" /> | |||
<add key="accessSecret" value="" /> | |||
<add key="regionIdForPop" value="cn-hangzhou" /> | |||
<add key="SignName" value="" /> | |||
<!--斑羚短信平台--> | |||
<add key="sdkappid" value="140009369387" /> | |||
<add key="appkey" value="4d2743a4233e5d8625eefa31f876721b" /> | |||
<!--一信通短信平台--> | |||
<add key="SpCode" value="" /> | |||
<add key="LoginName" value="" /> | |||
<add key="Password" value="" /> | |||
<!--发布时使用下方配置文件--> | |||
<!--<add key="SpCode" value="320328" /> | |||
<add key="LoginName" value="9c34cbd5462e8034d9b779887c1e8398" /> | |||
<add key="Password" value="29745012d0575978cd8c93d8d6c62f9d96e6b808eb9ac87845721c7c29b39c8f" />--> | |||
<add key="ClientSettingsProvider.ServiceUri" value="" /> | |||
</appSettings> | |||
<startup> | |||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> | |||
</startup> | |||
<runtime> | |||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | |||
<dependentAssembly> | |||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> | |||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" /> | |||
</dependentAssembly> | |||
</assemblyBinding> | |||
</runtime> | |||
<system.web> | |||
<membership defaultProvider="ClientAuthenticationMembershipProvider"> | |||
<providers> | |||
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" /> | |||
</providers> | |||
</membership> | |||
<roleManager defaultProvider="ClientRoleProvider" enabled="true"> | |||
<providers> | |||
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" /> | |||
</providers> | |||
</roleManager> | |||
</system.web> | |||
</configuration> |
@@ -0,0 +1,100 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Net.Http; | |||
using System.Net.Http.Headers; | |||
using System.Security.Cryptography; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Learun.Util; | |||
using Newtonsoft.Json; | |||
using Newtonsoft.Json.Linq; | |||
using Quanjiang.DigitalScholl.SendSms.Banling.Sms; | |||
namespace Quanjiang.DigitalScholl.SendSms.Banling | |||
{ | |||
/// <summary> | |||
/// 斑羚短信平台 | |||
/// </summary> | |||
public class BanLingSms : ISms | |||
{ | |||
private static readonly string SdkAppId = ConfigManager.AppSettings["sdkappid"].Value; | |||
private static readonly string AppKey = ConfigManager.AppSettings["appkey"].Value; | |||
public async Task<(string code, string randomNum, string message, string errorType)> SendSmsToSingle(string phoneNumber, SmsType st, List<string> sendParams = null) | |||
{ | |||
(string code, string randomNum, string message, string errorType) result; | |||
var (templatecode, templateparam, randomNum) = GetSmsTemplate(st, sendParams); | |||
try | |||
{ | |||
var singleSender = new SmsSingleSender(SdkAppId, AppKey); | |||
var singleResult = await Task.FromResult(singleSender.SendWithParam("86", phoneNumber, templatecode, templateparam, "深圳国际公益学院", "", "")); | |||
result = singleResult.result==0 ? ("OK", randomNum, "", "") : (singleResult.result.ToString(), "", singleResult.errmsg, "Client"); | |||
} | |||
catch (Exception e) | |||
{ | |||
result = ("", "", e.Message, e.GetType().ToString()); | |||
} | |||
return result; | |||
} | |||
public async Task<(string code, string randomNum, string message, string errorType)> SendSmsToMulti(List<string> phoneNumbers, SmsType st, List<string> sendParams = null) | |||
{ | |||
(string code, string randomNum, string message, string errorType) result; | |||
var (templatecode, templateparam, randomNum) = GetSmsTemplate(st, sendParams); | |||
try | |||
{ | |||
var multiSender = new SmsMultiSender(SdkAppId, AppKey); | |||
var multiResult = await Task.FromResult(multiSender.SendWithParam("86", phoneNumbers, templatecode, templateparam, "深圳国际公益学院", "", "")); | |||
result = multiResult.result == 0 ? ("OK", randomNum, "", "") : (multiResult.result.ToString(), "", multiResult.errmsg, "Client"); | |||
} | |||
catch (Exception e) | |||
{ | |||
result = ("", "", e.Message, e.GetType().ToString()); | |||
} | |||
return result; | |||
} | |||
/// <summary> | |||
/// 根据短信通知类型获取短信模板 | |||
/// </summary> | |||
/// <param name="st"></param> | |||
/// <param name="sendParams"></param> | |||
/// <returns></returns> | |||
private (string templateCode, List<string> templateParam, string randomNum) GetSmsTemplate(SmsType st, List<string> sendParams) | |||
{ | |||
(string templateCode, List<string> templateParam, string randomNum) result; | |||
var randomNum = CommonHelper.RandNum(6); | |||
switch (st) | |||
{ | |||
case SmsType.Register: | |||
result = ("141577", new List<string>() { randomNum, "5" }, randomNum); | |||
break; | |||
case SmsType.LoginBind: | |||
result = ("141578", new List<string>() { randomNum, "5" }, randomNum); | |||
break; | |||
case SmsType.ForgetPassWord: | |||
result = ("141581", new List<string>() { randomNum, "5" }, randomNum); | |||
break; | |||
case SmsType.LessionNotification: | |||
result = ("141583", sendParams, randomNum); | |||
break; | |||
case SmsType.LeaveNotification: | |||
result = ("141585", sendParams, randomNum); | |||
break; | |||
case SmsType.MakeUpMissedLessonsNotification: | |||
result = ("141588", sendParams, randomNum); | |||
break; | |||
case SmsType.ClassManagerLeaveNotification: | |||
result = ("156728", sendParams, randomNum); | |||
break; | |||
case SmsType.ClassManagerMakeUpMissedLessonsNotification: | |||
result = ("156729", sendParams, randomNum); | |||
break; | |||
default: | |||
throw new ArgumentOutOfRangeException(nameof(st), st, null); | |||
} | |||
return result; | |||
} | |||
} | |||
} |
@@ -0,0 +1,717 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Security.Cryptography; | |||
using System.Text; | |||
using Newtonsoft.Json; | |||
using Newtonsoft.Json.Linq; | |||
// newtonsoft json 模块请自行到 http://www.newtonsoft.com/json 下载 | |||
// 注意 json 库中有 .net 的多个版本,请开发者集成自己项目相应 .net 版本的 json 库 | |||
namespace Quanjiang.DigitalScholl.SendSms.Banling | |||
{ | |||
namespace Sms | |||
{ | |||
class SmsSingleSender | |||
{ | |||
string sdkappid; | |||
string appkey; | |||
string url = "https://msg.yundashi.com/api/sms/sendsms"; | |||
SmsSenderUtil util = new SmsSenderUtil(); | |||
public SmsSingleSender(string sdkappid, string appkey) | |||
{ | |||
this.sdkappid = sdkappid; | |||
this.appkey = appkey; | |||
} | |||
/** | |||
* 普通单发短信接口,明确指定内容,如果有多个签名,请在内容中以【】的方式添加到信息内容中,否则系统将使用默认签名 | |||
* @param type 短信类型,0 为普通短信,1 营销短信 | |||
* @param nationCode 国家码,如 86 为中国 | |||
* @param phoneNumber 不带国家码的手机号 | |||
* @param msg 信息内容,必须与申请的模板格式一致,否则将返回错误 | |||
* @param extend 扩展码,可填空 | |||
* @param ext 服务端原样返回的参数,可填空 | |||
* @return SmsSingleSenderResult | |||
*/ | |||
public SmsSingleSenderResult Send( | |||
int type, | |||
string nationCode, | |||
string phoneNumber, | |||
string msg, | |||
string extend, | |||
string ext) | |||
{ | |||
/* | |||
请求包体 | |||
{ | |||
"tel": { | |||
"nationcode": "86", | |||
"mobile": "13788888888" | |||
}, | |||
"type": 0, | |||
"msg": "你的验证码是1234", | |||
"sig": "fdba654e05bc0d15796713a1a1a2318c", | |||
"time": 1479888540, | |||
"extend": "", | |||
"ext": "" | |||
} | |||
应答包体 | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"ext": "", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
} | |||
*/ | |||
if (0 != type && 1 != type) | |||
{ | |||
throw new Exception("type " + type + " error"); | |||
} | |||
if (null == extend) | |||
{ | |||
extend = ""; | |||
} | |||
if (null == ext) | |||
{ | |||
ext = ""; | |||
} | |||
long random = util.GetRandom(); | |||
long curTime = util.GetCurTime(); | |||
// 按照协议组织 post 请求包体 | |||
JObject data = new JObject(); | |||
JObject tel = new JObject(); | |||
tel.Add("nationcode", nationCode); | |||
tel.Add("mobile", phoneNumber); | |||
data.Add("tel", tel); | |||
data.Add("msg", msg); | |||
data.Add("type", type); | |||
data.Add("sig", util.StrToHash(String.Format( | |||
"appkey={0}&random={1}&time={2}&mobile={3}", | |||
appkey, random, curTime, phoneNumber))); | |||
data.Add("time", curTime); | |||
data.Add("extend", extend); | |||
data.Add("ext", ext); | |||
string wholeUrl = url + "?sdkappid=" + sdkappid + "&random=" + random; | |||
HttpWebRequest request = util.GetPostHttpConn(wholeUrl); | |||
byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)); | |||
request.ContentLength = requestData.Length; | |||
Stream requestStream = request.GetRequestStream(); | |||
requestStream.Write(requestData, 0, requestData.Length); | |||
requestStream.Close(); | |||
// 接收返回包 | |||
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); | |||
Stream responseStream = response.GetResponseStream(); | |||
StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); | |||
string responseStr = streamReader.ReadToEnd(); | |||
streamReader.Close(); | |||
responseStream.Close(); | |||
SmsSingleSenderResult result; | |||
if (HttpStatusCode.OK == response.StatusCode) | |||
{ | |||
result = util.ResponseStrToSingleSenderResult(responseStr); | |||
} | |||
else | |||
{ | |||
result = new SmsSingleSenderResult(); | |||
result.result = -1; | |||
result.errmsg = "http error " + response.StatusCode + " " + responseStr; | |||
} | |||
return result; | |||
} | |||
/** | |||
* 指定模板单发 | |||
* @param nationCode 国家码,如 86 为中国 | |||
* @param phoneNumber 不带国家码的手机号 | |||
* @param templId 模板 id | |||
* @param templParams 模板参数列表,如模板 {1}...{2}...{3},那么需要带三个参数 | |||
* @param extend 扩展码,可填空 | |||
* @param ext 服务端原样返回的参数,可填空 | |||
* @return SmsSingleSenderResult | |||
*/ | |||
public SmsSingleSenderResult SendWithParam( | |||
string nationCode, | |||
string phoneNumber, | |||
string templId, | |||
List<string> templParams, | |||
string sign, | |||
string extend, | |||
string ext) | |||
{ | |||
/* | |||
请求包体 | |||
{ | |||
"tel": { | |||
"nationcode": "86", | |||
"mobile": "13788888888" | |||
}, | |||
"sign": "云大师", | |||
"tpl_id": 19, | |||
"params": [ | |||
"验证码", | |||
"1234", | |||
"4" | |||
], | |||
"sig": "fdba654e05bc0d15796713a1a1a2318c", | |||
"time": 1479888540, | |||
"extend": "", | |||
"ext": "" | |||
} | |||
应答包体 | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"ext": "", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
} | |||
*/ | |||
if (null == sign) | |||
{ | |||
sign = ""; | |||
} | |||
if (null == extend) | |||
{ | |||
extend = ""; | |||
} | |||
if (null == ext) | |||
{ | |||
ext = ""; | |||
} | |||
long random = util.GetRandom(); | |||
long curTime = util.GetCurTime(); | |||
// 按照协议组织 post 请求包体 | |||
JObject data = new JObject(); | |||
JObject tel = new JObject(); | |||
tel.Add("nationcode", nationCode); | |||
tel.Add("mobile", phoneNumber); | |||
data.Add("tel", tel); | |||
data.Add("sig", util.CalculateSigForTempl(appkey, random, curTime, phoneNumber)); | |||
data.Add("tpl_id", templId); | |||
data.Add("params", util.SmsParamsToJSONArray(templParams)); | |||
data.Add("sign", sign); | |||
data.Add("time", curTime); | |||
data.Add("extend", extend); | |||
data.Add("ext", ext); | |||
string wholeUrl = url + "?sdkappid=" + sdkappid + "&random=" + random; | |||
HttpWebRequest request = util.GetPostHttpConn(wholeUrl); | |||
byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)); | |||
request.ContentLength = requestData.Length; | |||
Stream requestStream = request.GetRequestStream(); | |||
requestStream.Write(requestData, 0, requestData.Length); | |||
requestStream.Close(); | |||
// 接收返回包 | |||
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); | |||
Stream responseStream = response.GetResponseStream(); | |||
StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); | |||
string responseStr = streamReader.ReadToEnd(); | |||
streamReader.Close(); | |||
responseStream.Close(); | |||
SmsSingleSenderResult result; | |||
if (HttpStatusCode.OK == response.StatusCode) | |||
{ | |||
result = util.ResponseStrToSingleSenderResult(responseStr); | |||
} | |||
else | |||
{ | |||
result = new SmsSingleSenderResult(); | |||
result.result = -1; | |||
result.errmsg = "http error " + response.StatusCode + " " + responseStr; | |||
} | |||
return result; | |||
} | |||
} | |||
class SmsSingleSenderResult | |||
{ | |||
/* | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"ext": "", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
} | |||
*/ | |||
public int result { set; get; } | |||
public string errmsg { set; get; } | |||
public string ext { set; get; } | |||
public string sid { set; get; } | |||
public int fee { set; get; } | |||
public override string ToString() | |||
{ | |||
return string.Format( | |||
"SmsSingleSenderResult\nresult {0}\nerrMsg {1}\next {2}\nsid {3}\nfee {4}", | |||
result, errmsg, ext, sid, fee); | |||
} | |||
} | |||
class SmsMultiSender | |||
{ | |||
string sdkappid; | |||
string appkey; | |||
string url = "https://sms.banling.com/intf/sendmultisms"; | |||
SmsSenderUtil util = new SmsSenderUtil(); | |||
public SmsMultiSender(string sdkappid, string appkey) | |||
{ | |||
this.sdkappid = sdkappid; | |||
this.appkey = appkey; | |||
} | |||
/** | |||
* 普通群发短信接口,明确指定内容,如果有多个签名,请在内容中以【】的方式添加到信息内容中,否则系统将使用默认签名 | |||
* 【注意】海外短信无群发功能 | |||
* @param type 短信类型,0 为普通短信,1 营销短信 | |||
* @param nationCode 国家码,如 86 为中国 | |||
* @param phoneNumbers 不带国家码的手机号列表 | |||
* @param msg 信息内容,必须与申请的模板格式一致,否则将返回错误 | |||
* @param extend 扩展码,可填空 | |||
* @param ext 服务端原样返回的参数,可填空 | |||
* @return SmsMultiSenderResult | |||
*/ | |||
public SmsMultiSenderResult Send( | |||
int type, | |||
string nationCode, | |||
List<string> phoneNumbers, | |||
string msg, | |||
string extend, | |||
string ext) | |||
{ | |||
/* | |||
请求包体 | |||
{ | |||
"tel": [ | |||
{ | |||
"nationcode": "86", | |||
"mobile": "13788888888" | |||
}, | |||
{ | |||
"nationcode": "86", | |||
"mobile": "13788888889" | |||
} | |||
], | |||
"type": 0, | |||
"msg": "你的验证码是1234", | |||
"sig": "fdba654e05bc0d15796713a1a1a2318c", | |||
"time": 1479888540, | |||
"extend": "", | |||
"ext": "" | |||
} | |||
应答包体 | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"ext": "", | |||
"detail": [ | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"mobile": "13788888888", | |||
"nationcode": "86", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
}, | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"mobile": "13788888889", | |||
"nationcode": "86", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
} | |||
] | |||
} | |||
*/ | |||
if (0 != type && 1 != type) | |||
{ | |||
throw new Exception("type " + type + " error"); | |||
} | |||
if (null == extend) | |||
{ | |||
extend = ""; | |||
} | |||
if (null == ext) | |||
{ | |||
ext = ""; | |||
} | |||
long random = util.GetRandom(); | |||
long curTime = util.GetCurTime(); | |||
// 按照协议组织 post 请求包体 | |||
JObject data = new JObject(); | |||
data.Add("tel", util.PhoneNumbersToJSONArray(nationCode, phoneNumbers)); | |||
data.Add("type", type); | |||
data.Add("msg", msg); | |||
data.Add("sig", util.CalculateSig(appkey, random, curTime, phoneNumbers)); | |||
data.Add("time", curTime); | |||
data.Add("extend", extend); | |||
data.Add("ext", ext); | |||
string wholeUrl = url + "?sdkappid=" + sdkappid + "&random=" + random; | |||
HttpWebRequest request = util.GetPostHttpConn(wholeUrl); | |||
byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)); | |||
request.ContentLength = requestData.Length; | |||
Stream requestStream = request.GetRequestStream(); | |||
requestStream.Write(requestData, 0, requestData.Length); | |||
requestStream.Close(); | |||
// 接收返回包 | |||
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); | |||
Stream responseStream = response.GetResponseStream(); | |||
StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); | |||
string responseStr = streamReader.ReadToEnd(); | |||
streamReader.Close(); | |||
responseStream.Close(); | |||
SmsMultiSenderResult result; | |||
if (HttpStatusCode.OK == response.StatusCode) | |||
{ | |||
result = util.ResponseStrToMultiSenderResult(responseStr); | |||
} | |||
else | |||
{ | |||
result = new SmsMultiSenderResult(); | |||
result.result = -1; | |||
result.errmsg = "http error " + response.StatusCode + " " + responseStr; | |||
} | |||
return result; | |||
} | |||
/** | |||
* 指定模板群发 | |||
* 【注意】海外短信无群发功能 | |||
* @param nationCode 国家码,如 86 为中国 | |||
* @param phoneNumbers 不带国家码的手机号列表 | |||
* @param templId 模板 id | |||
* @param params 模板参数列表 | |||
* @param sign 签名,如果填空,系统会使用默认签名 | |||
* @param extend 扩展码,可以填空 | |||
* @param ext 服务端原样返回的参数,可以填空 | |||
* @return SmsMultiSenderResult | |||
*/ | |||
public SmsMultiSenderResult SendWithParam( | |||
String nationCode, | |||
List<string> phoneNumbers, | |||
string templId, | |||
List<string> templParams, | |||
string sign, | |||
string extend, | |||
string ext) | |||
{ | |||
/* | |||
请求包体 | |||
{ | |||
"tel": [ | |||
{ | |||
"nationcode": "86", | |||
"mobile": "13788888888" | |||
}, | |||
{ | |||
"nationcode": "86", | |||
"mobile": "13788888889" | |||
} | |||
], | |||
"type": 0, | |||
"msg": "你的验证码是1234", | |||
"sig": "fdba654e05bc0d15796713a1a1a2318c", | |||
"time": 1479888540, | |||
"extend": "", | |||
"ext": "" | |||
} | |||
应答包体 | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"ext": "", | |||
"detail": [ | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"mobile": "13788888888", | |||
"nationcode": "86", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
}, | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"mobile": "13788888889", | |||
"nationcode": "86", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
} | |||
] | |||
} | |||
*/ | |||
if (null == sign) | |||
{ | |||
sign = ""; | |||
} | |||
if (null == extend) | |||
{ | |||
extend = ""; | |||
} | |||
if (null == ext) | |||
{ | |||
ext = ""; | |||
} | |||
long random = util.GetRandom(); | |||
long curTime = util.GetCurTime(); | |||
// 按照协议组织 post 请求包体 | |||
JObject data = new JObject(); | |||
data.Add("tel", util.PhoneNumbersToJSONArray(nationCode, phoneNumbers)); | |||
data.Add("sig", util.CalculateSigForTempl(appkey, random, curTime, phoneNumbers)); | |||
data.Add("tpl_id", templId); | |||
data.Add("params", util.SmsParamsToJSONArray(templParams)); | |||
data.Add("sign", sign); | |||
data.Add("time", curTime); | |||
data.Add("extend", extend); | |||
data.Add("ext", ext); | |||
string wholeUrl = url + "?sdkappid=" + sdkappid + "&random=" + random; | |||
HttpWebRequest request = util.GetPostHttpConn(wholeUrl); | |||
byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)); | |||
request.ContentLength = requestData.Length; | |||
Stream requestStream = request.GetRequestStream(); | |||
requestStream.Write(requestData, 0, requestData.Length); | |||
requestStream.Close(); | |||
// 接收返回包 | |||
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); | |||
Stream responseStream = response.GetResponseStream(); | |||
StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8")); | |||
string responseStr = streamReader.ReadToEnd(); | |||
streamReader.Close(); | |||
responseStream.Close(); | |||
SmsMultiSenderResult result; | |||
if (HttpStatusCode.OK == response.StatusCode) | |||
{ | |||
result = util.ResponseStrToMultiSenderResult(responseStr); | |||
} | |||
else | |||
{ | |||
result = new SmsMultiSenderResult(); | |||
result.result = -1; | |||
result.errmsg = "http error " + response.StatusCode + " " + responseStr; | |||
} | |||
return result; | |||
} | |||
} | |||
class SmsMultiSenderResult | |||
{ | |||
/* | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"ext": "", | |||
"detail": [ | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"mobile": "13788888888", | |||
"nationcode": "86", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
}, | |||
{ | |||
"result": 0, | |||
"errmsg": "OK", | |||
"mobile": "13788888889", | |||
"nationcode": "86", | |||
"sid": "xxxxxxx", | |||
"fee": 1 | |||
} | |||
] | |||
} | |||
*/ | |||
public class Detail | |||
{ | |||
public int result { get; set; } | |||
public string errmsg { get; set; } | |||
public string mobile { get; set; } | |||
public string nationcode { get; set; } | |||
public string sid { get; set; } | |||
public int fee { get; set; } | |||
public override string ToString() | |||
{ | |||
return string.Format( | |||
"\tDetail result {0} errmsg {1} mobile {2} nationcode {3} sid {4} fee {5}", | |||
result, errmsg, mobile, nationcode, sid, fee); | |||
} | |||
} | |||
public int result; | |||
public string errmsg = ""; | |||
public string ext = ""; | |||
public IList<Detail> detail; | |||
public override string ToString() | |||
{ | |||
if (null != detail) | |||
{ | |||
return String.Format( | |||
"SmsMultiSenderResult\nresult {0}\nerrmsg {1}\next {2}\ndetail:\n{3}", | |||
result, errmsg, ext, String.Join("\n", detail)); | |||
} | |||
else | |||
{ | |||
return String.Format( | |||
"SmsMultiSenderResult\nresult {0}\nerrmsg {1}\next {2}\n", | |||
result, errmsg, ext); | |||
} | |||
} | |||
} | |||
class SmsSenderUtil | |||
{ | |||
Random random = new Random(); | |||
public HttpWebRequest GetPostHttpConn(string url) | |||
{ | |||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); | |||
request.Method = "POST"; | |||
request.ContentType = "application/x-www-form-urlencoded"; | |||
return request; | |||
} | |||
public long GetRandom() | |||
{ | |||
return random.Next(999999)%900000 + 100000; | |||
} | |||
public long GetCurTime() | |||
{ | |||
Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; | |||
return unixTimestamp; | |||
} | |||
// 将二进制的数值转换为 16 进制字符串,如 "abc" => "616263" | |||
private static string ByteArrayToHex(byte[] byteArray) | |||
{ | |||
string returnStr = ""; | |||
if (byteArray != null) | |||
{ | |||
for (int i = 0; i < byteArray.Length; i++) | |||
{ | |||
returnStr += byteArray[i].ToString("x2"); | |||
} | |||
} | |||
return returnStr; | |||
} | |||
public string StrToHash(string str) | |||
{ | |||
SHA256 sha256 = SHA256Managed.Create(); | |||
byte[] resultByteArray = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(str)); | |||
return ByteArrayToHex(resultByteArray); | |||
} | |||
// 将单发回包解析成结果对象 | |||
public SmsSingleSenderResult ResponseStrToSingleSenderResult(string str) | |||
{ | |||
SmsSingleSenderResult result = JsonConvert.DeserializeObject<SmsSingleSenderResult>(str); | |||
return result; | |||
} | |||
// 将群发回包解析成结果对象 | |||
public SmsMultiSenderResult ResponseStrToMultiSenderResult(string str) | |||
{ | |||
SmsMultiSenderResult result = JsonConvert.DeserializeObject<SmsMultiSenderResult>(str); | |||
return result; | |||
} | |||
public JArray SmsParamsToJSONArray(List<string> templParams) | |||
{ | |||
JArray smsParams = new JArray(); | |||
foreach (string templParamsElement in templParams) | |||
{ | |||
smsParams.Add(templParamsElement); | |||
} | |||
return smsParams; | |||
} | |||
public JArray PhoneNumbersToJSONArray(string nationCode, List<string> phoneNumbers) | |||
{ | |||
JArray tel = new JArray(); | |||
int i = 0; | |||
do | |||
{ | |||
JObject telElement = new JObject(); | |||
telElement.Add("nationcode", nationCode); | |||
telElement.Add("mobile", phoneNumbers.ElementAt(i)); | |||
tel.Add(telElement); | |||
} while (++i < phoneNumbers.Count); | |||
return tel; | |||
} | |||
public string CalculateSigForTempl( | |||
string appkey, | |||
long random, | |||
long curTime, | |||
List<string> phoneNumbers) | |||
{ | |||
string phoneNumbersString = phoneNumbers.ElementAt(0); | |||
for (int i = 1; i < phoneNumbers.Count; i++) | |||
{ | |||
phoneNumbersString += "," + phoneNumbers.ElementAt(i); | |||
} | |||
return StrToHash(String.Format( | |||
"appkey={0}&random={1}&time={2}&mobile={3}", | |||
appkey, random, curTime, phoneNumbersString)); | |||
} | |||
public string CalculateSigForTempl( | |||
string appkey, | |||
long random, | |||
long curTime, | |||
string phoneNumber) | |||
{ | |||
List<string> phoneNumbers = new List<string>(); | |||
phoneNumbers.Add(phoneNumber); | |||
return CalculateSigForTempl(appkey, random, curTime, phoneNumbers); | |||
} | |||
public string CalculateSig( | |||
string appkey, | |||
long random, | |||
long curTime, | |||
List<string> phoneNumbers) | |||
{ | |||
string phoneNumbersString = phoneNumbers.ElementAt(0); | |||
for (int i = 1; i < phoneNumbers.Count; i++) | |||
{ | |||
phoneNumbersString += "," + phoneNumbers.ElementAt(i); | |||
} | |||
return StrToHash(String.Format( | |||
"appkey={0}&random={1}&time={2}&mobile={3}", | |||
appkey, random, curTime, phoneNumbersString)); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
using System; | |||
using System.Configuration; | |||
namespace Quanjiang.DigitalScholl.SendSms | |||
{ | |||
internal static class ConfigManager | |||
{ | |||
private static readonly bool Error; | |||
private static readonly Configuration AppConfig; | |||
static ConfigManager() | |||
{ | |||
var dllPath =$"{AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory}\\Quanjiang.DigitalScholl.SendSms.dll"; | |||
try | |||
{ | |||
AppConfig = ConfigurationManager.OpenExeConfiguration(dllPath); | |||
} | |||
catch (ConfigurationErrorsException) | |||
{ | |||
Error = true; | |||
} | |||
} | |||
public static KeyValueConfigurationCollection AppSettings | |||
{ | |||
get | |||
{ | |||
if (Error) return null; | |||
return AppConfig.AppSettings.Settings; | |||
} | |||
} | |||
public static ConnectionStringSettingsCollection ConnectionStrings | |||
{ | |||
get | |||
{ | |||
if (Error) return null; | |||
return AppConfig.ConnectionStrings.ConnectionStrings; | |||
} | |||
} | |||
public static T GetSection<T>(string name) where T : ConfigurationSection | |||
{ | |||
if (Error) return null; | |||
return AppConfig.GetSection(name) as T; | |||
} | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace Quanjiang.DigitalScholl.SendSms | |||
{ | |||
public interface ISms | |||
{ | |||
Task<(string code, string randomNum, string message, string errorType)> SendSmsToSingle(string phoneNumber, | |||
SmsType st, List<string> sendParams = null); | |||
Task<(string code, string randomNum, string message, string errorType)> SendSmsToMulti(List<string> phoneNumbers, | |||
SmsType st, List<string> sendParams = null); | |||
} | |||
/// <summary> | |||
/// 短信通知类型 | |||
/// </summary> | |||
public enum SmsType | |||
{ | |||
/// <summary> | |||
/// 注册 | |||
/// </summary> | |||
Register, | |||
/// <summary> | |||
/// 第三方(QQ,微信)快捷登录绑定 | |||
/// </summary> | |||
LoginBind, | |||
/// <summary> | |||
/// 忘记密码 | |||
/// </summary> | |||
ForgetPassWord, | |||
/// <summary> | |||
/// 开课通知 | |||
/// </summary> | |||
LessionNotification, | |||
/// <summary> | |||
/// 学员请假通知 | |||
/// </summary> | |||
LeaveNotification, | |||
/// <summary> | |||
/// 学员补课通知 | |||
/// </summary> | |||
MakeUpMissedLessonsNotification, | |||
/// <summary> | |||
/// 班主任请假提醒 | |||
/// </summary> | |||
ClassManagerLeaveNotification, | |||
/// <summary> | |||
/// 班主任补课提醒 | |||
/// </summary> | |||
ClassManagerMakeUpMissedLessonsNotification, | |||
/// <summary> | |||
/// 教学工作安排推送 | |||
/// </summary> | |||
EADateArrangeNotification, | |||
/// <summary> | |||
/// 流程提醒 | |||
/// </summary> | |||
WorkFlowNotification | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using System.Runtime.InteropServices; | |||
// 有关程序集的一般信息由以下 | |||
// 控制。更改这些特性值可修改 | |||
// 与程序集关联的信息。 | |||
[assembly: AssemblyTitle("Quanjiang.DigitalScholl.SendSms")] | |||
[assembly: AssemblyDescription("")] | |||
[assembly: AssemblyConfiguration("")] | |||
[assembly: AssemblyCompany("")] | |||
[assembly: AssemblyProduct("Quanjiang.DigitalScholl.SendSms")] | |||
[assembly: AssemblyCopyright("Copyright © 2018")] | |||
[assembly: AssemblyTrademark("")] | |||
[assembly: AssemblyCulture("")] | |||
// 将 ComVisible 设置为 false 会使此程序集中的类型 | |||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 | |||
//请将此类型的 ComVisible 特性设置为 true。 | |||
[assembly: ComVisible(false)] | |||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID | |||
[assembly: Guid("55f0f08d-2a9f-489a-be1b-2eeae80687e6")] | |||
// 程序集的版本信息由下列四个值组成: | |||
// | |||
// 主版本 | |||
// 次版本 | |||
// 生成号 | |||
// 修订号 | |||
// | |||
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 | |||
//通过使用 "*",如下所示: | |||
// [assembly: AssemblyVersion("1.0.*")] | |||
[assembly: AssemblyVersion("1.0.0.0")] | |||
[assembly: AssemblyFileVersion("1.0.0.0")] |
@@ -0,0 +1,96 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||
<ProjectGuid>{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}</ProjectGuid> | |||
<OutputType>Library</OutputType> | |||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||
<RootNamespace>Quanjiang.DigitalScholl.SendSms</RootNamespace> | |||
<AssemblyName>Quanjiang.DigitalScholl.SendSms</AssemblyName> | |||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> | |||
<FileAlignment>512</FileAlignment> | |||
<SccProjectName>QJ.SendSms</SccProjectName> | |||
<SccLocalPath>1~3d9d4e2a-0649-49e7-83e7-c48fae17202f</SccLocalPath> | |||
<SccAuxPath>http://101.201.103.178:8090/VaultService</SccAuxPath> | |||
<SccProvider>SourceGear Vault Visual Studio 2005 Client:{1EA47954-8515-402d-82D9-B5C332120A8D}</SccProvider> | |||
<TargetFrameworkProfile /> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\Debug\</OutputPath> | |||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<Prefer32Bit>false</Prefer32Bit> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||
<DebugType>pdbonly</DebugType> | |||
<Optimize>true</Optimize> | |||
<OutputPath>bin\Release\</OutputPath> | |||
<DefineConstants>TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<Prefer32Bit>false</Prefer32Bit> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Reference Include="aliyun-net-sdk-core"> | |||
<HintPath>..\packages\Sms\aliyun-net-sdk-core.dll</HintPath> | |||
</Reference> | |||
<Reference Include="aliyun-net-sdk-dybaseapi"> | |||
<HintPath>..\packages\Sms\aliyun-net-sdk-dybaseapi.dll</HintPath> | |||
</Reference> | |||
<Reference Include="aliyun-net-sdk-dysmsapi"> | |||
<HintPath>..\packages\Sms\aliyun-net-sdk-dysmsapi.dll</HintPath> | |||
</Reference> | |||
<Reference Include="Aliyun.MNS"> | |||
<HintPath>..\packages\Sms\Aliyun.MNS.dll</HintPath> | |||
</Reference> | |||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> | |||
</Reference> | |||
<Reference Include="System" /> | |||
<Reference Include="System.Configuration" /> | |||
<Reference Include="System.Core" /> | |||
<Reference Include="System.Net" /> | |||
<Reference Include="System.Net.Http" /> | |||
<Reference Include="System.ValueTuple, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath> | |||
</Reference> | |||
<Reference Include="System.Web" /> | |||
<Reference Include="System.Web.Extensions" /> | |||
<Reference Include="System.Xml.Linq" /> | |||
<Reference Include="System.Data.DataSetExtensions" /> | |||
<Reference Include="Microsoft.CSharp" /> | |||
<Reference Include="System.Data" /> | |||
<Reference Include="System.Xml" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="Yixintong\YixintongSms.cs" /> | |||
<Compile Include="Banling\BanLingSms.cs" /> | |||
<Compile Include="Banling\SmsSender.cs" /> | |||
<Compile Include="ISms.cs" /> | |||
<Compile Include="AliyunSms.cs" /> | |||
<Compile Include="ConfigManager.cs" /> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="App.config"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
<None Include="packages.config" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<WCFMetadata Include="Connected Services\" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\Learun.Framework.Module\Learun.Util\Learun.Util\Learun.Util.csproj"> | |||
<Project>{cf8ae293-88ab-436c-9720-a8386ba5d7b7}</Project> | |||
<Name>Learun.Util</Name> | |||
</ProjectReference> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
</Project> |
@@ -0,0 +1,157 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Specialized; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Web; | |||
using Learun.Util; | |||
using Newtonsoft.Json; | |||
using Newtonsoft.Json.Linq; | |||
namespace Quanjiang.DigitalScholl.SendSms | |||
{ | |||
/// <summary> | |||
/// 一信通短信平台 | |||
/// </summary> | |||
public class YixintongSms:ISms | |||
{ | |||
private static readonly string SpCode = ConfigManager.AppSettings["SpCode"].Value;//企业编号 | |||
private static readonly string LoginName = ConfigManager.AppSettings["LoginName"].Value;//用户名 | |||
private static readonly string Password = ConfigManager.AppSettings["Password"].Value;//接口密钥 | |||
public async Task<(string code, string randomNum, string message, string errorType)> SendSmsToSingle(string phoneNumber, SmsType st, List<string> sendParams = null) | |||
{ | |||
(string code, string randomNum, string message, string errorType) result; | |||
var (templatecode, templateparam, randomNum) = GetSmsTemplateBySmsType(st); | |||
try | |||
{ | |||
StringBuilder sb=new StringBuilder(); | |||
// 按照协议组织 post 请求包体 | |||
sb.Append("SpCode="+SpCode); | |||
sb.Append("&LoginName=" + LoginName); | |||
sb.Append("&Password=" + Password); | |||
sb.Append("&MessageContent=" + sendParams.FirstOrDefault()); | |||
sb.Append("&UserNumber=" + phoneNumber); | |||
//sb.Append("&templateId=" + templatecode);//测试帐号去掉 | |||
sb.Append("&SerialNumber=" + DateTime.Now.ToString("yyyyMMddHHmmssffffff")); | |||
sb.Append("&f=1"); | |||
//data.Add("ScheduleTime", ""); | |||
//data.Add("signCode", ""); | |||
//调接口 | |||
string pushresult = Learun.Util.HttpMethods.HttpPost("https://opassapi.infocloud.cc/sms/Api/Send.do", sb.ToString(), Encoding.GetEncoding("utf-8")); | |||
//返回体 | |||
pushresult = pushresult.Replace("<br>", "&"); | |||
NameValueCollection query = HttpUtility.ParseQueryString(pushresult, Encoding.GetEncoding("utf-8")); | |||
var objresult = new SmsResult(); | |||
objresult.result = Convert.ToInt32(query["result"]); | |||
objresult.description = query["description"]; | |||
objresult.taskid = query["taskid"]; | |||
objresult.faillist = query["faillist"]; | |||
result =(objresult.result.ToString(), phoneNumber, objresult.description, objresult.faillist); | |||
} | |||
catch (Exception e) | |||
{ | |||
result = ("", "", e.Message, e.GetType().ToString()); | |||
} | |||
return result; | |||
} | |||
public async Task<(string code, string randomNum, string message, string errorType)> SendSmsToMulti(List<string> phoneNumbers, SmsType st, List<string> sendParams = null) | |||
{ | |||
(string code, string randomNum, string message, string errorType) result; | |||
var (templatecode, templateparam, randomNum) = GetSmsTemplateBySmsType(st); | |||
try | |||
{ | |||
// 按照协议组织 post 请求包体 | |||
JObject data = new JObject(); | |||
data.Add("SpCode", SpCode); | |||
data.Add("LoginName", LoginName); | |||
data.Add("Password", Password); | |||
data.Add("MessageContent", sendParams.FirstOrDefault()); | |||
data.Add("UserNumber", string.Join(",", phoneNumbers.ToArray())); | |||
data.Add("templateId", templatecode); | |||
data.Add("SerialNumber", DateTime.Now.ToString("yyyyMMddHHmmssffffff")); | |||
data.Add("ScheduleTime", ""); | |||
data.Add("f", "1"); | |||
data.Add("signCode", ""); | |||
//调接口 | |||
string pushresult = Learun.Util.HttpMethods.HttpPost("https://api.ums86.com:9600/sms/Api/Send.do", JsonConvert.SerializeObject(data), Encoding.GetEncoding("gb2312")); | |||
//返回体 | |||
pushresult = pushresult.Replace("<br>", "&"); | |||
NameValueCollection query = HttpUtility.ParseQueryString(pushresult, Encoding.GetEncoding("gb2312")); | |||
var objresult = new SmsResult(); | |||
objresult.result = Convert.ToInt32(query["result"]); | |||
objresult.description = query["description"]; | |||
objresult.taskid = query["taskid"]; | |||
objresult.faillist = query["faillist"]; | |||
result = objresult.result == 0 ? ("OK", randomNum, "", "") : (objresult.result.ToString(), "", objresult.description, objresult.faillist); | |||
} | |||
catch (Exception e) | |||
{ | |||
result = ("", "", e.Message, e.GetType().ToString()); | |||
} | |||
return result; | |||
} | |||
/// <summary> | |||
/// 根据短信通知类型获取短信模板 | |||
/// </summary> | |||
/// <param name="st"></param> | |||
/// <returns></returns> | |||
private (string templateCode, string templateParam, string randomNum) GetSmsTemplateBySmsType(SmsType st) | |||
{ | |||
(string templateCode, string templateParam,string randomNum) result; | |||
var randomNum = CommonHelper.RandNum(6); | |||
switch (st) | |||
{ | |||
case SmsType.Register: | |||
result = ("SMS_137485060", JsonConvert.SerializeObject(new { code = randomNum }), randomNum); | |||
break; | |||
case SmsType.LoginBind: | |||
result = ("SMS_137485060", JsonConvert.SerializeObject(new { code = randomNum }), randomNum); | |||
break; | |||
case SmsType.ForgetPassWord: | |||
result = ("SMS_137485060", JsonConvert.SerializeObject(new { code = randomNum }), randomNum); | |||
break; | |||
case SmsType.EADateArrangeNotification: | |||
result = ("1", JsonConvert.SerializeObject(new { code = randomNum }), randomNum); | |||
break; | |||
case SmsType.WorkFlowNotification: | |||
result = ("0", "", ""); | |||
break; | |||
default: | |||
throw new ArgumentOutOfRangeException(nameof(st), st, null); | |||
} | |||
return result; | |||
} | |||
/// <summary> | |||
/// 发送短信返回内容 | |||
/// </summary> | |||
public class SmsResult { | |||
/// <summary> | |||
/// 错误代码(0:发送短信成功,0-34,) | |||
/// </summary> | |||
public int result { get; set; } | |||
/// <summary> | |||
/// 错误描述 | |||
/// </summary> | |||
public string description { get; set; } | |||
/// <summary> | |||
/// 任务编号 | |||
/// </summary> | |||
public string taskid { get; set; } | |||
/// <summary> | |||
/// 失败号码列表(可多个) | |||
/// </summary> | |||
public string faillist { get; set; } | |||
} | |||
} | |||
} |
@@ -0,0 +1,5 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<packages> | |||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" /> | |||
<package id="System.ValueTuple" version="4.3.0" targetFramework="net45" /> | |||
</packages> |
@@ -0,0 +1,116 @@ | |||
param($installPath, $toolsPath, $package, $project) | |||
# open json.net splash page on package install | |||
# don't open if json.net is installed as a dependency | |||
try | |||
{ | |||
$url = "http://www.newtonsoft.com/json/install?version=" + $package.Version | |||
$dte2 = Get-Interface $dte ([EnvDTE80.DTE2]) | |||
if ($dte2.ActiveWindow.Caption -eq "Package Manager Console") | |||
{ | |||
# user is installing from VS NuGet console | |||
# get reference to the window, the console host and the input history | |||
# show webpage if "install-package newtonsoft.json" was last input | |||
$consoleWindow = $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow]) | |||
$props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor ` | |||
[System.Reflection.BindingFlags]::NonPublic) | |||
$prop = $props | ? { $_.Name -eq "ActiveHostInfo" } | select -first 1 | |||
if ($prop -eq $null) { return } | |||
$hostInfo = $prop.GetValue($consoleWindow) | |||
if ($hostInfo -eq $null) { return } | |||
$history = $hostInfo.WpfConsole.InputHistory.History | |||
$lastCommand = $history | select -last 1 | |||
if ($lastCommand) | |||
{ | |||
$lastCommand = $lastCommand.Trim().ToLower() | |||
if ($lastCommand.StartsWith("install-package") -and $lastCommand.Contains("newtonsoft.json")) | |||
{ | |||
$dte2.ItemOperations.Navigate($url) | Out-Null | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
# user is installing from VS NuGet dialog | |||
# get reference to the window, then smart output console provider | |||
# show webpage if messages in buffered console contains "installing...newtonsoft.json" in last operation | |||
$instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor ` | |||
[System.Reflection.BindingFlags]::NonPublic) | |||
$consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor ` | |||
[System.Reflection.BindingFlags]::NonPublic) | |||
if ($instanceField -eq $null -or $consoleField -eq $null) { return } | |||
$instance = $instanceField.GetValue($null) | |||
if ($instance -eq $null) { return } | |||
$consoleProvider = $consoleField.GetValue($instance) | |||
if ($consoleProvider -eq $null) { return } | |||
$console = $consoleProvider.CreateOutputConsole($false) | |||
$messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor ` | |||
[System.Reflection.BindingFlags]::NonPublic) | |||
if ($messagesField -eq $null) { return } | |||
$messages = $messagesField.GetValue($console) | |||
if ($messages -eq $null) { return } | |||
$operations = $messages -split "==============================" | |||
$lastOperation = $operations | select -last 1 | |||
if ($lastOperation) | |||
{ | |||
$lastOperation = $lastOperation.ToLower() | |||
$lines = $lastOperation -split "`r`n" | |||
$installMatch = $lines | ? { $_.StartsWith("------- installing...newtonsoft.json ") } | select -first 1 | |||
if ($installMatch) | |||
{ | |||
$dte2.ItemOperations.Navigate($url) | Out-Null | |||
} | |||
} | |||
} | |||
} | |||
catch | |||
{ | |||
try | |||
{ | |||
$pmPane = $dte2.ToolWindows.OutputWindow.OutputWindowPanes.Item("Package Manager") | |||
$selection = $pmPane.TextDocument.Selection | |||
$selection.StartOfDocument($false) | |||
$selection.EndOfDocument($true) | |||
if ($selection.Text.StartsWith("Attempting to gather dependencies information for package 'Newtonsoft.Json." + $package.Version + "'")) | |||
{ | |||
# don't show on upgrade | |||
if (!$selection.Text.Contains("Removed package")) | |||
{ | |||
$dte2.ItemOperations.Navigate($url) | Out-Null | |||
} | |||
} | |||
} | |||
catch | |||
{ | |||
# stop potential errors from bubbling up | |||
# worst case the splash page won't open | |||
} | |||
} | |||
# still yolo |
@@ -130,6 +130,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quanjiang.DigitalSchool.Asp | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quanjiang.DigitalScholl.VisitService", "VisitService\Quanjiang.DigitalScholl.VisitService.csproj", "{1D482884-8749-41E7-B1E3-362612799615}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quanjiang.DigitalScholl.SendSms", "Quanjiang.DigitalScholl.SendSms\Quanjiang.DigitalScholl.SendSms.csproj", "{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
Debug|Android = Debug|Android | |||
@@ -1700,6 +1702,42 @@ Global | |||
{1D482884-8749-41E7-B1E3-362612799615}.Release|Windows-x64.Build.0 = Release|Any CPU | |||
{1D482884-8749-41E7-B1E3-362612799615}.Release|Windows-x86.ActiveCfg = Release|Any CPU | |||
{1D482884-8749-41E7-B1E3-362612799615}.Release|Windows-x86.Build.0 = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Android.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Android.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|iOS.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|iOS.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Windows-ARM.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Windows-ARM.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Windows-x64.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Windows-x64.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Windows-x86.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Debug|Windows-x86.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Android.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Android.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Any CPU.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Any CPU.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|iOS.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|iOS.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Windows-ARM.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Windows-ARM.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Windows-x64.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Windows-x64.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Windows-x86.ActiveCfg = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Development|Windows-x86.Build.0 = Debug|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Android.ActiveCfg = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Android.Build.0 = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|iOS.ActiveCfg = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|iOS.Build.0 = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Windows-ARM.ActiveCfg = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Windows-ARM.Build.0 = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Windows-x64.ActiveCfg = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Windows-x64.Build.0 = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Windows-x86.ActiveCfg = Release|Any CPU | |||
{55F0F08D-2A9F-489A-BE1B-2EEAE80687E6}.Release|Windows-x86.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||
@@ -1751,7 +1789,7 @@ Global | |||
{E05A2B9A-A939-450F-9A44-A8B3201D055A} = {ED258CD0-0A0C-490B-9D8F-B4CEC4467251} | |||
EndGlobalSection | |||
GlobalSection(ExtensibilityGlobals) = postSolution | |||
EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35 | |||
SolutionGuid = {968C278F-4142-4DFF-96B0-B3D70A649451} | |||
EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35 | |||
EndGlobalSection | |||
EndGlobal |