地址:/rrt/user/codeVerify/getVerifyCode.do
用途:用户获取短信验证码,如:注册页面中点击发送验证码,手机会收到相应验证码
请求方法:GET/POST.
请求参数:
{ caller:"", //系统标识【String类型】 timestamp:"", //时间戳(yyyyMMddHHmmssSSS)【String类型】 hashcode:"", //MD5加密(caller+secreKey+time)secreKey相当于密钥,需要两端一致【32位大写】 phoneNum:"", //账号(手机号码)【String类型】 validType:"" //验证类型【String类型】,1:注册,2:密码重置,3:用户激活,4:其他 }
返回值:
{ "status":200, //状态码【int类型,200为成功,400为失败】 "error":"成功", //状态信息【String类型】 "data":true }
例如在地址栏输入:localhost:8080/rrt-openapi-server/rrt/user/codeVerify/getVerifyCode.do?phoneNum=13000000000&validType=2
@Controller @RequestMapping("/rrt/user/codeVerify") public class RrtUserCodeVerifyController { @Autowired private CodeVerifyService service; @RequestMapping("/getVerifyCode") @ResponseBody public ResponseResult<Boolean> getVerifyCode(@Valid GetValidCodeForm code, BindingResult bindingResult){ ResponseResult<Boolean> result = new ResponseResult<Boolean>(); if (bindingResult.hasErrors()) { // 验证参数是否合法 FieldError fieldError = bindingResult.getFieldError(); result.setError(fieldError.getDefaultMessage()); result.setStatus(ResponseStatus.REQUEST_FAIL.getCode()); return result; } try { Boolean getResult = service.getVerifyCode(code.getPhoneNum(), code.getValidType());// 发送验证码 result.setData(getResult); } catch (Exception e) { e.printStackTrace(); result.setStatus(ResponseStatus.SERVER_ERR.getCode()); result.setError(ResponseStatus.SERVER_ERR.getText()); } return result; } }
/** * 短信验证码获取服务层 */ @Service @Transactional public class SMSCodeVerifyServiceImpl implements CodeVerifyService{ private static Logger log = LoggerFactory.getLogger(SMSCodeVerifyServiceImpl.class); @Autowired private SendCodeService<Boolean> sendSMSService; // 验证码发送服务 @Autowired private GenCodeService genCodeService; // 验证码生成服务 @Autowired private UserVerifyCodeDao userVerifyCodeDao; /** * 获取验证码 * @param phoneNum 手机号码 * @param validType 验证码类型 */ @Override public boolean getVerifyCode(String phoneNum, Integer validType) { String code = genCodeService.getCode(phoneNum); //生成验证码 if (code ==null) {//获取验证码失败时,返回失败结果 log.error("codeSMS--getVerifyCode;phoneNum:"+phoneNum+":validType:" +validType+" get verifyCode error;maybe phoneNum violate some setting"); return false; }else{ return sendSMSService.send(phoneNum, code, validType); // 发送验证码 } } /** * 验证验证码是否正确 * @param phoneNum 手机号码 * @param codeNum 验证码 * @param validType 验证码类型 */ @Override public boolean validate(String phoneNum, String codeNum, Integer validType) { UserVerifyCode verifyCode = userVerifyCodeDao.find(phoneNum); if (verifyCode == null) { log.error("codeSMS--validateCode;phoneNum:"+phoneNum+":codeNum:" +codeNum+":validType:"+validType+" validate code not exist"); return false; }else{ if (verifyCode.getValidType().intValue() == validType.intValue() && !verifyCode.getIsUse() && verifyCode.getCodeNum().equals(codeNum) && verifyCode.getOverTime().getTime() > System.currentTimeMillis()) { verifyCode.setIsUse(true); verifyCode.setValidTime(new Timestamp(System.currentTimeMillis())); return true; } } log.error("codeSMS--validateCode;phoneNum:"+phoneNum+":codeNum:" +codeNum+":validType:"+validType+" validate unsuccessful"); return false; } }
/** * 生成验证码,并判断是否重复和该手机号能否获取 * @author cyh * */ @Component public class SMSCodeGenServiceImpl implements GenCodeService{ private static Logger log = LoggerFactory.getLogger(SMSCodeGenServiceImpl.class); @Autowired private CheckVerify verify; @Override public String getCode(String phoneNum) { if(!verify.checkPhone(phoneNum)) return null; String code = getRandNum(); while(!verify.checkCode(phoneNum, code)){ code = getRandNum(); } return code; } private static String getRandNum(){ Random random = new Random(System.currentTimeMillis()); GetableSMSSetting smsSetting = SMSSendSettingFactory.getWrapInstance(); // 具体代码请看下图 log.trace("codeSMS--getRandNum;SMSSetting,codeLength:"+smsSetting.getCodeLength()); StringBuilder str = new StringBuilder(); for (int i = 0; i < smsSetting.getCodeLength(); i++) { str.append(random.nextInt(9)); } return str.toString(); } }
@Service public class SendSMSServiceImpl implements SendCodeService<Boolean>{ private static Logger log = LoggerFactory.getLogger(SendSMSServiceImpl.class); @Autowired @Qualifier("sendResCallBackServiceImpl") private Callback<Boolean> sendResponseCallBack; @Override public Boolean send(String phoneNum, String code, Integer validType) { Send sendRequest = new Send(); GetableSMSSetting smsSetting = SMSSendSettingFactory.getWrapInstance(); sendRequest.setContent(formateCodeSMS(code, smsSetting)); sendRequest.setReceiver(Arrays.asList(phoneNum)); formateSendRequest(sendRequest, smsSetting); log.debug("codeSMS--SendSMS;Request send sms param:"+sendRequest.toString()); // SendResponse response = SMSClient.getInstance(smsSetting.getServerUrl()).sendSMSMessage(sendRequest); // 实际应用中要使用这句,下面这句只用于测试时 SendResponse response = new SendResponse();response.setRequestId(1); if (response == null) { response = new SendResponse(); response.setRequestId(-1); } log.debug("codeSMS--SendSMS;phoneNum:"+phoneNum+":Request send sms repsonse:"+response.getRequestId()); return sendResponseCallBack.doIt(new SendResponseData(response, phoneNum, code, validType)); } /** * 格式化验证码短信 * @param code 验证码 * @param smsSetting 短信发送设置 * @return */ public String formateCodeSMS(String code, GetableSMSSetting smsSetting){ log.trace("codeSMS--SendSMS;SMSSetting,smsTemplate:"+smsSetting.getSMSTemplate()); return smsSetting.getSMSTemplate().replaceFirst("\\$\\{codeNum\\}", code); } /** * 格式化发送短信请求 * @param sendRequest * @param smsSetting */ public void formateSendRequest(Send sendRequest, GetableSMSSetting smsSetting){ sendRequest.setAccount(smsSetting.getSendAccount()); sendRequest.setPassword(smsSetting.getSendPasswd()); sendRequest.setExtNumber(smsSetting.getSendExtNumber()); sendRequest.setType(smsSetting.getSendType()); } /** * 封装发送短信处理结果信息Bean * @author cyh * */ public static class SendResponseData{ private SendResponse response; private String phoneNum; private String code; private Integer validType; public SendResponseData() { super(); } public SendResponseData(SendResponse response, String phoneNum, String code, Integer validType) { super(); this.response = response; this.phoneNum = phoneNum; this.code = code; this.validType = validType; } public SendResponse getResponse() { return response; } public SendResponseData setResponse(SendResponse response) { this.response = response; return this; } public String getPhoneNum() { return phoneNum; } public SendResponseData setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; return this; } public String getCode() { return code; } public SendResponseData setCode(String code) { this.code = code; return this; } public Integer getValidType() { return validType; } public SendResponseData setValidType(Integer validType) { this.validType = validType; return this; } } }
@Repository public class SystemSettingDao extends CoreDaoImpl<SystemSetting, PageForm>{ }
SystemSettingDao类只是继承了CoreDaoImpl类,这里不作其他处理。关于CoreDaoImpl类请查看本博客的《五、通用Dao层之CoreDao接口与CoreDaoImpl抽象类》