mirror of
https://gitee.com/blackfox/geekai.git
synced 2024-12-02 12:17:42 +08:00
feat: 添加支持多个短信服务商支持 添加短信宝服务商支持,同时添加配置示例
This commit is contained in:
parent
3e99b4cbf6
commit
e5e762efcd
@ -33,6 +33,23 @@ WeChatBot = false
|
|||||||
Sign = ""
|
Sign = ""
|
||||||
CodeTempId = ""
|
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 绘画图片
|
[OSS] # OSS 配置,用于存储 MJ 绘画图片
|
||||||
Active = "local" # 默认使用本地文件存储引擎
|
Active = "local" # 默认使用本地文件存储引擎
|
||||||
[OSS.Local]
|
[OSS.Local]
|
||||||
|
@ -17,6 +17,7 @@ type AppConfig struct {
|
|||||||
ApiConfig ChatPlusApiConfig // ChatPlus API authorization configs
|
ApiConfig ChatPlusApiConfig // ChatPlus API authorization configs
|
||||||
SmsConfig AliYunSmsConfig // AliYun send message service config
|
SmsConfig AliYunSmsConfig // AliYun send message service config
|
||||||
OSS OSSConfig // OSS config
|
OSS OSSConfig // OSS config
|
||||||
|
SMS SMSConfig // sms config
|
||||||
MjConfigs []MidJourneyConfig // mj AI draw service pool
|
MjConfigs []MidJourneyConfig // mj AI draw service pool
|
||||||
WeChatBot bool // 是否启用微信机器人
|
WeChatBot bool // 是否启用微信机器人
|
||||||
SdConfigs []StableDiffusionConfig // sd AI draw service pool
|
SdConfigs []StableDiffusionConfig // sd AI draw service pool
|
||||||
@ -71,14 +72,14 @@ type StableDiffusionConfig struct {
|
|||||||
Txt2ImgJsonPath string
|
Txt2ImgJsonPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
type AliYunSmsConfig struct {
|
//type AliYunSmsConfig struct {
|
||||||
AccessKey string
|
// AccessKey string
|
||||||
AccessSecret string
|
// AccessSecret string
|
||||||
Product string
|
// Product string
|
||||||
Domain string
|
// Domain string
|
||||||
Sign string // 短信签名
|
// Sign string // 短信签名
|
||||||
CodeTempId string // 验证码短信模板 ID
|
// CodeTempId string // 验证码短信模板 ID
|
||||||
}
|
//}
|
||||||
|
|
||||||
type AlipayConfig struct {
|
type AlipayConfig struct {
|
||||||
Enabled bool // 是否启用该支付通道
|
Enabled bool // 是否启用该支付通道
|
||||||
|
25
api/core/types/sms.go
Normal file
25
api/core/types/sms.go
Normal file
@ -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 // 实效性
|
||||||
|
}
|
@ -4,6 +4,7 @@ import (
|
|||||||
"chatplus/core"
|
"chatplus/core"
|
||||||
"chatplus/core/types"
|
"chatplus/core/types"
|
||||||
"chatplus/service"
|
"chatplus/service"
|
||||||
|
"chatplus/service/sms"
|
||||||
"chatplus/utils"
|
"chatplus/utils"
|
||||||
"chatplus/utils/resp"
|
"chatplus/utils/resp"
|
||||||
"strings"
|
"strings"
|
||||||
@ -17,7 +18,7 @@ const CodeStorePrefix = "/verify/codes/"
|
|||||||
type SmsHandler struct {
|
type SmsHandler struct {
|
||||||
BaseHandler
|
BaseHandler
|
||||||
redis *redis.Client
|
redis *redis.Client
|
||||||
sms *service.AliYunSmsService
|
sms *sms.SmsServiceManager
|
||||||
smtp *service.SmtpService
|
smtp *service.SmtpService
|
||||||
captcha *service.CaptchaService
|
captcha *service.CaptchaService
|
||||||
}
|
}
|
||||||
@ -25,7 +26,7 @@ type SmsHandler struct {
|
|||||||
func NewSmsHandler(
|
func NewSmsHandler(
|
||||||
app *core.AppServer,
|
app *core.AppServer,
|
||||||
client *redis.Client,
|
client *redis.Client,
|
||||||
sms *service.AliYunSmsService,
|
sms *sms.SmsServiceManager,
|
||||||
smtp *service.SmtpService,
|
smtp *service.SmtpService,
|
||||||
captcha *service.CaptchaService) *SmsHandler {
|
captcha *service.CaptchaService) *SmsHandler {
|
||||||
handler := &SmsHandler{redis: client, sms: sms, captcha: captcha, smtp: smtp}
|
handler := &SmsHandler{redis: client, sms: sms, captcha: captcha, smtp: smtp}
|
||||||
@ -63,7 +64,8 @@ func (h *SmsHandler) SendCode(c *gin.Context) {
|
|||||||
resp.ERROR(c, "系统已禁用手机号注册!")
|
resp.ERROR(c, "系统已禁用手机号注册!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = h.sms.SendVerifyCode(data.Receiver, code)
|
err = h.sms.GetUploadHandler().SendVerifyCode(data.Receiver, code)
|
||||||
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.ERROR(c, err.Error())
|
resp.ERROR(c, err.Error())
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"chatplus/service/oss"
|
"chatplus/service/oss"
|
||||||
"chatplus/service/payment"
|
"chatplus/service/payment"
|
||||||
"chatplus/service/sd"
|
"chatplus/service/sd"
|
||||||
|
"chatplus/service/sms"
|
||||||
"chatplus/service/wx"
|
"chatplus/service/wx"
|
||||||
"chatplus/store"
|
"chatplus/store"
|
||||||
"context"
|
"context"
|
||||||
@ -135,7 +136,7 @@ func main() {
|
|||||||
fx.Provide(admin.NewOrderHandler),
|
fx.Provide(admin.NewOrderHandler),
|
||||||
|
|
||||||
// 创建服务
|
// 创建服务
|
||||||
fx.Provide(service.NewAliYunSmsService),
|
fx.Provide(sms.NewSendServiceManager),
|
||||||
fx.Provide(func(config *types.AppConfig) *service.CaptchaService {
|
fx.Provide(func(config *types.AppConfig) *service.CaptchaService {
|
||||||
return service.NewCaptchaService(config.ApiConfig)
|
return service.NewCaptchaService(config.ApiConfig)
|
||||||
}),
|
}),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package service
|
package sms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"chatplus/core/types"
|
"chatplus/core/types"
|
||||||
@ -11,18 +11,19 @@ type AliYunSmsService struct {
|
|||||||
client *dysmsapi.Client
|
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(
|
client, err := dysmsapi.NewClientWithAccessKey(
|
||||||
"cn-hangzhou",
|
"cn-hangzhou",
|
||||||
config.SmsConfig.AccessKey,
|
config.AccessKey,
|
||||||
config.SmsConfig.AccessSecret)
|
config.AccessSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create client: %v", err)
|
return nil, fmt.Errorf("failed to create client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &AliYunSmsService{
|
return &AliYunSmsService{
|
||||||
config: &config.SmsConfig,
|
config: config,
|
||||||
client: client,
|
client: client,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -46,7 +47,6 @@ func (s *AliYunSmsService) SendVerifyCode(mobile string, code int) error {
|
|||||||
if response.Code != "OK" {
|
if response.Code != "OK" {
|
||||||
return fmt.Errorf("failed to send SMS:%v", response.Message)
|
return fmt.Errorf("failed to send SMS:%v", response.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package service
|
package sms
|
||||||
|
|
||||||
type SmsService interface {
|
type SmsService interface {
|
||||||
SendVerifyCode(mobile string, code int) error
|
SendVerifyCode(mobile string, code int) error
|
39
api/service/sms/sms_service_manager.go
Normal file
39
api/service/sms/sms_service_manager.go
Normal file
@ -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
|
||||||
|
}
|
86
api/service/sms/smsbao_sms_service.go
Normal file
86
api/service/sms/smsbao_sms_service.go
Normal file
@ -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{}
|
1
api/service/wanx/types.go
Normal file
1
api/service/wanx/types.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package wanx
|
@ -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"
|
api_url: "https://chat-bot-api.openai.azure.com/openai/deployments/{model}/chat/completions?api-version=2023-05-15"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "【阿里】千义通问",
|
name: "【阿里】通义千问",
|
||||||
value: "Qwen",
|
value: "Ali",
|
||||||
api_url: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
|
api_url: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
Loading…
Reference in New Issue
Block a user