tianyuan-api-server/apps/gateway/internal/logic/auth/getverifycodelogic.go
2024-10-02 00:57:17 +08:00

96 lines
2.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package auth
import (
"context"
"fmt"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
dysmsapi "github.com/alibabacloud-go/dysmsapi-20170525/v3/client"
"github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
"github.com/zeromicro/go-zero/core/logx"
"tianyuan-api/apps/gateway/internal/svc"
"tianyuan-api/apps/gateway/internal/types"
"math/rand"
"time"
)
type GetVerifyCodeLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetVerifyCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetVerifyCodeLogic {
return &GetVerifyCodeLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetVerifyCodeLogic) GetVerifyCode(req *types.GetVerifyCodeReq) (err error) {
// 校验 actionType 参数的值是否为 "login" 或 "register"
if req.ActionType != "login" && req.ActionType != "register" {
return fmt.Errorf("action_type 参数只能是 'login' 或 'register'")
}
// 检查手机号是否在一分钟内已发送过验证码
redisKey := fmt.Sprintf("%s:%s", req.ActionType, req.Phone)
exists, err := l.svcCtx.Redis.Exists(redisKey)
if err != nil {
return err
}
if exists {
// 如果 Redis 中已经存在标记,说明在 1 分钟内请求过,返回错误
return fmt.Errorf("一分钟内不能重复发送验证码")
}
// 生成随机验证码
code := fmt.Sprintf("%06d", rand.New(rand.NewSource(time.Now().UnixNano())).Intn(1000000))
// 调用阿里云短信服务发送验证码
client, err := l.CreateClient()
if err != nil {
return err
}
sendSmsRequest := &dysmsapi.SendSmsRequest{
SignName: tea.String(l.svcCtx.Config.VerifyCode.SignName),
TemplateCode: tea.String(l.svcCtx.Config.VerifyCode.TemplateCode),
PhoneNumbers: tea.String(req.Phone),
TemplateParam: tea.String(fmt.Sprintf("{\"code\":\"%s\"}", code)),
}
runtime := &service.RuntimeOptions{}
// 这里使用 *dysmsapi.SendSmsResponse 接收返回值
smsResp, err := client.SendSmsWithOptions(sendSmsRequest, runtime)
if err != nil {
return err
}
if *smsResp.Body.Code != "OK" {
return fmt.Errorf("短信发送失败: %s", *smsResp.Body.Message)
}
// 将验证码保存到 Redis设置过期时间
err = l.svcCtx.Redis.Setex(req.Phone, code, l.svcCtx.Config.VerifyCode.ValidTime) // 验证码有效期5分钟
if err != nil {
return err
}
// 在 Redis 中设置 1 分钟的标记,限制重复请求
err = l.svcCtx.Redis.Setex(redisKey, code, 60) // 标记 1 分钟内不能重复请求
if err != nil {
return err
}
// 构建返回给前端的响应
return nil
}
// 创建阿里云短信客户端
func (l *GetVerifyCodeLogic) CreateClient() (*dysmsapi.Client, error) {
config := &openapi.Config{
AccessKeyId: &l.svcCtx.Config.VerifyCode.AccessKeyID,
AccessKeySecret: &l.svcCtx.Config.VerifyCode.AccessKeySecret,
}
config.Endpoint = tea.String(l.svcCtx.Config.VerifyCode.EndpointURL)
return dysmsapi.NewClient(config)
}