☰
【Spring Boot】整合阿里云短信详细步骤(附源码)
2026/10/2 8:28:01 网站建设 项目流程

Spring Boot 整合阿里云短信(SMS)对接文档

本文档涵盖阿里云侧资质/签名/模板申请流程与后端整合、调用方式。

⚠️ 文档中 AccessKey ID / AccessKey Secret 等敏感信息已脱敏,真实值请以代码或配置中心为准。


一、整体说明

项说明
云服务阿里云短信服务(Dysmsapi)
SDKaliyun-java-sdk-core+aliyun-java-sdk-dysmsapi(v1 版 SDK)
核心接口SendSms(发送短信)
接入点cn-hangzhou/dysmsapi.aliyuncs.com
工具类com.jxbd.fsgdzc.util.AliyunSms#sendSms
发送方式通过status参数映射到不同短信模板,模板变量为 JSON(code/orderNo/name)

调用链路:

业务代码(Service/Controller/Task) │ Map<String,String> param(telNo / status / code / orderNo / name) ▼ AliyunSms.sendSms(param, null) │ 1. 按 status 选择模板 ID │ 2. 组装模板变量 JSON │ 3. DefaultAcsClient.getAcsResponse(SendSmsRequest) ▼ 阿里云短信服务 → 运营商 → 用户手机

二、阿里云侧开通与申请流程

2.1 开通短信服务

  1. 登录 阿里云控制台,完成企业实名认证(短信服务面向企业用户为主)。
  2. 搜索「短信服务」并开通(免费开通,按发送量计费)。
  3. 首次进入「短信服务控制台」会引导完成资质 + 签名 + 模板三件套,全部审核通过后才能发送。

经验值:资质审核一般 1~2 个工作日;签名/模板审核一般2 小时内(工作日),被驳回需按驳回原因修改后重新提交。

2.2 申请资质(短信资质)

阿里云自 2023 年起要求「先提交资质,再申请签名/模板」。

  1. 进入「短信服务控制台 → 国内消息 → 资质管理 → 新增资质」。
  2. 选择资质类型:
    • 企业资质:需上传营业执照、法人身份证正反面、经办人身份证(非法人办理时需授权书)。
    • 个人资质:仅可申请自用类签名/模板,业务范围受限。
  3. 填写企业名称、统一社会信用代码、归属行业等,提交审核。
  4. 审核通过后,资质状态变为「审核通过」,方可继续申请签名。

材料准备清单(企业)

材料要求
营业执照彩色扫描件/照片,清晰可辨且在有效期内
法人身份证正反面,四角完整
经办人身份证 + 授权书仅当经办人非法人时需要
行业证明(部分行业)医疗、金融等需提供对应经营许可

2.3 申请签名

短信签名是短信开头【】中的内容,例如本项目使用的【友医伴健康】。

  1. 进入「短信服务控制台 → 国内消息 → 签名管理 → 添加签名」。
  2. 填写:
    • 签名名称:建议 2~12 个字,与 App/公众号/网站/营业执照名称相关。
    • 签名来源:App(需提供应用商店链接 + 应用截图)/ 公众号 / 小程序 / 网站 / 企业全称简称。
    • 适用场景:验证码 / 短信通知 / 推广短信(通知类与营销类需分开申请)。
    • 关联资质:选择 2.2 中审核通过的资质。
  3. 提交后等待审核,通过后状态为「审核通过」。
  4. 记录签名名称,配置到代码request.setSignName("...")。

注意:签名必须与业务主体一致,否则易被驳回;一个签名可被多个模板复用。

2.4 新增模板

  1. 进入「短信服务控制台 → 国内消息 → 模板管理 → 添加模板」。

  2. 选择模板类型:

    • 验证码:您的验证码为${code},5分钟内有效。
    • 短信通知:如订单支付成功、订单指派等。
    • 推广短信:营销类,需单独申请签名。
  3. 填写模板内容,变量使用${变量名}占位,例如:

    尊敬的客户,您的订单${orderNo}已支付成功,我们将尽快为您安排陪诊服务。
  4. 填写变量说明(说明每个变量的含义与示例值)。

  5. 提交审核,通过后获得模板 CODE(形如SMS_508125195)。

  6. 将模板 CODE 配置到代码的status → templateCode映射中。

模板申请注意事项

  • 变量个数与顺序必须与代码里templateParam的 key 完全对应(本项目为code/orderNo/name)。
  • 模板中数字变量建议不要放在短信开头,避免被运营商判定为垃圾短信。
  • 验证码类模板必须包含验证码 + 有效期说明。
  • 同一业务内容不要重复提交多个相似模板,会被驳回。

2.5 创建 AccessKey(RAM 子账号)

