短信服务

aliyunintegrated-development

# 一、短信服务

好的第三方短信服务平台要具备一下五点:

  • 到达率高

  • 功能齐全

  • 短信价格合理

  • 售后服务完善

  • 信誉好

介于目前业界口碑排行,最终选择阿里云短信平台。

# 二、阿里云短信平台

# 2.1 阿里SMS简介

短信服务(Short Message Service)是广大企业客户快速触达手机用户所优选使用的通信能力。调用API或用群发助手,即可发送验证码、通知类和营销类短信;国内验证短信秒级触达,到达率最高可达99%;国际/港澳台短信覆盖200多个国家和地区,安全稳定,广受出海企业选用。

短信平台网址:

https://www.aliyun.com/search?spm=5176.19720258.J_3207526240.25.e9392c4aQ6RF2n&scene=all&k=短信服务 (opens new window)

阿里云短信服务官网API文档:

https://next.api.aliyun.com/document/Dysmsapi/2017-05-25/overview (opens new window)

# 2.2 产品优势

快速稳定:3秒可达,99%到达率,国内短信与工信部携号转网平台实时互联。

接入便捷:群发助手,简单便捷。API和多语言SDK接入,有效节约开发时间与成本。

智能监控调度:电信级运维保障,实时监控、自动切换,确保发送成功率。

高并发:高效的调度算法解决高峰时段的业务压力。

# 2.3 阿里云配置SMS

# 开通阿里云账户

开通阿里云账户https://www.aliyun.com (opens new window)

# 购买短信套餐包

在阿里云平台搜索短信服务,进行购买短信套餐包。

阿里云SMS短信平台购买方案
资源包规格 购买时长(月) 价格(元)
1000条 24个月 50
2000条 24个月 100
5000条 24个月 180
1.5万条 24个月 705
5万条 24个月 2150
20万条 24个月 8064

表1-1短信套餐包

# 获取AccessKeyID和密钥

AccessKey ID和AccessKey Secret是您访问阿里云API的密钥,具有该账户完全的权限,请您妥善保管。

为了安全起见,请使用子用户AccessKey。

获取AccessKey:https://ram.console.aliyun.com/users/new (opens new window)

# 申请签名

签名是短信中能代表发送者属性的字段。

添加签名:https://dysms.console.aliyun.com/domestic/text/sign/add (opens new window)

# 申请模板

模板即具体发送的短信内容。

申请模板:https://dysms.console.aliyun.com/domestic/text/template/add (opens new window)

# 系统设置

系统设置:https://dysms.console.aliyun.com/general (opens new window)

# 2.4 SDK接入(旧版)

环境要求

  • 最低要求Java 8

  • 安装 SDK 核心库 OpenAPI ,可以通过 POM 文件引入的方式来安装。

https://help.aliyun.com/document_detail/55284.htm

# 代码开发

# 配置yml
#短信配置信息
message:
  ali_message:
    ali_accessKey_Id: LTAIlz8rCF976lQ
    ali_accessKey_Secret: HDtzEAUIplSXT2czrasr2DvC40
    # 通知的短信签名
    signName_inform: xxx科技有限公司
    # 通知的短信模板
    templateCode_inform: SMS_158345131
1
2
3
4
5
6
7
8
9
# 引入SDK
<properties>
    <aliyun-java-sdk-core.version>3.3.1</aliyun-java-sdk-core.version>
    <aliyun-java-sdk-dysmsapi.version>1.0.0</aliyun-java-sdk-dysmsapi.version>
</properties>

<!-- 短信服务 -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>${aliyun-java-sdk-core.version}</version>
</dependency>
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
    <version>${aliyun-java-sdk-dysmsapi.version}</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 发送短信API
@Component
@Data
public class MessageProperties {
    /**
     *  阿里云API的密钥
     */
    @Value("${message.ali_message.ali_accessKey_Id}")
    private String aliAccessKeyId;

    @Value("${message.ali_message.ali_accessKey_Secret}")
    private String aliAccessKeySecret;

    /**
     * 短信签名
     */
    @Value("${message.ali_message.signName_inform}")
    private String signNameInform;

    /**
     * 短信模板 - 注册验证码
     */
    @Value("${message.ali_message.templateCode_inform}")
    private String templateCodeInform;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

封装对象

public class SmsDTO implements Serializable {

    private static final long serialVersionUID = 3712925418243796538L;

    /**
     * 短信签名名称
     */
    private String signNameInform;

    /**
     * 短信模板CODE
     */
    private String templateCodeInform;

    /**
     * 接收短信的手机号码
     */
    private String phoneNumbers;

    /**
     * 发送短信内容
     */
    private String content;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 阿里云短信服务工具类
@Component
@Slf4j
public class SmsUtils {

    @Autowired
    private MessageProperties resourcesProperties;

