From 5c41903221fd7a20e0a8de822c67123865a56918 Mon Sep 17 00:00:00 2001 From: masoodk Date: Wed, 17 Jan 2024 13:34:50 +0330 Subject: [PATCH] feat(adapter): add kavenegar sms provider adapter --- adapter/sms_provider/adapter.go | 17 ------- adapter/sms_provider/kavenegar/adapter.go | 25 ++++++++++ adapter/sms_provider/kavenegar/otp/otp.go | 13 +++++ .../sms_provider/kavenegar/otp/send_otp.go | 50 +++++++++++++++++++ adapter/sms_provider/send.go | 6 --- config.yml | 6 +++ config/config.go | 14 +++--- go.mod | 1 + go.sum | 2 + main.go | 9 ++-- service/benefactor/benefactor/send_otp.go | 10 ++-- service/benefactor/benefactor/service.go | 9 ++-- 12 files changed, 120 insertions(+), 42 deletions(-) delete mode 100644 adapter/sms_provider/adapter.go create mode 100644 adapter/sms_provider/kavenegar/adapter.go create mode 100644 adapter/sms_provider/kavenegar/otp/otp.go create mode 100644 adapter/sms_provider/kavenegar/otp/send_otp.go delete mode 100644 adapter/sms_provider/send.go diff --git a/adapter/sms_provider/adapter.go b/adapter/sms_provider/adapter.go deleted file mode 100644 index de0bf96..0000000 --- a/adapter/sms_provider/adapter.go +++ /dev/null @@ -1,17 +0,0 @@ -package smsprovider - -type Config struct { - Host string `koanf:"host"` - Port int `koanf:"port"` -} - -type Adapter struct{} - -//nolint -func New(config Config) Adapter { - // rdb := redis.NewClient(&redis.Options{ - // Addr: fmt.Sprintf("%s:%d", config.Host, config.Port), - //}) - - return Adapter{} -} diff --git a/adapter/sms_provider/kavenegar/adapter.go b/adapter/sms_provider/kavenegar/adapter.go new file mode 100644 index 0000000..0554996 --- /dev/null +++ b/adapter/sms_provider/kavenegar/adapter.go @@ -0,0 +1,25 @@ +package kavenegar + +import "github.com/kavenegar/kavenegar-go" + +type Config struct { + APIKey string `koanf:"api_key"` + OtpTemplateNewUser string `koanf:"otp_template_new_user"` + OtpTemplateRegisteredUser string `koanf:"otp_template_registered_user"` +} +type Adapter struct { + config Config + api *kavenegar.Kavenegar +} + +func New(config Config) *Adapter { + return &Adapter{config: config, api: kavenegar.New(config.APIKey)} +} + +func (a Adapter) Client() *kavenegar.Kavenegar { + return a.api +} + +func (a Adapter) Config() Config { + return a.config +} diff --git a/adapter/sms_provider/kavenegar/otp/otp.go b/adapter/sms_provider/kavenegar/otp/otp.go new file mode 100644 index 0000000..6da4ffc --- /dev/null +++ b/adapter/sms_provider/kavenegar/otp/otp.go @@ -0,0 +1,13 @@ +package kavenegarotp + +import ( + smsprovider "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider/kavenegar" +) + +type Adapter struct { + adapter *smsprovider.Adapter +} + +func New(conn *smsprovider.Adapter) *Adapter { + return &Adapter{adapter: conn} +} diff --git a/adapter/sms_provider/kavenegar/otp/send_otp.go b/adapter/sms_provider/kavenegar/otp/send_otp.go new file mode 100644 index 0000000..20afa3c --- /dev/null +++ b/adapter/sms_provider/kavenegar/otp/send_otp.go @@ -0,0 +1,50 @@ +package kavenegarotp + +import ( + "fmt" + + richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" + "github.com/kavenegar/kavenegar-go" +) + +func (a Adapter) SendForNewUser(phoneNumber, code string) { + const op = richerror.Op("kavenegarotp.Send") + + params := &kavenegar.VerifyLookupParam{} + if _, err := a.adapter.Client().Verify.Lookup(phoneNumber, a.adapter.Config().OtpTemplateNewUser, code, params); err != nil { + //nolint + switch err := err.(type) { + case *kavenegar.APIError: + // log error + fmt.Println(fmt.Errorf("error(%s):%w", op, err)) + case *kavenegar.HTTPError: + // log error + fmt.Println(fmt.Errorf("error(%s):%w", op, err)) + default: + // log error + fmt.Println(fmt.Errorf("error(%s):%w", op, err)) + } + } + // TODO - log res res.Status +} + +func (a Adapter) SendForRegisteredUser(phoneNumber, code string) { + const op = richerror.Op("kavenegarotp.Send") + + params := &kavenegar.VerifyLookupParam{} + if _, err := a.adapter.Client().Verify.Lookup(phoneNumber, a.adapter.Config().OtpTemplateRegisteredUser, code, params); err != nil { + //nolint + switch err := err.(type) { + case *kavenegar.APIError: + // log error + fmt.Println(fmt.Errorf("error(%s):%w", op, err)) + case *kavenegar.HTTPError: + // log error + fmt.Println(fmt.Errorf("error(%s):%w", op, err)) + default: + // log error + fmt.Println(fmt.Errorf("error(%s):%w", op, err)) + } + } + // TODO - log res res.Status +} diff --git a/adapter/sms_provider/send.go b/adapter/sms_provider/send.go deleted file mode 100644 index 687a6a2..0000000 --- a/adapter/sms_provider/send.go +++ /dev/null @@ -1,6 +0,0 @@ -package smsprovider - -//nolint -func (a Adapter) SendSms(phoneNumber string, code string) error { - return nil -} diff --git a/config.yml b/config.yml index 4e90d9f..ac73534 100644 --- a/config.yml +++ b/config.yml @@ -27,6 +27,12 @@ sms_provider: benefactor_service: length_of_otp_code: 5 +kavenegar_sms_provider: + api_key: insert_your_api_key + otp_template_new_user: ebhomeverify + otp_template_registered_user: ebhomeverify + + diff --git a/config/config.go b/config/config.go index d9e2e36..8d0b548 100644 --- a/config/config.go +++ b/config/config.go @@ -2,7 +2,7 @@ package config import ( "git.gocasts.ir/ebhomengo/niki/adapter/redis" - smsprovider "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider" + smsprovider "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider/kavenegar" "git.gocasts.ir/ebhomengo/niki/repository/mysql" authservice "git.gocasts.ir/ebhomengo/niki/service/auth/benefactor" benefactorservice "git.gocasts.ir/ebhomengo/niki/service/benefactor/benefactor" @@ -13,10 +13,10 @@ type HTTPServer struct { } type Config struct { - HTTPServer HTTPServer `koanf:"http_server"` - Mysql mysql.Config `koanf:"mysql"` - Auth authservice.Config `koanf:"auth"` - Redis redis.Config `koanf:"redis"` - SmsProvider smsprovider.Config `koanf:"sms_provider"` - BenefactorSvc benefactorservice.Config `koanf:"benefactor_service"` + HTTPServer HTTPServer `koanf:"http_server"` + Mysql mysql.Config `koanf:"mysql"` + Auth authservice.Config `koanf:"auth"` + Redis redis.Config `koanf:"redis"` + KavenegarSmsProvider smsprovider.Config `koanf:"kavenegar_sms_provider"` + BenefactorSvc benefactorservice.Config `koanf:"benefactor_service"` } diff --git a/go.mod b/go.mod index 9b5c792..00f6c19 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/go-ozzo/ozzo-validation/v4 v4.3.0 github.com/go-sql-driver/mysql v1.6.0 github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/kavenegar/kavenegar-go v0.0.0-20221124112814-40341057b5ca github.com/knadh/koanf v1.5.0 github.com/labstack/echo-jwt/v4 v4.2.0 github.com/labstack/echo/v4 v4.11.4 diff --git a/go.sum b/go.sum index 205d41d..14df7a8 100644 --- a/go.sum +++ b/go.sum @@ -161,6 +161,8 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kavenegar/kavenegar-go v0.0.0-20221124112814-40341057b5ca h1:aEyiDaExheG7fNpEYcILCVGgM7jlLzTVgxEQAGaepeM= +github.com/kavenegar/kavenegar-go v0.0.0-20221124112814-40341057b5ca/go.mod h1:CRhvvr4KNAyrg+ewrutOf+/QoHs7lztSoLjp+GqhYlA= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs= diff --git a/main.go b/main.go index e517b59..b587710 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,8 @@ package main import ( "git.gocasts.ir/ebhomengo/niki/adapter/redis" - smsprovider "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider" + smsprovider "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider/kavenegar" + kavenegarotp "git.gocasts.ir/ebhomengo/niki/adapter/sms_provider/kavenegar/otp" "git.gocasts.ir/ebhomengo/niki/config" httpserver "git.gocasts.ir/ebhomengo/niki/delivery/http_server" "git.gocasts.ir/ebhomengo/niki/repository/migrator" @@ -22,7 +23,6 @@ import ( func main() { cfg := config.C() - // TODO - add command for migrations mgr := migrator.New(cfg.Mysql) mgr.Up() @@ -44,10 +44,11 @@ func setupServices(cfg config.Config) ( redisAdapter := redis.New(cfg.Redis) RedisOtp := redisotp.New(redisAdapter) benefactorMysql := mysqlbenefactor.New(MysqlRepo) - smsProvider := smsprovider.New(cfg.SmsProvider) + kavenegarSmsProvider := smsprovider.New(cfg.KavenegarSmsProvider) + otpSmsProvider := kavenegarotp.New(kavenegarSmsProvider) authGenerator := authservice.New(cfg.Auth) - benefactorSvc = benefactorservice.New(cfg.BenefactorSvc, RedisOtp, smsProvider, authGenerator, benefactorMysql) + benefactorSvc = benefactorservice.New(cfg.BenefactorSvc, RedisOtp, otpSmsProvider, authGenerator, benefactorMysql) benefactorVld = benefactorvalidator.New() diff --git a/service/benefactor/benefactor/send_otp.go b/service/benefactor/benefactor/send_otp.go index b4d69ce..4cf8cb5 100644 --- a/service/benefactor/benefactor/send_otp.go +++ b/service/benefactor/benefactor/send_otp.go @@ -27,10 +27,12 @@ func (s Service) SendOtp(ctx context.Context, req benefactoreparam.SendOtpReques 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) + if isExist { + // Log error in sms provider + go s.smsProviderClient.SendForRegisteredUser(req.PhoneNumber, newCode) + } else { + // Log error in sms provider + go s.smsProviderClient.SendForNewUser(req.PhoneNumber, newCode) } // we use code in sendOtpResponse until sms provider will implement diff --git a/service/benefactor/benefactor/service.go b/service/benefactor/benefactor/service.go index 44abd23..8e2136a 100644 --- a/service/benefactor/benefactor/service.go +++ b/service/benefactor/benefactor/service.go @@ -31,19 +31,20 @@ type RedisOtp interface { DeleteCodeByPhoneNumber(ctx context.Context, phoneNumber string) (bool, error) } -type SmsProviderClient interface { - SendSms(phoneNumber string, code string) error +type OtpSmsProviderClient interface { + SendForNewUser(phoneNumber string, code string) + SendForRegisteredUser(phoneNumber string, code string) } type Service struct { config Config redisOtp RedisOtp - smsProviderClient SmsProviderClient + smsProviderClient OtpSmsProviderClient auth AuthGenerator repo Repository } -func New(cfg Config, redisOtp RedisOtp, smsProviderClient SmsProviderClient, +func New(cfg Config, redisOtp RedisOtp, smsProviderClient OtpSmsProviderClient, auth AuthGenerator, repo Repository, ) Service { return Service{