业务:
手机端点击发送验证码,调用第三方平台(我们用的是“任信了”平台)的接口,去给手机发短信验证码。
过程:
代码:
/*** 发送短信验证码 * @param json 前台传入电话号码* @return 返回发送结果向前台*/@RequestMapping("/getTestCode")@ResponseBodypublic GetTestCodeResult sendTestCode(@RequestParam(value="phone",defaultValue="") String phoneNumber ){GetTestCodeResult result = new GetTestCodeResult();if(phoneNumber == null || phoneNumber.length()==0 ){result.setState(Result.ERROR);result.setMessage("手机号为空");return result;}String code =TestCode.getCode();if( code== null || code.length()==0){result.setState(Result.ERROR);result.setMessage("无效的验证码");return result;}try {SMS.batchsendsm(phoneNumber,code);} catch (Exception e) {result.setState(Result.ERROR);result.setMessage("验证码发送失败");return result;}TestCodeInforVo testCodeInfor = new TestCodeInforVo();testCodeInfor.setCode(code);testCodeInfor.setPhone(phoneNumber);testCodeInfor.setDate(System.currentTimeMillis());testCodeInforMap.put(phoneNumber,testCodeInfor);result.setState(Result.SUCCESS);result.setMessage("验证码发送成功");result.setData(code); //测试return result;}
上面这个是发送验证码的方法,其中包括了2个工具类:
No.1 生成5位随机数
public class TestCode {private final static int codeLength =5;/*** @see 产生随机验证码* @return 验证码字符串*/public static String getCode(){Random rand = new Random();int a ;String result ="";for( int j =0; j<codeLength; j++ ){a = Math.abs( rand.nextInt()%9 );result += String.valueOf(a);}return result;}
}
No.2 调用第三方发送短信接口
package com.cn.zhongcai.util.app.util;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class SMS {//把接口地址和参数赋值,之后调用SMS3方法,参数photo是手机号,code是之前生成的验证码。public static void batchsendsm(String phone,String code){try{String userid = URLEncoder.encode("15732622061","UTF-8"); //188 String url = "http://apis.renxinl.com:8080/smsgate/varsend.do?";String para = "user="+userid+"&pwd=9fa41ab9c5352bc29babd621a73d¶ms="+phone+","+code+"&mid=15552";String str="";str=SMS3(para,url);System.out.println(str);}catch (Exception e) {e.printStackTrace();}}//postData是上面拼接的参数值,postURL 是接口的地址。我觉得这个方法是能访问到第三方接口的方法。public static String SMS3(String postData,String postUrl){try{URL url = new URL(postUrl);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("POST");conn.setRequestProperty("accept", "*/*");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");conn.setUseCaches(false);conn.setDoOutput(true);conn.setDoInput(true);OutputStreamWriter out= new OutputStreamWriter(conn.getOutputStream(),"UTF-8");out.write(postData);out.flush();out.close();if(conn.getResponseCode()!=HttpURLConnection.HTTP_OK){System.out.println("connect failed!");return "";}String line,result = "";BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));while((line= in.readLine()) != null){result += line+"\n";}in.close();return result;}catch(IOException e){e.printStackTrace(System.out);}return "";} }
其中:
1、我从第三方那要了一个demo,从中摘出来自己需要用的代码。
2、短信接口有固定模板和变量模板, 这里我们用到的是变量模板,因为验证码是个变量。
3、接口文档里给的很清楚:
4、其中最后一步保存,该手机号的验证码和发送时间,用到了一个Map保存。
private final static Map<String, TestCodeInforVo> testCodeInforMap = new HashMap<String,TestCodeInforVo>();
发送完验证码之后:
testCodeInforMap.put(phoneNumber,testCodeInfor);
保存到了map里面,到时候找验证码和时间,也从这个map里面找,手机号是key,这个保存着验证码和时间的实体是value。
短信验证码就到此告一段落。接下来看登陆的逻辑:
登陆的过程:
登陆代码:
/*** 用户登录接口* @param json 登录参数* @return 登录成功返回用户信息*/@RequestMapping("/login")@ResponseBodypublic LoginResult login(@RequestParam(value="testCode",defaultValue="") String testCode,@RequestParam(value="identity",defaultValue="") String identity,@RequestParam(value="phone",defaultValue="") String phone, HttpServletRequest request){//String serverPath = request.getScheme() + "://"+ request.getServerName() + ":" + // request.getServerPort()+request.getContextPath() + "/";LoginResult result = new LoginResult();if( identity == null || identity.length() == 0 ){result.setState(Result.ERROR);result.setMessage("证件号为空");return result;}if(phone== null || phone.length() == 0 ){result.setState(Result.ERROR);result.setMessage("手机号为空");return result;}if( testCode == null || testCode.length() == 0 ){result.setState(Result.ERROR);result.setMessage("验证码为空");return result;}TestCodeInforVo testCodeInfor = (TestCodeInforVo) testCodeInforMap.get(phone);if( testCodeInfor == null || testCodeInfor.getCode() == null || testCodeInfor.getCode().length()==0 ){result.setState(Result.ERROR);result.setMessage("验证码不存在");return result;}if(!testCode.equals(testCodeInfor.getCode())){result.setState(Result.ERROR);result.setMessage("验证码错误");return result;}testCodeInforMap.remove(phone);//验证验证码是否过期if( System.currentTimeMillis()- testCodeInfor.getDate() > testCodeOutDate ){result.setState(Result.ERROR);result.setMessage("验证码已过期");return result;} List<UserEntity> users = userService.getUserByPhoneIdentity(phone,identity);if( users.isEmpty()){result.setState(Result.ERROR);result.setMessage("用户不存在");return result;}if( users.size() != 1){result.setState(Result.ERROR);result.setMessage("认证用户不唯一");return result;} if( users.get(0).getAccountStatus() != null && users.get(0).getAccountStatus().equals("0")){result.setState(Result.ERROR);result.setMessage("该用户被冻结");return result;}UserEntity user = users.get(0);user.setQrCode(user.getQrCode());user.setPersonalPhotos(user.getPersonalPhotos());user.setIdCardAvatarFace(user.getIdCardAvatarFace());user.setIdCardNationalEmblem(user.getIdCardNationalEmblem());String siteID="";//根据user的role去判断该用户所在的站点IDif (user.getRole()==0) {//0是管理员//根据用户的ID去站点表里查询站点的最早添加的哪一个站点IdsiteID=userService.findSiteIDByTimeAdmin(user.getId());}if(user.getRole()==2)//2是业主{//根据用户的ID去站点表里查询站点的最早添加的哪一个站点IdsiteID=userService.findSiteIDByTimeOwner(user.getId());}if (user.getRole()==1) {//1是营业员//营业员对应的,最早添加的哪一个站点IdsiteID=userService.findSiteIDByTimeOwnerSale(user.getId());}user.setSiteID(siteID);result.setState(Result.SUCCESS);result.setMessage("登录成功");AppLoginUser appUser=new AppLoginUser();HttpSession session=request.getSession();appUser.setUserID(user.getId());appUser.setUserName(user.getName());appUser.setUserNum(user.getUserNumber());OrgStructure org=orgService.getOrgByAccount(user.getName());//appUser.setOrgId(org.getOrgId());session.setAttribute("appLoginUser", appUser);result.setData(user);return result;}
其中:
1、判断验证码是否正确:(从刚才那个map里面,根据手机号取值)
TestCodeInforVo testCodeInfor = (TestCodeInforVo) testCodeInforMap.get(phone);
从这个实体里面取出验证码和时间。
2、验证码是否过期:
过期时间:
private final static long testCodeOutDate = 5*60*1000; //验证码过期时间
//验证验证码是否过期if( System.currentTimeMillis()- testCodeInfor.getDate() > testCodeOutDate ){result.setState(Result.ERROR);result.setMessage("验证码已过期");return result;}
验证完之后删除他:
testCodeInforMap.remove(phone);
3、当初想的是存到session里面会怎么写,还没想好,希望路过的大神指导。
小结:
发送验证码和登陆的逻辑之前觉得挺复杂的,当画图总结一遍之后,思路就清楚多了,还是要静下心来多总结。