// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
//
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
//
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
|
using Admin.NET.Core.Service;
|
using Admin.NET.Core;
|
using Furion.DependencyInjection;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using Microsoft.Extensions.Options;
|
using Dm.util;
|
using Aop.Api.Domain;
|
using Furion.FriendlyException;
|
using Furion.DataValidation;
|
using static QRCoder.PayloadGenerator;
|
using System.Net;
|
using Org.BouncyCastle.Asn1.Ocsp;
|
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Authorization;
|
using Furion.DynamicApiController;
|
using System.ComponentModel;
|
using System.ComponentModel.DataAnnotations;
|
using Yitter.IdGenerator;
|
using Lazy.Captcha.Core;
|
using Furion;
|
using NewLife;
|
|
namespace FZCZTB.NET.SYSService.MSM;
|
/// <summary>
|
/// 政采短信服务
|
/// </summary>
|
[AllowAnonymous]
|
[ApiDescriptionSettings("FZCAPISYS",Order = 149)]
|
public class ZCSMSService : IDynamicApiController,ITransient
|
{
|
private readonly SMSConfigOptions _smsOptions;
|
private readonly SysCacheService _sysCacheService;
|
private readonly ICaptcha _captcha;
|
public ZCSMSService(IOptions<SMSConfigOptions> smsOptions,
|
SysCacheService sysCacheService,
|
ICaptcha captcha
|
)
|
{
|
|
_smsOptions = smsOptions.Value;
|
_sysCacheService = sysCacheService;
|
|
_captcha = captcha;
|
}
|
|
|
/// <summary>
|
/// 根据藏用模版格式化短信内容 会自动贴上标签
|
/// </summary>
|
/// <param name="Code"> 需要替换的内容,用于替换末班内容的code部分</param>
|
/// <param name="Key"></param>
|
[NonAction]
|
public string FormartMessage(string? Code, string Key = "VCode")
|
{
|
var Temp= _smsOptions.lingKai.Templates.Where(x => x.TemplateCode == Key).FirstOrDefault();
|
if ( Temp != null )
|
{
|
if(Code != null)
|
{
|
|
return Temp.Content.replace("${code}", Code) + Temp.SignName;
|
|
}
|
|
else
|
return Temp.Content+Temp.SignName;
|
}
|
if (Code == null)
|
throw Oops.Oh("短信内容为空");
|
return Code;
|
}
|
|
|
/// <summary>
|
/// 发送短信
|
/// </summary>
|
/// <param name="Content">要替换的内容</param>
|
[NonAction]
|
public async Task SendSMSAsync(string Content,string Phone)
|
{
|
if (!Phone.TryValidate(ValidationTypes.PhoneNumber).IsValid) throw Oops.Oh("请正确填写手机号码");
|
|
if( string.IsNullOrEmpty(Content)) throw Oops.Oh("请填写正确的手机号码");
|
|
string postdata1 = "CorpID=" + _smsOptions.lingKai.Number + "&Pwd=" + _smsOptions.lingKai.AccountPassPassword + "&Mobile=" + Phone + "&Content="+ Content + "&SendTime=";
|
string code = (string)await HttpPost(_smsOptions.lingKai.Url, postdata1);
|
|
var data = Convert.ToInt64(code);
|
if (data > 0)
|
{
|
return ;
|
}
|
Oops.Oh($"发送短信失败,错误码{data}");
|
|
|
}
|
|
|
|
|
/// <summary>
|
/// 获取验证码 🔖
|
/// </summary>
|
/// <returns></returns>
|
[AllowAnonymous]
|
[SuppressMonitor]
|
[DisplayName("获取验证码")]
|
public dynamic GetCaptcha()
|
{
|
var codeId = YitIdHelper.NextId().ToString();
|
var captcha = _captcha.Generate(codeId);
|
var expirySeconds = App.GetOptions<CaptchaOptions>()?.ExpirySeconds ?? 60;
|
return new { Id = codeId, Img = captcha.Base64, ExpirySeconds = expirySeconds };
|
}
|
|
/// <summary>
|
/// 校验短信验证码
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
[AllowAnonymous]
|
[DisplayName("校验短信验证码")]
|
public bool VerifyCode(SmsVerifyCodeInput input)
|
{
|
var verifyCode = _sysCacheService.Get<string>($"{CacheConst.KeyPhoneVerCode}{input.Phone}");
|
|
if (string.IsNullOrWhiteSpace(verifyCode)) throw Oops.Oh("验证码不存在或已失效,请重新获取!");
|
|
if (verifyCode != input.Code) throw Oops.Oh("验证码错误!");
|
_sysCacheService.Remove($"{CacheConst.KeyPhoneVerCode}{input.Phone}");
|
return true;
|
}
|
/// <summary>
|
/// 发送验证短信,要要验证码 需要输入校验,避免电脑攻击
|
/// </summary>
|
/// <param name="phoneNumber"> 电话号码</param>
|
/// <param name="VerifyCode">图片校验数据</param>
|
/// <param name="VerifyCodeId">检验的ID</param>
|
/// <returns></returns>
|
[AllowAnonymous]
|
[DisplayName("发送验证码")]
|
public async Task SendSMS([Required] string phoneNumber , [Required] string VerifyCode, [Required] string VerifyCodeId)
|
{
|
if (!phoneNumber.TryValidate(ValidationTypes.PhoneNumber).IsValid) throw Oops.Oh("请正确填写手机号码");
|
|
// 校验验证码
|
if (!_captcha.Validate(VerifyCodeId, VerifyCode)) throw Oops.Oh(ErrorCodeEnum.D0008);
|
_captcha.Generate(VerifyCodeId);
|
|
// 生成随机验证码
|
var random = new Random();
|
var verifyCode = random.Next(100000, 999999);
|
|
var templateParam = new
|
{
|
code = verifyCode
|
};
|
var code= FormartMessage(verifyCode.toString());
|
|
await SendSMSAsync(code, phoneNumber);
|
|
_sysCacheService.Set($"{CacheConst.KeyPhoneVerCode}{phoneNumber}", verifyCode, TimeSpan.FromSeconds(_smsOptions.lingKai.VerifyTimeOut.ToInt()));
|
|
|
|
|
}
|
|
/// <summary>
|
/// 发送验证码
|
/// </summary>
|
/// <param name="Url"> 链接</param>
|
/// <param name="postDataStr"> 验证码</param>
|
/// <returns></returns>
|
private async Task<string> HttpPost(string Url, string postDataStr)
|
{
|
//HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
|
//request.Method = "POST";
|
//request.ContentType = "application/x-www-form-urlencoded;charset=gb2312";
|
|
//byte[] postData = Encoding.GetEncoding("gb2312").GetBytes(postDataStr);
|
//request.ContentLength = postData.Length;
|
//Stream myRequestStream = request.GetRequestStream();
|
//myRequestStream.Write(postData, 0, postData.Length);
|
//myRequestStream.Close();
|
//HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
|
//Stream myResponseStream = response.GetResponseStream();
|
//StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("gb2312"));
|
//string retString = myStreamReader.ReadToEnd();
|
//myStreamReader.Close();
|
//myResponseStream.Close();
|
|
//return retString;
|
// 创建 HttpClient 实例
|
using var httpClient = new HttpClient();
|
// 准备要发送的内容,设置编码和内容类型
|
var content = new StringContent(postDataStr, Encoding.GetEncoding("gb2312"), "application/x-www-form-urlencoded");
|
// 发送 POST 请求
|
var response = await httpClient.PostAsync(Url, content);
|
// 确保请求成功,若失败则抛出异常
|
response.EnsureSuccessStatusCode();
|
// 读取响应内容
|
return await response.Content.ReadAsStringAsync();
|
}
|
|
}
|