134 lines
3.5 KiB
Go
134 lines
3.5 KiB
Go
package user
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
|
|
"github.com/SamuelTariku/FortuneBet-Backend/internal/pkgs/helpers"
|
|
afro "github.com/amanuelabay/afrosms-go"
|
|
"github.com/resend/resend-go/v2"
|
|
"github.com/twilio/twilio-go"
|
|
twilioApi "github.com/twilio/twilio-go/rest/api/v2010"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
func (s *Service) SendOtp(ctx context.Context, sentTo string, otpFor domain.OtpFor, medium domain.OtpMedium, provider domain.OtpProvider) error {
|
|
otpCode := helpers.GenerateOTP()
|
|
|
|
message := fmt.Sprintf("Welcome to Fortune bets, your OTP is %s please don't share with anyone.", otpCode)
|
|
|
|
switch medium {
|
|
case domain.OtpMediumSms:
|
|
switch provider {
|
|
case domain.TwilioSms:
|
|
if err := s.SendTwilioSMSOTP(ctx, sentTo, message, provider); err != nil {
|
|
return err
|
|
}
|
|
case domain.AfroMessage:
|
|
if err := s.SendAfroMessageSMSOTP(ctx, sentTo, message, provider); err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
return fmt.Errorf("invalid sms provider: %s", provider)
|
|
}
|
|
case domain.OtpMediumEmail:
|
|
if err := s.SendEmailOTP(ctx, sentTo, message); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
otp := domain.Otp{
|
|
SentTo: sentTo,
|
|
Medium: medium,
|
|
For: otpFor,
|
|
Otp: otpCode,
|
|
Used: false,
|
|
CreatedAt: time.Now(),
|
|
ExpiresAt: time.Now().Add(OtpExpiry),
|
|
}
|
|
|
|
return s.otpStore.CreateOtp(ctx, otp)
|
|
}
|
|
|
|
func hashPassword(plaintextPassword string) ([]byte, error) {
|
|
hash, err := bcrypt.GenerateFromPassword([]byte(plaintextPassword), 12)
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
return hash, nil
|
|
}
|
|
|
|
func (s *Service) SendAfroMessageSMSOTP(ctx context.Context, receiverPhone, message string, provider domain.OtpProvider) error {
|
|
apiKey := s.config.AFRO_SMS_API_KEY
|
|
senderName := s.config.AFRO_SMS_SENDER_NAME
|
|
hostURL := s.config.ADRO_SMS_HOST_URL
|
|
endpoint := "/api/send"
|
|
|
|
// API endpoint has been updated
|
|
// TODO: no need for package for the afro message operations (pretty simple stuff)
|
|
request := afro.GetRequest(apiKey, endpoint, hostURL)
|
|
request.BaseURL = "https://api.afromessage.com/api/send"
|
|
|
|
request.Method = "GET"
|
|
request.Sender(senderName)
|
|
request.To(receiverPhone, message)
|
|
|
|
response, err := afro.MakeRequestWithContext(ctx, request)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if response["acknowledge"] == "success" {
|
|
return nil
|
|
} else {
|
|
fmt.Println(response["response"].(map[string]interface{}))
|
|
return errors.New("SMS delivery failed")
|
|
}
|
|
}
|
|
|
|
func (s *Service) SendTwilioSMSOTP(ctx context.Context, receiverPhone, message string, provider domain.OtpProvider) error {
|
|
accountSid := s.config.TwilioAccountSid
|
|
authToken := s.config.TwilioAuthToken
|
|
senderPhone := s.config.TwilioSenderPhoneNumber
|
|
|
|
client := twilio.NewRestClientWithParams(twilio.ClientParams{
|
|
Username: accountSid,
|
|
Password: authToken,
|
|
})
|
|
|
|
params := &twilioApi.CreateMessageParams{}
|
|
params.SetTo(receiverPhone)
|
|
params.SetFrom(senderPhone)
|
|
params.SetBody(message)
|
|
|
|
_, err := client.Api.CreateMessage(params)
|
|
if err != nil {
|
|
return fmt.Errorf("%s", "Error sending SMS message: %s"+err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) SendEmailOTP(ctx context.Context, receiverEmail, message string) error {
|
|
apiKey := s.config.ResendApiKey
|
|
client := resend.NewClient(apiKey)
|
|
formattedSenderEmail := "FortuneBets <" + s.config.ResendSenderEmail + ">"
|
|
params := &resend.SendEmailRequest{
|
|
From: formattedSenderEmail,
|
|
To: []string{receiverEmail},
|
|
Subject: "FortuneBets - One Time Password",
|
|
Text: message,
|
|
}
|
|
|
|
_, err := client.Emails.Send(params)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|