1.进入阿里云

地址:云市场_镜像市场_软件市场_建站软件_服务器软件_AI应用_API接口_应用市场 - 阿里云

1.1 进入后点击控制台

1.2 在产品与服务中搜索短信服务

1.3 在国内消息中新增资质

1.4 在国内消息中新增签名(签名需要等运营商全部报备完成,否则短信可能会发送错误)

1.5 在国内消息中新增模板

1.6 在套餐包资费中购买国内通用短信套餐包

2.购买完成后,创建用户

2.1 创建好之后,要把账户的 accessKeyIdaccessKeySecret 保存下来 ( 非常重要 !!! )

3.写代码

3.1 调用sdk

在node.js终端中安装:

$ npm install @alicloud/sms-sdk --save
$ npm install dotenv
$ npm install redis

3.2 dotenv 是一个在 Node.js 项目中常用的工具库,主要用于管理环境变量。

核心功能

1.环境变量管理:将项目配置(如数据库连接、API密钥等敏感信息)从代码中分离出来,存储在外部的 .env 文件中

2.安全保护:防止敏感信息(如密码、密钥)直接暴露在代码仓库中

3.多环境支持:方便地为不同环境(开发、测试、生产)配置不同的变量

工作原理

1.创建一个 .env 文件在项目根目录

2.在这个文件中以 KEY=VALUE 格式存储配置

3.在应用启动时,dotenv 会将这些变量加载到 process.env 中

3.2.1 代码
# 阿里云短信配置
ALIYUN_ACCESS_KEY_ID="您的AccessKey ID"     # 您的AccessKey ID
ALIYUN_ACCESS_KEY_SECRET="您的Secret"       # 您的Secret

# Redis 配置
REDIS_URL='您的Redis服务器地址'             #您的Redis服务器地址
REDIS_PASSWORD='您的Redis访问密码'          #您的Redis访问密码

3.3 在宝塔中配置 redis

3.3.1 在宝塔中安装redis

3.3.2 安装之后,点击redis  设置redis密码

3.3.3 进入配置文件 配置 bind 0.0.0.0(如果node.js后端代码已经上传到宝塔中,可以不动,如果没有上传到宝塔中,配置之后 Redis服务器地址写你的 公网ip)

3.3.4 protected-mode no  # 关闭保护模式

3.3.5 配置好之后 点击重启服务

3.3.6 重启服务之后 在宝塔 安全 → 防火墙 放行 6379 端口。

3.4 完整代码

// 1. 环境变量加载(必须在所有模块导入前执行)
// 使用 dotenv 从 .env 文件加载环境变量到 process.env
require('dotenv').config();

const { createClient } = require('redis'); // Redis 客户端

// 2. 阿里云短信 SDK 导入
// 官方提供的 Node.js SDK,封装了短信发送接口
const SMSClient = require('@alicloud/sms-sdk');

// 初始化 Redis 客户端
const redisClient = createClient({
  url: process.env.REDIS_URL, // Redis 连接地址
  password: process.env.REDIS_PASSWORD // Redis 密码
});

// 监听 Redis 连接事件
redisClient.on('connect', () => {
  console.log('Redis 客户端已连接');
});

redisClient.on('error', (err) => {
  console.error('Redis 连接错误:', err);
});

// 3. 初始化短信客户端
// 注意:ALIYUN_ACCESS_KEY_ID 和 ALIYUN_ACCESS_KEY_SECRET 需在 .env 中配置
const smsClient = new SMSClient({
  accessKeyId: process.env.ALIYUN_ACCESS_KEY_ID,       // 从环境变量读取访问密钥ID
  secretAccessKey: process.env.ALIYUN_ACCESS_KEY_SECRET, // 从环境变量读取访问密钥
  endpoint: 'https://dysmsapi.aliyuncs.com'           // 阿里云短信服务API地址(不可更改)
});

// 连接 Redis
(async () => {
  try {
    await redisClient.connect();
    console.log('Redis 连接成功');
  } catch (err) {
    console.error('Redis 连接失败:', err);
    process.exit(1); // 如果 Redis 连接失败,退出应用
  }
})();

/**
 * 发送短信验证码
 * @param {string} phoneNumber - 手机号码
 * @param {number} [expireTime=300] - 验证码有效期(秒),默认5分钟
 * @returns {Promise<Object>} 包含发送结果的对象
 */
// 4. 导出短信发送方法
exports.sendVerificationCode = async (req, res) => {
  const {phoneNumber}=req.body
  const expireTime=300 // 验证码有效期(秒),默认5分钟
  try {
    // 4.1 生成6位随机验证码(范围:100000-999999)
    const verificationCode = Math.floor(100000 + Math.random() * 900000).toString();
    
    // 4.2 生成唯一请求标识(防止重放攻击)
    // 组合时间戳和随机字符串确保唯一性
    const nonce = Date.now() + Math.random().toString(36).substring(2);
    
    // 4.3 获取当前ISO格式时间戳(阿里云要求UTC时间)
    const timestamp = new Date().toISOString();

    // 4.4 存储验证码到Redis,设置过期时间
    await redisClient.setEx(
      `sms:verification:${phoneNumber}`, // Key格式: sms:verification:手机号
      expireTime, // 过期时间(秒)
      verificationCode  // 验证码值
    );
    
    // 4.5 调用短信发送接口
    const result = await smsClient.sendSMS({
      PhoneNumbers: phoneNumber,                      // 接收号码
      SignName: '短信签名',                           // 短信签名
      TemplateCode: '短信模板CODE',                   // 短信模板CODE
      TemplateParam: JSON.stringify({ code:verificationCode }), // 模板参数
      __nonce: nonce,                                 // 防重放随机数
      __timestamp: timestamp                          // 当前时间戳
    });

    // 4.6 成功响应
    res.send({ 
      success: 0,
      data: {
        message: '短信发送成功',                       // 业务提示信息
        requestId: result.RequestId,                  // 阿里云请求ID(用于排查问题)
      }
    });

  } catch (error) {
    // 4.7. 错误处理
    console.error('[SMS_ERROR] 完整诊断:', {
      message: error.message,                        // 错误描述
      requestId: error.data?.RequestId,              // 阿里云请求ID(重要!)
      recommend: error.data?.Recommend,              // 阿里云官方诊断链接
      timestamp: new Date().toISOString()            // 错误发生时间
    });
    
    // 4.8 失败响应
    res.status(500).send({
      success: 1,
      message: '短信发送失败',                        // 用户友好提示
      error:{                                       // 返回详细错误
        error: error.message,                       // 原始错误信息
        diagnoseUrl: error.data?.Recommend          // 问题排查链接
      }
    });
  }
};

