package benefactorservice import ( "context" benefactoreparam "git.gocasts.ir/ebhomengo/niki/param/benefactor/benefactore" errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" "math/rand" "time" ) func (s Service) SendOtp(ctx context.Context, req benefactoreparam.SendOtpRequest) (benefactoreparam.SendOtpResponse, error) { const op = "benefactorservice.SendOtp" isExist, iErr := s.redisOtp.IsExistPhoneNumber(ctx, req.PhoneNumber) if iErr != nil { return benefactoreparam.SendOtpResponse{}, richerror.New(op).WithErr(iErr).WithKind(richerror.KindUnexpected) } if isExist { return benefactoreparam.SendOtpResponse{}, richerror.New(op).WithMessage(errmsg.ErrorMsgOtpCodeExist).WithKind(richerror.KindForbidden) } newCode := s.generateVerificationCode() spErr := s.redisOtp.SaveCodeWithPhoneNumber(ctx, req.PhoneNumber, newCode, s.config.OtpExpireTime) if spErr != nil { return benefactoreparam.SendOtpResponse{}, richerror.New(op).WithErr(spErr).WithKind(richerror.KindUnexpected) } //TODO- use goroutine sErr := s.smsProviderClient.SendSms(req.PhoneNumber, newCode) if sErr != nil { return benefactoreparam.SendOtpResponse{}, richerror.New(op).WithErr(sErr).WithKind(richerror.KindUnexpected) } // we use code in sendOtpResponse until sms provider will implement return benefactoreparam.SendOtpResponse{ PhoneNumber: req.PhoneNumber, Code: newCode, //TODO - have to remove it in production }, nil } func (s Service) generateVerificationCode() string { rand.NewSource(time.Now().UnixNano()) result := make([]byte, s.config.LengthOfOtpCode) for i := 0; i < s.config.LengthOfOtpCode; i++ { result[i] = s.config.OtpChars[rand.Intn(len(s.config.OtpChars))] } return string(result) }