不要使用主账号 AccessKey,建议创建 RAM 用户并授予最小权限。

  1. 进入「RAM 访问控制 → 用户 → 创建用户」,勾选「OpenAPI 调用访问」。
  2. 创建后保存AccessKey ID与AccessKey Secret(Secret 仅创建时展示一次)。
  3. 为该用户授权:系统策略AliyunDysmsFullAccess(或自定义仅含dysms:SendSms的策略)。
  4. 将 AccessKey 配置到项目中(推荐通过配置中心/环境变量注入,而非硬编码)。

2.6 计费与配额

  • 按发送条数计费,可购买短信套餐包降低成本。
  • 默认有流控限制(如同一手机号验证码类 1 分钟内 1 条、1 小时内 5 条等),可在控制台申请调整。
  • 建议在控制台开启「发送量预警」,避免异常刷量。

三、后端整合

3.1 引入依赖

server/jxbd-fsgdzc/pom.xml:

<!-- 阿里云 SDK 核心 --><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>3.3.1</version></dependency><!-- 阿里云短信 SDK --><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-dysmsapi</artifactId><version>1.0.0</version></dependency>

3.2 配置项(建议改造为可配置)

当前实现将 AccessKey 与模板 ID硬编码在AliyunSms中,不便于多环境切换与密钥轮换。建议改为读取配置:

# application-dev.ymlaliyun:sms:access-key-id:"LTAI****************"# RAM 用户 AccessKeyIdaccess-key-secret:"************************"# RAM 用户 AccessKeySecretregion-id:"cn-hangzhou"endpoint:"dysmsapi.aliyuncs.com"sign-name:"友医伴健康"# 短信签名templates:captcha:"SMS_508015266"# 0 验证码paid:"SMS_508125195"# 1 下单支付成功assigned:"SMS_508160180"# 2 订单指派给陪诊师back:"SMS_507950246"# 3 订单回退通知管理员canceled:"SMS_507930223"# 4 订单取消通知管理员和陪诊师remindToday:"SMS_508015231"# 5 开始陪诊前提前一天通知就诊人auditPass:"SMS_508180014"# 6 陪诊师资格审核通过通知用户timeoutUser:"SMS_509425064"# 7 订单超时15分钟通知陪诊师timeoutCustomer:"SMS_509740055"# 8 订单超时通知客户购买超时服务

后续新增模板时,只需在配置中增加一项 + 在映射中注册,无需改动业务代码。

3.3 工具类源码

路径:server/jxbd-fsgdzc/src/main/java/com/jxbd/fsgdzc/util/AliyunSms.java(AccessKey 已脱敏)