/**
 * 验证短信验证码
 * @param {string} phoneNumber - 手机号码
 * @param {string} inputCode - 用户输入的验证码
 * @returns {Promise<Object>} 包含验证结果的对象
 */

// 验证短信验证码
exports.verifyCode = async (req, res) => {
  const { phoneNumber, inputCode } = req.body;
  try {
    // 1. 从Redis获取存储的验证码
    const storedCode = await redisClient.get(`sms:verification:${phoneNumber}`);
    
    // 2. 检查验证码是否存在
    if (!storedCode) {
      return res.send({
        status:1,
        isValid: false,
        message: '验证码已过期或不存在'
      });
    }
    
    // 3. 比较验证码
    if (storedCode !== inputCode) {
      return res.send({
        status:1,
        isValid: false,
        message: '验证码错误'
      });
    }
    
    // 4. 验证成功,删除Redis中的验证码(防止重复使用)
    await redisClient.del(`sms:verification:${phoneNumber}`);
    
    return res.send({
      status:0,
      isValid: true,
      message: '验证成功'
    });
  } catch (error) {
    return res.status(500).send({
      status:1,
      isValid: false,
      message: '验证服务异常',
    });
  }
}
3.4.1 完整代码(去掉redis版本)
// 1. 环境变量加载(必须在所有模块导入前执行)
// 使用 dotenv 从 .env 文件加载环境变量到 process.env
require('dotenv').config();

// 2. 阿里云短信 SDK 导入
// 官方提供的 Node.js SDK,封装了短信发送接口
const SMSClient = require('@alicloud/sms-sdk');

// 3. 初始化短信客户端
// 注意:ALIYUN_ACCESS_KEY_ID 和 ALIYUN_ACCESS_KEY_SECRET 需在 .env 中配置
const smsClient = new SMSClient({
  accessKeyId: process.env.ALIYUN_ACCESS_KEY_ID,       // 从环境变量读取访问密钥ID
  secretAccessKey: process.env.ALIYUN_ACCESS_KEY_SECRET, // 从环境变量读取访问密钥
  endpoint: 'https://dysmsapi.aliyuncs.com'           // 阿里云短信服务API地址(不可更改)
});

// 4. 导出短信发送方法
exports.SendVerificationCode = async (req, res) => {
  try {
    // 4.1 生成6位随机验证码(范围:100000-999999)
    const verificationCode = Math.floor(100000 + Math.random() * 900000).toString();
    
    // 4.2 生成唯一请求标识(防止重放攻击)
    // 组合时间戳和随机字符串确保唯一性
    const nonce = Date.now() + Math.random().toString(36).substring(2);
    
    // 4.3 获取当前ISO格式时间戳(阿里云要求UTC时间)
    const timestamp = new Date().toISOString();

	const {phoneNumber}=req.body
    
    // 4.4 调用短信发送接口
    const result = await smsClient.sendSMS({
      PhoneNumbers: phoneNumber,                       // 接收号码
      SignName: '短信签名',                            // 短信签名
      TemplateCode: '短信模板CODE',                   // 短信模板CODE
      TemplateParam: JSON.stringify({ code:verificationCode }), // 模板变量(JSON格式)
      __nonce: nonce,                                 // 防重放随机数
      __timestamp: timestamp                          // 当前时间戳
    });

    // 4.5 成功响应
    res.send({ 
      success: 0,
      data: {
        message: '短信发送成功',                      // 业务提示信息
        requestId: result.RequestId,                  // 阿里云请求ID(用于排查问题)
      }
    });

  } catch (error) {
    // 5. 错误处理
    console.error('[SMS_ERROR] 完整诊断:', {
      message: error.message,                        // 错误描述
      requestId: error.data?.RequestId,              // 阿里云请求ID(重要!)
      recommend: error.data?.Recommend,              // 阿里云官方诊断链接
      timestamp: new Date().toISOString()            // 错误发生时间
    });
    
    // 5.1 失败响应
    res.status(500).send({
      success: 1,
      message: '短信发送失败',                        // 用户友好提示
      error:{                                        // 返回详细错误
        error: error.message,                       // 原始错误信息
        diagnoseUrl: error.data?.Recommend          // 问题排查链接
      }
    });
  }
};

3.5 使用 Apifox 调用发送短信接口 

3.6 使用 Apifox 调用验证短信验证码接口

4.完结 🌼

Logo

网易智企-云信开发者社区是面向全网开发者的技术交流与服务平台,依托近 29 年 IM、音视频技术积累,提供 IM、RTC、实时对话智能体、云原生、短信等全场景开发资源。

更多推荐