接入腾讯云短信服务 实现手机验证注册


上回说到 ,完成了security的接入和登录功能,但是在准备登录尝试security的强大时发现,还没有完成注册功能,根本没有账号提供登录,那么这回,就实现手机号注册功能。

手机号注册逻辑很简单,说白了就是证明手机号是你自己的就行了,具体流程就是,用户请求服务,服务生成验证码,通过短信形式发送到指定手机号上,然后请求注册接口,携带注册信息、手机号和手机收到的验证码,服务收到注册请求,校验验证码是不是之前自己发出的,校验通过后保存注册用户信息即完成注册。逻辑流程都很简单,这里主要是记录一下,对接云短信服务的过程。

云短信服务商

既然要发短信,那肯定是直接接入云短信服务,支持短信服务的云服务商一抓一大把,价格基本合理,但是基本上所有短信服务商为了防止不良用途,都需要校验我们的营业执照之类的资料,总之想接入还是蛮麻烦,然而我这里以学习为目的,搞这些资料不容易,所以这里选择了腾讯云的短信服务,首先腾讯的地位和名头毋庸置疑,其次也是最重要的一点,腾讯云可以通过公众号来申请短信服务,而公众号的开通就很方便了。

这里短信服务的开通就不介绍了,反正按照平台提示一步步来就行了,基本所有平台都一样。

创建短信发送服务

考虑到可能还有别的业务需要用到短信服务,所以稍微对短信服务封装一下

在项目路径下创建一个包起名叫send,叫send是打算将发送邮件相关的服务也放在这个包,所以不适合叫sms,就干脆叫send好了,逻辑没啥好说的,下面直接上代码好了。

创建SendController,用于对外提供发送短信或邮件的接口,目前只需要一个接口


/*** @author: ZhangZhao* @date: 2022/2/10 11:59* @description: 对外提供发送短信或邮件服务*/
@RestController
@RequiredArgsConstructor
@RequestMapping(SysApi.SEND)
public class SendController {private final SmsSendService smsSendService;/*** 发送短信验证码* @param req 手机号和短信类型* @return 发送结果*/@PostMapping("/verificationCode")public Result<Void> sendVerificationCode(@Valid @RequestBody SendVerificationCodeReq req){SmsTypeEnum smsType = SmsTypeEnum.getEnumByCode(req.getTypeCode());smsSendService.sendVerificationCode(smsType.getSmsTemplateId(),req.getPhoneNum());return Result.success();}}

SendVerificationCodeReq类


/*** @author: ZhangZhao* @date: 2022/2/10 14:45* @description: 发送验证码接口入参*/
@Setter
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SendVerificationCodeReq {/*** 这个字段对应`SmsTypeEnum`枚举类中的标识码*/@NotNull(message = "验证码类型必须填写!")private Integer typeCode;@NotNull(message = "手机号不能为空!")@Pattern(regexp = Constants.Regexp.PHONE_NUM,message = "请填写正确的手机号!")private String phoneNum;}

这个接口专门用于发送验证码短信,通过SmsTypeEnum来标识不同的业务验证码和对应的短信模板


/*** @author: ZhangZhao* @date: 2022/2/10 14:55* @description: 短信类型枚举:用于描述短信用途和对应短信模板*/
@Getter
@AllArgsConstructor
public enum  SmsTypeEnum {/*** 注册验证码*/SMS_PIN_REGISTER(10001,"1299215","注册验证码"),/*** 登录验证码 TODO 登录短信模版还未创建*/SMS_PIN_LOGIN(10002,"","登录验证码"),;/*** 标识码*/private final Integer code;/*** 短信模板ID*/private final String smsTemplateId;/*** 描述*/private final String message;private static final Set<SmsTypeEnum> ALL = EnumSet.allOf(SmsTypeEnum.class);public static SmsTypeEnum getEnumByCode(Integer code) {if(code==null){return null;}return ALL.stream().filter(o->o.code.equals(code)).findAny().orElseThrow(()->new BusinessException("错误编码枚举类: "+code+ "未匹配到相关值!"));}public boolean is(Integer code){return getCode().equals(code);}
}

创建SmsSendService 专门用于发送短信的服务,后续涉及到短信相关的业务,也在这里,目前只有一个方法,发送短信验证码

