From 57dc01842e55ce3b111b297a68601193907b9bd8 Mon Sep 17 00:00:00 2001 From: MelvinKim Date: Tue, 13 Jun 2023 11:05:14 +0300 Subject: [PATCH] feat: add send premium sms api --- client.go | 3 +- models.go | 13 ++++++ sms.go | 41 ++++++++++++++++++ sms_test.go | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 1 deletion(-) diff --git a/client.go b/client.go index 12e04ed..d14bb9c 100644 --- a/client.go +++ b/client.go @@ -87,6 +87,7 @@ func (s *client) background() { if err != nil { s.authFailed = true } + s.authFailed = false case t := <-s.accessTokenTicker.C: logrus.Println("SIL Comms Access Token updated at: ", t) @@ -94,7 +95,7 @@ func (s *client) background() { if err != nil { s.authFailed = true } - + s.authFailed = false } } } diff --git a/models.go b/models.go index 0b64ded..1b2f11f 100644 --- a/models.go +++ b/models.go @@ -46,3 +46,16 @@ type BulkSMSResponse struct { Created string `json:"created"` Updated string `json:"updated"` } + +// PremiumSMSResponse is the response returned after making a request to SILCOMMS to send a premium SMS +type PremiumSMSResponse struct { + GUID string `json:"guid"` + Body string `json:"body"` + Msisdn string `json:"msisdn"` + SMSType string `json:"sms_type"` + Gateway string `json:"gateway"` + Carrier string `json:"carrier"` + Subscription string `json:"subscription"` + Direction string `json:"direction"` + State string `json:"state"` +} diff --git a/sms.go b/sms.go index 24c0e72..556324c 100644 --- a/sms.go +++ b/sms.go @@ -49,6 +49,8 @@ func MustNewSILCommsLib() *CommsLib { // SendBulkSMS returns a 202 Accepted synchronous response while the API attempts to send the SMS in the background. // An asynchronous call is made to the app's sms_callback URL with a notification that shows the Bulk SMS status. // An asynchronous call is made to the app's sms_callback individually for each of the recipients with the SMS status. +// message - message to be sent via the Bulk SMS +// recipients - phone number(s) to receive the Bulk SMS func (l CommsLib) SendBulkSMS(ctx context.Context, message string, recipients []string) (*BulkSMSResponse, error) { path := "/v1/sms/bulk/" payload := struct { @@ -85,3 +87,42 @@ func (l CommsLib) SendBulkSMS(ctx context.Context, message string, recipients [] return &bulkSMS, nil } + +// SendPremiumSMS is used to send a premium SMS using SILCOMMS gateway +// message - message to be sent via the premium SMS +// msisdn - phone number to receive the premium SMS +// subscription - subscription/offer associated with the premium SMS +func (l CommsLib) SendPremiumSMS(ctx context.Context, message, msisdn, subscription string) (*PremiumSMSResponse, error) { + path := "/v1/sms/sms/" + payload := struct { + Body string `json:"body"` + Msisdn string `json:"msisdn"` + Subscription string `json:"subscription"` + }{ + Body: message, + Msisdn: msisdn, + Subscription: subscription, + } + + response, err := l.client.MakeRequest(ctx, http.MethodPost, path, nil, payload, true) + if err != nil { + return nil, fmt.Errorf("failed to make send premium sms request: %v", err) + } + if response.StatusCode != http.StatusOK { + return nil, fmt.Errorf("invalid send premium sms response code, got: %d", response.StatusCode) + } + + var resp APIResponse + err = json.NewDecoder(response.Body).Decode(&resp) + if err != nil { + return nil, fmt.Errorf("failed to decode send premium sms api response: %w", err) + } + + var premiumSMS PremiumSMSResponse + err = mapstructure.Decode(resp.Data, &premiumSMS) + if err != nil { + return nil, fmt.Errorf("failed to decode send premium sms data in api response: %w", err) + } + + return &premiumSMS, nil +} diff --git a/sms_test.go b/sms_test.go index 0a58317..d898b18 100644 --- a/sms_test.go +++ b/sms_test.go @@ -131,3 +131,122 @@ func TestSILCommsLib_SendBulkSMS(t *testing.T) { }) } } + +func TestSILCommsLib_SendPremiumSMS(t *testing.T) { + type args struct { + ctx context.Context + message string + msisdn string + subscription string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Happy case: send premium sms", + args: args{ + ctx: context.Background(), + message: "test premium sms", + msisdn: gofakeit.Phone(), + subscription: "01262626626", + }, + wantErr: false, + }, + { + name: "Sad case: invalid status code", + args: args{ + ctx: context.Background(), + message: "test premium sms", + msisdn: gofakeit.Phone(), + subscription: "01262626626", + }, + wantErr: true, + }, + { + name: "Sad case: invalid API response", + args: args{ + ctx: context.Background(), + message: "test premium sms", + msisdn: gofakeit.Phone(), + subscription: "01262626626", + }, + wantErr: true, + }, + { + name: "Sad case: invalid premium SMS data response", + args: args{ + ctx: context.Background(), + message: "test premium sms", + msisdn: gofakeit.Phone(), + subscription: "01262626626", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + silcomms.MockLogin() + + l := silcomms.MustNewSILCommsLib() + + if tt.name == "Happy case: send premium sms" { + httpmock.RegisterResponder(http.MethodPost, fmt.Sprintf("%s/v1/sms/sms/", silcomms.BaseURL), func(r *http.Request) (*http.Response, error) { + resp := silcomms.APIResponse{ + Status: silcomms.StatusSuccess, + Message: "success", + Data: silcomms.PremiumSMSResponse{ + GUID: gofakeit.UUID(), + }, + } + return httpmock.NewJsonResponse(http.StatusOK, resp) + }) + } + + if tt.name == "Sad case: invalid status code" { + httpmock.RegisterResponder(http.MethodPost, fmt.Sprintf("%s/v1/sms/sms/", silcomms.BaseURL), func(r *http.Request) (*http.Response, error) { + return httpmock.NewJsonResponse(http.StatusUnauthorized, nil) + }) + } + + if tt.name == "Sad case: invalid API response" { + httpmock.RegisterResponder(http.MethodPost, fmt.Sprintf("%s/v1/sms/sms/", silcomms.BaseURL), func(r *http.Request) (*http.Response, error) { + resp := map[string]interface{}{ + "status": 1234, + "message": 1234, + } + + return httpmock.NewJsonResponse(http.StatusOK, resp) + }) + } + + if tt.name == "Sad case: invalid premium SMS data response" { + httpmock.RegisterResponder(http.MethodPost, fmt.Sprintf("%s/v1/sms/sms/", silcomms.BaseURL), func(r *http.Request) (*http.Response, error) { + resp := silcomms.APIResponse{ + Status: silcomms.StatusSuccess, + Message: "success", + Data: map[string]interface{}{ + "guid": 123456, + "carrier": 123456, + "message": 123456, + }, + } + return httpmock.NewJsonResponse(http.StatusOK, resp) + }) + } + + got, err := l.SendPremiumSMS(tt.args.ctx, tt.args.message, tt.args.msisdn, tt.args.subscription) + if (err != nil) != tt.wantErr { + t.Errorf("SILCommsLib.SendPremiumSMS() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !tt.wantErr && got == nil { + t.Errorf("SILCommsLib.SendPremiumSMS() expected response not to be nil for %v", tt.name) + return + } + }) + } +}