Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add multiple sms #27

Merged
merged 5 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ This is a powerful open-source library for sending SMS message, which will help

We support the following SMS providers, welcome to contribute.

- [Aliyun](https://www.aliyun.com/product/sms)
- [Tencent](https://cloud.tencent.com/document/product/382)
- [Twilio](https://www.twilio.com)
- [GCCPAY](https://gccpay.com/)
- [Infobip](https://www.infobip.com/)
- [SUBMAIL](https://en.mysubmail.com/)
- [SmsBao](https://www.smsbao.com/)
- [Alibaba Cloud](https://www.aliyun.com/product/sms)
- [Tencent Cloud](https://cloud.tencent.com/document/product/382)
- [Baidu Cloud](https://cloud.baidu.com/product/sms.html)
- [VolcEngine](https://www.volcengine.com/product/cloud-sms)
- [Huawei](https://www.huaweicloud.com/product/msgsms.html)
- [Huawei Cloud](https://www.huaweicloud.com/product/msgsms.html)
- [UCloud](https://www.ucloud.cn/site/product/usms.html)
- [Huyi](https://www.ihuyi.com/)

## Installation
Expand Down Expand Up @@ -51,7 +58,32 @@ SendMessage(param map[string]string, targetPhoneNumber ...string) error
- `param` the parameters in the SMS template, such as 6 random numbers
- `targetPhoneNumber` the receivers, such as `+8612345678910`

## Demo
## Example

### Twilio

Please get necessary information from Twilio [console](https://console.twilio.com/)

```go
package main

import "github.com/casdoor/go-sms-sender"

func main() {
client, err := go_sms_sender.NewSmsClient(go_sms_sender.Twilio, "ACCOUNT_SID", "AUTH_TOKEN", "", "TEMPLATE_CODE")
if err != nil {
panic(err)
}

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

### Aliyun

Expand Down Expand Up @@ -103,4 +135,4 @@ func main() {

## License

This project is licensed under the [Apache 2.0 license](LICENSE).
This project is licensed under the [Apache 2.0 license](LICENSE).
9 changes: 9 additions & 0 deletions basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const (
MockSms = "Mock SMS"
SUBMAIL = "SUBMAIL SMS"
BaiduCloud = "Baidu Cloud SMS"
UCloud = "UCloud SMS"
GCCPAY = "GCCPAY SMS"
Infobip = "Infobip SMS"
)

type SmsClient interface {
Expand Down Expand Up @@ -55,6 +58,12 @@ func NewSmsClient(provider string, accessId string, accessKey string, sign strin
return GetSubmailClient(accessId, accessKey, template)
case BaiduCloud:
return GetBceClient(accessId, accessKey, sign, template, other)
case UCloud:
return GetUcloudClient(accessId, accessKey, sign, template, other)
case GCCPAY:
return GetGCCPAYClient(accessId, accessKey, template)
case Infobip:
return GetInfobipClient(accessId, accessKey, other)
default:
return nil, fmt.Errorf("unsupported provider: %s", provider)
}
Expand Down
127 changes: 127 additions & 0 deletions gccpay.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// 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 (
"bytes"
"crypto/md5"
"crypto/rand"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
)

type GCCPAYClient struct {
clientname string
secret string
template string
}

type params struct {
Mobile string `json:"mobile"`
TemplateCode string `json:"template_code"`
TemplateParams map[string]string `json:"template_params"`
}

func GetGCCPAYClient(clientname string, secret string, template string) (*GCCPAYClient, error) {
gccPayClient := &GCCPAYClient{
clientname: clientname,
secret: secret,
template: template,
}

return gccPayClient, nil
}

func RandStringBytesCrypto(n int) (string, error) {
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(b), nil
}

func Md5(str string) string {
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}

func (c *GCCPAYClient) SendMessage(param map[string]string, targetPhoneNumber ...string) error {
_, ok := param["code"]
if !ok {
return fmt.Errorf("missing parameter: msg code")
}

if len(targetPhoneNumber) < 1 {
return fmt.Errorf("missing parameter: targetPhoneNumber")
}

reqParams := make(map[string]params)

for _, mobile := range targetPhoneNumber {
if strings.HasPrefix(mobile, "+") {
mobile = mobile[1:]
}
randomString, err := RandStringBytesCrypto(16)
if err != nil {
return fmt.Errorf("SMS key generation failed")
}

reqParams[randomString] = params{
Mobile: mobile,
TemplateCode: c.template,
TemplateParams: param,
}
}

requestBody := new(bytes.Buffer)
err := json.NewEncoder(requestBody).Encode(reqParams)
if err != nil {
return fmt.Errorf("SMS sending failed")
}

// sign
timestamp := time.Now().Unix()

sign := Md5(fmt.Sprintf("%s%d%s", c.clientname, timestamp, c.secret))

reqUrl := "https://smscenter.sgate.sa/api/v1/client/sendSms"

// send request
req, _ := http.NewRequest("POST", reqUrl, requestBody)
req.Header.Set("clientname", c.clientname)
req.Header.Set("timestamp", fmt.Sprintf("%d", timestamp))
req.Header.Set("sign", sign)
req.Header.Set("content-type", "application/json;")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}

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

return nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.639
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.639
github.com/twilio/twilio-go v0.26.0
github.com/ucloud/ucloud-sdk-go v0.22.4 // indirect
github.com/volcengine/volc-sdk-golang v1.0.19
)
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswD
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
Expand All @@ -54,18 +56,23 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLD
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
Expand All @@ -76,10 +83,14 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.639 h1:98cUzYW
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.639/go.mod h1:JX7a56foe9SsC6mCYOPGFx4YdRLBP/PJWQFuZQuhCt4=
github.com/twilio/twilio-go v0.26.0 h1:wFW4oTe3/LKt6bvByP7eio8JsjtaLHjMQKOUEzQry7U=
github.com/twilio/twilio-go v0.26.0/go.mod h1:lz62Hopu4vicpQ056H5TJ0JE4AP0rS3sQ35/ejmgOwE=
github.com/ucloud/ucloud-sdk-go v0.22.4 h1:QFQoHAnlNN69dzPW4ArWrIg8CfZ0zfo5vcTOzhMSdVQ=
github.com/ucloud/ucloud-sdk-go v0.22.4/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw=
github.com/volcengine/volc-sdk-golang v1.0.19 h1:jJp+aJgK0e//rZ9I0K2Y7ufJwvuZRo/AQsYDynXMNgA=
github.com/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF0Ui9vIInTojMM0IfSS4=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand All @@ -99,10 +110,12 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
Loading