阿里云短信服务调用详解

最近项目需求使用了阿里云的短信服务给用户发送验证,写此文章记录学习。

接口申请:

步骤 1 创建阿里云账号

为了访问短信服务,您需要有一个阿里云账号。如果没有,可首先按照如下步骤创建阿里云账号:

  1. 访问阿里云 官方网站,单击页面上的 免费注册 按钮。
  2. 按照屏幕提示完成注册流程并进行实名认证,短信服务只支持实名认证用户使用。为了更好地使用阿里云服务,建议尽快完成实名认证,否则部分阿里云服务将无法使用。具体实名认证流程,请参考 这里

步骤 2 获取阿里云访问密钥

为了使用短信发送API-JAVA SDK,您必须申请阿里云的访问密钥。

阿里云访问秘钥是阿里云为用户使用 API(非控制台)来访问其云资源设计的“安全口令”。您可以用它来签名 API 请求内容以通过服务端的安全验证。

该访问秘钥成对(AccessKeyId 与 AccessKeySecret)生成和使用。每个阿里云用户可以创建多对访问秘钥,且可随时启用(Active)、禁用(Inactive)或者删除已经生成的访问秘钥对。

您可以通过阿里云控制台的 秘钥管理页面 创建、管理所有的访问秘钥对,且保证它处于“启用”状态。由于访问秘钥是阿里云对 API 请求进行安全验证的关键因子,请妥善保管你的访问秘钥。如果某些秘钥对出现泄漏风险,建议及时删除该秘钥对并生成新的替代秘钥对。

步骤 3 在控制台完成模板与签名的申请,获得调用接口必备的参数

短信签名

根据用户属性来创建符合自身属性的签名信息。企业用户需要上传相关企业资质证明,个人用户需要上传证明个人身份的证明。

注意:短信签名需要审核通过后才可以使用。

短信模板

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

短信模板可以支持验证码、短信通知、推广短信三种模式。验证码和短信通知,通过变量替换实现个性短信定制。推广短信不支持在模板中添加变量。

短信模板需要审核通过后才可以使用。

为了成功发送短信通知,您至少需要完成以下步骤

一、在控制台完成短信签名与短信模板的申请,获得调用接口必备的参数

在“短信签名”页面完成签名的申请,获得短信签名的字符串 签名申请手册

在“短信模板”页面完成模板的申请,获得模板ID。模板申请手册

 

 

开通阿里云短信服务链接:https://www.aliyun.com/product/sms?spm=5176.doc55324.765261.224.SSoWpM

使用阿里云的短信服务,需要注册登录自己的阿里云控制台,然后进入AccessKeys的处理界面

短信验证获取 AccessKey ID和AccessKey

短信服务文档

 https://help.aliyun.com/product/44282.html?spm=a2c4g.11186623.3.1.60861a81MfZAoZ

 

技术对接步骤

1:下载SDK工具包:SDK工具包中一共包含了2个类库,一个aliyun-java-sdk-core包,另外一个是alicom-dysms-api包
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.0.6</version> <!-- 注:如提示报错,先升级基础包版,无法解决可联系技术支持 -->
</dependency>
<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
  <version>1.1.0</version>
</dependency>

 

2: 编写样例程序

发送短信接口(SendSms)

//设置超时时间-可自行调整
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
final String accessKeyId = "yourAccessKeyId";//你的accessKeyId,参考本文档步骤2
final String accessKeySecret = "yourAccessKeySecret";//你的accessKeySecret,参考本文档步骤2
//初始化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个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为国际区号+号码,如“85200000000”
 request.setPhoneNumbers("1500000000");
 //必填:短信签名-可在短信控制台中找到
 request.setSignName("云通信");
 //必填:短信模板-可在短信控制台中找到,发送国际/港澳台消息时,请使用国际/港澳台短信模版
 request.setTemplateCode("SMS_1000000");
 //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
 //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
 request.setTemplateParam("{\"name\":\"Tom\", \"code\":\"123\"}");
 //可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
 //request.setSmsUpExtendCode("90997");
 //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
 request.setOutId("yourOutId");
//请求失败这里会抛ClientException异常
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
if(sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
//请求成功
}

参数

入参列表
参数名称参数类型必填与否样例取值参数说明
PhoneNumbers String 必须 15000000000 短信接收号码,支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为:国际区号+号码,如“85200000000”
SignName String 必须 云通信 短信签名
TemplateCode String 必须 SMS_0000 短信模板ID,发送国际/港澳台消息时,请使用国际/港澳台短信模版
TemplateParam String 可选 {“code”:”1234”,”product”:”ytx”} 短信模板变量替换JSON串,友情提示:如果JSON中需要带换行符,请参照标准的JSON协议。
SmsUpExtendCode String 可选 90999 上行短信扩展码,无特殊需要此字段的用户请忽略此字段
OutId String 可选 abcdefgh 外部流水扩展字段
出参列表
出参名称出参类型样例取值参数说明
RequestId String 8906582E-6722 请求ID
Code String OK 状态码-返回OK代表请求成功,其他错误码详见错误码列表
Message String 请求成功 状态码的描述
BizId String 134523^4351232 发送回执ID,可根据该ID查询具体的发送状态

 

