mirror of https://gitee.com/godoos/godoos.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.4 KiB
142 lines
3.4 KiB
package baidu
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Region = string
|
|
|
|
const (
|
|
// _ Region = ""
|
|
RegionBJ = "bj"
|
|
RegionGZ = "gz"
|
|
)
|
|
|
|
// BaiduSMS is config of sms service. AccessKey, SecretKey, Region should be provided
|
|
// Region is one of "bj" and "gz"
|
|
type BaiduSMS struct {
|
|
AccessKey string
|
|
SecretKey string
|
|
Region string
|
|
}
|
|
|
|
// SuccessResponse is success body of baidu response
|
|
type SuccessResponse struct {
|
|
Code string `json:"code"`
|
|
Message string `json:"message"`
|
|
RequestID string `json:"requestId"`
|
|
}
|
|
|
|
// ErrSendFail is fail body of baidu response
|
|
type ErrSendFail struct {
|
|
HTTPCode int
|
|
APICode string
|
|
Message string
|
|
RequestID string
|
|
}
|
|
|
|
func (e *ErrSendFail) Error() string {
|
|
return fmt.Sprintf(
|
|
"Baidu SMS API error, httpcode: %d, code: %s, message: %s, requestID: %s",
|
|
e.HTTPCode, e.APICode, e.Message, e.RequestID,
|
|
)
|
|
}
|
|
|
|
const (
|
|
// Version of baidusms
|
|
Version = "3.0.0"
|
|
gzHost = "smsv3.gz.baidubce.com"
|
|
bjHost = "smsv3.bj.baidubce.com"
|
|
)
|
|
|
|
func (bd BaiduSMS) sendRequest(method string, path string, body string) (*SuccessResponse, error) {
|
|
now := time.Now()
|
|
auth := auth{bd.AccessKey, bd.SecretKey}
|
|
var host string
|
|
if strings.ToLower(bd.Region) == "gz" {
|
|
host = gzHost
|
|
} else {
|
|
host = bjHost
|
|
}
|
|
targetURL := fmt.Sprintf("https://%s%s", host, path)
|
|
req, err := http.NewRequest(method, targetURL, strings.NewReader(body))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
req.Header.Add("User-Agent", fmt.Sprintf("bce-sdk-go/%s", Version))
|
|
req.Header.Add("Host", host)
|
|
req.Header.Add("Connection", "close")
|
|
req.Header.Add("Content-Type", "application/json")
|
|
req.Header.Add("Content-Length", strconv.FormatInt(req.ContentLength, 10))
|
|
req.Header.Add("x-bce-date", getCanonicalTime(now))
|
|
sum := sha256.Sum256([]byte(body))
|
|
req.Header.Add("x-bce-content-sha256", hex.EncodeToString(sum[:]))
|
|
headers := req.Header
|
|
req.Header.Add("Authorization", auth.generateAuthorization(method, path, headers, url.Values{}, now))
|
|
client := &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == http.StatusOK {
|
|
bodyBytes, readErr := io.ReadAll(resp.Body)
|
|
if readErr != nil {
|
|
return nil, readErr
|
|
}
|
|
var s SuccessResponse
|
|
err = json.Unmarshal(bodyBytes, &s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if s.Code != "1000" {
|
|
// only 1000 is correct
|
|
return nil, &ErrSendFail{
|
|
HTTPCode: resp.StatusCode,
|
|
APICode: s.Code,
|
|
Message: s.Message,
|
|
RequestID: s.RequestID,
|
|
}
|
|
}
|
|
return &s, nil
|
|
}
|
|
return nil, &ErrSendFail{
|
|
HTTPCode: resp.StatusCode,
|
|
}
|
|
}
|
|
|
|
type requestBody struct {
|
|
SignatureID string `json:"signatureId"`
|
|
Mobile string `json:"mobile"`
|
|
Template string `json:"template"`
|
|
ContentVar map[string]string `json:"contentVar"`
|
|
}
|
|
|
|
// SendSMSCode will call HTTP request to Baidu API to send a sms
|
|
// mobile should be array (length limited in 1-200) of E.164 phoneNumber
|
|
func (bd BaiduSMS) SendSMSCode(
|
|
mobile []string,
|
|
template string,
|
|
signatureID string,
|
|
contentVar map[string]string,
|
|
) (*SuccessResponse, error) {
|
|
path := "/api/v3/sendSms"
|
|
body := requestBody{signatureID, strings.Join(mobile, ","), template, contentVar}
|
|
bodyStr, err := json.Marshal(body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return bd.sendRequest("POST", path, string(bodyStr))
|
|
}
|
|
|