前言
基本上在所有的APP或者网站上注册用户时大家都可以通过手机号进行注册,这是一个项目必备的功能之一,但是怎么实现的呢?通过接通短信接口,这一点大家想必都明白,接下来大家来看下具体操作,如有不对,请轻喷
第一步、找个短信批发商注册个账号,
笔者这里选用的是荣联-云通讯平台,只需要注册一个账号,进入管理控制台自己查看信息即可,创建APP会产生APPID
二、配置文件
我这使用的是SSM框架,进行如下配置(下面所有属性都在荣联里面找得到)
三、编写service层代码
package cn.yunfan.itrip.service.sms.impl;
import cn.yunfan.utils.SystemConfig;
import com.cloopen.rest.sdk.CCPRestSmsSDK;
import cn.yunfan.itrip.service.sms.SmsService;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Set;
@Service
public class SmsServiceImpl implements SmsService {
Logger logger= Logger.getLogger(SmsServiceImpl.class);
@Resource
private SystemConfig systemConfig;
@Override
public void send(String to, String templateId, String[] datas) throws Exception {
HashMap<String,Object>result =null;
//初始化官方发送短信的工具类
CCPRestSmsSDK restAPI = new CCPRestSmsSDK();
//根据主机和端口,初始化:resultAPI.init("app.cloopen.com","8883");
restAPI.init(systemConfig.getSmsServerIP(),systemConfig.getSmsServerPort());
//*初始化主账号和主账号令牌,对应官网开发者主账号下的ACCOUNT SID 和 AUTH TOKEN
//认证我的开发者账号
restAPI.setAccount(systemConfig.getSmsAccountSid(),systemConfig.getSmsAuthToken());
//爱旅行的应用Id
restAPI.setAppId(systemConfig.getSmsAppID());
result= restAPI.sendTemplateSMS(to,templateId,datas);
logger.debug("SDKTestGetSubAccounts result="+result);
if("000000".equals(result.get("statusCode"))){//000000表示发送成功
//正常返回输出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);
logger.debug(key+"="+object);
}
}else{
//异常返回输出错误码和错误信息
System.out.println("错误码="+result.get("statusCode")+"错误信息="+result.get("statusMsg"));
logger.error("错误码="+result.get("statusCode")+"错误信息="+result.get("statusMsg"));
throw new Exception("错误码="+result.get("statusCode")+"错误信息="+result.get("statusMsg"));
}
}
}
PS:由于笔者使用了redis作为缓存和一些工具类,这里我就在下面一一列出
1、RedisAPI
package cn.yunfan.utils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* RedisAPI
* @author bdqn_hl
* @date 2014-3-15
*/
public class RedisAPI {
public JedisPool jedisPool;
public JedisPool getJedisPool() {
return jedisPool;
}
public void setJedisPool(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
/**
* set key and value to redis
* @param key
* @param value
* @return
*/
public boolean set(String key,String value){
try{
Jedis jedis = jedisPool.getResource();
jedis.set(key, value);
return true;
}catch(Exception e){
e.printStackTrace();
}
return false;
}
/**
* set key and value to redis
* @param key
* @param seconds 有效期
* @param value
* @return
*/
public boolean set(String key,int seconds,String value){
try{
Jedis jedis = jedisPool.getResource();
jedis.setex(key, seconds, value);
return true;
}catch(Exception e){
e.printStackTrace();
}
return false;
}
/**
* 判断某个key是否存在
* @param key
* @return
*/
public boolean exist(String key){
try{
Jedis jedis = jedisPool.getResource();
return jedis.exists(key);
}catch(Exception e){
e.printStackTrace();
}
return false;
}
/**
* 返还到连接池
* @param pool
* @param redis
*/
public static void returnResource(JedisPool pool,Jedis redis){
if(redis != null){
pool.returnResource(redis);
}
}
/**
* 获取数据
* @param key
* @return
*/
public String get(String key){
String value = null;
Jedis jedis = null;
try{
jedis = jedisPool.getResource();
value = jedis.get(key);
}catch(Exception e){
e.printStackTrace();
}finally{
//返还到连接池
returnResource(jedisPool, jedis);
}
return value;
}
/**
* 查询key的有效期,当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。
* 注意:在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。
* @param key
* @return 剩余多少秒
*/
public Long ttl(String key){
try{
Jedis jedis = jedisPool.getResource();
return jedis.ttl(key);
}catch(Exception e){
e.printStackTrace();
}
return (long) -2;
}
/**
* 删除
* @param key
*/
public void delete(String key){
try{
Jedis jedis = jedisPool.getResource();
jedis.del(key);
}catch(Exception e){
e.printStackTrace();
}
}
}
2、SystemCofing
package cn.yunfan.utils;
/**
* SystemConfig
* @author hanlu
*
*/
public class SystemConfig {
/**
* 文件上传路径,通过properties文件进行配置
*/
private String fileUploadPathString;
/**
* 上传文件访问URL,通过properties文件进行配置
*/
private String visitImgUrlString;
/**
* 生成订单的机器码,通过properties文件进行配置
*/
private String machineCode;
private String orderProcessOK;
private String orderProcessCancel;
/**
* 云通信短信平台账户Account Sid
*/
private String smsAccountSid;
/**
* 云通信短信平台账户Auth Toke
*/
private String smsAuthToken;
/**
* 云通信短信平台账户App ID
*/
private String smsAppID;
/**
* 云通信短信平台Server IP
*/
private String smsServerIP;
/**
* 云通信短信平台Server Port
*/
private String smsServerPort;
/**
* 在线支付交易完成通知后续处理接口的地址
*/
private String tradeEndsUrl;
/**
* 支付模块发送Get请求是否使用代理
*/
private Boolean tradeUseProxy;
/**
* 代理主机
*/
private String tradeProxyHost;
/**
* 代理端口
*/
private Integer tradeProxyPort;
public String getTradeEndsUrl() {
return tradeEndsUrl;
}
public void setTradeEndsUrl(String tradeEndsUrl) {
this.tradeEndsUrl = tradeEndsUrl;
}
public Boolean getTradeUseProxy() {
return tradeUseProxy;
}
public void setTradeUseProxy(Boolean tradeUseProxy) {
this.tradeUseProxy = tradeUseProxy;
}
public String getTradeProxyHost() {
return tradeProxyHost;
}
public void setTradeProxyHost(String tradeProxyHost) {
this.tradeProxyHost = tradeProxyHost;
}
public Integer getTradeProxyPort() {
return tradeProxyPort;
}
public void setTradeProxyPort(Integer tradeProxyPort) {
this.tradeProxyPort = tradeProxyPort;
}
public String getSmsAccountSid() {
return smsAccountSid;
}
public void setSmsAccountSid(String smsAccountSid) {
this.smsAccountSid = smsAccountSid;
}
public String getSmsAuthToken() {
return smsAuthToken;
}
public void setSmsAuthToken(String smsAuthToken) {
this.smsAuthToken = smsAuthToken;
}
public String getSmsAppID() {
return smsAppID;
}
public void setSmsAppID(String smsAppID) {
this.smsAppID = smsAppID;
}
public String getSmsServerIP() {
return smsServerIP;
}
public void setSmsServerIP(String smsServerIP) {
this.smsServerIP = smsServerIP;
}
public String getSmsServerPort() {
return smsServerPort;
}
public void setSmsServerPort(String smsServerPort) {
this.smsServerPort = smsServerPort;
}
public String getOrderProcessOK() {
return orderProcessOK;
}
public void setOrderProcessOK(String orderProcessOK) {
this.orderProcessOK = orderProcessOK;
}
public String getOrderProcessCancel() {
return orderProcessCancel;
}
public void setOrderProcessCancel(String orderProcessCancel) {
this.orderProcessCancel = orderProcessCancel;
}
public String getMachineCode() {
return machineCode;
}
public void setMachineCode(String machineCode) {
this.machineCode = machineCode;
}
public String getVisitImgUrlString() {
return visitImgUrlString;
}
public void setVisitImgUrlString(String visitImgUrlString) {
this.visitImgUrlString = visitImgUrlString;
}
public String getFileUploadPathString() {
return fileUploadPathString;
}
public void setFileUploadPathString(String fileUploadPathString) {
this.fileUploadPathString = fileUploadPathString;
}
}
3、验证电话号码格式 ValiPhone
package cn.yunfan.utils;
import java.util.regex.Pattern;
public class ValidPhone {
public static boolean validata(String phoneNumber){
String pattern = "(1[345678]\\d{9})";
Pattern r = Pattern.compile(pattern);
return r.matcher(phoneNumber).matches();
}
}
4、MD5密码加密
package cn.yunfan.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
public class MD5 {
public static String getMd5(String plainText,int length) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes());
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
// 32位
// return buf.toString();
// 16位
// return buf.toString().substring(0, 16);
return buf.toString().substring(0, length);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
public static int getRandomCode(){
int max=9999;
int min=1111;
Random random = new Random();
return random.nextInt(max)%(max-min+1) + min;
}
public static void main(String[] args) {
System.out.println(MD5.getMd5("helloadsfdsffsf",6));
System.out.println(getRandomCode());
}
}
5、数据传输对象 Dto工具类
package cn.yunfan.itrip.pojo.dto;
/**
* 数据传输对象(后端输出对象)
* @param <T>
* Created by hanlu on 2017/5/7.
*/
public class Dto<T>{
private String success; //判断系统是否出错做出相应的true或者false的返回,与业务无关,出现的各种异常
private String errorCode;//该错误码为自定义,一般0表示无错
private String msg;//对应的提示信息
private T data;//具体返回数据内容(pojo、自定义VO、其他)
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package cn.yunfan.itrip.pojo.dto;
import io.swagger.annotations.ApiModelProperty;
/**
* 数据传输对象(输入对象)
*/
public class InputDto {
@ApiModelProperty(value="单一参数传入")
private String paramString;
@ApiModelProperty(value="多个参数传入")
private String[] paramStrings;
public String getParamString() {
return paramString;
}
public void setParamString(String paramString) {
this.paramString = paramString;
}
public String[] getParamStrings() {
return paramStrings;
}
public void setParamStrings(String[] paramStrings) {
this.paramStrings = paramStrings;
}
}
6、EmptyUtils工具
package cn.yunfan.utils;
import java.util.Collection;
import java.util.Map;
/**
* <p>判断是否是空的 工具类</p>
* @author XX
* @version v1.0
* @since 2015/5/5
*/
public class EmptyUtils {
//判空
public static boolean isEmpty(Object obj){
if (obj == null)
return true;
if (obj instanceof CharSequence)
return ((CharSequence) obj).length() == 0;
if (obj instanceof Collection)
return ((Collection) obj).isEmpty();
if (obj instanceof Map)
return ((Map) obj).isEmpty();
if (obj instanceof Object[]) {
Object[] object = (Object[]) obj;
if (object.length == 0) {
return true;
}
boolean empty = true;
for (int i = 0; i < object.length; i++) {
if (!isEmpty(object[i])) {
empty = false;
break;
}
}
return empty;
}
return false;
}
public static boolean isNotEmpty(Object obj){
return !isEmpty(obj);
}
private boolean validPropertyEmpty(Object ...args) {
for (int i = 0; i < args.length; i++) {
if(EmptyUtils.isEmpty(args[i])){
return true;
}
}
return false;
}
}
第四步、编写Controller层
package cn.yunfan.itrip.controller;
import cn.yunfan.itrip.pojo.dto.Dto;
import cn.yunfan.itrip.pojo.ItripUser;
import cn.yunfan.itrip.service.user.UserService;
import cn.yunfan.itrip.pojo.vo.userinfo.ItripUserVO;
import cn.yunfan.utils.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Controller
@RequestMapping("/api")
public class UserController {
@Resource
UserService userService;
//验证是否该注册名存在
@RequestMapping(value = "/ckusr", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public Dto checkUser(@RequestParam String name) {
try {
//判断注册的用户名是否存在 -- 如果返回真则已存在 --否者可以使用
if (userService.findUserByUserCode(name) != null) {
return DtoUtil.returnFail("用户已经存在", ErrorCode.AUTH_USER_ALREADY_EXISTS);
}
} catch (Exception ex) {
ex.printStackTrace();
return DtoUtil.returnFail("服务器正忙,请稍后再试", ErrorCode.AUTH_UNKNOWN);
}
return DtoUtil.returnSuccess("用户名可用");
}
//手机注册
@RequestMapping(value = "registerbyphone",method = RequestMethod.POST)
public @ResponseBody Dto registerByPhone(@RequestBody ItripUser userVo){
if(!ValidPhone.validata(userVo.getUserCode())){
return DtoUtil.returnFail("手机号码格式不正确",ErrorCode.AUTH_ILLEGAL_USERCODE);
}
try{
// 调用发送短信、插入用户数据
userVo.setActivated(0);
userVo.setUserType(0); //自己注册的账号
userVo.setUserPassword(MD5.getMd5(userVo.getUserPassword(),32));
userService.itripexCreateUserByPhone(userVo);
return DtoUtil.returnSuccess("手机注册成功");//返回一个成功的Json对象
}catch (Exception ex){
ex.printStackTrace();
}
return DtoUtil.returnFail("手机注册失败!",ErrorCode.AUTH_UNKNOWN);
}
//激活手机账号
@RequestMapping("/validatephone")
public @ResponseBody Dto activeByPhone(@RequestParam String user ,@RequestParam String code){
if(!ValidPhone.validata(user)){ //验证手机号是否正确
return DtoUtil.returnFail("手机号码格式不正确",ErrorCode.AUTH_ILLEGAL_USERCODE);
}
try {//调用激活
boolean isActived = userService.activateByPhone(user,code);
if(isActived){
return DtoUtil.returnSuccess("激活成功!");
}
}catch (Exception ex){
ex.printStackTrace();
}
return DtoUtil.returnFail("手机激活失败!",ErrorCode.AUTH_ACTIVATE_FAILED);
}
}
第五步、运行代码,测试成功