短信接口调用错误码:https://help.aliyun.com/knowledge_detail/57717.html?spm=a2c4g.11186623.2.20.37103144DVn56z

短信发送记录查询接口(QuerySendDetails)

用于查询短信发送的状态,是否成功到达终端用户手机

 //设置超时时间
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");
        //云通信产品-短信API服务产品名称(短信产品名固定,无需修改)
        final String product = "Dysmsapi";
        //云通信产品-短信API服务产品域名(接口地址固定,无需修改)
        final String domain = "dysmsapi.aliyuncs.com";
        //此处需要替换成开发者自己的AK信息
        final String accessKeyId = "yourAccessKeyId";
        final String accessKeySecret = "yourAccessKeySecret";
        //初始化ascClient
        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("150000000");
        //可选-调用发送短信接口时返回的BizId
        request.setBizId("1234567^8901234");
        //必填-短信发送的日期 支持30天内记录查询(可查其中一天的发送数据),格式yyyyMMdd
        request.setSendDate("20170513");
        //必填-页大小
        request.setPageSize(10L);
        //必填-当前页码从1开始计数
        request.setCurrentPage(1L);
        //hint 此处可能会抛出异常,注意catch
        QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);
        //获取返回结果
       if(querySendDetailsResponse.getCode() != null && querySendDetailsResponse.getCode().equals("OK")){
        //代表请求成功
      }

 

 

入参列表

参数名称参数类型必填与否样例取值参数说明
PhoneNumber String 必须 15000000000 短信接收号码,如果需要查询国际短信,号码前需要带上对应国家的区号,区号的获取详见国际短信支持国家信息查询API接口
BizId String 可选 1234^1234 发送流水号,从调用发送接口返回值中获取
SendDate String 必须 20170525 短信发送日期格式yyyyMMdd,支持最近30天记录查询
PageSize Number 必须 10 页大小Max=50
CurrentPage Number 必须 1 当前页码

出参列表

出参名称出参类型样例取值参数说明
RequestId String 8906582E-6722 请求ID
Code String OK 状态码-返回OK代表请求成功,其他错误码详见错误码列表
Message String 请求成功 状态码的描述
TotalCount Number 100 发送总条数
smsSendDetailDTOs Object - 发送明细结构体,详见Demo样例

Demo样例

出参名称出参类型样例取值参数说明
phoneNum String 13000000000 手机号码
sendStatus Number 1 发送状态 1:等待回执,2:发送失败,3:发送成功
errCode String DELIVERED 运营商短信错误码
templateCode String SMS_000 模板ID
content String 【阿里云】你好! 短信内容
sendDate Object 2017-05-25 00:00:00 发送时间
receiveDate String 2017-05-25 00:00:00 接收时间
outId String 123 外部流水扩展字段

 

发送批量短信接口(SendBatchSms)

//设置超时时间-可自行调整
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
final String accessKeyId = "yourAccessKeyId";//你的accessKeyId,参考本文档步骤2
final String accessKeySecret = "yourAccessKeySecret";//你的accessKeySecret,参考本文档步骤2
//初始化ascClient,暂时不支持多region(请勿修改)
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,
accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
 //组装请求对象
 SendBatchSmsRequest request = new SendBatchSmsRequest();
 //使用post提交
 request.setMethod(MethodType.POST);
 //必填:待发送手机号。支持JSON格式的批量调用,批量上限为100个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
 request.setPhoneNumberJson("[\"1500000000\",\"1500000001\"]");
 //必填:短信签名-支持不同的号码发送不同的短信签名
 request.setSignNameJson("[\"云通信\",\"云通信\"]");
 //必填:短信模板-可在短信控制台中找到
 request.setTemplateCode("SMS_1000000");
 //必填:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
 //友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
 request.setTemplateParamJson("[{\"name\":\"Tom\", \"code\":\"123\"},{\"name\":\"Jack\", \"code\":\"456\"}]");
 //可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
 //request.setSmsUpExtendCodeJson("[\"90997\",\"90998\"]");
//请求失败这里会抛ClientException异常
SendBatchSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
if(sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
//请求成功
}

 

 

参数

入参列表
参数名称参数类型必填与否样例取值参数说明
PhoneNumberJson String 必须 [“15000000000”,”15000000001”] 短信接收号码,JSON格式,批量上限为100个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
SignNameJson String 必须 [“云通信”,”云通信”] 短信签名,JSON格式
TemplateCode String 必须 SMS_0000 短信模板ID
TemplateParamJson String 必须 [{“code”:”1234”,”product”:”ytx1”},{“code”:”5678”,”product”:”ytx2”}] 短信模板变量替换JSON串,友情提示:如果JSON中需要带换行符,请参照标准的JSON协议。
SmsUpExtendCodeJson String 可选 [“90999”,”90998”] 上行短信扩展码,JSON格式,无特殊需要此字段的用户请忽略此字段
出参列表
出参名称出参类型样例取值参数说明
RequestId String 8906582E-6722 请求ID
Code String OK 状态码-返回OK代表请求成功,其他错误码详见错误码列表
Message String 请求成功 状态码的描述
BizId String 134523^4351232 发送回执ID,可根据该ID查询具体的发送状态

