Java 使用阿里云短信发送短信验证码,重置密码功能实现

avatar 2019年12月14日19:46:10 0 1034 views
前两天帮一个老朋友写了一个通过短信重置密码的功能。 本文主要介绍一下阿里云短信的使用,其实挺简单的,这里记录一下分享给需要的朋友。 大致的步骤如下
  1. 开通阿里云短信功能
  2. 创建密钥和
  3. 创建短信签名
  4. 创建短信模板
  5. 购买短信包,5000条/250元
  6. 根据官网提供 demo 和文档进行开发
先介绍一下阿里云短信平台相关操作

一、开通阿里云短信平台

1.进入官网

官网地址:https://dysms.console.aliyun.com/dysms.htm 直接点击开通即可  

2.查看新手指导

 

3.创建国内短信签名

签名就是短信中【】里的内容,短信中会自动加在最前面,一般是公司简称。  

4.创建短信模板

短信模板就是短信的具体内容,因为我们这个是验证码短信,就是我们需要把自己通过 java 代码生成的数字放到模板内容里,所以这个地方需要加一个变量,如 ${code}。 最终可以获得短信模板

5.开通短信包

 

6.安全设置

可以对每小时发送总来限制,也可以对某一个手机号设置发送频率 这对防盗刷很必要  

7.创建阿里云密钥

阿里云密钥是在阿里云平台里是通用的,如果没有创建可以在该页面创建。 页面地址:https://usercenter.console.aliyun.com/ 创建完后获得 AccessKey ID 和 Access Key Secret 这个需要妥善保管  

二、官方文档说明

用SendSms发送短信。

SendSms接口是短信发送接口,支持在一次请求中向多个不同的手机号码发送同样内容的短信。

如果您需要在一次请求中分别向多个不同的手机号码发送不同签名和模版内容的短信,请使用SendBatchSms接口。

调用该接口发送短信时,请注意:

  • 发送短信会根据发送量计费,价格请参考计费说明
  • 在一次请求中,最多可以向1000个手机号码发送同样内容的短信。

请求参数

 
名称 类型 是否必选 示例值 描述
PhoneNumbers String 15900000000

接收短信的手机号码。

格式:

  • 国内短信:11位手机号码,例如15951955195。
  • 国际/港澳台消息:国际区号+号码,例如85200000000。

支持对多个手机号码发送短信,手机号码之间以英文逗号(,)分隔。上限为1000个手机号码。批量调用相对于单条调用及时性稍有延迟。

说明 验证码类型短信,建议使用单独发送的方式。
SignName String 阿里云

短信签名名称。请在控制台签名管理页面签名名称一列查看。

说明 必须是已添加、并通过审核的短信签名。
TemplateCode String SMS_153055065

短信模板ID。请在控制台模板管理页面模板CODE一列查看。

说明 必须是已添加、并通过审核的短信签名;且发送国际/港澳台消息时,请使用国际/港澳台短信模版。
AccessKeyId String LTAIP00vvvvvvvvv

主账号AccessKey的ID。

Action String SendSms

系统规定参数。取值:SendSms

OutId String abcdefgh

外部流水扩展字段。

SmsUpExtendCode String 90999

上行短信扩展码,无特殊需要此字段的用户请忽略此字段。

TemplateParam String {"code":"1111"}

短信模板变量对应的实际值,JSON格式。

说明 如果JSON中需要带换行符,请参照标准的JSON协议处理。

返回数据

 
名称 类型 示例值 描述
BizId String 900619746936498440^0

发送回执ID,可根据该ID在接口QuerySendDetails中查询具体的发送状态。

Code String OK

请求状态码。

Message String OK

状态码的描述。

RequestId String F655A8D5-B967-440B-8683-DAD6FF8DE990

请求ID。

示例

请求示例


http(s)://[Endpoint]/?PhoneNumbers=15900000000
&SignName=阿里云
&TemplateCode=SMS_153055065
&<公共请求参数>

正常返回示例

XML 格式

<SendSmsResponse>
      <Message>OK</Message>
      <RequestId>44DF7A95-603F-4651-9298-BE1850BEB53F</RequestId>
      <BizId>336006646937050335^0</BizId>
      <Code>OK</Code>
