diff --git a/packages/ui/certd-client/src/locales/langs/en-US/certd.ts b/packages/ui/certd-client/src/locales/langs/en-US/certd.ts index 60c1d71a..af8aac99 100644 --- a/packages/ui/certd-client/src/locales/langs/en-US/certd.ts +++ b/packages/ui/certd-client/src/locales/langs/en-US/certd.ts @@ -587,6 +587,7 @@ export default { commFeature: "Commercial feature", smsProvider: "SMS provider", aliyunSms: "Aliyun SMS", + tencentSms: "Tencent SMS", yfySms: "YFY SMS", smsTest: "SMS test", testMobilePlaceholder: "Enter test mobile number", diff --git a/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts b/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts index 60ea53a5..ed5b7207 100644 --- a/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts +++ b/packages/ui/certd-client/src/locales/langs/zh-CN/certd.ts @@ -593,6 +593,7 @@ export default { commFeature: "商业版功能", smsProvider: "短信提供商", aliyunSms: "阿里云短信", + tencentSms: "腾讯云短信", yfySms: "易发云短信", smsTest: "短信测试", testMobilePlaceholder: "输入测试手机号", diff --git a/packages/ui/certd-client/src/views/sys/settings/tabs/register.vue b/packages/ui/certd-client/src/views/sys/settings/tabs/register.vue index 2272ae8f..d115f1f9 100644 --- a/packages/ui/certd-client/src/views/sys/settings/tabs/register.vue +++ b/packages/ui/certd-client/src/views/sys/settings/tabs/register.vue @@ -45,6 +45,7 @@ {{ t("certd.aliyunSms") }} + {{ t("certd.tencentSms") }} {{ t("certd.yfySms") }} diff --git a/packages/ui/certd-server/src/controller/sys/settings/sys-settings-controller.ts b/packages/ui/certd-server/src/controller/sys/settings/sys-settings-controller.ts index 14f58f5b..ac9bb252 100644 --- a/packages/ui/certd-server/src/controller/sys/settings/sys-settings-controller.ts +++ b/packages/ui/certd-server/src/controller/sys/settings/sys-settings-controller.ts @@ -164,7 +164,8 @@ export class SysSettingsController extends CrudController { @Post('/getSmsTypeDefine', { summary: 'sys:settings:view' }) async getSmsTypeDefine(@Body('type') type: string) { - return this.ok(SmsServiceFactory.getDefine(type)); + const define =await SmsServiceFactory.getDefine(type); + return this.ok(define); } diff --git a/packages/ui/certd-server/src/modules/basic/service/code-service.ts b/packages/ui/certd-server/src/modules/basic/service/code-service.ts index 93445b7d..1a252efc 100644 --- a/packages/ui/certd-server/src/modules/basic/service/code-service.ts +++ b/packages/ui/certd-server/src/modules/basic/service/code-service.ts @@ -83,7 +83,7 @@ export class CodeService { } const smsType = sysSettings.sms.type; const smsConfig = sysSettings.sms.config; - const sender: ISmsService = SmsServiceFactory.createSmsService(smsType); + const sender: ISmsService = await SmsServiceFactory.createSmsService(smsType); const accessGetter = new AccessSysGetter(this.accessService); sender.setCtx({ accessService: accessGetter, diff --git a/packages/ui/certd-server/src/modules/basic/sms/factory.ts b/packages/ui/certd-server/src/modules/basic/sms/factory.ts index 48a33886..74566e54 100644 --- a/packages/ui/certd-server/src/modules/basic/sms/factory.ts +++ b/packages/ui/certd-server/src/modules/basic/sms/factory.ts @@ -1,25 +1,28 @@ -import { AliyunSmsService } from './aliyun-sms.js'; -import { YfySmsService } from './yfy-sms.js'; export class SmsServiceFactory { - static createSmsService(type: string) { - const cls = this.GetClassByType(type); + static async createSmsService(type: string) { + const cls = await this.GetClassByType(type); return new cls(); } - static GetClassByType(type: string) { + static async GetClassByType(type: string) { switch (type) { case 'aliyun': + const {AliyunSmsService} = await import("./aliyun-sms.js") return AliyunSmsService; case 'yfysms': + const {YfySmsService} = await import("./yfy-sms.js") return YfySmsService; + case 'tencent': + const {TencentSmsService} = await import("./tencent-sms.js") + return TencentSmsService; default: throw new Error('不支持的短信服务类型'); } } - static getDefine(type: string) { - const cls = this.GetClassByType(type); + static async getDefine(type: string) { + const cls = await this.GetClassByType(type); return cls.getDefine(); } } diff --git a/packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts b/packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts new file mode 100644 index 00000000..4032aff4 --- /dev/null +++ b/packages/ui/certd-server/src/modules/basic/sms/tencent-sms.ts @@ -0,0 +1,124 @@ +import {ISmsService, PluginInputs, SmsPluginCtx} from './api.js'; +import {TencentAccess} from "@certd/plugin-lib"; + +export type TencentSmsConfig = { + accessId: string; + signName: string; + codeTemplateId: string; + appId: string; + region: string; +}; + +export class TencentSmsService implements ISmsService { + static getDefine() { + return { + name: 'tencent', + desc: '腾讯云短信服务', + input: { + accessId: { + title: '腾讯云授权', + component: { + name: 'access-selector', + type: 'tencent', + }, + required: true, + }, + region: { + title: '区域', + value:"ap-beijing", + component: { + name: 'a-select', + vModel: 'value', + options:[ + {value:"ap-beijing",label:"华北地区(北京)"}, + {value:"ap-guangzhou",label:"华南地区(广州)"}, + {value:"ap-nanjing",label:"华东地区(南京)"}, + ] + }, + helper:"随便选一个", + required: true, + }, + signName: { + title: '签名', + component: { + name: 'a-input', + vModel: 'value', + }, + required: true, + }, + appId: { + title: '应用ID', + component: { + name: 'a-input', + vModel: 'value', + }, + required: true, + }, + codeTemplateId: { + title: '验证码模板Id', + component: { + name: 'a-input', + vModel: 'value', + }, + required: true, + }, + } as PluginInputs, + }; + } + + ctx: SmsPluginCtx; + + setCtx(ctx: any) { + this.ctx = ctx; + } + + + async getClient() { + const sdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/sms/v20210111/index.js'); + const client = sdk.v20210111.Client; + const access = await this.ctx.accessService.getById(this.ctx.config.accessId); + + + // const region = this.region; + const clientConfig = { + credential: { + secretId: access.secretId, + secretKey: access.secretKey, + }, + region: this.ctx.config.region, + profile: { + httpProfile: { + endpoint: `sms.${access.intlDomain()}tencentcloudapi.com`, + }, + }, + }; + + return new client(clientConfig); + } + + async sendSmsCode(opts: { mobile: string; code: string; phoneCode: string }) { + const { mobile, code, phoneCode } = opts; + + const client = await this.getClient(); + const smsConfig = this.ctx.config; + const params = { + "PhoneNumberSet": [ + `+${phoneCode}${mobile}` + ], + "SmsSdkAppId": smsConfig.appId, + "TemplateId": smsConfig.codeTemplateId, + "SignName": smsConfig.signName, + "TemplateParamSet": [ + code + ] + }; + const ret = await client.SendSms(params); + this.checkRet(ret); + } + + checkRet(ret: any) { + if (!ret || ret.Error) { + throw new Error('执行失败:' + ret.Error.Code + ',' + ret.Error.Message); + } + } +}