Skip to content

Commit

Permalink
feat: implemented SMS provider "OSON SMS" (#39)
Browse files Browse the repository at this point in the history
* sms provider 'OSON SMS' implemented

* improvement of oson sms SMS service; changed module to original value; 'OSON SMS' provider is included in the list of README.md

* feat: add 'OSON SMS' provider

* Update go.mod

---------

Co-authored-by: Eric Luo <[email protected]>
  • Loading branch information
waffle-frame and hsluoyz authored Mar 3, 2024
1 parent 0fb4ce1 commit bf4c467
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ We support the following SMS providers, welcome to contribute.
- [UCloud](https://www.ucloud.cn/site/product/usms.html)
- [Huyi](https://www.ihuyi.com/)
- [Netgsm](https://www.netgsm.com.tr/)
- [Oson Sms](https://osonsms.com/)

## Installation

Expand Down Expand Up @@ -164,6 +165,33 @@ func main() {
}
```

### Oson Sms

- senderId: is `login`
- secretAccessKey: is `hash`
- signName: is `from`
- templateCode: is `message`

```go
package main

func main() {
client, err := go_sms_sender.NewSmsClient(go_sms_senderOsonSms, "senderId", "secretAccessKey", "signName", "templateCode")
if err != nil {
panic(err)
}

params := map[string]string{}
params["code"] = "123456"
phoneNumer := "+992123456789"
err = client.SendMessage(params, phoneNumer)
if err != nil {
panic(err)
}
}
```


### Running Tests

To run tests for the `go-sms-sender` library, navigate to the root folder of the project in your terminal and execute the following command:
Expand Down
3 changes: 3 additions & 0 deletions basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (
Huyi = "Huyi SMS"
MockSms = "Mock SMS"
Netgsm = "Netgsm SMS"
OsonSms = "OSON SMS"
)

type SmsClient interface {
Expand Down Expand Up @@ -76,6 +77,8 @@ func NewSmsClient(provider string, accessId string, accessKey string, sign strin
return GetNetgsmClient(accessId, accessKey, sign, template)
case MockSms:
return NewMocker(accessId, accessKey, sign, template, other)
case OsonSms:
return GetOsonClient(accessId, accessKey, sign, template)
default:
return nil, fmt.Errorf("unsupported provider: %s", provider)
}
Expand Down
120 changes: 120 additions & 0 deletions oson.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package go_sms_sender

import (
"crypto/sha256"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"

"github.com/google/uuid"
)

type OsonClient struct {
Endpoint string
SenderID string
SecretAccessHash string
Sign string
Message string
}

type OsonResponse struct {
Status string // ok
Timestamp time.Time // 2017-07-07 16:58:12
TxnId string // f89xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe0b
MsgId uint // 40127
SmscMsgId string // 45f22479
SmscMsgStatus string // success
SmscMsgParts string // 1
}

func GetOsonClient(senderId, secretAccessHash, sign, message string) (*OsonClient, error) {
return &OsonClient{
Endpoint: "https://api.osonsms.com/sendsms_v1.php",
SenderID: senderId,
SecretAccessHash: secretAccessHash,
Sign: sign,
Message: message,
}, nil
}

func (c *OsonClient) SendMessage(param map[string]string, targetPhoneNumber ...string) (err error) {
// Init http client for make request to sms center. Set a timeout of 25+
// seconds to ensure that the response from the SMS center has been
// processed.
client := &http.Client{
Timeout: 20 * time.Second,
}

if c.Message == "" {
c.Message = fmt.Sprintf("Hello. Your authorization code: %s", param["code"])
} else {
c.Message += param["code"]
}

txnID := uuid.New()
buildStrHash := strings.Join([]string{txnID.String(), c.SenderID, c.Sign, targetPhoneNumber[0], c.SecretAccessHash}, ";")

hash := sha256.New()
hash.Write([]byte(buildStrHash))
bs := hash.Sum(nil)
strHash := fmt.Sprintf("%x", bs)

urlLink, err := url.Parse(c.Endpoint)
if err != nil {
return
}

urlParams := url.Values{}
urlParams.Add("from", c.Sign)
urlParams.Add("phone_number", targetPhoneNumber[0])
urlParams.Add("msg", c.Message)
urlParams.Add("str_hash", strHash)
urlParams.Add("txn_id", txnID.String())
urlParams.Add("login", c.SenderID)

urlLink.RawQuery = urlParams.Encode()

request, err := http.NewRequest(http.MethodGet, urlLink.String(), nil)
if err != nil {
return
}

resp, err := client.Do(request)
if err != nil {
return
}

resultBytes, err := io.ReadAll(resp.Body)
if err != nil {
return err
}

var result OsonResponse
if err = json.Unmarshal(resultBytes, &result); err != nil {
return
}

if result.Status != "ok" {
return fmt.Errorf("sms service returned error status not 200: Status Code: %d Error: %s", resp.StatusCode, string(resultBytes))
}

return
}

0 comments on commit bf4c467

Please sign in to comment.