ark-member/internal/logic/generate_refresh_code_logic.go

129 lines
2.9 KiB
Go
Raw Normal View History

2024-07-21 15:57:56 +00:00
package logic
import (
"context"
2024-07-25 14:01:22 +00:00
"crypto/rand"
"fmt"
"math/big"
2024-07-21 15:57:56 +00:00
"member/gen_result/pb/member"
2024-07-25 14:01:22 +00:00
"member/internal/domain"
ers "member/internal/lib/error"
2024-07-21 15:57:56 +00:00
"member/internal/svc"
2024-07-25 14:01:22 +00:00
"strconv"
2024-07-21 15:57:56 +00:00
"github.com/zeromicro/go-zero/core/logx"
)
type GenerateRefreshCodeLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewGenerateRefreshCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GenerateRefreshCodeLogic {
return &GenerateRefreshCodeLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
2024-07-25 14:01:22 +00:00
type generateRefreshCodeReq struct {
Account string `json:"account" validate:"account"`
// CodeType 1 email 2 phone
CodeType int32 `json:"code_type" validate:"required,oneof=1 2 3"`
}
var codeMap = map[int32]string{
1: "email",
2: "phone",
}
func getCodeNameByCode(code int32) (string, bool) {
res, ok := codeMap[code]
if !ok {
return "", false
}
return res, true
}
func generateVerifyCode(digits int) (string, error) {
if digits <= 0 {
// 預設為六位數
digits = 6
}
// 計算最大值 (10^digits - 1)
exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(digits)), nil)
// 生成隨機數
randomNumber, err := rand.Int(rand.Reader, exp)
if err != nil {
return "", err
}
// 將隨機數轉換為 string
verifyCode := strconv.Itoa(int(randomNumber.Int64()))
// 如果隨機數的位數少於指定的位數,則補 0
if len(verifyCode) < digits {
verifyCode = fmt.Sprintf("%0*d", digits, randomNumber)
}
return verifyCode, nil
}
2024-07-21 15:57:56 +00:00
// GenerateRefreshCode 這個帳號驗證碼(十分鐘),通用的
func (l *GenerateRefreshCodeLogic) GenerateRefreshCode(in *member.GenerateRefreshCodeReq) (*member.GenerateRefreshCodeResp, error) {
2024-08-02 02:10:25 +00:00
// 驗證資料
if err := l.svcCtx.Validate.ValidateAll(&generateRefreshCodeReq{
2024-07-25 14:01:22 +00:00
Account: in.GetAccount(),
CodeType: in.GetCodeType(),
2024-08-02 02:10:25 +00:00
}); err != nil {
2024-07-25 14:01:22 +00:00
return nil, ers.InvalidFormat(err.Error())
}
checkType, status := getCodeNameByCode(in.GetCodeType())
if !status {
return nil, ers.InvalidFormat(fmt.Errorf("failed to get correct code type").Error())
}
rk := fmt.Sprintf("verify:%s:%s", checkType, in.GetAccount())
// 拿過就不要再拿了
get, err := l.svcCtx.Redis.Get(rk)
if err != nil {
return nil, ers.DBError("failed to connect to redis", err.Error())
}
if get != "" {
return &member.GenerateRefreshCodeResp{
Status: &member.BaseResp{
Code: domain.CodeOk.ToString(),
Message: "success",
Error: "",
},
Data: &member.VerifyCode{
VerifyCode: get,
},
}, nil
}
code, err := generateVerifyCode(6)
if !status {
return nil, ers.ArkInternal(err.Error())
}
err = l.svcCtx.Redis.Setex(rk, code, 600)
if err != nil {
return nil, ers.ArkInternal(err.Error())
}
2024-07-21 15:57:56 +00:00
2024-07-25 14:01:22 +00:00
return &member.GenerateRefreshCodeResp{
Status: &member.BaseResp{
Code: domain.CodeOk.ToString(),
Message: "success",
Error: "",
},
Data: &member.VerifyCode{
VerifyCode: code,
},
}, nil
2024-07-21 15:57:56 +00:00
}