</SendSmsResponse>

JSON 格式

{
	"Message":"OK",
	"RequestId":"2184201F-BFB3-446B-B1F2-C746B7BF0657",
	"BizId":"197703245997295588^0",
	"Code":"OK"
}

错误码

访问错误中心查看更多错误码。

 

二、代码示例

官方示例:点此

1.添加依赖

  1. <dependency>
  2.     <groupId>com.aliyun</groupId>
  3.     <artifactId>aliyun-java-sdk-core</artifactId>
  4.     <version>4.0.3</version>
  5. </dependency>
 

2.示例

  1. package org.chwin.firefighting.apiserver.sysmanage.controller;
  2. import com.alibaba.fastjson.JSON;
  3. import com.aliyuncs.CommonRequest;
  4. import com.aliyuncs.CommonResponse;
  5. import com.aliyuncs.DefaultAcsClient;
  6. import com.aliyuncs.IAcsClient;
  7. import com.aliyuncs.exceptions.ClientException;
  8. import com.aliyuncs.exceptions.ServerException;
  9. import com.aliyuncs.http.MethodType;
  10. import com.aliyuncs.profile.DefaultProfile;
  11. import org.chwin.firefighting.apiserver.device.util.RedisUtil;
  12. import org.chwin.firefighting.apiserver.sysmanage.entity.SysUser;
  13. import org.chwin.firefighting.apiserver.sysmanage.mapper.SysUserMapper;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.web.bind.annotation.PostMapping;
  16. import org.springframework.web.bind.annotation.RestController;
  17. import java.util.HashMap;
  18. import java.util.Map;
  19. import java.util.Objects;
  20. /**
  21.  * 发送短信示例
  22.  *
  23.  * @author 言曌
  24.  * @date 2019-12-14 19:10
  25.  */
  26. @RestController
  27. public class DemoController {
  28.     @Autowired
  29.     private SysUserMapper sysUserMapper;
  30.     @Autowired
  31.     private RedisUtil redisUtil;
  32.     @PostMapping(value = "/sendForgetSms")
  33.     public Map<String, Object> sendForgetSms(String account, String phone) {
  34.         Map<String, Object> resultMap = new HashMap<>();
  35.         // 1.校验账号和手机号是否匹配
  36.         // 业务逻辑示例,不需要可以去掉
  37.         SysUser sysUser = sysUserMapper.findByAccount(account);
  38.         if (sysUser == null || !Objects.equals(phone, sysUser.getPhone())) {
  39.             resultMap.put("code"500);
  40.             resultMap.put("msg""账号和手机号不匹配");
  41.             return resultMap;
  42.         }
  43.         // 2.发送短信
  44.         // 相关配置可以放在 application.properties 里,这里为了简单直接写在代码里
  45.         // 注意
  46.         DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou",
  47.                 "<AccessKey ID>",
  48.                 "<Access Key Secret>");
  49.         IAcsClient client = new DefaultAcsClient(profile);
  50.         // 只需要修改签名和模板名称
  51.         CommonRequest request = new CommonRequest();
  52.         request.setMethod(MethodType.POST);
  53.         request.setDomain("dysmsapi.aliyuncs.com");
  54.         request.setVersion("2017-05-25");
  55.         request.setAction("SendSms");
  56.         request.putQueryParameter("RegionId""cn-hangzhou");
  57.         request.putQueryParameter("PhoneNumbers", phone);
  58.         request.putQueryParameter("SignName""<签名名称>"); // 签名名称
  59.         request.putQueryParameter("TemplateCode""<模板编码>"); //模板编码
  60.         // 随机六位验证码
  61.         Integer code = (int) ((Math.random() * 9 + 1) * 100000);
  62.         String jsonParam = "{\"number\": " + code + "}";
  63.         request.putQueryParameter("TemplateParam", jsonParam); // 需要传json格式,参数为模板编码 ${code} 的code
  64.         try {
  65.             // 将验证码存储到 redis, 5分钟过期
  66.             redisUtil.set("sms::user::forget::" + phone, code, 60 * 5L);
  67.             // 发送短信
  68.             CommonResponse response = client.getCommonResponse(request);
  69.             SmsResponseData smsResponseData = JSON.parseObject(response.getData(), SmsResponseData.class);
  70.             // 发送成功
  71.             if("OK".equals(smsResponseData.getCode())) {
  72.                 resultMap.put("code"200);
  73.                 resultMap.put("msg""发送成功");
  74.             } else if ("isv.BUSINESS_LIMIT_CONTROL".equals(smsResponseData.getCode())) {
  75.                 resultMap.put("code"500);
  76.                 resultMap.put("msg""短信发送频率超限");
  77.             }
  78.             // else if
  79.             // 更多错误码参考
  80.             // https://help.aliyun.com/document_detail/101346.html?spm=a2c1g.8271268.10000.122.772fdf25rYnhIc
  81.         } catch (ServerException e) {
  82.             e.printStackTrace();
  83.             resultMap.put("code"500);
  84.             resultMap.put("msg""发送失败");
  85.         } catch (ClientException e) {
  86.             e.printStackTrace();
  87.             resultMap.put("code"500);
  88.             resultMap.put("msg""发送失败");
  89.         }
  90.         return resultMap;
  91.     }
  92.     /**
  93.      * 阿里短信响应封装类
  94.      */
  95.     private static class SmsResponseData {
  96.         private String Message;
  97.         private String RequestId;
  98.         private String BizId;
  99.         private String Code;
  100.         public String getMessage() {
  101.             return Message;
  102.         }
  103.         public void setMessage(String message) {
  104.             Message = message;
  105.         }
  106.         public String getRequestId() {
  107.             return RequestId;
  108.         }
  109.         public void setRequestId(String requestId) {
  110.             RequestId = requestId;
  111.         }
  112.         public String getBizId() {
  113.             return BizId;
  114.         }
  115.         public void setBizId(String bizId) {
  116.             BizId = bizId;
  117.         }
  118.         public String getCode() {
  119.             return Code;
  120.         }
  121.         public void setCode(String code) {
  122.             Code = code;
  123.         }
  124.     }
  125. }
  顺便贴一下重置密码的代码
  1. /**
  2.  * 重置密码,验证短信并修改密码
  3.  * @param account
  4.  * @param phone
  5.  * @param code
  6.  * @param password
  7.  * @param confirmPassword
  8.  * @return
  9.  */
  10. @PostMapping(value = "/checkForgetSms")
  11. public Map<String, Object> checkForgetSms(
  12.         String account,
  13.         String phone,
  14.         String code,
  15.         String password,
  16.         String confirmPassword) {
  17.     Map<String, Object> resultMap = new HashMap<>();
  18.     // 1.校验两次密码是否一致
  19.     if (!Objects.equals(password, confirmPassword)) {
  20.         resultMap.put("code"500);
  21.         resultMap.put("msg""密码和确认密码不一致");
  22.         return resultMap;
  23.     }
  24.     // 2.校验账号和手机号是否匹配
  25.     SysUser sysUser = sysUserMapper.findByAccount(account);
  26.     if (sysUser == null || !Objects.equals(phone, sysUser.getPhone())) {
  27.         resultMap.put("code"500);
  28.         resultMap.put("msg""账号和手机号不匹配");
  29.         return resultMap;
  30.     }
  31.     // 3.校验验证码是否正确
  32.     String checkCode = String.valueOf(redisUtil.get("sms::user::forget::" + phone));
  33.     if (StringUtils.isEmpty(checkCode) || !Objects.equals(checkCode, code)) {
  34.         // 验证码错误
  35.         resultMap.put("code"500);
  36.         resultMap.put("msg""验证码错误");
  37.         return resultMap;
  38.     }
  39.     // 验证码正确,修改密码,md5加密一次
  40.     sysUser.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));
  41.     sysUserMapper.updateByPrimaryKeySelective(sysUser);
  42.     resultMap.put("code"200);
  43.     resultMap.put("msg""重置成功");
  44.     return resultMap;
  45. }
 
  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
avatar

发表评论

avatar 登录者:匿名
您需要登录才能评论,可以选择注册或者QQ快速登录

     

已通过评论:0   待审核评论数:0