package sms_tool import ( "context" "errors" "fmt" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v5/client" util "github.com/alibabacloud-go/tea-utils/v2/service" "github.com/alibabacloud-go/tea/tea" "github.com/redis/go-redis/v9" "time" ) type SmsClient struct { SmsConfig Cache ICacheAdapter client *dysmsapi20170525.Client } type SmsConfig struct { AccessKeyId string `json:"accessKeyId"` AccessKeySecret string `json:"accessKeySecret"` Endpoint string `json:"endpoint"` } func NewSmsClient(smsConfig *SmsConfig) (smsClient SmsClient, err error) { config := &openapi.Config{} if smsConfig.AccessKeyId == "" { return SmsClient{}, errors.New("AccessKeyId 不能为空") } if smsConfig.AccessKeySecret == "" { return SmsClient{}, errors.New("AccessKeySecret 不能为空") } if smsConfig.Endpoint == "" { smsConfig.Endpoint = "dysmsapi.aliyuncs.com" } config.AccessKeyId = tea.String(smsConfig.AccessKeyId) config.AccessKeySecret = tea.String(smsConfig.AccessKeySecret) // Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi config.Endpoint = tea.String(smsConfig.Endpoint) smsClient.client = &dysmsapi20170525.Client{} smsClient.client, err = dysmsapi20170525.NewClient(config) return smsClient, err } // SendSms 发送短信 func (c *SmsClient) SendSms(params *SendSmsParams) (res *dysmsapi20170525.SendSmsResponse, err error) { smsParams := &dysmsapi20170525.SendSmsRequest{ OutId: tea.String(params.OutId), OwnerId: tea.Int64(params.OwnerId), PhoneNumbers: tea.String(params.PhoneNumbers), ResourceOwnerAccount: tea.String(params.ResourceOwnerAccount), ResourceOwnerId: tea.Int64(params.ResourceOwnerId), SignName: tea.String(params.SignName), SmsUpExtendCode: tea.String(params.SmsUpExtendCode), TemplateCode: tea.String(params.TemplateCode), TemplateParam: tea.String(params.TemplateParam), } runtime := &util.RuntimeOptions{} return c.client.SendSmsWithOptions(smsParams, runtime) } // GetCode 获取验证码 func (c *SmsClient) GetCode(ctx context.Context, key string) (code string, err error) { if c.Cache == nil { return "", errors.New("缓存不能为空") } value, err := c.Cache.Get(ctx, key) if err != nil { return "", err } return value.(string), nil } // SaveCode 保存验证码 func (c *SmsClient) SaveCode(ctx context.Context, key string, code string, expire time.Duration, frequency time.Duration) (err error) { if c.Cache == nil { return errors.New("缓存不能为空") } frequencyKey := fmt.Sprintf(CodeFrequencyKey, key) if frequency != 0 { // 判断验证码是否频繁 frequencyValue, err := c.Cache.Get(ctx, frequencyKey) if err != nil { if errors.Is(err, redis.Nil) { // 缓存中没有数据 fmt.Printf("缓存中没有数据") } else { return err } } if frequencyValue != nil && frequencyValue.(string) == CodeFrequencyValue { return errors.New("code发送频繁,请稍后再试") } } //保存code err = c.Cache.Set(ctx, key, code, expire) if err != nil { return err } if frequency != 0 { // 保存验证码发送频率 err = c.Cache.Set(ctx, frequencyKey, CodeFrequencyValue, frequency) if err != nil { return err } } return nil } // DeleteCode 删除验证码 func (c *SmsClient) DeleteCode(ctx context.Context, key string) (err error) { if c.Cache == nil { return errors.New("缓存不能为空") } err = c.Cache.Del(ctx, key) return err } // VerifyCode 校验验证码 func (c *SmsClient) VerifyCode(ctx context.Context, key string, verifyCode string) (ok bool, err error) { //获取验证码 code, err := c.GetCode(ctx, key) if err != nil { return false, err } //校验验证码 if code != verifyCode { return false, errors.New("code不一致") } //删除验证码 _ = c.DeleteCode(ctx, key) return true, nil }