好的,以下是一个封装了腾讯云发送短信接口的示例代码,你可以参考使用:
package sms
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"sort"
"strings"
"time"
jsoniter "github.com/json-iterator/go"
)
const (
smsAPIHost = "sms.tencentcloudapi.com"
smsAPIMethod = "POST"
smsAPIVersion = "2019-07-11"
signatureMethod = "HmacSHA256"
defaultTimeout = 10 * time.Second
)
type TencentCloudSMS struct {
SecretID string // API密钥ID
SecretKey string // API密钥KEY
DefaultSign string // 默认签名名称
DefaultTplID int // 默认模板ID
}
func (tcs *TencentCloudSMS) Send(phoneNumbers []string, tplID int, params []string, signName string) error {
if len(phoneNumbers) == 0 || tplID == 0 {
return errors.New("invalid phone numbers or tpl ID")
}
if signName == "" {
signName = tcs.DefaultSign
}
if tplID == 0 {
tplID = tcs.DefaultTplID
}
paramsJSON, _ := jsoniter.Marshal(params)
queryParams := map[string]string{
"Action": "SendSms",
"Version": smsAPIVersion,
"PhoneNumberSet.N": fmt.Sprintf("%d", len(phoneNumbers)),
}
for i := range phoneNumbers {
queryParams[fmt.Sprintf("PhoneNumberSet.%d", i+1)] = phoneNumbers[i]
}
queryParams["TemplateID"] = fmt.Sprintf("%d", tplID)
queryParams["SmsSdkAppid"] = tcs.SecretID
queryParams["SignName"] = signName
queryParams["TemplateParamSet.N"] = string(paramsJSON)
queryParams["Nonce"] = fmt.Sprintf("%d", time.Now().Unix())
queryParams["Timestamp"] = fmt.Sprintf("%d", time.Now().Unix())
queryParams["SignatureMethod"] = signatureMethod
queryParams["SecretId"] = tcs.SecretID
signature := sign(smsAPIMethod, smsAPIHost, "/", queryParams, tcs.SecretKey)
queryParams["Signature"] = signature
client := http.Client{Timeout: defaultTimeout}
req, err := http.NewRequest(smsAPIMethod, fmt.Sprintf("https://%s/", smsAPIHost), strings.NewReader(buildQuery(queryParams)))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
bodyBytes, _ := ioutil.ReadAll(resp.Body)
var response struct {
Response struct {
Result string `json:"Result"`
Error struct {
Code string `json:"Code"`
Message string `json:"Message"`
} `json:"Error"`
} `json:"Response"`
}
err = jsoniter.Unmarshal(bodyBytes, &response)
if err != nil {
return errors.New(fmt.Sprintf("parse response failed:%s", bodyBytes))
}
if response.Response.Error.Code != "" || response.Response.Result == "failed" {
return errors.New(response.Response.Error.Message)
}
return nil
}
func sign(method string, host string, path string, params map[string]string, secretKey string) string {
var keys []string
for key := range params {
keys = append(keys, key)
}
sort.Strings(keys)
var query string
for _, key := range keys {
query += fmt.Sprintf("%s=%s&", percentEncode(key), percentEncode(params[key]))
}
query = strings.TrimSuffix(query, "&")
str2sign := fmt.Sprintf("%s%s?%s", method, host, query)
mac := hmac.New(sha256.New, []byte(secretKey))
mac.Write([]byte(str2sign))
sum := mac.Sum(nil)
signatureBytes := make([]byte, base64.StdEncoding.EncodedLen(len(sum)))
base64.StdEncoding.Encode(signatureBytes, sum)
return string(signatureBytes)
}
func buildQuery(params map[string]string) string {
query := url.Values{}
for k, v := range params {
query.Add(k, v)
}
return query.Encode()
}
func percentEncode(s string) string {
s = url.QueryEscape(s)
s = strings.ReplaceAll(s, "+", "%20")
s = strings.ReplaceAll(s, "*", "%2A")
s = strings.ReplaceAll(s, "%7E", "~")
return s
}
使用示例:
package main
import (
"fmt"
"github.com/your_username/go-sms"
)
var tencentSMS *sms.TencentCloudSMS
func init() {
tencentSMS = &sms.TencentCloudSMS{
SecretID: "your_secret_id",
SecretKey: "your_secret_key",
DefaultSign: "default_sign_name",
DefaultTplID: 12345,
}
}
func main() {
phoneNumbers := []string{"12345678901"}
tplID := 0 // 如果tplID为0,则使用默认模板ID
params := []string{"param1", "param2"}
signName := "" // 如果signName为空,则使用默认签名名称
err := tencentSMS.Send(phoneNumbers, tplID, params, signName)
if err != nil {
fmt.Printf("send sms failed: %s\n", err.Error())
} else {
fmt.Println("send sms success")
}
}
请注意,此代码示例仅供参考,并不适用于生产环境。在实际项目中,还需要进行错误处理、参数校验等工作。