Fork me on GitHub

SpringBoot(21) 基于阿里大于的短信验证微服务

SpringBoot(21) 基于阿里大于的短信验证微服务

阿里大于其实就是阿里云下提供的一个服务,有开放API及SDK,用起来很方便,至于怎么去注册,开启服务,申请签名,生成短信模板,获取AccessKey,下载SDK和Demo等等操作就不详细介绍了,网上有很多的教程很详细,可以参考这篇博客:

https://blog.csdn.net/qq1031893936/article/details/81173878

其中下载SDK地址: https://help.aliyun.com/document_detail/55359.html?spm=5176.doc55284.2.6.iRVRZy

这里主要是写短信验证功能是怎么实现的。并把它做成一个微服务的这样通用框架,然后通过这个短信上的微服务框架,使得用户服务可以通过rabbitMQ(正好项目中也用到了rabbitMQ)调用短信微服务实现与阿里大于的交换,实现短信的发送和验证。

SDK下载之后解压目录如下,api_demo是官方例程,api_sdk中包含了两个jar包

1

在项目中添加两个jar包(aliyun-java-sdk-core-3.3.1.jar和aliyun-java-sdk-dysmsapi-1.0.0.jar),并在Maven(pom.xml文件)中添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--阿里大于-->
<dependency>
<groupId>aliyun-java-sdk-core</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/aliyun-java-sdk-core-3.3.1.jar</systemPath>
</dependency>

<dependency>
<groupId>aliyun-java-sdk-dysmsapi</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/aliyun-java-sdk-dysmsapi-1.0.0.jar</systemPath>
</dependency>

这样的话其实就已经完成了基础的配置。

然后api_demo下有官方给出的demo具体代码如下,其实就是两个核心函数,sendSms()实现的是发短信的功能,querySendDetails()实现查询发送短信的详细信息.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package com.springboot.SecKill.SMSVerification;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.dysmsapi.transform.v20170525.SendSmsResponseUnmarshaller;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;

import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
* Created on 17/6/7.
* 短信API产品的DEMO程序,工程中包含了一个SmsDemo类,直接通过
* 执行main函数即可体验短信产品API功能(只需要将AK替换成开通了云通信-短信产品功能的AK即可)
* 工程依赖了2个jar包(存放在工程的libs目录下)
* 1:aliyun-java-sdk-core.jar
* 2:aliyun-java-sdk-dysmsapi.jar
*
* 备注:Demo工程编码采用UTF-8
* 国际短信发送请勿参照此DEMO
*/
public class SmsDemo {

//产品名称:云通信短信API产品,开发者无需替换
static final String product = "Dysmsapi";
//产品域名,开发者无需替换
static final String domain = "dysmsapi.aliyuncs.com";

// TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
static final String accessKeyId = "yourAccessKeyId";
static final String accessKeySecret = "yourAccessKeySecret";

public static SendSmsResponse sendSms() throws ClientException {

//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");

//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);

//组装请求对象-具体描述见控制台-文档部分内容
SendSmsRequest request = new SendSmsRequest();
//必填:待发送手机号
request.setPhoneNumbers("15000000000");
//必填:短信签名-可在短信控制台中找到
request.setSignName("云通信");
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode("SMS_1000000");
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
request.setTemplateParam("{\"name\":\"Tom\", \"code\":\"123\"}");

//选填-上行短信扩展码(无特殊需求用户请忽略此字段)
//request.setSmsUpExtendCode("90997");

//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
request.setOutId("yourOutId");

//hint 此处可能会抛出异常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

return sendSmsResponse;
}


public static QuerySendDetailsResponse querySendDetails(String bizId) throws ClientException {

//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");

//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);

//组装请求对象
QuerySendDetailsRequest request = new QuerySendDetailsRequest();
//必填-号码
request.setPhoneNumber("15000000000");
//可选-流水号
request.setBizId(bizId);
//必填-发送日期 支持30天内记录查询,格式yyyyMMdd
SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
request.setSendDate(ft.format(new Date()));
//必填-页大小
request.setPageSize(10L);
//必填-当前页码从1开始计数
request.setCurrentPage(1L);

//hint 此处可能会抛出异常,注意catch
QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);

return querySendDetailsResponse;
}

public static void main(String[] args) throws ClientException, InterruptedException {

//发短信
SendSmsResponse response = sendSms();
System.out.println("短信接口返回的数据----------------");
System.out.println("Code=" + response.getCode());
System.out.println("Message=" + response.getMessage());
System.out.println("RequestId=" + response.getRequestId());
System.out.println("BizId=" + response.getBizId());

Thread.sleep(3000L);

//查明细
if(response.getCode() != null && response.getCode().equals("OK")) {
QuerySendDetailsResponse querySendDetailsResponse = querySendDetails(response.getBizId());
System.out.println("短信明细查询接口返回数据----------------");
System.out.println("Code=" + querySendDetailsResponse.getCode());
System.out.println("Message=" + querySendDetailsResponse.getMessage());
int i = 0;
for(QuerySendDetailsResponse.SmsSendDetailDTO smsSendDetailDTO : querySendDetailsResponse.getSmsSendDetailDTOs())
{
System.out.println("SmsSendDetailDTO["+i+"]:");
System.out.println("Content=" + smsSendDetailDTO.getContent());
System.out.println("ErrCode=" + smsSendDetailDTO.getErrCode());
System.out.println("OutId=" + smsSendDetailDTO.getOutId());
System.out.println("PhoneNum=" + smsSendDetailDTO.getPhoneNum());
System.out.println("ReceiveDate=" + smsSendDetailDTO.getReceiveDate());
System.out.println("SendDate=" + smsSendDetailDTO.getSendDate());
System.out.println("SendStatus=" + smsSendDetailDTO.getSendStatus());
System.out.println("Template=" + smsSendDetailDTO.getTemplateCode());
}
System.out.println("TotalCount=" + querySendDetailsResponse.getTotalCount());
System.out.println("RequestId=" + querySendDetailsResponse.getRequestId());
}

}
}

