mirror of https://github.com/veypi/OneAuth.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
3.0 KiB
Go
115 lines
3.0 KiB
Go
|
2 months ago
|
package sms_providers
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
|
||
|
|
"github.com/veypi/OneAuth/cfg"
|
||
|
|
)
|
||
|
|
|
||
|
|
// SMSProvider 短信服务商接口
|
||
|
|
type SMSProvider interface {
|
||
|
|
// SendSMS 发送短信
|
||
|
|
SendSMS(ctx context.Context, req *SendSMSRequest) (id string, err error)
|
||
|
|
|
||
|
|
// GetName 获取服务商名称
|
||
|
|
GetName() string
|
||
|
|
}
|
||
|
|
|
||
|
|
var factory *ProviderFactory
|
||
|
|
var providers = make(map[string]SMSProvider)
|
||
|
|
|
||
|
|
func GetSMSProvider(region string) (SMSProvider, error) {
|
||
|
|
if factory == nil {
|
||
|
|
factory = NewProviderFactory()
|
||
|
|
// 初始化各区域的短信服务商
|
||
|
|
for region, regionConfig := range cfg.Config.SMS.Regions {
|
||
|
|
provider, err := factory.Create(regionConfig)
|
||
|
|
if err != nil {
|
||
|
|
return nil, fmt.Errorf("failed to create provider for region %s: %w", region, err)
|
||
|
|
}
|
||
|
|
providers[region] = provider
|
||
|
|
}
|
||
|
|
provider, err := factory.Create(cfg.Config.SMS.Default)
|
||
|
|
if err != nil {
|
||
|
|
return nil, fmt.Errorf("failed to create default provider: %w", err)
|
||
|
|
}
|
||
|
|
providers["default"] = provider
|
||
|
|
}
|
||
|
|
p, ok := providers[region]
|
||
|
|
if !ok {
|
||
|
|
p, ok = providers["default"]
|
||
|
|
if !ok {
|
||
|
|
return nil, fmt.Errorf("no SMS provider found for region %s", region)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return p, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// SendSMSRequest 发送短信请求
|
||
|
|
type SendSMSRequest struct {
|
||
|
|
Phone string `json:"phone"` // 手机号
|
||
|
|
TemplateID string `json:"template_id"` // 模板ID
|
||
|
|
Params map[string]string `json:"params"` // 模板参数
|
||
|
|
Region string `json:"region"` // 区域
|
||
|
|
Purpose string `json:"purpose"` // 用途
|
||
|
|
}
|
||
|
|
|
||
|
|
// SendSMSResponse 发送短信响应
|
||
|
|
type SendSMSResponse struct {
|
||
|
|
MessageID string `json:"message_id"` // 消息ID
|
||
|
|
Status string `json:"status"` // 发送状态
|
||
|
|
Cost float64 `json:"cost"` // 费用
|
||
|
|
Error string `json:"error"` // 错误信息
|
||
|
|
}
|
||
|
|
|
||
|
|
// ProviderFactory 服务商工厂
|
||
|
|
type ProviderFactory struct {
|
||
|
|
providers map[string]func(cfg.RegionConfig) (SMSProvider, error)
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewProviderFactory 创建服务商工厂
|
||
|
|
func NewProviderFactory() *ProviderFactory {
|
||
|
|
factory := &ProviderFactory{
|
||
|
|
providers: make(map[string]func(cfg.RegionConfig) (SMSProvider, error)),
|
||
|
|
}
|
||
|
|
|
||
|
|
// 注册服务商
|
||
|
|
factory.Register("aliyun", NewAliyunProvider)
|
||
|
|
factory.Register("tencent", NewTencentProvider)
|
||
|
|
|
||
|
|
return factory
|
||
|
|
}
|
||
|
|
|
||
|
|
// Register 注册服务商
|
||
|
|
func (f *ProviderFactory) Register(name string, constructor func(cfg.RegionConfig) (SMSProvider, error)) {
|
||
|
|
f.providers[name] = constructor
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create 创建服务商实例
|
||
|
|
func (f *ProviderFactory) Create(config cfg.RegionConfig) (SMSProvider, error) {
|
||
|
|
constructor, exists := f.providers[config.Provider]
|
||
|
|
if !exists {
|
||
|
|
return nil, &ProviderError{
|
||
|
|
Provider: config.Provider,
|
||
|
|
Message: "unsupported provider",
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return constructor(config)
|
||
|
|
}
|
||
|
|
|
||
|
|
// ProviderError 服务商错误
|
||
|
|
type ProviderError struct {
|
||
|
|
Provider string
|
||
|
|
Message string
|
||
|
|
Err error
|
||
|
|
}
|
||
|
|
|
||
|
|
func (e *ProviderError) Error() string {
|
||
|
|
if e.Err != nil {
|
||
|
|
return e.Provider + ": " + e.Message + ": " + e.Err.Error()
|
||
|
|
}
|
||
|
|
return e.Provider + ": " + e.Message
|
||
|
|
}
|