    /**
     * 发送短信
     * @param phoneNum  必填:待发送手机号
     * @param signName  必填:短信签名,传入的短信签名必须是在阿里云“管理中心-短信签名管理”中的可用签名
     * @param templateCode  必填:短信模板ID,传入的模板必须是在阿里云“管理中心-短信模板管理”中的可用模板。示例:SMS_585014
     * @param templateParam  可选:模板中的变量替换JSON串
     * @return
     * @throws ClientException
     */
    public String sendMsg(String phoneNum, String signName, String templateCode, String templateParam ) throws ClientException {//拿到手机号
        //调用阿里通信接口
        //设置超时时间-可自行调整
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
        //初始化ascClient需要的几个参数
        final String product = "Dysmsapi";//短信API产品名称(短信产品名固定,无需修改)
        final String domain = "dysmsapi.aliyuncs.com";//短信API产品域名(接口地址固定,无需修改)

        //******此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
        //你的accessKeyId,
        final String accessKeyId = resourcesProperties.getAliAccessKeyId();
        //你的accessKeySecret,
        final String accessKeySecret = resourcesProperties.getAliAccessKeySecret();

        //初始化ascClient,暂时不支持多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();
        //使用post提交
        request.setMethod(MethodType.POST);
        //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
        request.setPhoneNumbers(phoneNum);
        //必填:短信签名-可在短信控制台中找到
        request.setSignName(signName);
        //必填:短信模板-可在短信控制台中找到
        request.setTemplateCode(templateCode);
        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
        //生成几位的验证码
//     String numeric = RandomStringTLUtils.randomNumeric(6);

        if(StringUtils.isNotBlank(templateParam)){
            request.setTemplateParam(templateParam);
        }
        //可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
//        request.setSmsUpExtendCode("90997");
        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
//        request.setOutId("yourOutId");

        //请求失败这里会抛ClientException异常
        SendSmsResponse sendSmsResponse = new  SendSmsResponse();
        try {
            sendSmsResponse = acsClient.getAcsResponse(request);
        } catch (Exception e) {
            log.error(e.getMessage());;
        }
        if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
            //请求成功
            //真实应用的时候验证码在服务端有记录
            //客户端由客户来输入
            //客户输入的验证码和服务端做匹配
            return sendSmsResponse.getCode();
        }

        return "error";
    }

}
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
# 接收数据接口
public class AliyunSmsSend {

    /**
     * 发送短信 - 注册功能发送短信验证码
     *
     * @param smsDTO
     * @date 2022/4/13 17:43
     * @author superC
     */
    public static void sendSms2Register(SmsDTO smsDTO) {
        try {
            //模板中的变量替换JSON串(code为模板中的变量)
            String templateParam = "{\"code\":\"" + smsDTO.getContent() + "\"}";
            String result = SmsUtils.sendMessage(smsDTO.getPhoneNumbers(), smsDTO.getSignNameInform(), smsDTO.getTemplateCodeInform(), templateParam);
            logger.debug("发送短信结果:{}", result);
        } catch (ClientException e) {
            logger.error("【捕获发送短信异常】\r\n异常记录:", e);
            ;
        }
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 2.5 SDK接入(新版)

新版SDK API (opens new window)

# 1、短信服务使用

  1. 身份管理→用户→权限管理,添加用户操作权限;
  2. 创建用户 AccessKey及密钥;
  3. 购买短信服务套餐;
  4. 申请签名;
  5. 申请模板;

# 2、短信服务测试

https://dysms.console.aliyun.com/quickstart

每个账号限制授权5个测试手机号

测试专用模版只支持4-6位纯数字、测试专用签名+模版只能结合使用。

# 测试专用签名
  • 签名名称:阿里云短信测试
  • 使用场景:发送测试短信
# 测试专用模版
  • 模版名称:测试专用模板
  • 模版Code:SMS_154950909
  • 模版类型:验证码
  • 模版内容:您正在使用阿里云短信测试服务,体验验证码是:${code},如非本人操作,请忽略本短信!

# 3、代码开发

# 配置文件
base:
  config:
    aliyun:
      sms:
        endpoint: dysmsapi.aliyuncs.com
        accesskeyId: 你的AccessKey-ID
        accesskeySecret: 你的AccessKey-Secret
        signNameInform: 阿里云短信测试
        # 短信模板
        templateCodeInform:
          loginCaptcha: SMS_154950909
1
2
3
4
5
6
7
8
9
10
11
# 引入SDK
<properties>
    <aliyun-sms.version>2.0.9</aliyun-sms.version>
</properties>

<!-- ********  短信服务-新版SDK Begin  ********** -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>dysmsapi20170525</artifactId>
    <version>${aliyun-sms.version}</version>
</dependency>
<!-- ********  短信服务-新版SDK End  ********** -->
1
2
3
4
5
6
7
8
9
10
11
# 发送短信API
/**
 * 单条短信发送
 *
 * @param client        调用AliyunSmsBase.createClient()创建
 * @param phoneNumbers  接收短信的手机号码,多个用英文逗号隔开
 * @param signName      短信签名名称,eg: "阿里云"
 * @param templateCode  短信模板CODE
 * @param templateParam 短信模板变量对应的实际值,eg:{"code":"1234"}
 * @return sendResp.body.bizId可用于查询短信发送结果
 * @throws Exception
 */
public static SendSmsResponse send(Client client, String phoneNumbers, String signName, String templateCode, String templateParam) throws Exception {
    SendSmsRequest sendReq = new SendSmsRequest()
            .setPhoneNumbers(phoneNumbers)
            .setSignName(signName)
            .setTemplateCode(templateCode)
            .setTemplateParam(templateParam);
    return client.sendSms(sendReq);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19