运行必须源码:app/(controller/model/service/middleware/lib/utils/validate/router)、config/、database/(migrations/seeders/sql)、启动脚本、app/public/templates 模板。 已忽略运行非必须:node_modules/、logs/、run/、app/public 运行时上传数据、.env*、构建/缓存产物。
79 lines
2.7 KiB
JavaScript
79 lines
2.7 KiB
JavaScript
'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;
|