SpringBoot 实现手机短信验证码

下面是我具体实现的

<!-- 阿里云OSS -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>2.8.3</version>
        </dependency>

 

/**
 * Created by mhSui on 2019/12/05.
 *
 * @author mhSui
 */
@Slf4j
@Configuration
public class SmsUtil {

	@Value("${aliyun.accessKeyId}")
	private String accessKeyId;

	@Value("${aliyun.secret}")
	private String secret;

	@Value("${aliyun.signName}")
	private String signName;

	@Value("${aliyun.templateCode}")
	private String templateCode;

	@Value("${aliyun.paramName}")
	private String paramName;

	@Autowired
	private RedisClient redisClient;

	/**
	 * 发送短信.
	 * @param mobile 手机号
	 * @return String
	 */
	@SuppressWarnings("deprecated")
	public String sendSms(String mobile) {
		// 检验手机号码
		boolean isPhone = isPhone(mobile);
		if (!isPhone) {
			return ProcessEnum.PHONE_FORMAT_ERROR;
		}
		// 校验是否重复发送
		String code = this.redisClient.get(mobile);
		if (code != null) {
			return ProcessEnum.SMS_FREQUENTLY;
		}

		String kaptcha = this.getKaptcha();
		Map<String, String> map = new HashMap<>(1);
		map.put(this.paramName, kaptcha);
		String templateParam = JSON.toJSONString(map);

		DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou",
				this.accessKeyId, this.secret);
		IAcsClient client = new DefaultAcsClient(profile);

		CommonRequest request = new CommonRequest();
		request.setMethod(MethodType.POST);
		request.setDomain("dysmsapi.aliyuncs.com");
		request.setVersion("2017-05-25");
		request.setAction("SendSms");
		request.putQueryParameter("RegionId", "cn-hangzhou");
		request.putQueryParameter("PhoneNumbers", mobile);
		request.putQueryParameter("SignName", this.signName);
		request.putQueryParameter("TemplateCode", this.templateCode);
		request.putQueryParameter("TemplateParam", templateParam);

		try {
			CommonResponse response = client.getCommonResponse(request);
			String responseMessage = JSONObject.parseObject(response.getData())
					.getString("Message");

			if (!"ok".equals(responseMessage)) {
				// 短信发送成功,将验证码存储到redis,并设置过期时间为5分钟
				this.redisClient.set(mobile, kaptcha);
				this.redisClient.expire(mobile, 15 * 60);
				return ProcessEnum.SUCCESS;
			}

		}
		catch (ClientException e) {
			// 短信发送失败
			return ProcessEnum.SMS_FAILED;
		}
		// 短信发送失败
		return ProcessEnum.SMS_FAILED;

	}

	/**
	 * 中国电信号段 133、149、153、173、177、180、181、189、199. 中国联通号段
	 * 130、131、132、145、155、156、166、175、176、185、186. 中国移动号段
	 * 134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188、198.
	 * 其他号段. 14号段以前为上网卡专属号段,如中国联通的是145,中国移动的是147等等. 虚拟运营商. 电信:1700、1701、1702.
	 * 移动:1703、1705、1706. 联通:1704、1707、1708、1709、171. 卫星通信:1349.
	 * @param phone phone
	 * @return boolean
	 */
	public static boolean isPhone(String phone) {
		String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";
		if (phone.length() != 11) {
			log.info("手机号应为11位数");
			return false;
		}
		else {
			Pattern p = Pattern.compile(regex);
			Matcher m = p.matcher(phone);
			boolean isMatch = m.matches();
			if (!isMatch) {
				log.info("手机号格式不正确");
			}
			return isMatch;
		}
	}

	/**
	 * 校验短信验证码.
	 * @param mobile mobile
	 * @param kaptcha kaptcha
	 * @return 校验结果
	 */
	public Boolean checkKaptcha(String mobile, String kaptcha) {
		String s = this.redisClient.get(mobile);
		return s != null && s.equals(kaptcha);
	}

	/**
	 * 生成短信验证码并存储.
	 * @return kaptcha
	 */
	private String getKaptcha() {
		StringBuilder str = new StringBuilder();
		Random random = new Random();

		for (int i = 0; i < 4; i++) {
			// 生成一个[0,10)
			int randomInt = random.nextInt(10);
			str.append(randomInt);
		}
		return str.toString();
	}

}

  

posted @ 2020-01-13 14:59  SurpriseSui  阅读(2491)  评论(0编辑  收藏  举报