# 功能描述

实现发送短信操作。
配置文件为application-sms.yml

提示

(1) 需在application.yml中增加spring.profiles.active中增加sms才能激活配置文件
(2) 需设置application-sms.yml中的sei.cloud.sms.enabled为true才能开启短信服务

# 配置一览表

#######  sms 发送短信配置 ########
sei:
    cloud:
        sms:
            enabled: true #是否开启短信服务
            master: "cm" #缺省的短信服务商
            service: #短信服务商
                yunpian: #云片短信服务商
                    enabled: false #是否开启云片短信服务
                    master: #缺省系统的配置,必须配置
                        master: #缺省系统的缺省操作,必须配置
                            config: # 运营商配置项,必须配置
                                apiKey:
                            template: "您的验证码是{},在5分钟内有效。"  #缺省短信模板,必须配置
                            log: 0 # 0:所有都记录,不管成功还是失败,1:只记录发送成功的
                            #              ip: #ip限额,在指定时间内可发送的次数
                            #                time: 300 #时间周期(秒)
                            #                count: 1 #时间周期内可发送的次数
                            mobile: #手机号码限额,在指定时间内可发送的次数
                                time: 60 #时间周期(秒)
                                count: 1 #时间周期内可发送的次数
                                keepTime: 300 #每个短信内容保存有效时长(秒)
                cm: # 移动短信服务商
                    enabled: true #是否开启移动短信服务
                    master: #缺省系统的配置,必须配置
                        master: #缺省系统的缺省操作,必须配置
                            config: # 运营商配置项,必须配置
                                url: "http://112.35.1.155:1992/sms/norsubmit" # 网关
                                ecName: "重庆邮电大学"
                                apId: ""
                                secretKey: ""
                                sign: ""
                                addSerial: "1"
                            template: "您的验证码是{},在5分钟内有效。"  #缺省短信模板,必须配置
                            log: 0 # 0:所有都记录,不管成功还是失败,1:只记录发送成功的
                            #              ip: #ip限额,在指定时间内可发送的次数
                            #                time: 300 #、时间周期(秒)
                            #                count: 5 #时间周期内可发送的次数
                            mobile: #手机号码限额,在指定时间内可发送的次数
                                time: 60 #时间周期(秒)
                                count: 1 #时间周期内可发送的次数
                                keepTime: 300 #每个短信内容保存有效时长(秒)
                    jmjf: #居民积分系统,配置样式如同master,如果不配置则采用master配置
                        master: #居民积分系统的缺省操作配置,覆盖上级master默认的缺省配置
                            config: # 居民积分系统短信配置,覆盖缺省配置
                            template: #缺省短信模板,覆盖缺省模板
                            log: 0 # 0:所有都记录,不管成功还是失败,1:只记录发送成功的
                            #              ip: #ip限额,在指定时间内可发送的次数
                            #               、 time: 300 #时间周期(秒)
                            #                count: 1 #时间周期内可发送的次数
                            mobile: #手机号码限制
                                time: 60 #时间周期(秒)
                                count: 1 #时间周期内可发送的次数
                                keepTime: 300 #每个短信内容保存有效时长(秒)
                        login: #居民积分系统的登录action配置
                            config: # 居民积分系统短信配置,覆盖缺省配置
                            template: "您的验证码是{},在5分钟内有效。"  #缺省短信模板,覆盖上级模板
                            log: 0 # 0:所有都记录,不管成功还是失败,1:只记录发送成功的
                            #              ip: #ipip限额,在指定时间内可发送的次数
                            #                time: 300 #时间周期(秒)
                            #                count: 1 #时间周期内可发送的次数
                            mobile: #手机号码限额,在指定时间内可发送的次数
                                time: 60 #时间周期(秒)
                                count: 1 #时间周期内可发送的次数
                                keepTime: 300 #每个短信内容保存有效时长(秒)

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

# Service接口

# 第一步 引入包

<dependency>
    <groupId>sei-cloud</groupId>
    <artifactId>sms</artifactId>
</dependency>
1
2
3
4

# 第二步 引入接口

@Resource
    SmsService smsService;
1
2

