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 }