diff --git a/packages/ui/certd-client/src/components/captcha/captcha-input.vue b/packages/ui/certd-client/src/components/captcha/captcha-input.vue index bf0e308d..99d2c36c 100644 --- a/packages/ui/certd-client/src/components/captcha/captcha-input.vue +++ b/packages/ui/certd-client/src/components/captcha/captcha-input.vue @@ -56,10 +56,10 @@ function onChange(data: any) { } async function getCaptchaForm() { - return await captchaRef.value.getCaptchaForm(); + return await captchaRef.value?.getCaptchaForm(); } async function reset() { - await captchaRef.value.reset(); + await captchaRef.value?.reset(); } defineExpose({ getCaptchaForm, diff --git a/packages/ui/certd-client/src/components/captcha/captchas/tencent_captcha.vue b/packages/ui/certd-client/src/components/captcha/captchas/tencent_captcha.vue index e8b1181a..bc7a5297 100644 --- a/packages/ui/certd-client/src/components/captcha/captchas/tencent_captcha.vue +++ b/packages/ui/certd-client/src/components/captcha/captchas/tencent_captcha.vue @@ -53,6 +53,13 @@ function callback(res: { ret: number; ticket: string; randstr: string; errorCode // res(验证成功) = {ret: 0, ticket: "String", randstr: "String"} // res(请求验证码发生错误,验证码自动返回trerror_前缀的容灾票据) = {ret: 0, ticket: "String", randstr: "String", errorCode: Number, errorMessage: "String"} // 此处代码仅为验证结果的展示示例,真实业务接入,建议基于ticket和errorCode情况做不同的业务处理 + + if (res.errorCode && res.errorCode > 0) { + notification.error({ + message: `验证码验证失败:${res.errorMessage || res.errorCode}`, + }); + } + if (res.ret === 0) { emitChange({ ticket: res.ticket, @@ -116,7 +123,7 @@ function emitChange(value: any) { emit("change", value); } function reset() { - captchaInstanceRef.value.instance.reset(); + captchaInstanceRef.value?.instance?.reset(); } watch( diff --git a/packages/ui/certd-client/src/views/framework/register/index.vue b/packages/ui/certd-client/src/views/framework/register/index.vue index 931dd84e..831696dd 100644 --- a/packages/ui/certd-client/src/views/framework/register/index.vue +++ b/packages/ui/certd-client/src/views/framework/register/index.vue @@ -61,7 +61,7 @@ - + @@ -118,6 +118,7 @@ export default defineComponent({ password: "", confirmPassword: "", captcha: null, + captchaForEmail: null, }); const rules = { @@ -180,10 +181,10 @@ export default defineComponent({ message: "请通过验证码", }, ], - imgCode: [ + captchaForEmail: [ { required: true, - message: "请输入验证码", + message: "请通过验证码", }, ], }; @@ -204,7 +205,7 @@ export default defineComponent({ password: formState.password, username: formState.username, email: formState.email, - captcha: formState.captcha, + captcha: registerType.value === "email" ? formState.captchaForEmail : formState.captcha, validateCode: formState.validateCode, }) as any ); diff --git a/packages/ui/certd-server/src/plugins/plugin-captcha/tencent/index.ts b/packages/ui/certd-server/src/plugins/plugin-captcha/tencent/index.ts index f87e009c..7ddc9808 100644 --- a/packages/ui/certd-server/src/plugins/plugin-captcha/tencent/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-captcha/tencent/index.ts @@ -3,57 +3,54 @@ import { ICaptchaAddon } from "../api.js"; import { TencentAccess } from "@certd/plugin-lib"; @IsAddon({ - addonType:"captcha", - name: 'tencent', - title: '腾讯云验证码', - desc: '', - showTest:false, + addonType: "captcha", + name: "tencent", + title: "腾讯云验证码", + desc: "", + showTest: false, }) -export class TencentCaptcha extends BaseAddon implements ICaptchaAddon{ - +export class TencentCaptcha extends BaseAddon implements ICaptchaAddon { @AddonInput({ - title: '腾讯云授权', - helper: '腾讯云授权', + title: "腾讯云授权", + helper: "腾讯云授权", component: { - name: 'access-selector', - vModel:"modelValue", + name: "access-selector", + vModel: "modelValue", from: "sys", - type: 'tencent', //固定授权类型 + type: "tencent", //固定授权类型 }, required: true, }) - accessId :number; + accessId: number; @AddonInput({ - title: '验证ID', + title: "验证ID", component: { - name:"a-input-number", - placeholder: 'CaptchaAppId', + name: "a-input-number", + placeholder: "CaptchaAppId", }, - helper:"[腾讯云验证码](https://cloud.tencent.com/act/cps/redirect?redirect=37716&cps_key=b3ef73330335d7a6efa4a4bbeeb6b2c9)", + helper: "[腾讯云验证码](https://cloud.tencent.com/act/cps/redirect?redirect=37716&cps_key=b3ef73330335d7a6efa4a4bbeeb6b2c9)", required: true, }) - captchaAppId:number; + captchaAppId: number; @AddonInput({ - title: '验证Key', + title: "验证Key", component: { - placeholder: 'AppSecretKey', + placeholder: "AppSecretKey", }, required: true, }) - appSecretKey = ''; + appSecretKey = ""; - - async onValidate(data?:any) { + async onValidate(data?: any) { if (!data) { - return false + return false; } + const access = await this.getAccess(this.accessId); - const access = await this.getAccess(this.accessId) - - const sdk =await import("tencentcloud-sdk-nodejs/tencentcloud/services/captcha/v20190722/index.js"); + const sdk = await import("tencentcloud-sdk-nodejs/tencentcloud/services/captcha/v20190722/index.js"); const CaptchaClient = sdk.v20190722.Client; @@ -70,35 +67,40 @@ export class TencentCaptcha extends BaseAddon implements ICaptchaAddon{ }, }; -// 实例化要请求产品的client对象,clientProfile是可选的 + // 实例化要请求产品的client对象,clientProfile是可选的 const client = new CaptchaClient(clientConfig); const params = { - "CaptchaType": 9, //固定值9 - "UserIp": "127.0.0.1", - "Ticket": data.ticket, - "Randstr": data.randstr, - "AppSecretKey": this.appSecretKey, - "CaptchaAppId": this.captchaAppId, + CaptchaType: 9, //固定值9 + UserIp: "127.0.0.1", + Ticket: data.ticket, + Randstr: data.randstr, + AppSecretKey: this.appSecretKey, + CaptchaAppId: this.captchaAppId, }; - const res = await client.DescribeCaptchaResult(params) - - if (res.CaptchaCode == 1) { - // 验证成功 - // verification successful - return true; - } else { - // 验证失败 - // verification failed - this.logger.error("腾讯云验证码验证失败",res.CaptchaMsg) - return false; + try { + const res = await client.DescribeCaptchaResult(params); + if (res.CaptchaCode == 1) { + // 验证成功 + // verification successful + return true; + } else { + // 验证失败 + // verification failed + this.logger.error("腾讯云验证码验证失败", res.CaptchaMsg); + return false; + } + } catch (err) { + if (data.ticket.startsWith("trerror_") && err.message.includes("账户已欠费")) { + this.logger.error("腾讯云验证码账户欠费,临时放行:", err.message); + return true; + } + throw err } } - - async getCaptcha(): Promise { + async getCaptcha(): Promise { return { captchaAppId: this.captchaAppId, - } + }; } - }