# 第三步 使用接口


/**
 * 短信发送服务
 * @author xiong
 */
public interface SmsService {

    /**
     * 获得事件类
     * @return List
     */
    List<SmsEvent> getSmsEvents();

    /**
     * 使用指定的短信服务商发送短信(只发送短信,不判断限额,不缓存,不写日志, 不触发事件)
     * @param source: (可选)来源
     * @param service: (可选)短信服务商编码,如果不设置则采用系统默认的服务商
     * @param template: (可选)内容模板,如果不设置则采用系统配置文件模板,注意:模板中需要有占位符{},例如:您的验证码是{},在5分钟内有效。
     * @param content: (必须)发送的内容,例如:内容为123,则按上例组装后的短信内容为:您的验证码是123,在5分钟内有效。
     * @param mobile: (必须)手机号码
     * @return SendResult
     */
    LinkedHashMap<String, SendResult> sendOnly(String source, String service, String template, String content, Object... mobile);

    /**
     * 获得手机号码的短信内容
     * @param mobile: (必须)手机号码
     * @param service: (可选)短信服务商编码
     * @param project: (可选)项目编码
     * @param action: (可选)项目动作编码
     * @return String
     */
    String getSmsContent(String mobile, String service, String project, String action);

    /**
     * 获得手机号码最新的短信内容并从缓存中删除
     * @param mobile: (必须)手机号码
     * @param service: (可选)服务商编码
     * @param project: (可选)项目编码
     * @param action: (可选)项目动作编码
     * @return String
     */
    String getSmsContentAndRemove(String mobile, String service, String project, String action);

    /**
     * 发送短信
     * JSON格式:
     * {
     *      mobile: (必须)手机号码
     *      source: (可选)来源
     *      project: (可选)项目编码,须与验证时的project对应
     *      action: (可选)项目动作编码,须与验证时的action对应
     *      service: (可选)短信服务商,须与验证时的service对应
     * }
     * @param json: 前端提交的原始请求
     * @return ResMsg
     * ResMsg格式:
     * {
     *      code: 状态标志
     *      data: {
     *          手机号: { // SendResult类型
     *              success: true 代表该手机号发送成功,false:发送失败
     *              content: 发送的内容
     *              response: 运营商返回原始数据字符串
     *              responseObj: 运营商返回原始数据对象
     *              reason: 系统错误(非运营商错误)信息
     *          }
     *      }
     * }
     */
    ResMsg send(JSONObject json);

    /**
     * 发送短信
     * @param json: (可选)前端提交的原始请求
     * @param source: (可选)来源
     * @param events: (可选)是否触发事件
     * @param saveLog: (可选)是否保存日志
     * @param cache: 是否缓存
     * @param checkQuota: 是否检查限额
     * @param service: (可选)短信服务商编码,如果为null,则使用系统默认的
     * @param project: (可选)项目编码
     * @param action: (可选)项目动作编码
     * @param template: (可选)短信模板
     * @param content:  (必须)短信内容
     * @param mobile: (必须)手机号码
     * @return ResMsg
     */
    ResMsg send(JSONObject json, String source, boolean events, boolean saveLog, boolean cache, boolean checkQuota, String service, String project, String action, String template, String content, Object... mobile);

    /**
     * 验证短信内容
     * JSON格式:
     * {
     *      mobile: (必须)手机号码
     *      content: (必须)用户输入的内容
     *      keep: (可选)默认为false,验证后立即清除缓存,为true则继续保留在缓存中直到超时
     *      project: (可选)项目编码,须与验证时的project对应
     *      action: (可选)项目动作编码,须与验证时的action对应
     *      service: (可选)短信服务商,须与验证时的service对应
     * }
     * @param json: 前端提交信息,包含用户输入的短信内容
     * @return ResMsg
     */
    ResMsg check(JSONObject json);

    /**
     * 验证短信内容
     * @param mobile: (必须)手机号码
     * @param content: (必须)用户输入的内容
     * @param keep: (可选)默认为false,验证后立即清除缓存,为true则继续保留在缓存中直到超时
     * @param json: (可选)前端提交的原始请求
     * @param service: (可选)短信服务商编码,如果为null,则使用系统默认的
     * @param project: (可选)项目编码
     * @param action: (可选)项目动作编码
     * @return
     */
    ResMsg check(String mobile, String content, boolean keep, JSONObject json, String service, String project, String action);

