| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- package internal
- import (
- "context"
- "encoding/json"
- "fmt"
- "github.com/gogf/gf/v2/encoding/gjson"
- "github.com/gogf/gf/v2/os/glog"
- rand "math/rand"
- "strings"
- "sync"
- "time"
- "yx-dataset-server/app/errors"
- "yx-dataset-server/app/model"
- "yx-dataset-server/app/schema"
- "yx-dataset-server/library/logger"
- "yx-dataset-server/library/redis"
- "yx-dataset-server/library/sms"
- "yx-dataset-server/library/utils"
- )
- // NewVerifyCode 创建VerifyCode
- func NewVerifyCode(
- mUser model.IUser,
- ) *VerifyCode {
- return &VerifyCode{
- userModel: mUser,
- }
- }
- // VerifyCode 创建VerifyCode对象
- type VerifyCode struct {
- sync.RWMutex
- userModel model.IUser
- }
- func (a *VerifyCode) getKey(businessType int, tel, storeType string) string {
- return utils.Base64Encode(fmt.Sprintf("%d%s%s", businessType, tel, storeType))
- }
- // Check 检查手机号及验证码的有效性
- func (a *VerifyCode) Check(ctx context.Context, req schema.VerifyCodeCheck) (bool, error) {
- if req.Tel == "" || len(req.Tel) < 11 {
- return false, errors.New("请输入合法的手机号")
- }
- var businessType string
- switch req.BusinessType {
- case 1:
- businessType = "login"
- case 2:
- businessType = "changePass"
- default:
- return false, errors.New("业务类型参数不正确")
- }
- if req.Token == "" {
- req.Token = fmt.Sprintf("%s:%s:%s", businessType, "code", req.Tel)
- }
- val, err := redis.GetClient().Get(ctx, req.Token)
- if err != nil {
- return false, errors.ErrBadRequest
- } else if val == "" {
- return false, errors.New("验证码已失效,请重新获取验证码")
- }
- var item schema.VerifyCodeItem
- if err := json.Unmarshal([]byte(val), &item); err != nil {
- return false, err
- }
- return item.Code == req.Code && item.BusinessType == req.BusinessType, nil
- }
- // SendCode 发送短信验证码
- func (a *VerifyCode) ALiYunSendSms(ctx context.Context, req schema.VerifyCodeRequest) (*schema.VerifyCodeResponse, error) {
- a.Lock()
- defer a.Unlock()
- switch req.Bzty {
- case 1:
- req.TemplateId = utils.GetConfig("aliyun_sms.loginTemplateCode").String()
- req.BusinessTypeStr = "login"
- case 2:
- req.TemplateId = utils.GetConfig("aliyun_sms.passwordTemplateCode").String()
- req.BusinessTypeStr = "changePass"
- }
- telStoreKey := fmt.Sprintf("%s:%s", "telCount", req.Tel)
- telStoreData, err := redis.GetClient().Get(ctx, telStoreKey)
- if err != nil {
- return nil, errors.ErrBadRequest
- }
- if telStoreData != "" {
- var telStoreItem schema.StoreCountItem
- _ = json.NewDecoder(strings.NewReader(telStoreData)).Decode(&telStoreItem)
- if telStoreItem.Count >= 50 {
- return nil, errors.New("该手机号已被限制获取验证码,请于次日重试")
- }
- req.TelCount = telStoreItem.Count
- }
- codeKey := fmt.Sprintf("%s:%s:%s", req.BusinessTypeStr, "code", req.Tel)
- err = a.aliyunSend(ctx, req)
- if err != nil {
- return nil, err
- }
- logger.Printf(ctx, "短信发送成功:[手机号:%s]", req.Tel[7:11])
- return &schema.VerifyCodeResponse{
- Token: codeKey,
- }, nil
- }
- func (a *VerifyCode) aliyunSend(ctx context.Context, req schema.VerifyCodeRequest) error {
- if req.Batch {
- return sms.SendBatchSms(sms.ALiYunSendBatchSmsArgs{
- TemplateCode: req.TemplateId,
- TemplateParam: req.ParamsJson,
- PhoneNumbers: req.Tel,
- })
- }
- // 随机生成6位验证码
- code := fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
- paramJson := gjson.New("")
- _ = paramJson.Set("code", code)
- glog.Infof(ctx, "验证码发送成功[手机号%s,验证码:%s]", req.Tel, code)
- //发送短信验证码
- err := sms.SendSms(sms.ALiYunSendSmsArgs{
- TemplateCode: req.TemplateId,
- TemplateParam: paramJson.MustToJsonString(),
- PhoneNumbers: req.Tel,
- })
- if err != nil {
- return err
- }
- expired := time.Minute * 5
- resendLimit := time.Second * 60
- // 存储重发限制
- resendLimitKey := fmt.Sprintf("%s:%s:%s", req.BusinessTypeStr, "checkResend", req.Tel)
- err = redis.GetClient().Set(ctx, resendLimitKey, 1, resendLimit)
- if err != nil {
- return errors.ErrBadRequest
- }
- // 存储验证码
- codeKey := fmt.Sprintf("%s:%s:%s", req.BusinessTypeStr, "code", req.Tel)
- codeData := schema.VerifyCodeItem{
- Code: code,
- BusinessType: req.Bzty,
- }
- err = redis.GetClient().Set(ctx, codeKey, codeData, expired)
- if err != nil {
- return errors.ErrBadRequest
- }
- return nil
- }
|