From 9c73e165608b0956c3913242cd7a825e2e365ca8 Mon Sep 17 00:00:00 2001 From: whale_fall <15826189779@163.com> Date: Mon, 22 Jan 2024 16:38:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E7=9F=AD=E4=BF=A1=E6=9C=8D=E5=8A=A1=E5=95=86?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20=E6=B7=BB=E5=8A=A0=E7=9F=AD=E4=BF=A1?= =?UTF-8?q?=E5=AE=9D=E6=9C=8D=E5=8A=A1=E5=95=86=E6=94=AF=E6=8C=81,?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E6=B7=BB=E5=8A=A0=E9=85=8D=E7=BD=AE=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/config.sample.toml | 17 ++++ api/core/types/config.go | 17 ++-- api/core/types/sms.go | 25 ++++++ api/handler/sms_handler.go | 8 +- api/main.go | 3 +- api/service/{ => sms}/aliyun_sms_service.go | 12 +-- api/service/{ => sms}/sms_service.go | 2 +- api/service/sms/sms_service_manager.go | 39 ++++++++++ api/service/sms/smsbao_sms_service.go | 86 +++++++++++++++++++++ api/service/wanx/types.go | 1 + web/src/views/admin/ApiKey.vue | 4 +- 11 files changed, 193 insertions(+), 21 deletions(-) create mode 100644 api/core/types/sms.go rename api/service/{ => sms}/aliyun_sms_service.go (85%) rename api/service/{ => sms}/sms_service.go (82%) create mode 100644 api/service/sms/sms_service_manager.go create mode 100644 api/service/sms/smsbao_sms_service.go create mode 100644 api/service/wanx/types.go diff --git a/api/config.sample.toml b/api/config.sample.toml index 6282604f..1e93001c 100644 --- a/api/config.sample.toml +++ b/api/config.sample.toml @@ -33,6 +33,23 @@ WeChatBot = false Sign = "" CodeTempId = "" +[Sms] # Sms 配置,用于发送短信 + Active = "SmsBao" # 默认使用 + [Sms.SmsBao] + Account = "" #账号 + ApiKey = "" # apikey + Domain = "api.smsbao.com" # 发送短信的域名 + Sign = "【鲸落科技】" # 签名 + CodeTemplate = "您的验证码是{code}。请于{num}分钟内使用,若非本人操作,请忽略本短信。" # 短信模板 + Num = "30" # 短信有效期 + [Sms.Ali] + AccessKey = "" + AccessSecret = "" + Product = "Dysmsapi" + Domain = "dysmsapi.aliyuncs.com" + Sign = "" + CodeTempId = "" + [OSS] # OSS 配置,用于存储 MJ 绘画图片 Active = "local" # 默认使用本地文件存储引擎 [OSS.Local] diff --git a/api/core/types/config.go b/api/core/types/config.go index 0a54341a..f381799e 100644 --- a/api/core/types/config.go +++ b/api/core/types/config.go @@ -17,6 +17,7 @@ type AppConfig struct { ApiConfig ChatPlusApiConfig // ChatPlus API authorization configs SmsConfig AliYunSmsConfig // AliYun send message service config OSS OSSConfig // OSS config + SMS SMSConfig // sms config MjConfigs []MidJourneyConfig // mj AI draw service pool WeChatBot bool // 是否启用微信机器人 SdConfigs []StableDiffusionConfig // sd AI draw service pool @@ -71,14 +72,14 @@ type StableDiffusionConfig struct { Txt2ImgJsonPath string } -type AliYunSmsConfig struct { - AccessKey string - AccessSecret string - Product string - Domain string - Sign string // 短信签名 - CodeTempId string // 验证码短信模板 ID -} +//type AliYunSmsConfig struct { +// AccessKey string +// AccessSecret string +// Product string +// Domain string +// Sign string // 短信签名 +// CodeTempId string // 验证码短信模板 ID +//} type AlipayConfig struct { Enabled bool // 是否启用该支付通道 diff --git a/api/core/types/sms.go b/api/core/types/sms.go new file mode 100644 index 00000000..4b1d62c8 --- /dev/null +++ b/api/core/types/sms.go @@ -0,0 +1,25 @@ +package types + +type SMSConfig struct { + Active string + ALI AliYunSmsConfig + SMSBAO SmsBaoSmsConfig +} + +type AliYunSmsConfig struct { + AccessKey string + AccessSecret string + Product string + Domain string + Sign string // 短信签名 + CodeTempId string // 验证码短信模板 ID +} + +type SmsBaoSmsConfig struct { + Account string //短信包平台注册的用户名 + ApiKey string //apiKey + Domain string //域名 + Sign string // 短信签名 + CodeTemplate string // 验证码短信模板 匹配 + Num string // 实效性 +} diff --git a/api/handler/sms_handler.go b/api/handler/sms_handler.go index c58eedb5..03cc8faa 100644 --- a/api/handler/sms_handler.go +++ b/api/handler/sms_handler.go @@ -4,6 +4,7 @@ import ( "chatplus/core" "chatplus/core/types" "chatplus/service" + "chatplus/service/sms" "chatplus/utils" "chatplus/utils/resp" "strings" @@ -17,7 +18,7 @@ const CodeStorePrefix = "/verify/codes/" type SmsHandler struct { BaseHandler redis *redis.Client - sms *service.AliYunSmsService + sms *sms.SmsServiceManager smtp *service.SmtpService captcha *service.CaptchaService } @@ -25,7 +26,7 @@ type SmsHandler struct { func NewSmsHandler( app *core.AppServer, client *redis.Client, - sms *service.AliYunSmsService, + sms *sms.SmsServiceManager, smtp *service.SmtpService, captcha *service.CaptchaService) *SmsHandler { handler := &SmsHandler{redis: client, sms: sms, captcha: captcha, smtp: smtp} @@ -63,7 +64,8 @@ func (h *SmsHandler) SendCode(c *gin.Context) { resp.ERROR(c, "系统已禁用手机号注册!") return } - err = h.sms.SendVerifyCode(data.Receiver, code) + err = h.sms.GetUploadHandler().SendVerifyCode(data.Receiver, code) + } if err != nil { resp.ERROR(c, err.Error()) diff --git a/api/main.go b/api/main.go index 879c93fb..47172ab4 100644 --- a/api/main.go +++ b/api/main.go @@ -12,6 +12,7 @@ import ( "chatplus/service/oss" "chatplus/service/payment" "chatplus/service/sd" + "chatplus/service/sms" "chatplus/service/wx" "chatplus/store" "context" @@ -135,7 +136,7 @@ func main() { fx.Provide(admin.NewOrderHandler), // 创建服务 - fx.Provide(service.NewAliYunSmsService), + fx.Provide(sms.NewSendServiceManager), fx.Provide(func(config *types.AppConfig) *service.CaptchaService { return service.NewCaptchaService(config.ApiConfig) }), diff --git a/api/service/aliyun_sms_service.go b/api/service/sms/aliyun_sms_service.go similarity index 85% rename from api/service/aliyun_sms_service.go rename to api/service/sms/aliyun_sms_service.go index d3414ee6..b58f35b9 100644 --- a/api/service/aliyun_sms_service.go +++ b/api/service/sms/aliyun_sms_service.go @@ -1,4 +1,4 @@ -package service +package sms import ( "chatplus/core/types" @@ -11,18 +11,19 @@ type AliYunSmsService struct { client *dysmsapi.Client } -func NewAliYunSmsService(config *types.AppConfig) (*AliYunSmsService, error) { +func NewAliYunSmsService(appConfig *types.AppConfig) (*AliYunSmsService, error) { + config := &appConfig.SMS.ALI // 创建阿里云短信客户端 client, err := dysmsapi.NewClientWithAccessKey( "cn-hangzhou", - config.SmsConfig.AccessKey, - config.SmsConfig.AccessSecret) + config.AccessKey, + config.AccessSecret) if err != nil { return nil, fmt.Errorf("failed to create client: %v", err) } return &AliYunSmsService{ - config: &config.SmsConfig, + config: config, client: client, }, nil } @@ -46,7 +47,6 @@ func (s *AliYunSmsService) SendVerifyCode(mobile string, code int) error { if response.Code != "OK" { return fmt.Errorf("failed to send SMS:%v", response.Message) } - return nil } diff --git a/api/service/sms_service.go b/api/service/sms/sms_service.go similarity index 82% rename from api/service/sms_service.go rename to api/service/sms/sms_service.go index 371ea20e..03b61d05 100644 --- a/api/service/sms_service.go +++ b/api/service/sms/sms_service.go @@ -1,4 +1,4 @@ -package service +package sms type SmsService interface { SendVerifyCode(mobile string, code int) error diff --git a/api/service/sms/sms_service_manager.go b/api/service/sms/sms_service_manager.go new file mode 100644 index 00000000..36d9f47b --- /dev/null +++ b/api/service/sms/sms_service_manager.go @@ -0,0 +1,39 @@ +package sms + +import ( + "chatplus/core/types" + "strings" +) + +type SmsServiceManager struct { + handler SmsService +} + +const Ali = "Ali" +const SmsBao = "SmsBao" + +func NewSendServiceManager(config *types.AppConfig) (*SmsServiceManager, error) { + active := SmsBao + if config.OSS.Active != "" { + active = strings.ToUpper(config.SMS.Active) + } + var handler SmsService + switch active { + case Ali: + client, err := NewAliYunSmsService(config) + if err != nil { + return nil, err + } + handler = client + break + case SmsBao: + handler = NewSmsBaoSmsService(config) + break + } + + return &SmsServiceManager{handler: handler}, nil +} + +func (m *SmsServiceManager) GetUploadHandler() SmsService { + return m.handler +} diff --git a/api/service/sms/smsbao_sms_service.go b/api/service/sms/smsbao_sms_service.go new file mode 100644 index 00000000..cc19a584 --- /dev/null +++ b/api/service/sms/smsbao_sms_service.go @@ -0,0 +1,86 @@ +package sms + +import ( + "chatplus/core/types" + logger2 "chatplus/logger" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strconv" + "strings" +) + +var logger = logger2.GetLogger() + +type SmsBaoSmsService struct { + config *types.SmsBaoSmsConfig +} + +func NewSmsBaoSmsService(appConfig *types.AppConfig) *SmsBaoSmsService { + return &SmsBaoSmsService{ + config: &appConfig.SMS.SMSBAO, + } +} + +var statusStr = map[string]string{ + "0": "短信发送成功", + "-1": "参数不全", + "-2": "服务器空间不支持,请确认支持curl或者fsocket,联系您的空间商解决或者更换空间", + "30": "密码错误", + "40": "账号不存在", + "41": "余额不足", + "42": "账户已过期", + "43": "IP地址限制", + "50": "内容含有敏感词", +} + +func (s *SmsBaoSmsService) SendVerifyCode(mobile string, code int) error { + + content := fmt.Sprintf("%s%s", s.config.Sign, s.config.CodeTemplate) + template := replaceTemplate(content, s.config.Num, code) + + md5Hash := s.config.ApiKey + params := url.Values{} + params.Set("u", s.config.Account) + params.Set("p", md5Hash) + params.Set("m", mobile) + params.Set("c", template) + + // 判断 s.config.Domain 是否为空 + if s.config.Domain == "" { + // 设置默认值 + s.config.Domain = "api.smsbao.com" + // 记录日志,提醒用户默认值被使用 + logger.Infof("SmsBao.config.Domain is empty. Using default value: %s", s.config.Domain) + } + real_url := fmt.Sprintf("https://%s/sms?", s.config.Domain) + sendURL := real_url + params.Encode() + logger.Infof("send SmsBao content: %v", template) + + response, err := http.Get(sendURL) + if err != nil { + return err + } + defer response.Body.Close() + + body, err := ioutil.ReadAll(response.Body) + if err != nil { + return err + } + result := string(body) + logger.Infof("send SmsBao result: %v", statusStr[result]) + + if result != "0" { + return fmt.Errorf("failed to send SMS:%v", statusStr[result]) + } + return nil +} + +func replaceTemplate(template, num string, code int) string { + result := strings.ReplaceAll(template, "{code}", strconv.Itoa(code)) + result = strings.ReplaceAll(result, "{num}", num) + return result +} + +var _ SmsService = &SmsBaoSmsService{} diff --git a/api/service/wanx/types.go b/api/service/wanx/types.go new file mode 100644 index 00000000..23a6e31c --- /dev/null +++ b/api/service/wanx/types.go @@ -0,0 +1 @@ +package wanx diff --git a/web/src/views/admin/ApiKey.vue b/web/src/views/admin/ApiKey.vue index 5f44bd53..51700cb4 100644 --- a/web/src/views/admin/ApiKey.vue +++ b/web/src/views/admin/ApiKey.vue @@ -176,8 +176,8 @@ const platforms = ref([ api_url: "https://chat-bot-api.openai.azure.com/openai/deployments/{model}/chat/completions?api-version=2023-05-15" }, { - name: "【阿里】千义通问", - value: "Qwen", + name: "【阿里】通义千问", + value: "Ali", api_url: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation" }, ])