然后在SpringBoot中具体的使用阿里大于来实现短信验证,注册登录功能.

1. 在application.properties文件中添加配置

1
2
accessKeyId = xxxxx;
accessKeySecret = xxxxx;

2. 短信发送类

其实就是吧官方的demo修改一下,把其中的一些参数改变成为传入参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package com.springboot.SecKill.SMSVerification;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.dysmsapi.transform.v20170525.SendSmsResponseUnmarshaller;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;

import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@Component
public class SMSUtil {

//产品名称:云通信短信API产品,开发者无需替换
static final String product = "Dysmsapi";
//产品域名,开发者无需替换
static final String domain = "dysmsapi.aliyuncs.com";

@Autowired
private Environment environment;

public SendSmsResponse sendSms(String mobile,String template_code,String sign_name,String param) throws ClientException {

//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");

//读取配置文件中的这两个配置变量
String accessKeyId = environment.getProperty("accessKeyId");
String accessKeySecret = environment.getProperty("accessKeySecret");

//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);

//组装请求对象-具体描述见控制台-文档部分内容
SendSmsRequest request = new SendSmsRequest();
//必填:待发送手机号
request.setPhoneNumbers(mobile); //你要发送的手机号
//必填:短信签名-可在短信控制台中找到
request.setSignName(sign_name); //必须是你自己的已经审核通过的签名
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode(template_code); //模板CODE
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
request.setTemplateParam(param);

//选填-上行短信扩展码(无特殊需求用户请忽略此字段)
//request.setSmsUpExtendCode("90997");

//可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
request.setOutId("yourOutId");

//hint 此处可能会抛出异常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

return sendSmsResponse;
}


public QuerySendDetailsResponse querySendDetails(String mobile,String bizId) throws ClientException {

//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");

//读取配置文件中的这两个配置变量
String accessKeyId = environment.getProperty("accessKeyId");
String accessKeySecret = environment.getProperty("accessKeySecret");

//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);

//组装请求对象
QuerySendDetailsRequest request = new QuerySendDetailsRequest();
//必填-号码
request.setPhoneNumber(mobile);
//可选-流水号
request.setBizId(bizId);
//必填-发送日期 支持30天内记录查询,格式yyyyMMdd
SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
request.setSendDate(ft.format(new Date()));
//必填-页大小
request.setPageSize(10L);
//必填-当前页码从1开始计数
request.setCurrentPage(1L);

//hint 此处可能会抛出异常,注意catch
QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);

return querySendDetailsResponse;
}
}

3. rabbitMQ实现短信接收

rabbitMQ中显定义一个队列,并初始化(下面就是简要的把要添加的内容写出来了,项目中使用了不止这一个对列)

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
public class MQConfig {

public static final String SMS_QUEUE = "Sms.QUEUE";

/**
* Direct 交换机模式
*/
//队列
@Bean
public Queue Sms_QUEUE() {
return new Queue(SECKILL_QUEUE,true);
}

然后接收类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.springboot.SecKill.SMSVerification;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.springboot.SecKill.rabbitmq.MQConfig;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
* @author WilsonSong
* @date 2019/1/6/006
*/
@Component
public class SMSListener {

@Autowired
private SMSUtil smsUtil;

@RabbitListener(queues = MQConfig.SMS_QUEUE)
public void sendSms(Map<String,String> map){
try {
SendSmsResponse response = smsUtil.sendSms(map.get("mobile"),
map.get("template_code") ,
map.get("sign_name") ,
map.get("param") );
System.out.println("code:"+response.getCode());
System.out.println("message:"+response.getMessage());


} catch (ClientException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

其实到这里就形成了一个通用的短信发送服务,用户在注册或登录的时候只需要通过RabbitMQ读取MQConfig.SMS_QUEUE对列中的短信即可。

4. 写一个网页测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Controller
public class QueueController {

@Autowired
AmqpTemplate amqpTemplate;


@RequestMapping("/sendmap")
public void sendMap(){
Map map=new HashMap<>();
map.put("mobile", "xxxxxx"); //手机号
map.put("template_code", "SMS_xxxxxxx"); //短信模板,模板CODE
map.put("sign_name","xxxxxx"); //申请的短信签名
map.put("param", "{\"name\":\"xxxx\"}"); //你自己定义的短线模板的格式和参数

amqpTemplate.convertAndSend(MQConfig.Sms_QUEUE, map);
}
}

到这里其实就完成了,接下来就是把这个整合到登陆注册页面上去,实现短信的发送,验证功能,其实具体的流程是很简单的,就是生成-RabbitMQ-后端检验,具体的就有些繁琐,就不具体详细写了,完整的代码可以去我的github上下载,右侧有链接。

本文标题:SpringBoot(21) 基于阿里大于的短信验证微服务

文章作者:WilsonSong

发布时间:2019年01月06日 - 20:01

最后更新:2019年01月12日 - 18:01

原始链接:https://songwell1024.github.io/2019/01/06/CheckSmsCode/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------本文结束感谢您的阅读-------------