短信消息API

当您使用短信的API接口发送短信后,可以通过使用MNS的Queue模型来接收短信的回执消息,假如服务出现异常情况时(如网络问题),导致消息回执未成功获取,还可以通过短信发送记录查询API接口进行一定的补偿(目前支持30天内发送记录的查询,可查询一天的发送数据)。

消息的订阅

  • 云通信的所有业务消息都通过MNS消息服务向外发送。用户每订阅一个类别的消息(比如上行短信消息SmsUp),系统都会为用户分配一个独立的消息队列。
  • 用户可以通过阿里云账号拿到一个临时的token用于获取队列中的消息。用户可以下载demo,编写简单的消息处理类即可完成消息处理的任务。
  • 在页面上订阅消息,订阅完消息后,能拿到消息队列名称(queueName)。比如:Alicom-Queue-xxxxxx-SmsReport 。队列名字每个用户都不同。

路径:短信产品进入控制台→应用开发→接口调用→云通信消息接收→短信状态报告接收→向右滑动(MNS消息队列消费模式。接收消息队列信息,请下载消息服务SDK进行程序编写,详见API文档)

消息类型

短信提供2种消息类型SmsReport(短信回执报告消息) 和 SmsUp(上行短信消息)

  • 通过订阅SmsReport短信状态报告,可以获知每条短信的发送情况,了解短信是否达到终端用户的状态与相关信息
  • 通过订阅SmsUp上行短信消息,可以获知终端用户回复短信的内容
  • 短信回执消息SmsReport消息体格式
    名称类型描述示例
    phone_number String 短信接收号码 13000000000
    success Boolean 发送是否成功 true
    biz_id String 发送回执ID 1234^345
    out_id String 调用发送短信接口时传的outId 123456
    send_time String 转发给运营商的时间 2017-06-01 10:00:00
    report_time String 收到运营商回执的时间 2017-06-01 10:00:05
    err_code String 错误码 UNKNOW
    err_msg String 错误信息 未知异常
    sms_size String 140字节算一条短信,短信长度超过140字节时会拆分成多条短信发送 1,2,3
    上行短信消息SmsUp
    名称类型描述示例
    phone_number String 短信接收号码 13000000000
    content String 短信内容 true
    sign_name String 短信签名 【阿里云】
    send_time String 时间 2017-06-01 10:00:00
    dest_code String 扩展码 123456
    sequence_id Double 消息序列ID 123456
/**
 * 只能用于接收云通信的消息,不能用于接收其他业务的消息
 */
public class ReceiveAlicomMsgDemo {
    private static Log logger=LogFactory.getLog(ReceiveAlicomMsgDemo.class);
    //以短信回执消息处理为例
    static class MyMessageListener implements MessageListener{
        private Gson gson=new Gson();
        @Override
        public boolean dealMessage(Message message) {
            System.out.println("message handle: " + message.getReceiptHandle());
            System.out.println("message body: " + message.getMessageBodyAsString());
            System.out.println("message id: " + message.getMessageId());
            System.out.println("message dequeue count:" + message.getDequeueCount());
            //以短信回执消息处理为例
            try{
                Map<String,Object> contentMap=gson.fromJson(message.getMessageBodyAsString(), HashMap.class);
                String phoneNumber=(String)contentMap.get("phone_number");
                Boolean success=(Boolean)contentMap.get("success");
                String bizId=(String)contentMap.get("biz_id");
                String outId=(String)contentMap.get("out_id");
                String sendTime=(String)contentMap.get("send_time");
                String reportTime=(String)contentMap.get("report_time");
                String errCode=(String)contentMap.get("err_code");
                String errMsg=(String)contentMap.get("err_msg");
                //TODO 这里开始写业务代码
            }catch(com.google.gson.JsonSyntaxException e){
               logger.error("error_json_format:"+message.getMessageBodyAsString(),e);
            }
            Boolean dealResult=true;
            return dealResult;//返回true,则工具类自动删除已拉取的消息。
        }
    }
    public static void main(String[] args) throws com.aliyuncs.exceptions.ClientException, ParseException {
        DefaultAlicomMessagePuller puller=new DefaultAlicomMessagePuller();
        String accessKeyId="yourAccessKeyId";
        String accessKeySecret="yourAccessKeySecret";
        String messageType="SmsReport";//短信回执:SmsReport,短信上行:SmsUp
        String queueName="yourQueueName";//在云通信页面开通相应业务消息后,就能在页面上获得对应的queueName
        puller.startReceiveMsg(accessKeyId,accessKeySecret ,messageType,queueName , new MyMessageListener());
    }
}

 

posted @ 2019-04-11 11:46  2020持之以恒  阅读(2343)  评论(0编辑  收藏  举报