Files
competition-website/app/service/sms.js
WorkBuddy a303cf2d53 chore: 后端首次基线提交
运行必须源码:app/(controller/model/service/middleware/lib/utils/validate/router)、config/、database/(migrations/seeders/sql)、启动脚本、app/public/templates 模板。
已忽略运行非必须:node_modules/、logs/、run/、app/public 运行时上传数据、.env*、构建/缓存产物。
2026-08-17 12:25:42 +08:00

79 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
const Service = require('egg').Service;
/**
* 短信网关服务(阿里云 Dysmsapi)
*
* 仅负责把"服务端已生成的验证码"下发给手机号,不参与验证码的存证与校验
* (校验仍由 ctx.session 在 auth 控制器中完成,契约见 verify_sms_and_import_lock 测试)。
*
* 依赖 SDK(生产环境需 npm install):
* @alicloud/openapi-client
* @alicloud/dysmsapi20170525
* @alicloud/tea-util
*/
class SmsService extends Service {
/**
* 发送短信验证码
* @param {string} phone - 接收短信的手机号
* @param {string} code - 6 位验证码(由调用方生成并存入 session)
* @returns {Promise<{ok:boolean, message:string}>}
*/
async sendVerifyCode(phone, code) {
const { ctx, app } = this;
const cfg = app.config.sms && app.config.sms.aliyun;
if (!cfg || !cfg.accessKeyId || !cfg.accessKeySecret) {
ctx.logger.error('[短信网关] 未配置阿里云密钥,无法发送');
return { ok: false, message: '短信网关未配置' };
}
let OpenApi;
let Dysmsapi;
let Util;
try {
OpenApi = require('@alicloud/openapi-client');
Dysmsapi = require('@alicloud/dysmsapi20170525');
Util = require('@alicloud/tea-util');
} catch (e) {
ctx.logger.error('[短信网关] 未安装阿里云 SDK:' + e.message);
return { ok: false, message: '短信网关 SDK 未安装' };
}
try {
const config = new OpenApi.Config({
accessKeyId: cfg.accessKeyId,
accessKeySecret: cfg.accessKeySecret,
endpoint: cfg.endpoint,
});
const client = new Dysmsapi.default(config);
const request = new Dysmsapi.SendSmsRequest({
phoneNumbers: String(phone),
signName: cfg.signName,
templateCode: cfg.templateCode,
templateParam: JSON.stringify({ code: String(code) }),
});
const runtime = new Util.RuntimeOptions({});
runtime.readTimeout = 5000;
runtime.connectTimeout = 5000;
const response = await client.sendSmsWithOptions(request, runtime);
const body = response && response.body;
if (body && body.code === 'OK') {
ctx.logger.info(`[短信网关] 验证码已下发至 ${phone}`);
return { ok: true, message: '验证码发送成功' };
}
const reason = (body && (body.message || body.code)) || '未知错误';
ctx.logger.error(`[短信网关] 下发失败:${reason}`);
return { ok: false, message: reason };
} catch (err) {
ctx.logger.error('[短信网关] 调用异常:' + (err && err.message));
return { ok: false, message: (err && err.message) || '短信网关调用异常' };
}
}
}
module.exports = SmsService;