网站或者移动端应用的手机验证码功能,现在应用到的地方非常多,但是具体实现都差不多,也比较简单,正好最近我们网站需要开发这么个功能。所以记录以下:
1 首先选择一家短信服务提供商,大概时六分一条吧,我们选择的是容联云通讯,然后他们会提供接口文档或者demo。
2 接口调用方式,可以使用http方式,就是直接在前端页面中访问某个url,并传入相关参数,也可以将jar文件添加导classpath,然后使用他们demo里的类即可。使用http方式本质上还是调用远端的sdk,这里选择sdk方式。
3下边是页面上的一些js,主要控制点击后在过60s才可以再次点击。
function send(){
var telphone=$("#tel").val();
if(telphone==""){
alert("请输入手机号");
return;
}
//1服务器端生成验证码
$.post("/userCenter/GenerateAndSendTelValidateCode",{operate:"generateCode"},function(code){
//2调用接口,发送短信
sendTelCode(telphone,code);
//3设置按钮不可用
$("#btnCode").attr("disabled", "disabled");
setMyTimeout();
});
}
//调用接口发送短信
function sendTelCode(telphone,code){
$.post("/userCenter/GenerateAndSendTelValidateCode",{operate:"sendTelCode",telphone:telphone,code:code},function(message){
if("success"==message){
alert("短信发送成功");
}else{
alert("短信发送失败");
}
});
}
//验证
function validTel(){
$.post("/userCenter/GenerateAndSendTelValidateCode",{operate:"getTelCode"},function(code){
if(""!=code){
var pageCode=$("#code").val();
var telphone=$("#tel").val();
var userId = $("#userId").val();
if(""==pageCode){
alert("请输入验证码");
return;
}
// if(pageCode==code){
//修改数据库用户状态:手机已验证
$.post("/userCenter/GenerateAndSendTelValidateCode",{operate:"updateTelState",userId:userId},function(message){
if("success"==message){
alert("验证成功,保存配置后可以使用手机号登录了");
}else{
alert("短信验证失败");
}
});
// }else{
// alert("验证码不正确");
// }
}
});
}
//设置定时器
var count = 60;
function setMyTimeout(){
if (count > 0) {
setTimeout(setMyTimeout, 1000);
$("#btnCode").val((count--) + "秒之后点击获取");
}
else {
count=5;
$("#btnCode").val("点击获取验证码");
$("#btnCode").attr("disabled", "");
}
}
2 对于服务器端:
主要生成验证码,发送验证码,不过短信模版需要自己上提供商网站操作。然后将应用id,模版id 账户传进去即可。
/**
* Servlet implementation class GenerateTelValidateCode
*/
public class GenerateAndSendTelValidateCode extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String account = CmsGlobals
.getCmsProperty("yuntongxin.account");
private static final String token = CmsGlobals
.getCmsProperty("yuntongxin.token");
private static final String appId = CmsGlobals
.getCmsProperty("yuntongxin.appId");
private static final String templateId = CmsGlobals
.getCmsProperty("yuntongxin.templateId");
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String operate = request.getParameter("operate");
PrintWriter out = response.getWriter();
response.setContentType("text/html;charset=utf-8");
response.setHeader("Cache-Control", "no-cache");
HttpSession session = request.getSession();
if ("generateCode".equals(operate)) {
// 产生随机的认证码
char[] rands = generateCheckCode();
String code = new String(rands);
// 将当前验证码存入到Session中
session.setAttribute("validateNum", new String(rands));
// 返回json验证码
out.print(code);
} else if ("getTelCode".equals(operate)) {
String sessionCode = (String) session.getAttribute("validateNum");
out.print(sessionCode);
} else if ("sendTelCode".equals(operate)) {
String telphone = request.getParameter("telphone");
String code = request.getParameter("code");
sendTelCode(telphone, code, out);
} else if ("updateTelState".equals(operate)) {
updateTelState(request, out);
}
out.flush();
out.close();
}
private void sendTelCode(String telphone, String code, PrintWriter out) {
HashMap<String, Object> result = null;
// 初始化SDK
CCPRestSmsSDK restAPI = new CCPRestSmsSDK();
// ******************************注释*********************************************
// *初始化服务器地址和端口 *
// *沙盒环境(用于应用开发调试):restAPI.init("sandboxapp.cloopen.com", "8883");*
// *生产环境(用户应用上线使用):restAPI.init("app.cloopen.com", "8883"); *
// *******************************************************************************
restAPI.init("sandboxapp.cloopen.com", "8883");
// ******************************注释*********************************************
// *初始化主帐号和主帐号令牌,对应官网开发者主账号下的ACCOUNT SID和AUTH TOKEN *
// *ACOUNT SID和AUTH TOKEN在登陆官网后,在“应用-管理控制台”中查看开发者主账号获取*
// *参数顺序:第一个参数是ACOUNT SID,第二个参数是AUTH TOKEN。 *
// *******************************************************************************
restAPI.setAccount(account, token);
// ******************************注释*********************************************
// *初始化应用ID *
// *测试开发可使用“测试Demo”的APP ID,正式上线需要使用自己创建的应用的App ID *
// *应用ID的获取:登陆官网,在“应用-应用列表”,点击应用名称,看应用详情获取APP ID*
// *******************************************************************************
restAPI.setAppId(appId);
// ******************************注释****************************************************************
// *调用发送模板短信的接口发送短信 *
// *参数顺序说明: *
// *第一个参数:是要发送的手机号码,可以用逗号分隔,一次最多支持100个手机号 *
// *第二个参数:是模板ID,在平台上创建的短信模板的ID值;测试的时候可以使用系统的默认模板,id为1。 *
// *系统默认模板的内容为“【云通讯】您使用的是云通讯短信模板,您的验证码是{1},请于{2}分钟内正确输入”*
// *第三个参数是要替换的内容数组。 *
// **************************************************************************************************
// **************************************举例说明***********************************************************************
// *假设您用测试Demo的APP ID,则需使用默认模板ID 1,发送手机号是13800000000,传入参数为6532和5,则调用方式为
// *
// *result = restAPI.sendTemplateSMS("13800000000","1" ,new
// String[]{"6532","5"}); *
// *则13800000000手机号收到的短信内容是:【云通讯】您使用的是云通讯短信模板,您的验证码是6532,请于5分钟内正确输入 *
// *********************************************************************************************************************
result = restAPI.sendTemplateSMS(telphone, templateId, new String[] {
code, "1" });
System.out.println("SDKTestGetSubAccounts result=" + result);
if ("000000".equals(result.get("statusCode"))) {
// 正常返回输出data包体信息(map)
HashMap<String, Object> data = (HashMap<String, Object>) result
.get("data");
Set<String> keySet = data.keySet();
for (String key : keySet) {
Object object = data.get(key);
System.out.println(key + " = " + object);
}
out.print("success");
} else {
// 异常返回输出错误码和错误信息
System.out.println("错误码=" + result.get("statusCode") + " 错误信息= "
+ result.get("statusMsg"));
out.print(result.get("statusMsg"));
}
}
private void updateTelState(HttpServletRequest request, PrintWriter out) {
long userid = Long.valueOf(request.getParameter("userId"));
int result = 0;
try {
result = SqlHandler
.excuteSQL("update userinfo set telphone_valid = 1 where userid = "
+ userid);
} catch (Exception ex) {
ex.printStackTrace();
}
if (result != -1) {
out.print("success");
HttpSession session = request.getSession();
LoginUserInfo user = (LoginUserInfo) session.getAttribute("user");
user.setTelphoneValid(1);
session.setAttribute("user", user);
} else {
out.print("error");
}
}
private char[] generateCheckCode() {
// 定义验证码的字符表
String chars = "2345679ACDEFGHGKLNPQRSTUVXYZ";
char[] rands = new char[4];
for (int i = 0; i < 4; i++) {
int rand = (int) (Math.random() * 28);
rands[i] = chars.charAt(rand);
}
return rands;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}