第一次接阿里云发短信,大多数人会卡在几个固定的地方:签名被退回,模板改了几轮还没过,接口明明返回成功,手机却收不到。这篇按实际接入顺序,把几道审核和常见坑梳理一遍,最后附一段 Node.js 示例。

开通前先确认资质
阿里云发短信的第一道门槛是实名认证。个人和企业的资质要求不一样:企业账号一般要提供营业执照,才能申请短信签名。个人账号也能申请个人签名,但可用的业务范围和发送量都有限制,做正式业务的话,还是建议按企业来走。
动手前先想清楚短信要做什么用,因为不同类型的审核松紧差别很大:
- 验证码类(登录、注册、找回密码):模板固定,变量少,通常最容易通过。
- 通知类(订单状态、物流、预约成功):要把业务背景写清楚,模板描述必须和实际发送的场景对得上。
- 营销类(促销、优惠推送):审核最严,必须带上退订方式,内容也要符合相关法规。
签名和模板,最容易被退回的两关
签名一般是企业名或产品名的简称,比如“某某科技”“某某商城”。提交时签名要和营业执照或产品名称保持一致,换一种叫法,基本就会被打回。
模板是短信正文的格式,变量用 ${code} 这样的占位符表示。以验证码为例,可以这样写:
您的验证码为 ${code},5 分钟内有效,请勿泄露给他人。
被驳回的原因大多集中在几处:模板里混进了未报备的营销词,变量位置不合适,没有交代业务背景,或者内容和申请的场景对不上。每次提交前拿审核规范逐条对一遍,比被退回来再改省事。模板审核一般要几个小时到一两个工作日,所以上线计划里要留出这段时间,别等到发布前一天才提交。
AccessKey 怎么配
调用接口需要 AccessKey ID 和 AccessKey Secret。别直接用主账号的密钥,去 RAM(访问控制)里新建一个子用户,只给短信服务相关的权限。密钥放在环境变量或密钥管理服务里,不要写进源码,也别提交到代码仓库。密钥一旦泄露,轻则被人刷量,重则产生真实费用。
Node.js 示例:发送验证码
下面用官方 SDK 的 Dysmsapi 服务做一个发送验证码的例子。先安装依赖:
npm install @alicloud/dysmsapi20170525 @alicloud/openapi-client @alicloud/tea-util
发送逻辑如下,密钥从环境变量读取:
const Dysmsapi20170525 = require(‘@alicloud/dysmsapi20170525’);
const OpenApi = require(‘@alicloud/openapi-client’);
const Util = require(‘@alicloud/tea-util’);
function createClient() {
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’
});
return new Dysmsapi20170525.default(config);
}
async function sendSms(phone, code) {
const client = createClient();
const request = new Dysmsapi20170525.SendSmsRequest({
phoneNumbers: phone,
signName: ‘某某科技’,
templateCode: ‘SMS_XXXXXXXX’,
templateParam: JSON.stringify({ code })
});
const res = await client.sendSmsWithOptions(request, new Util.RuntimeOptions({}));
if (res.body.code !== ‘OK’) {
throw new Error(`发送失败:${res.body.code} ${res.body.message}`);
}
return res.body.bizId;
}
有三处值得留意。第一,密钥走环境变量,源码里不留痕迹。第二,成功与否要看 res.body.code,只看 HTTP 状态码不够。第三,返回的 bizId 要存下来,出了问题可以拿它去控制台查这一条短信的回执。另外,签名和模板编号要换成你自己审核通过的内容,示例里的占位值直接运行会失败。
常见错误码怎么处理
接入时最常碰到的报错大致是下面几类:
- isv.BUSINESS_LIMIT_CONTROL:同一号码发送太频繁。在业务层加发送间隔,用户反复点击时直接提示稍后再试。
- isv.MOBILE_NUMBER_ILLEGAL:手机号格式不对。调用前先做一次格式校验,别把脏数据送到接口。
- isv.TEMPLATE_MISSING_PARAMETERS:模板变量缺失或名称不一致。对照 templateParam 的键名和模板里的变量名,大小写和拼写都要完全相同。
- isv.AMOUNT_NOT_ENOUGH:账户余额不足。充值或开通后付费之后再重试。
排查时先看错误码,再去控制台看发送记录和回执状态。接口返回成功但用户没收到,问题通常出在运营商拦截、号码状态,或者内容触发了风控。这类情况要结合日志和运营商反馈一起看,只盯着代码很难定位。
上线前的几项检查
正式上线前,至少走完这几步:用测试号码完整跑一遍流程;给发送接口加频率限制,防止被恶意刷量;发送失败要做重试和告警,但重试次数必须设上限,否则故障时会一直消耗费用;每条短信的 bizId 和业务单号都记下来,对账和客服查询时用得上。
还有一点容易被忽略。短信会用到用户手机号,属于个人信息,隐私政策里要写清用途,并遵守《个人信息保护法》等相关规定。营销类短信要给出明确的退订方式,否则投诉来得很快。
回到开头的问题,阿里云发短信的顺序其实很固定:先完成实名认证,再申请签名和模板,然后配好 RAM 子账号和密钥,最后调 SDK 发送,出问题就对照错误码排查。签名和模板是耗时最长的一关,尽早提交。代码部分把密钥和结果判断做扎实,大部分坑都能绕开。