一、认识阿里云短信服务
短信服务是当今企业业务系统中不可或缺的基础通信能力。无论是用户注册登录时的验证码发送、订单状态变更后的通知推送、服务到期前的提醒触达,还是会员活动中的营销推广,短信都承担着连接企业与用户的重要角色。阿里云短信服务作为企业级通信服务,国内验证短信秒级触达,到达率最高可达99%,国际短信覆盖200多个国家和地区,历经双十一等极端流量场景考验。
然而在实际接入过程中,短信并不是调用一个接口、把内容发出去那么简单。尤其是首次接入时,企业通常需要依次完成资质提交、签名申请、模板审核、运营商实名报备、API对接、发送状态查询和回执配置等多个环节。本文将从零开始,完整拆解整个接入链路,并提供多种主流开发语言的SDK集成示例。
需要先登录阿里云控制台,点击:阿里云控制台
二、整体接入流程概览
一条短信从你想发送到用户收到,中间经过了完整的审核与发送链路。全流程可以拆解为以下核心环节:
- 账号准备与开通服务:注册阿里云账号、完成企业实名认证、开通短信服务
- 申请资质:提交企业营业执照等资质材料,审核通过后方可申请签名
- 申请短信签名:创建签名并等待审核通过,工作时间提交最快24小时
- 运营商实名报备:2025年起新增的必要环节,平均5至7个工作日
- 申请短信模板:创建模板并等待审核通过,约2至4小时
- 购买资源包或充值:确保账户有足够余额
- 发送短信:通过控制台群发助手或API、SDK程序化发送
需要注意的是,阿里云短信服务目前仅支持企业认证账号。个人认证用户功能受限,无法发送营销短信,且可能影响签名审核通过率。如果个人认证用户仅需发送验证码短信,可以考虑申请开通阿里云号码认证服务的短信认证功能。
三、准备工作
3.1 注册账号与企业实名认证
访问阿里云官网注册账号后,需要进行企业实名认证。个体工商户通常也算企业认证。实名认证是开通短信服务的硬性门槛。
3.2 开通短信服务
在阿里云产品列表中找到短信服务并开通,登录短信服务控制台,根据提示完成服务开通。
3.3 购买资源包或确保余额充足
短信服务计费方式分为按量计费和套餐包两种。国际站默认采用短信资源包付费模式,需要先购买资源包。如果有短信套餐包则先扣除套餐包,超出套餐包额度后按量计费,扣除账户余额。建议根据业务需要选择最优的计费方案。短信服务使用全流程中,仅在发送短信时产生费用。
3.4 创建RAM用户并获取AccessKey
AccessKey是调用API的凭证。强烈建议使用RAM子用户的AccessKey,并授予其AliyunDysmsFullAccess权限策略,这比直接使用主账号的AccessKey更安全。
创建RAM用户的步骤:
- 访问RAM控制台创建子用户
- 为该子用户设置对应的权限,推荐授予AliyunDysmsFullAccess短信管理权限
- 获取该子用户的AccessKey ID和AccessKey Secret
安全最佳实践:使用环境变量存储AccessKey(禁止硬编码)、定期轮换密钥、遵循最小权限原则。
四、申请短信资质
短信资质是阿里云对发送方身份的基础审核,相当于确认你是谁。企业需要提交营业执照或相关证件,阿里云会审核企业信息的真实性。资质审核通过后,才能进入签名和模板的申请环节。
申请资质需要填写的信息包括:
- 单位名称
- 单位法人姓名
- 单位法人身份证号
- 有效期
- 单位管理人手机号
需要上传的材料包括:
- 单位营业执照
- 单位法人身份证正反面
- 单位管理人身份证正反面
资质审核预计需要2个工作日左右。若签名归属方的企业营业执照、组织机构代码证、税务登记证不是同一张证件(非三证合一),需要分别上传。
五、申请短信签名
签名就是用户收到短信时最前面方括号里的那个名字,比如〖淘宝〗、〖菜鸟网络〗。它是短信发送方的身份标识,让用户知道这条短信是谁发的。签名必须与你提交的资质相匹配,也就是说资质是A公司,签名就应当是A公司相关的名称。
5.1 签名申请要求
短信签名需符合企事业单位名、已注册商标名的要求:
- 全称:与企业资质证照上的名称完全一致
- 简称:必须是企业名称的子集,能唯一标识企业,不可为中性词(如服务提醒)
签名来源需要有明确的来源以证明其归属性。请选择签名所归属的资质,建议选择当前已通过的资质,否则签名审核可能会失败。
5.2 运营商实名报备
从2025年起,短信签名审核通过后,阿里云会自动向运营商发起实名制报备。这个流程平均需要5至7个工作日,部分情况可能需要7至10个工作日或更长,且运营商并未对时效做出承诺。报备期间,签名无法用于发送短信。
很多用户容易把签名审核通过和签名实名制报备完成理解成同一件事,但实际上它们是两个不同的环节。短信签名审核主要确认签名是否符合平台侧申请规范;短信签名实名制报备则是向运营商或供应商报备短信子端口号实名信息。签名审核通过只代表签名已通过平台侧审核,但在运营商侧实名制报备流程未完全完成前,短信仍然可能发送失败。如果短信发送失败并返回PORT_NOT_REGISTERED错误码,应优先检查签名的运营商报备结果。
5.3 数字短信签名特殊要求
数字短信签名需进行平台审核和运营商报备,签名的三网报备状态中至少有一个报备成功,才可申请模板。运营商报备时长为5至7个工作日。
六、申请短信模板
如果说签名解决的是谁发的的问题,那模板解决的就是发什么。阿里云短信服务不允许自由填写短信内容,所有发送的短信都必须基于已审核通过的模板。这既是为了满足内容合规要求,也是防止短信被滥用的关键机制。
模板内容支持变量占位符,用variable的格式表示。比如验证码模板可以写成:您的验证码为:{variable}的格式表示。比如验证码模板可以写成:您的验证码为:{code},请勿泄露他人。其中${code}在实际发送时会被替换为真实的验证码数字。需要注意的是,变量名不能使用mobile、email等敏感词,否则审核可能不通过。
模板审核预计需要2至4小时。创建模板时,必须关联签名,从而关联到签名对应的资质信息,以提升审核效率。
七、通过API、SDK发送短信
签名和模板都审核通过后,就可以正式发送短信。阿里云短信服务支持两种主要发送模式:一种是通过控制台手动发送,另一种是通过API或SDK程序化发送。
以下分别以Java、Python、PHP、Node.js、Go五种主流开发语言为例,展示如何通过官方SDK调用SendSms接口发送短信。
7.1 Java SDK
首先在项目的pom.xml中添加阿里云短信服务SDK的依赖。Java 8或以上版本是必要的运行环境。
package com.aliyun.sample; import com.aliyun.teaopenapi.models.Config; import com.aliyun.dysmsapi20170525.Client; import com.aliyun.dysmsapi20170525.models.SendSmsRequest; import com.aliyun.dysmsapi20170525.models.SendSmsResponse; import com.aliyun.teautil.models.RuntimeOptions; public class SendSmsExample { public static void main(String[] args) throws Exception { // 初始化配置对象 Config config = new Config() .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")) .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")) .setEndpoint("dysmsapi.aliyuncs.com"); Client client = new Client(config); SendSmsRequest request = new SendSmsRequest() .setPhoneNumbers("13800000000") .setSignName("您的短信签名") .setTemplateCode("SMS_123456789") .setTemplateParam("{\"code\":\"123456\"}"); RuntimeOptions runtime = new RuntimeOptions(); SendSmsResponse response = client.sendSmsWithOptions(request, runtime); System.out.println("发送结果: " + response.getBody().getCode()); System.out.println("请求ID: " + response.getBody().getRequestId()); } }
7.2 Python SDK
阿里云官方提供的Python语言SDK,基于阿里云OpenAPI规范构建,封装了认证、请求签名、HTTP通信、错误处理等底层逻辑。
# -*- coding: utf-8 -*- import os from aliyunsdkcore.client import AcsClient from aliyunsdkdysmsapi.request.v20170525 import SendSmsRequest # 初始化客户端 client = AcsClient( os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'), os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), 'cn-hangzhou' ) request = SendSmsRequest.SendSmsRequest() request.set_PhoneNumbers('13800000000') request.set_SignName('您的短信签名') request.set_TemplateCode('SMS_123456789') request.set_TemplateParam('{"code":"123456"}') response = client.do_action_with_exception(request) print(response.decode('utf-8'))
7.3 PHP SDK
推荐使用阿里云官方SDK,避免手动cURL遗漏签名、编码及错误处理。PHP 5.5以上版本均可支持。
<?php require_once 'vendor/autoload.php'; use AlibabaCloud\Client\AlibabaCloud; use AlibabaCloud\Client\Exception\ClientException; use AlibabaCloud\Client\Exception\ServerException; // 初始化客户端 AlibabaCloud::accessKeyClient( getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'), getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET') )->regionId('cn-hangzhou')->asDefaultClient(); try { $result = AlibabaCloud::rpc() ->product('Dysmsapi') ->version('2017-05-25') ->action('SendSms') ->method('POST') ->host('dysmsapi.aliyuncs.com') ->options([ 'query' => [ 'PhoneNumbers' => '13800000000', 'SignName' => '您的短信签名', 'TemplateCode' => 'SMS_123456789', 'TemplateParam' => '{"code":"123456"}' ] ]) ->request(); print_r($result->toArray()); } catch (ClientException $e) { echo $e->getErrorMessage() . PHP_EOL; } catch (ServerException $e) { echo $e->getErrorMessage() . PHP_EOL; }
7.4 Node.js、TypeScript SDK
阿里云短信服务SDK for Node.js支持验证码短信、营销短信、国际短信等多种业务场景。
const DysmsapiClient = require('@alicloud/dysmsapi20170525'); const OpenApi = require('@alicloud/openapi-client'); const Util = require('@alicloud/tea-util'); async function sendSms() { // 初始化配置 const config = new OpenApi.Config({ accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID, accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET, endpoint: 'dysmsapi.aliyuncs.com' }); const client = new DysmsapiClient.default(config); const request = new DysmsapiClient.SendSmsRequest({ phoneNumbers: '13800000000', signName: '您的短信签名', templateCode: 'SMS_123456789', templateParam: '{"code":"123456"}' }); try { const response = await client.sendSms(request); console.log('发送结果:', response.body.code); console.log('请求ID:', response.body.requestId); } catch (error) { console.error('发送失败:', error.message); } } sendSms();
7.5 Go SDK
阿里云短信服务OpenAPI基于HTTPS加RESTful设计,采用POST /?Action=SendSms统一路由,所有请求需签名、时间戳及随机串。
package main import ( "fmt" "os" "github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi" ) func main() { // 初始化客户端 client, err := dysmsapi.NewClientWithAccessKey( "cn-hangzhou", os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"), ) if err != nil { panic(err) } request := dysmsapi.CreateSendSmsRequest() request.Scheme = "https" request.PhoneNumbers = "13800000000" request.SignName = "您的短信签名" request.TemplateCode = "SMS_123456789" request.TemplateParam = `{"code":"123456"}` response, err := client.SendSms(request) if err != nil { fmt.Println("发送失败:", err) return } fmt.Println("发送结果:", response.Code) fmt.Println("请求ID:", response.RequestId) }
八、发送状态回执与错误排查
8.1 发送状态回执
API返回Code为OK但短信实际发送失败或未收到时,需要进一步排查。应检查签名状态:确认使用的签名是否在当前阿里云账号下且状态为审核通过。跨账号使用签名将无法发送。登录短信服务控制台,在业务统计大于发送记录页面,查看该条短信的运营商回执错误码,根据错误码定位具体失败原因。
8.2 常见错误码
- PORT_NOT_REGISTERED:当前使用端口号尚未完成企业实名制报备流程。应优先检查签名的运营商报备结果。
- 签名无效或不存在:签名已失效、不存在或已被拒绝。登录短信服务控制台,在签名管理页面查看此签名是否审核通过。
- 签名格式错误:删除签名中的空格、特殊符号,修改错别字。
最近短信发送失败可能是因为签名的实名制报备不完整。即使返回了不同的错误码,失败原因通常也是运营商拦截了使用未报备签名发送的短信。
九、安全实践与成本优化
9.1 安全最佳实践
- 使用环境变量存储AccessKey,禁止在代码中硬编码
- 定期轮换AccessKey密钥
- 遵循最小权限原则,仅授予必要权限
- 使用RAM子账号而非主账号的AccessKey
9.2 成本优化策略
- 根据业务量选择合适的套餐包,超出套餐包额度后按量计费
- 国内短信验证码秒级触达,到达率最高可达99%
- 国际短信覆盖200多个国家和地区,但不同国家有不同合规要求
- 印度需要完成DLT注册,沙特阿拉伯需要预注册Sender ID,美国、加拿大推荐使用当地号码以提高到达率
十、国际短信特别说明
国际短信流程更为简化,大部分国家和地区无需预先申请签名和模板。只需完成账号注册、实名认证和充值,即可通过控制台或API直接调用发送。但部分国家有特殊要求,需提前了解:
- 印度:需要完成DLT注册
- 沙特阿拉伯:需要预注册Sender ID
- 美国、加拿大:推荐使用当地号码(长码、短码)以提高到达率
十一、常见问题与解答
问1:个人认证账号能否使用阿里云短信服务?
阿里云短信服务目前仅支持企业认证账号。个人认证用户功能受限,无法发送营销短信,且可能影响签名审核通过率。如果仅需发送验证码短信,可以考虑申请开通阿里云号码认证服务的短信认证功能。
问2:短信签名审核通过后就能立即发送短信吗?
不能。签名审核通过后,还需要完成运营商实名制报备,这个过程平均需要5至7个工作日。报备完成前签名无法用于发送短信。签名审核通过和运营商报备完成是两个不同的环节。
问3:短信模板中的变量有什么限制?
模板内容支持变量占位符,格式为${variable}。变量名不能使用mobile、email等敏感词,否则审核可能不通过。
问4:API返回Code为OK但用户收不到短信怎么办?
首先检查签名状态是否为审核通过且在当前账号下。然后登录短信服务控制台,在业务统计大于发送记录页面查看运营商回执错误码。特别要注意检查签名是否已完成运营商实名制报备。
问5:如何安全地使用AccessKey?
强烈建议使用RAM子用户的AccessKey并授予AliyunDysmsFullAccess权限。使用环境变量存储AccessKey,禁止硬编码,定期轮换密钥,遵循最小权限原则。
问6:国际短信和国内短信在申请流程上有什么区别?
国际短信流程更为简化,大部分国家和地区无需预先申请签名和模板,完成账号准备后即可直接发送。但部分国家有特殊合规要求,如印度的DLT注册、沙特阿拉伯的Sender ID预注册等,需要提前了解。