Skip to content

Commit

Permalink
Report send api call success
Browse files Browse the repository at this point in the history
  • Loading branch information
chankiyu22 committed Sep 24, 2024
2 parents 1ad8649 + 693ae99 commit e7a03f8
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 63 deletions.
2 changes: 2 additions & 0 deletions pkg/handler/send.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ var _ = RequestSchema.Add("TemplateVariables", sms_infra.TemplateVariablesSchema

type Result struct {
ClientResponse string `json:"client_response"`
Success bool `json:"success"`
}

func init() {
Expand Down Expand Up @@ -99,6 +100,7 @@ func (h *SendHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.JSON.WriteResponse(w, &api.Response{
Result: Result{
ClientResponse: string(sendResult.ClientResponse),
Success: sendResult.Success,
},
})
}
54 changes: 13 additions & 41 deletions pkg/lib/infra/sms/accessyou.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package sms

import (
"bytes"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"net/url"
"regexp"

"github.com/authgear/authgear-sms-gateway/pkg/lib/type_util"
"github.com/authgear/authgear-sms-gateway/pkg/lib/infra/sms/accessyou/apis"
)

type AccessYouClient struct {
Expand Down Expand Up @@ -49,52 +46,27 @@ func (n *AccessYouClient) Send(options *SendOptions) (*SendResult, error) {
// Access you phone number should have no +
m1 := regexp.MustCompile(`[\+\-]+`)
to := m1.ReplaceAllString(options.To, "")
req, _ := http.NewRequest(
"POST",
fmt.Sprintf(
"%v/sendsms.php?accountno=%v&pwd=%v&tid=1&phone=%v&a=%v&user=%v&from=%v",
n.BaseUrl,
n.AccountNo,
n.Pwd,
to,
url.QueryEscape(options.Body),
n.User,
n.Sender),
nil)
req.Header.Set("Cookie", "dynamic=sms")
respData, sendSMSResponse, err := apis.SendSMS(
n.Client,
n.BaseUrl,
n.AccountNo,
n.User,
n.Pwd,
n.Sender,
to,
url.QueryEscape(options.Body),
)
n.Logger.Info(fmt.Sprintf("%v", sendSMSResponse))

resp, err := n.Client.Do(req)
if err != nil {
n.Logger.Error(fmt.Sprintf("%v", err))
return nil, err
}
defer resp.Body.Close()

n.Logger.Info("Attempt to parse")
respData, err := io.ReadAll(resp.Body)

// The response data is in format
// "\ufeff{\"msg_status\":\"100\",\"msg_status_desc\":\"Successfully submitted message. \\u6267\\u884c\\u6210\\u529f\",\"phoneno\":\"852********\",\"msg_id\":852309279}"

// Remove BOM token from resp json
respData = bytes.Replace(respData, []byte("\ufeff"), []byte(""), -1)

accessYouResponse := &AccessYouResponse{}
err = json.Unmarshal(respData, &accessYouResponse)
if err != nil {
n.Logger.Error(fmt.Sprintf("Unmarshal error: %v", err))
return nil, err
}
n.Logger.Info(fmt.Sprintf("%v", accessYouResponse))
return &SendResult{
ClientResponse: respData,
Success: sendSMSResponse.Status == "100",
}, nil
}

type AccessYouResponse struct {
Status string `json:"msg_status"`
Description string `json:"msg_status_desc"`
PhoneNo type_util.SensitivePhoneNumber `json:"phoneno"`
}

var _ RawClient = &AccessYouClient{}
55 changes: 55 additions & 0 deletions pkg/lib/infra/sms/accessyou/apis/sendsms.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package apis

import (
"bytes"
"fmt"
"io"
"net/http"

"github.com/authgear/authgear-sms-gateway/pkg/lib/infra/sms/accessyou/models"
)

func SendSMS(
client *http.Client,
baseUrl string,
accountNo string,
user string,
pwd string,
sender string,
to string,
body string,
) ([]byte, *models.SendSMSResponse, error) {
req, _ := http.NewRequest(
"POST",
fmt.Sprintf(
"%v/sendsms.php?accountno=%v&pwd=%v&tid=1&phone=%v&a=%v&user=%v&from=%v",
baseUrl,
accountNo,
pwd,
to,
body,
user,
sender),
nil)
req.Header.Set("Cookie", "dynamic=sms")

resp, err := client.Do(req)
if err != nil {
return nil, nil, err
}
defer resp.Body.Close()

respData, err := io.ReadAll(resp.Body)

// The response data is in format
// "\ufeff{\"msg_status\":\"100\",\"msg_status_desc\":\"Successfully submitted message. \\u6267\\u884c\\u6210\\u529f\",\"phoneno\":\"852********\",\"msg_id\":852309279}"

// Remove BOM token from resp json
respData = bytes.Replace(respData, []byte("\ufeff"), []byte(""), -1)

sendSMSResponse, err := models.ParseSendSMSResponse(respData)
if err != nil {
return respData, nil, err
}
return respData, sendSMSResponse, err
}
23 changes: 23 additions & 0 deletions pkg/lib/infra/sms/accessyou/models/sendsms.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package models

import (
"encoding/json"

"github.com/authgear/authgear-sms-gateway/pkg/lib/type_util"
)

type SendSMSResponse struct {
MessageID int `json:"msg_id"`
Status string `json:"msg_status"`
Description string `json:"msg_status_desc"`
PhoneNo type_util.SensitivePhoneNumber `json:"phoneno"`
}

func ParseSendSMSResponse(jsonData []byte) (*SendSMSResponse, error) {
response := &SendSMSResponse{}
err := json.Unmarshal(jsonData, &response)
if err != nil {
return nil, err
}
return response, nil
}
1 change: 1 addition & 0 deletions pkg/lib/infra/sms/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type SendOptions struct {

type SendResult struct {
ClientResponse []byte
Success bool
}

type RawClient interface {
Expand Down
1 change: 1 addition & 0 deletions pkg/lib/infra/sms/nexmo.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func (n *NexmoClient) Send(options *SendOptions) (*SendResult, error) {
j, err := json.Marshal(resp)
return &SendResult{
ClientResponse: j,
Success: report.Status == nexmo.ResponseSuccess,
}, err
}

Expand Down
27 changes: 5 additions & 22 deletions pkg/lib/infra/sms/sendcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package sms
import (
"errors"
"fmt"
"io"
"log/slog"
"net/http"
"strings"

. "github.com/authgear/authgear-sms-gateway/pkg/lib/infra/sms/sendcloud"
"github.com/authgear/authgear-sms-gateway/pkg/lib/infra/sms/sendcloud/apis"
"github.com/authgear/authgear-sms-gateway/pkg/lib/infra/sms/sendcloud/models"
)

var ErrMissingSendCloudConfiguration = errors.New("accessyou: configuration is missing")
Expand Down Expand Up @@ -75,7 +75,7 @@ func (n *SendCloudClient) Send(options *SendOptions) (*SendResult, error) {
if err != nil {
return nil, err
}
sendCloudRequest := NewSendCloudRequest(
sendRequest := models.NewSendRequest(
string(template.TemplateMsgType),
[]string{
options.To,
Expand All @@ -85,28 +85,11 @@ func (n *SendCloudClient) Send(options *SendOptions) (*SendResult, error) {
makeVarsFromTemplateVariables(options.TemplateVariables),
)

n.Logger.Debug(fmt.Sprintf("Presign: %v", sendCloudRequest.Presign()))
values := sendCloudRequest.ToValues()
values.Set("signature", sendCloudRequest.Sign(n.SMSKey))

data := values.Encode()
n.Logger.Debug(fmt.Sprintf("data: %v", data))

req, _ := http.NewRequest("POST", fmt.Sprintf("%v/smsapi/send", n.BaseUrl), strings.NewReader(data))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := n.Client.Do(req)

if err != nil {
n.Logger.Error(fmt.Sprintf("Client.Do error: %v", err))
return nil, err
}
defer resp.Body.Close()

respData, err := io.ReadAll(resp.Body)
n.Logger.Error(fmt.Sprintf("resp: %v", string(respData)))
respData, sendResponse, err := apis.Send(n.Client, n.BaseUrl, &sendRequest, n.SMSKey)

return &SendResult{
ClientResponse: respData,
Success: sendResponse.StatusCode == 200,
}, nil
}

Expand Down
35 changes: 35 additions & 0 deletions pkg/lib/infra/sms/sendcloud/apis/send.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package apis

import (
"fmt"
"io"
"net/http"
"strings"

"github.com/authgear/authgear-sms-gateway/pkg/lib/infra/sms/sendcloud/models"
)

func Send(client *http.Client, baseUrl string, sendRequest *models.SendRequest, smsKey string) ([]byte, *models.SendResponse, error) {
values := sendRequest.ToValues()
values.Set("signature", sendRequest.Sign(smsKey))

data := values.Encode()

req, _ := http.NewRequest("POST", fmt.Sprintf("%v/smsapi/send", baseUrl), strings.NewReader(data))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)

if err != nil {
return nil, nil, err
}
defer resp.Body.Close()

respData, err := io.ReadAll(resp.Body)

sendResponse, err := models.ParseSendResponse(respData)
if err != nil {
return respData, nil, err
}

return respData, sendResponse, err
}
109 changes: 109 additions & 0 deletions pkg/lib/infra/sms/sendcloud/models/send.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package models

import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"net/url"
"strings"
)

type SendRequest struct {
msgType string
phone []string
sendRequestId string
smsUser string
templateId string
vars map[string]interface{}
}

func NewSendRequest(
msgType string,
phone []string,
smsUser string,
templateId string,
vars map[string]interface{},
) SendRequest {
s := SendRequest{
msgType: msgType,
phone: phone,
smsUser: smsUser,
templateId: templateId,
vars: vars,
}
presign := s.Presign()
h := md5.Sum([]byte(presign))
sendRequestId := hex.EncodeToString(h[:])
return SendRequest{
msgType: msgType,
phone: phone,
sendRequestId: sendRequestId,
smsUser: smsUser,
templateId: templateId,
vars: vars,
}
}

func (r *SendRequest) Presign() string {
vars, _ := json.Marshal(r.vars)
return strings.Join([]string{
fmt.Sprintf("msgType=%v", r.msgType),
fmt.Sprintf("phone=%v", strings.Join(r.phone, ",")),
fmt.Sprintf("sendRequestId=%v", r.sendRequestId),
fmt.Sprintf("smsUser=%v", r.smsUser),
fmt.Sprintf("templateId=%v", r.templateId),
fmt.Sprintf("vars=%v", string(vars)),
}, "&")
}

func (r *SendRequest) ToMap() map[string]interface{} {
vars, _ := json.Marshal(r.vars)
return map[string]interface{}{
"msgType": r.msgType,
"phone": strings.Join(r.phone, ","),
"sendRequestId": r.sendRequestId,
"smsUser": r.smsUser,
"templateId": r.templateId,
"vars": vars,
}
}

func (r *SendRequest) ToValues() url.Values {
vars, _ := json.Marshal(r.vars)
values := url.Values{}
values.Set("msgType", fmt.Sprintf("%v", r.msgType))
values.Set("phone", strings.Join(r.phone, ","))
values.Set("sendRequestId", r.sendRequestId)
values.Set("smsUser", r.smsUser)
values.Set("templateId", fmt.Sprintf("%v", r.templateId))
values.Set("vars", string(vars))
return values
}

func (r *SendRequest) Sign(key string) string {
signStr := fmt.Sprintf("%v&%v&%v", key, r.Presign(), key)
h := md5.Sum([]byte(signStr))
return hex.EncodeToString(h[:])
}

type SendResponseInfo struct {
SuccessCount int `json:"successCount,omitempty"`
SMSIDs []string `json:"smsIds,omitempty"`
}

type SendResponse struct {
Result bool `json:"result,omitempty"`
StatusCode int `json:"statusCode,omitempty"`
Message string `json:"message,omitempty"`
Info *SendResponseInfo `json:"info"`
}

func ParseSendResponse(jsonData []byte) (*SendResponse, error) {
response := &SendResponse{}
err := json.Unmarshal(jsonData, &response)
if err != nil {
return nil, err
}
return response, nil
}
Loading

0 comments on commit e7a03f8

Please sign in to comment.