packagecom.jxbd.fsgdzc.util;importcom.alibaba.fastjson.JSONObject;importcom.aliyuncs.DefaultAcsClient;importcom.aliyuncs.IAcsClient;importcom.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;importcom.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;importcom.aliyuncs.exceptions.ClientException;importcom.aliyuncs.profile.DefaultProfile;importcom.aliyuncs.profile.IClientProfile;importcom.jxbd.common.core.domain.AjaxResult;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjavax.servlet.http.HttpSession;importjava.util.Map;publicclassAliyunSms{privatestaticfinalLoggerlog=LoggerFactory.getLogger(AliyunSms.class);staticfinalStringproduct="Dysmsapi";staticfinalStringdomain="dysmsapi.aliyuncs.com";staticfinalStringaccessKeyId="LTAI****************";// 已脱敏staticfinalStringaccessKeySecret="************************";// 已脱敏publicAliyunSms(){}publicstaticAjaxResultsendSms(Map<String,String>params,HttpSessionsession)throwsClientException{Stringtel=(String)params.get("telNo");Stringcode=(String)params.get("code");StringorderNo=(String)params.get("orderNo");Stringname=(String)params.get("name");System.setProperty("sun.net.client.defaultConnectTimeout","10000");System.setProperty("sun.net.client.defaultReadTimeout","10000");IClientProfileprofile=DefaultProfile.getProfile("cn-hangzhou",accessKeyId,accessKeySecret);DefaultProfile.addEndpoint("cn-hangzhou","cn-hangzhou",product,domain);IAcsClientacsClient=newDefaultAcsClient(profile);SendSmsRequestrequest=newSendSmsRequest();request.setPhoneNumbers(tel);request.setSignName("友医伴健康");Stringstatus=(String)params.get("status");Stringtemplate=null;if("0".equals(status)){template="SMS_508015266";//验证码}elseif("1".equals(status)){template="SMS_508125195";//下单支付成功}elseif("2".equals(status)){// template = "SMS_508030056";//订单指派给陪诊师template="SMS_508160180";//订单指派给陪诊师}elseif("3".equals(status)){template="SMS_507950246";//订单回退通知管理员}elseif("4".equals(status)){template="SMS_507930223";//订单取消通知管理员和陪诊师}elseif("5".equals(status)){template="SMS_508015231";//开始陪诊前提前一天通知就诊人}elseif("6".equals(status)){template="SMS_508180014";//陪诊师资格审核通过后通知用户}elseif("7".equals(status)){template="SMS_509425064";//订单超时15分钟通知陪诊师(让客户购买延时服务)}elseif("8".equals(status)){template="SMS_509740055";//订单超时通知客户购买超时服务}request.setTemplateCode(template);log.info("模板id为:"+template);JSONObjectobj=newJSONObject();obj.put("code",code);obj.put("orderNo",orderNo);obj.put("name",name);request.setTemplateParam(obj.toJSONString());try{SendSmsResponsesendSmsResponse=(SendSmsResponse)acsClient.getAcsResponse(request);log.info("短信接口返回的数据--------start--------");log.info("Code="+sendSmsResponse.getCode());log.info("Message="+sendSmsResponse.getMessage());log.info("RequestId="+sendSmsResponse.getRequestId());log.info("BizId="+sendSmsResponse.getBizId());log.info("短信接口返回的数据-------- end --------");}catch(ClientExceptionvar14){log.error(var14.getMessage());var14.printStackTrace();}returnAjaxResult.success();}}

3.4 调用示例

以「订单指派给陪诊师后发送通知」为例(这里最好改成异步执行,防止阻塞主流程,影响性能与用户体验,并且在阿里云短信控制台设置流控限制):

// 发送短信 TODOSysUsersysUser=sysUserService.selectUserById(assignUserId);Map<String,String>param=newHashMap<>();param.put("telNo",sysUser.getPhonenumber());// param.put("name", sysUser.getNickName());param.put("orderNo",tOrder.getOrderNo());//指派订单模板param.put("status","2");//调用阿里云发送短信try{AliyunSms.sendSms(param,null);}catch(ClientExceptione){log.error("发送短信出错:"+e.getMessage());e.printStackTrace();}

参数约定

key是否必填说明
telNo必填接收手机号,多个号码用英文逗号分隔(单次最多 1000 个)
status必填业务场景编码,决定使用哪个模板(见 4.1)
code场景相关验证码,仅status=0使用
orderNo场景相关订单号
name场景相关姓名(当前部分场景已注释)

只有当前模板里声明过的变量才会生效:工具类固定提交code/orderNo/name三个变量,多余变量不影响发送,缺失变量会导致发送失败。


四、模板对照与调用点

4.1status→ 模板对照表

status模板 CODE用途使用的变量
0SMS_508015266验证码code
1SMS_508125195下单支付成功orderNo
2SMS_508160180订单指派给陪诊师orderNo
3SMS_507950246订单回退通知管理员orderNo
4SMS_507930223订单取消通知管理员和陪诊师orderNo
5SMS_508015231开始陪诊前提前一天通知就诊人orderNo
6SMS_508180014陪诊师资格审核通过后通知用户name
7SMS_509425064订单超时 15 分钟通知陪诊师orderNo
8SMS_509740055订单超时通知客户购买超时服务orderNo

历史模板SMS_508030056(订单指派)已废弃,改用SMS_508160180。

4.2 调用点清单

场景status位置
小程序登录验证码0service/impl/IJxMpWxServiceImpl.java
订单支付成功1wxpay/service/WxPayServiceImpl.java(微信支付回调成功后)
订单指派 / 回退2/3service/impl/TOrderServiceImpl.java
订单取消4service/impl/TOrderServiceImpl.java
陪诊前一日提醒5service/impl/TOrderServiceImpl.java
陪诊师资格审核通过6controller/TMedicalApplicationController.java
订单超时通知陪诊师7service/impl/TOrderServiceImpl.java(定时任务)
订单超时通知客户8service/impl/TOrderServiceImpl.java(定时任务)

五、常见错误码

返回 Code说明处理建议
OK发送成功—
isv.SMS_SIGNATURE_ILLEGAL签名不合法 / 未审核通过检查SignName与签名状态
isv.SMS_TEMPLATE_ILLEGAL模板不合法 / 未审核通过检查模板 CODE 与状态
isv.MOBILE_NUMBER_ILLEGAL手机号格式错误校验手机号
isv.AMOUNT_NOT_ENOUGH账户余额不足充值 / 购买套餐包
isv.BUSINESS_LIMIT_CONTROL触发流控降低频率或申请提额
isv.OUT_OF_SERVICE业务停机(欠费)检查账户状态
isv.PARAM_LENGTH_LIMIT/isv.INVALID_PARAMETERS参数不合法(如变量缺失/超长)核对模板变量
SignatureDoesNotMatchAccessKey 错误检查 AK/SK 配置

排查时优先查看日志中的Code与Message,并在控制台「发送记录」中核对实际下发结果。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询