短信验证码发送后,采用redis存储,具体发送短信的代码参照的腾讯云文档 [https://cloud.tencent.com/document/product/382/43194]:

    /*** 发送短信验证码* @param smsTemplateId 短信模板ID* @param phoneNum      手机号*/@Overridepublic void sendVerificationCode(String smsTemplateId, String phoneNum) {//生成验证码String vCode = RandomUtil.randomNumbers(Constants.PIN_LENGTH);log.debug("{} generate vCode {}",phoneNum,vCode);//组装发送信息 发送验证码SendSmsInfoDto sendSmsInfo = SendSmsInfoDto.builder().templateId(smsTemplateId).phoneNumList(Collections.singletonList(phoneNum))//这里设置 短信模板参数 按模板中对应的{1},{2}顺序添加.contextParamArray(new String[]{vCode, String.valueOf(CacheConstants.CacheExpire.PHONE_PIN_EXPIRE)}).build();this.sendSms(sendSmsInfo);//存入redis 5分钟过期// 存入key为 `PIN_CODE_`+ 传入手机号redisService.setCacheObject(CacheConstants.CacheKey.PHONE_PIN_KEY_PREFIX+phoneNum,vCode,CacheConstants.CacheExpire.PHONE_PIN_EXPIRE, TimeUnit.MINUTES);}
 /*** 发送短信 * @param sendSmsInfo 发送信息*/private void sendSms(SendSmsInfoDto sendSmsInfo){//校验参数String templateId = sendSmsInfo.getTemplateId();AssertUtil.isMeets(templateId, StrUtil::isNotBlank,"短信模板不能为空!");List<String> phoneNumList = sendSmsInfo.getPhoneNumList();AssertUtil.isMeets(phoneNumList, CollectionUtil::isNotEmpty,"下发手机号不能为空!");//处理手机号 需要 采用 E.164 标准,+[国家或地区码][手机号] 这里处理手机号的方法不赘述String[] standardPhoneNumList = phoneNumList.stream().filter(StrUtil::isNotBlank).map(this::formatPhoneNum).toArray(String[]::new);try {//实例化一个认证对象Credential cred = new Credential(smsConfig.getSecretId(), smsConfig.getSecretKey());// * 实例化要请求产品(以sms为例)的client对象SmsClient client = new SmsClient(cred, smsConfig.getSmsServiceRegion());//* 实例化一个请求对象,根据调用的接口和实际情况,可以进一步设置请求参数SendSmsRequest req = new SendSmsRequest();req.setSmsSdkAppId(smsConfig.getSdkAppId());req.setSignName(smsConfig.getSignName());//* 国际/港澳台短信 SenderId: 国内短信填空,默认未开通,req.setSenderId(Constants.Str.EMPTY);//* 用户的 session 内容: 可以携带用户侧 ID 等上下文信息,server 会原样返回req.setSessionContext(sendSmsInfo.getExtendInfo());//* 短信号码扩展号: 默认未开通,如需开通请联系 [sms helper]req.setExtendCode(Constants.Str.EMPTY);req.setTemplateId(templateId);//* 下发手机号码,最多不要超过200个手机号req.setPhoneNumberSet(standardPhoneNumList);//* 模板参数: 若无模板参数,则设置为空req.setTemplateParamSet(sendSmsInfo.getContextParamArray());//* 通过 client 对象调用 SendSms 方法发起请求。SendSmsResponse res = client.SendSms(req);// 输出json格式的字符串回包log.debug("Sms send Info :{}",SendSmsResponse.toJsonString(res));} catch (TencentCloudSDKException e) {log.error("Sms send fail! param:{},Exception:{}",sendSmsInfo.toString() ,e.getMessage());throw new BusinessException("短信发送异常,请稍后再试!");}}

现在调用/verificationCode 接口即可发送短信

添加注册接口

回到我们的user模块下,在UserController中添加注册接口

/*** 用户注册* @param req 注册信息* @return 注册状态*/@PostMapping("/register")public Result<Void> register(@Valid @RequestBody RegisterReq req){userService.register(req);return  Result.success();}

RegisterReq类


/*** @author: Li Zhongyang* @date: 2021/12/29 13:08* @description: 注册接口 入参*/
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class RegisterReq {/*** 用户名*/@NotNull(message = "用户名必须填写!")@Length(min = 6,max = 14,message = "用户名长度须为6-14字符!")private String nickName;/*** 手机号码*/@NotNull(message = "手机号不能为空!")@Pattern(regexp = Constants.Regexp.PHONE_NUM,message = "请填写正确的手机号!")private String phoneNum;/*** 密码*/@NotNull(message = "手机号不能为空!")private String password;/*** 验证码*/@NotNull(message = "验证码不能为空!")private String verificationCode;}

在service中实现注册方法

/***  注册* <p>* 手机号注册* @param req 注册信息*/@Override@Transactional(rollbackFor = Exception.class)public void register(RegisterReq req) {//校验验证码是否正确String phoneNum = req.getPhoneNum();//根据手机号从redis中取之前发送的验证码,跟传入的验证码对比String phonePin = redisService.getCacheObject(CacheConstants.CacheKey.PHONE_PIN_KEY_PREFIX+phoneNum);AssertUtil.isMeets(req.getVerificationCode(),s-> StrUtil.equals(s,phonePin),"验证码错误");String encodePassword = SecureUtil.md5(req.getPassword());String nickName = req.getNickName();//判断当前手机号是否已经注册 用户名是否已经存在UserAuthsInfo getAuthsInfoByPhone = userAuthsInfoMapper.getUserAuthsInfo(phoneNum);AssertUtil.isNull(getAuthsInfoByPhone,"当前手机号已绑定账号,请前往登录!");UserAuthsInfo getAuthsInfoByUsername = userAuthsInfoMapper.getUserAuthsInfo(nickName);AssertUtil.isNull(getAuthsInfoByUsername,"当前用户名已被占用!");//用户信息入库//添加用户基本信息UserBaseInfo userBaseInfo = UserBaseInfo.builder()//Constants.DEFAULT_AVATAR_URL 这个常量为默认头像URL.avatarUrl(Constants.DEFAULT_AVATAR_URL[0]).nickName(req.getNickName()).build();userBaseInfoMapper.saveUserBaseInfo(userBaseInfo);//添加授权信息 手机号注册默认支持 手机号登录 和 用户名登录List<UserAuthsInfo> userAuthsInfoList=new ArrayList<>();UserAuthsInfo userAuthsInfoByPhone = UserAuthsInfo.builder().userId(userBaseInfo.getId())//手机号登录 账号为手机号.identityType(IdentityTypeEnum.PHONE.getCode()).identifier(phoneNum).credential(encodePassword).encryptType(EncryptTypeEnum.MD5.getCode()).build();userAuthsInfoList.add(userAuthsInfoByPhone);UserAuthsInfo userAuthsInfoByUsername = UserAuthsInfo.builder().userId(userBaseInfo.getId())//用户名登录 账号为用户名.identityType(IdentityTypeEnum.USERNAME.getCode()).identifier(nickName).credential(encodePassword).encryptType(EncryptTypeEnum.MD5.getCode()).build();userAuthsInfoList.add(userAuthsInfoByUsername);userAuthsInfoMapper.batchSaveUserAuthInfo(userAuthsInfoList);//设置默认详细信息UserDetailInfo userDetailInfo = UserDetailInfo.builder().userId(userBaseInfo.getId()).nickName(nickName).phoneNum(phoneNum).build();userDetailInfoMapper.saveUserDetailInfo(userDetailInfo);}

总结

现在第三方服务商提供的服务都很智能,基本都有完整的接入文档,按照文档基本不会有问题。对于短信服务来说,所有的云服务商都大同小异。

FLY攻略之第二回: 接入腾讯云短信服务 实现手机验证注册相关推荐

  1. Springboot+Redis接入腾讯云短信服务实现验证码发送

    目录 一.开通腾讯云短信服务 二.代码实现 三.测试 申请阿里云短信服务需要以上线APP或已备案网站,腾讯云短信服务可以使用微信公众号申请,注册个人微信公众号比较方便,改用腾讯云短信服务,参考官方SD ...

  2. 接入腾讯云短信服务(史上最详细+该短信服务如何申请成功+发送短信验证码API讲解+相关错误分析)

    2021/8/17/23:01{2021/8/17/23:01}2021/8/17/23:01 文章目录 前言 一.如何成功申请到腾讯云短信服务 1.签名申请 2.正文模板申请 二.发送短信API开发 ...

  3. SpringBoot工程接入腾讯云短信服务平台

    由于业务需要,需要使用第三方短信平台,进行验证码的发送.网上的短信服务平台主要由:百度.腾讯.阿里云:采用官方提供的SDK,调用接口即可. 腾讯云短信服务平台和阿里云短信服务平台,一般步骤为:注册-- ...

  4. 项目接入腾讯云短信服务SMS实现向用户发送手机验证码

    1.自述 早在18年的时候,我就在项目中使用过阿里云的短信服务,现在我上阿里云短信控制台看,还能看到当时创建的短信签名,如下图所示. 出于某种原因,我现在想重新申请一个新的签名,却审批失败了,原因是: ...

  5. 接入腾讯云短信(免费+个人开发者)

    接入腾讯云短信 前言 以下全是自己个人自己实验 肯定一点肯定免费试用100条短信 肯定两点不需要什么营业执照啥的,只需要自己免费申请公众号即可 1.注册微信公众号 https://mp.weixin. ...

  6. springboot 最新腾讯云短信接入的坑(包含所有操作流程)

    腾讯云接入短信,需要填写备案好的域名,且通过域名能正常访问到你的网站.如果你的服务器,域名全部都在腾讯云,请确保你的服务器可达,且域名已完成备案,域名的某个A记录正常(通常是www),通过这个记录值可 ...

  7. 阿里云短信服务接入流程

    背景 在最近的项目需求中, 需要将复用阿里短信能力, 实现用户手机号验证: 如果用户号码验证通过后, 可以让用户上传文件资料并进行打印. 故核心内容就是: 阿里云短信服务接入, 下面我们主要来介绍下阿 ...

  8. python 阿里云短信服务接入流程

    阿里云短信服务接入流程 最近公司项目中的业务需求包括使用阿里云发送短信,所以写一篇博客和大家分享一下python使用sdk对接阿里云短息api的流程. 阿里云官方文档 链接 左侧导航栏中有很多部分,着 ...

  9. ThinkPHP5.1接入阿里云短信服务(原大鱼最新版)指导

    ♘背景 随着科技发展的推动,曾经充满温馨问候与回忆的短信业务,如今绝大多数局限于 验证码发送.诈骗/骚扰信息.业务推送 的使用 而作为一名IT搬砖的码农,对于第三方服务的接入也是必须掌握的技能,此处介 ...

最新文章

  1. Swift可选绑定、断言
  2. 建模大师怎么安装到revit中_全面解析Revit软件在装配式建筑项目中的建模思路...
  3. 2021,我在枯燥乏味中寻找坚持下去的理由
  4. MATLAB教程(1) MATLAB 基础知识(2)
  5. 微软自带报ocienvcreate失败_微软推出的免费神器,治好了我的拖延症!
  6. CodeForces Contest #1114: Round #538 (Div. 2)
  7. C语言字符型char和整型int的关系和示例
  8. sql 的 where 和 having 的区别和用法
  9. 计算机代数与数论pdf,基础数论算法 - maTHμ - 计算机代数系统.pdf
  10. 解决Ureport2报表工具设置条件属性报错Bug
  11. python股票量化如何选股?
  12. 键盘无响应-如何修复键盘注册表
  13. 文献管理软件Zotero常用插件安装及配置使用
  14. 通信工程是计算机类还是电子信息类公考,通信工程属于电子信息类吗
  15. 建立简单的VR项目,并且将所需要的资产迁移到新建的VR项目中。
  16. 2005-04-28 把爸爸锁在阳台上
  17. php关键词回复源码,PHP对接公众号搜索自动回复源码
  18. Java学习第一周(2.20~2.24)
  19. 【原】拯救你的机械硬盘!
  20. maya腿的蒙皮旋转枢轴_完美动力小课堂:怎么快速修改物体枢轴?这个方法值得收藏!...

热门文章

  1. Java ArrayList 实现去重
  2. 常用的数据可视化工具有哪些?
  3. 积分商城运营中,签到任务以及兑换任务的制定要点
  4. 发射、加速与着陆:一群科学家的奥林帕斯探索之旅
  5. pdfjs 参数_pdf.js实战,含水印、电子签章解决方案
  6. 用PYTHON脚本拆分M3U文件
  7. 3月16日 CV,CA,CTRV等运动模型,EKF,UKF在运动模型下的分析与实践
  8. NLP自然语言处理学习笔记(十二)(转自咕泡AI)
  9. 制作系统启动盘和制作windows+Ubuntu双系统启动盘
  10. 《誓言今生》收视夺冠 白庆琳上演“苦尽甘来”