    /**
     * 移除指定号码的限制
     * @param mobile: 手机号码
     * @return ResMsg
     */
    void removeLimit(String mobile);
}
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

# Controller接口


/**
 * @author xiong
 */
@Tag(name = "短信服务")
@Controller
@ConditionalOnProperty(name = "sei.cloud.sms.enabled", havingValue = "true")
@RequestMapping("/api/sms/")
public class SmsController {

    @Operation(summary = "发送短信")
    @RequestMapping(value="/public/send", method = RequestMethod.POST,produces = { MediaType.APPLICATION_JSON_VALUE })
    public @ResponseBody ResMsg send(@RequestBody JSONObject json);

    @Operation(summary = "验证短信内容")
    @RequestMapping(value="/public/check", method = RequestMethod.POST,produces = { MediaType.APPLICATION_JSON_VALUE })
    public @ResponseBody ResMsg check(@RequestBody JSONObject json);
    
    @Operation(summary = "清除指定手机号的限制")
    @RequestMapping(value="/removeLimit", method = RequestMethod.POST,produces = { MediaType.APPLICATION_JSON_VALUE })
    public @ResponseBody ResMsg removeLimit(@RequestBody JSONObject json);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 框架短信事件

使用时通过继承本类实现回调。


public abstract class SmsEvent {

    /**
     * 接收到前端请求发送回调时回调
     * @param json: 前端请求的JSON数据
     * @param resMsg: 返回前端的信息
     * @return boolean 返回false将终止后续操作
     */
    public boolean acceptQuest(JSONObject json, ResMsg resMsg) {
        return true;
    }

    /**
     * 发送短信前回调
     * @param service: 短信服务商编码
     * @param project: 项目编码
     * @param action: 项目动作编码
     * @param parms: 参数,包括:mobile: 手机号码,template模板和content,修改此参数将以此参数为准
     * @param json: 前端提交的JSON原始数据
     * @param resMsg: 返回前端的信息
     * @return 返回true将发送短信,返回false将终止操作
     */
    public boolean send_before(String service, String project, String action, Map<String, String> parms, JSONObject json, ResMsg resMsg) {
        return true;
    }

    /**
     * 发送后回调
     * @param service: 短信服务商编码
     * @param project: 项目编码
     * @param action: 项目动作编码
     * @param mobile: 手机号码
     * @param content: 发送的内容
     * @param parms: 提交给短信服务商的参数
     * @param sendResult: 发送结果
     * @param json: 前端提交的JSON原始数据
     * @param resMsg: 返回前端的信息
     */
    public void send_after(String service, String project, String action, String mobile, String content, Map<String, ?> parms, SendResult sendResult, JSONObject json, ResMsg resMsg) {

    }

    /**
     * 短信验证前回调
     * @param service: 短信服务商编码
     * @param project: 项目编码
     * @param action: 项目动作编码
     * @param mobile: 手机号码
     * @param content: 发送的内容
     * @param smsContent: 短信的内容
     * @param json: 前端提交的JSON原始数据
     * @param resMsg: 返回前端的信息
     * @return 返回true将继续验证短信,返回false将终止操作
     */
    public boolean checkBefore(String service, String project, String action, String mobile, String content, String smsContent, JSONObject json, ResMsg resMsg) {
        return true;
    }

    /**
     * 短信验证后回调
     * @param success: 是否验证成功
     * @param service: 短信服务商编码
     * @param project: 项目编码
     * @param action: 项目动作编码
     * @param mobile: 手机号码
     * @param content: 用户输入的内容
     * @param smsContent: 短信的内容
     * @param json: 前端提交的JSON原始数据
     * @param resMsg: 返回前端的信息
     */
    public void checkAfter(boolean success, String service, String project, String action, String mobile, String content, String smsContent, JSONObject json, ResMsg resMsg) {

    }
}
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