我们在做网站尤其是用户注册时难免会用到使用手机号注册,给用户发送验证码用于效验身份。因为要用到给手机发送短信,所以需求运营商提供接口(当然这个需要一定的费用^-^)。
下面是实现方案:
一、web.config中需要增加短信发送接口:
<appSettings>
<!--短信发送接口-->
<add key="MeiSheng.Passport" value="******"/>
<add key="MeiSheng.Password" value="******"/>
<add key="MeiSheng.NewPassport" value="******"/>
<add key="MeiSheng.NewPassword" value="******"/>
<add key="MeiSheng.NewUrl" value="******"/>
<add key="MeiSheng.pingzheng" value="******"/>
</appSettings>
二、html页面代码如下:
<div class="valGroup">
<div class="valGroup-item-1 inline-block">
<span>*</span> 手机号码:</div>
<div class="valGroup-item-2 formControls inline-block">
<asp:TextBox ID="txtTel" runat="server" ajaxurl="/tools/validreg.ashx?regType=validPhone"
CssClass="input-text-1" datatype="m" nullmsg="请输入手机号码" sucmsg=" " placeholder="请输入手机号码"></asp:TextBox>
</div>
<div class="inline-block telmsg">
</div>
</div>
<div class="valGroup">
<div class="valGroup-item-1 inline-block">
<span>*</span> 短信验证码:</div>
<div class="valGroup-item-2 formControls inline-block">
<asp:TextBox ID="txtTelCode" runat="server" CssClass="input-text-1" datatype="n6" nullmsg="请输入手机收到的短信验证码!" errormsg="请输入手机收到的短信验证码!" sucmsg="<font color='green'>恭喜您,验证成功!</font>"
ajaxurl="" Width="200px"></asp:TextBox>
<div style="display: inline-block; vertical-align: middle; margin-top: -2px; height: 38px;" id="divSend">
<a class="telcode" id="getCode" href="#">获取短信验证码</a>
</div>
</div>
<div class="inline-block">
</div>
</div>
三、js代码:
var iTime = 119;
var eTime = 0;
//验证码发送时间
function RemainTime() {
var ahtml = "";
if (iTime > 0) {
ahtml = '提交成功(' + iTime + '秒)';
Account = setTimeout("RemainTime()", 1000);
iTime = iTime - 1;
eTime = 1;
if (!document.getElementById("cover0"))
$("#divSend").append('<div id="cover0" class="input-sm" style="width:100%; height:42px;background-color:#FFF;opacity:.40;filter: alpha(opacity=60);position:relative; margin-top:-40px; z-index:99999;"></div>');//在2分钟内不允许重复点击
} else {
clearTimeout(Account);
ahtml = '获取短信验证码';
iTime = 119;
eTime = 0;
$("#cover0").remove();
}
$(".telcode").html(ahtml);
}
$(function () {
var valid_rule = $("#register").Validform({
datatype: {//传入自定义datatype类型,可以是正则,也可以是函数(函数内会传入一个参数);
"n6": /^\d{6}$/
},
tiptype: 2
});
$("#txtTel").blur(function () {
$("#txtTelCode").attr("ajaxurl", "/tools/validreg.ashx?regType=validCode&ctype=1&phone=" + $('#txtTel').val());
});
});
//获取短信验证码
$('#getCode').click(function () {
$('#txtTel').focus();
$('#txtTel').blur();
if (!$("#txtTel").val()) {
return false;
}
else {
setTimeout('SendTelMsg()', 300);
}
});
//发送短信验证码
function SendTelMsg() {
if ($(".telmsg span").html() == "<font color=\"green\">该手机号可用</font>") {
if (eTime > 0) { return false; }
$(".telcode").html('已提交');
eTime = 1;
$.ajax({
method: 'post',
timeout: 30,
async: false, //同步请求,防止重复提交请求
data: { mobile: $("#txtTel").val(), mb: "MB-2015061926(模板编号)", ctype: 1 },
dataTpye: 'json',
url: "/tools/validreg.ashx?regType=sendCode",
success: function (data) {
var par = eval('(' + data + ')');
if ($.trim(par.status) === "y") {
RemainTime(); //倒计时
} else {
eTime = 0;
alert(par.info);
}
},
error: function (data) {
eTime = 0;
alert('未知错误');
}
});
$(".telcode").html('获取短信验证码');
return false;
}
else {
return false;
}
}
四、后台代码:
#region //发送短信验证码
public void SendTelCode(HttpContext context)
{
string tel = context.Request.Form["mobile"];
string mb = context.Request.Form["mb"];
int type = Convert.ToInt32(context.Request.Form["ctype"]);
if (recm.CountMessage(tel, 24, 2) < 5) //一天之内最多只能发送5条
{
if (recm.CountTwoMessage(tel, 120, 2) > 0) //2分钟之内只能发送1次
{
context.Response.Write("{ \"info\":\"发送过于频繁,请稍后再试!\", \"status\":\"n\" }");
context.Response.End();
}
else
{
string randnum = randcode();
RegCodeInfo info = new RegCodeInfo();
info.RCRandNum = randnum;
info.RCTel = tel;
info.RCcount = 1;
info.RCIP = FormatGetIP();
info.RCType = type;
if (recm.Insert(info))
{
if (Labbase.Common.SendMsg.sendTemplateSms(tel, mb, "@1@=" + randnum + ",@2@=30").Equals("恭喜您发送成功!"))
{
context.Response.Write("{ \"info\":\"<font color='green'>验证码发送成功,请注意查收!</font>\", \"status\":\"y\" }");
context.Response.End();
}
else
{
context.Response.Write("{ \"info\":\"验证码发送失败,请稍后再试!\", \"status\":\"n\" }");
context.Response.End();
}
}
else
{
context.Response.Write("{ \"info\":\"验证码发送失败,请稍后再试!\", \"status\":\"n\" }");
context.Response.End();
}
}
}
else
{
context.Response.Write("{ \"info\":\"发送超出限制,请联系管理员!\", \"status\":\"n\" }");
context.Response.End();
}
}
#endregion
#region //短信验证码验证
public void TelCodeValid(HttpContext context)
{
string phone = context.Request.QueryString["phone"];
string code = Labbase.Common.DTRequest.GetString("param");
int type2 = Convert.ToInt32(context.Request.QueryString["ctype"]);
if (recm.CountYouXiao(phone, code, 30, type2) > 0) //验证用户输入的手机验证码是否在有效期之内
{
context.Response.Write("{ \"info\":\"<font color='green'>验证成功!</font>\", \"status\":\"y\" }");
context.Response.End();
}
else
{
context.Response.Write("{ \"info\":\"注册失败,请确认验证码!\", \"status\":\"n\" }");
context.Response.End();
}
}
#endregion
#region//生成随机验证码
public string randcode()
{
char[] chars = "1234567890".ToCharArray();
System.Random random = new Random();
string code = string.Empty;
for (int i = 0; i < 6; i++) code += chars[random.Next(0, chars.Length)].ToString(); //随机生成验证码字符串(6个字符)
return code;
}
#endregion
#region//设置本地IP地址
public static string FormatGetIP()
{
return "58.56.17.206";
}
#endregion
五、用到的类:
public class SendMsg
{
#region =====发送普通短信=====
/// <summary>
/// 发送普通短信
/// </summary>
/// <param name="mobile">手机号码, 多个号码以英文逗号隔开,最多支持100个号码</param>
/// <param name="content">短信内容</param>
/// <returns>返回发送状态,状态说明见下载包中的接口文档</returns>
public static String SendTextSms(string mobile, string content)
{
string account = ConfigHelper.GetConfig("MeiSheng.NewPassport");
string password = ConfigHelper.GetConfig("MeiSheng.NewPassword");
string HTTP_URL = ConfigHelper.GetConfig("MeiSheng.NewUrl");
string veryCode = ConfigHelper.GetConfig("MeiSheng.pingzheng");
StringBuilder param = new StringBuilder();
param.Append("&username=").Append(account);
param.Append("&password=").Append(password);
//通信认证密码
param.Append("&veryCode=").Append(veryCode);
param.Append("&mobile=").Append(mobile);
param.Append("&content=").Append(content);
//短信类型。1-普通短信,2-模板短信。
param.Append("&msgtype=").Append("1");
param.Append("&code=").Append("utf-8");
//发送定时短信
//param.Append("&sendtime=").Append("20151001113000");
String address = String.Format("{0}sendMsg{1}", HTTP_URL, param.ToString());
//发送短信,并获取发送状态
String result = DTRequest.GetPagePost(address);//address
string message = "";
XmlDocument xd = new XmlDocument();
xd.LoadXml(result);
XmlNode node = xd.SelectSingleNode("sms/mt/status");
string html = node.InnerText;
if (html == "100")
{
message = "发送失败";
}
else if (html == "101")
{
message = "用户账号不存在或密码错误";
}
else if (html == "102")
{
message = "账号已禁用";
}
else if (html == "103")
{
message = "参数不正确";
}
else if (html == "105")
{
message = "短信内容超过300字、或为空、或内容编码格式不正确";
}
else if (html == "106")
{
message = "手机号码超过100个或合法的手机号码为空,每次最多提交100个";
}
else if (html == "108")
{
message = "余额不足";
}
else if (html == "109")
{
message = "指定访问ip地址错误";
}
else if (html == "114")
{
message = "模板短信序号不存在";
}
else if (html == "115")
{
message = "短信签名标签序号不存在";
}
else if (html.StartsWith("110#"))
{
message = "短信内容存在系统保留关键词" + html.Substring(4) + ",如有多个词,使用逗号分隔:110#(李老师,成人)";
}
else if (html == "116")
{
message = "认证码不正确";
}
else if (html == "117")
{
message = "未开通此接入方式";
}
else
{
message = "恭喜您发送成功!";
}
return message;
}
#endregion
#region =====发送模版短信(短信模版的创建参考客户端操作手册)=====
/// <summary>
/// 发送模版短信(短信模版的创建参考客户端操作手册)
/// 模版:@1@会员,动态验证码@2@(五分钟内有效)。请注意保密,勿将验证码告知他人。
/// 参数值:@1@=member,@2@=4293
/// 最终短信内容:【短信签名】member会员,动态验证码4293(五分钟内有效)。请注意保密,勿将验证码告知他人。
/// </summary>
/// <param name="mobile">接收人手机号</param>
/// <param name="tempId">模版编号</param>
/// <param name="content">各参数值,以英文逗号隔开,如:@1@=member,@2@=4293</param>
/// <returns>返回发送状态</returns>
public static String sendTemplateSms(string mobile, string tempId, string content)
{
string account = ConfigHelper.GetConfig("MeiSheng.NewPassport");
string password = ConfigHelper.GetConfig("MeiSheng.NewPassword");
string HTTP_URL = ConfigHelper.GetConfig("MeiSheng.NewUrl");
string veryCode = ConfigHelper.GetConfig("MeiSheng.pingzheng");
StringBuilder param = new StringBuilder();
param.Append("&username=").Append(account);
param.Append("&password=").Append(password);
param.Append("&veryCode=").Append(veryCode);
param.Append("&mobile=").Append(mobile);
param.Append("&content=").Append(content);
param.Append("&msgtype=").Append("2");
param.Append("&tempid=").Append(tempId);
param.Append("&code=").Append("utf-8");
String address = String.Format("{0}sendMsg{1}", HTTP_URL, param.ToString());
//发送短信,并获取发送状态
String result = DTRequest.GetPagePost(address);
string message = "";
XmlDocument xd = new XmlDocument();
xd.LoadXml(result);
XmlNode node = xd.SelectSingleNode("sms/mt/status");
string html = node.InnerText;
if (html == "100")
{
message = "发送失败";
}
else if (html == "101")
{
message = "用户账号不存在或密码错误";
}
else if (html == "102")
{
message = "账号已禁用";
}
else if (html == "103")
{
message = "参数不正确";
}
else if (html == "105")
{
message = "短信内容超过300字、或为空、或内容编码格式不正确";
}
else if (html == "106")
{
message = "手机号码超过100个或合法的手机号码为空,每次最多提交100个";
}
else if (html == "108")
{
message = "余额不足";
}
else if (html == "109")
{
message = "指定访问ip地址错误";
}
else if (html == "114")
{
message = "模板短信序号不存在";
}
else if (html == "115")
{
message = "短信签名标签序号不存在";
}
else if (html.StartsWith("110#"))
{
message = "短信内容存在系统保留关键词" + html.Substring(4) + ",如有多个词,使用逗号分隔:110#(李老师,成人)";
}
else if (html == "116")
{
message = "认证码不正确";
}
else if (html == "117")
{
message = "未开通此接入方式";
}
else
{
message = "恭喜您发送成功!";
}
return message;
}
#endregion
#region =====获取短信状态报告 =====
/**
* 获取短信状态报告
* @return 返回数据格式:
* <?xml version="1.0" encoding="UTF-8"?>
<sms>
<rpt>
<mobile>15951977097</mobile>
<msgid>7799292837969854465</msgid>
<status>MA:0006</status>
<time>2015-06-12 15:10:53</time>
<extno/>
</rpt>
<rpt>
<mobile>15951977097</mobile>
<msgid>7799388495481470979</msgid>
<status>MA:0006</status>
<time>2015-06-12 15:16:17</time>
<extno/>
</rpt>
</sms>
*/
public static String QueryReport(string account, string password, string veryCode, string HTTP_URL)
{
StringBuilder param = new StringBuilder();
param.Append("&username=").Append(account);
param.Append("&password=").Append(password);
param.Append("&veryCode=").Append(veryCode);
String address = String.Format("{0}queryReport{1}", HTTP_URL, param.ToString());
//获取短信状态报告
String result = DTRequest.GetPagePost(address);
return result;
}
#endregion
#region =====获取上行短信,只能获取当前的短信状态,不能根据msgid获取状态,具体介绍请查看接口文档 =====
/// <summary>
/// 获取上行短信 ,只能获取当前的短信状态,不能根据msgid获取状态,具体介绍请查看接口文档
/// </summary>
/// <returns>返回当日截止到当前的所有短信状态</returns>
public static String QueryMo(string account, string password, string veryCode, string HTTP_URL)
{
StringBuilder param = new StringBuilder();
param.Append("&username=").Append(account);
param.Append("&password=").Append(password);
param.Append("&veryCode=").Append(veryCode);
String address = String.Format("{0}queryMo{1}", HTTP_URL, param.ToString());
//获取上行短信
String result = DTRequest.GetPagePost(address);
return result;
}
#endregion
#region =====余额查询=====
/// <summary>
///余额查询
/// </summary>
/// <returns>返回当前余额</returns>
public static String GetAmount(string account, string password, string veryCode, string HTTP_URL)
{
StringBuilder param = new StringBuilder();
param.Append("&username=").Append(account);
param.Append("&password=").Append(password);
param.Append("&veryCode=").Append(veryCode);
String address = String.Format("{0}getAmount{1}", HTTP_URL, param.ToString());
//获取当前余额
String result = DTRequest.GetPagePost(address);
string message = "";
XmlDocument xd = new XmlDocument();
xd.LoadXml(result);
XmlNode node = xd.SelectSingleNode("sms/mt/status");
string html = node.InnerText;
if (html == "100")
{
message = "查询余额失败";
}
else if (html == "101")
{
message = "用户账号不存在或密码错误";
}
else if (html == "102")
{
message = "账号已禁用";
}
else if (html == "103")
{
message = "参数不正确";
}
else if (html == "105")
{
message = "认证码错误";
}
else if (html == "117")
{
message = "未开通此接入方式";
}
else
{
XmlNode node1 = xd.SelectSingleNode("sms/mt/account");
message = Utils.StrToInt(node1.InnerText, 0) * 10 + "条";
}
return message;
}
#endregion
}
/// <summary>
/// 获取配置文件的值。
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string GetConfig(string key)
{
key = System.Web.Configuration.WebConfigurationManager.AppSettings[key];
return string.IsNullOrEmpty(key) ? string.Empty : key;
}
/// <summary>
/// POST请求短信平台会用到
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static string GetPagePost(string url)
{
HttpWebRequest httpReq;
HttpWebResponse httpResp;
StringBuilder strBuff = new StringBuilder();
int byteRead = 0;
int byteCount = 256;
char[] cbuffer = new char[byteCount];
try
{
Uri httpURL = new Uri(url);
httpReq = (HttpWebRequest)WebRequest.Create(httpURL);
httpReq.Method = "POST";
httpResp = (HttpWebResponse)httpReq.GetResponse();
Stream respStream = httpResp.GetResponseStream();
// httpResp.Dispose();
//StreamReader类的Read方法依次读取网页源程序代码每一行的内容,直至行尾(读取的编码格式:UTF8)
StreamReader respStreamReader = new StreamReader(respStream, Encoding.UTF8);
byteRead = respStreamReader.Read(cbuffer, 0, byteCount);
while (byteRead != 0)
{
string strResp = new string(cbuffer, 0, byteRead);
strBuff.Append(strResp);
byteRead = respStreamReader.Read(cbuffer, 0, byteCount);
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
finally
{
}
return strBuff.ToString();
}