package utils import ( "crypto/hmac" "crypto/sha1" "encoding/base64" "encoding/json" "errors" "fmt" "io/ioutil" "math/rand" "net/http" "net/url" "strconv" "strings" "time" ) const sortQueryStringFmt string = "AccessKeyId=%s" + "&Action=SendSms" + "&Format=JSON" + "&OutId=123" + "&PhoneNumbers=%s" + "&RegionId=cn-hangzhou" + "&SignName=%s" + "&SignatureMethod=HMAC-SHA1" + "&SignatureNonce=%s" + "&SignatureVersion=1.0" + "&TemplateCode=%s" + "&TemplateParam=%s" + "&Timestamp=%s" + "&Version=2017-05-25" func encodeLocal(encodeStr string) string { urlEncode := url.QueryEscape(encodeStr) urlEncode = strings.Replace(urlEncode, "+", "%%20", -1) urlEncode = strings.Replace(urlEncode, "*", "%2A", -1) urlEncode = strings.Replace(urlEncode, "%%7E", "~", -1) urlEncode = strings.Replace(urlEncode, "/", "%%2F", -1) return urlEncode } // SendSmsReply 发送短信返回 type SendSmsReply struct { Code string `json:"Code,omitempty"` Message string `json:"Message,omitempty"` } func SendSms(phone string, paramStr string, signName string, templateCode string) error { const token string = "IP2dC1XDM15A6mCt3yTRDk3ZWHri19&" // 阿里云 accessSecret 注意这个地方要添加一个 & AccessKeyId := "LTAI5t6oHZUFW5bqNTbDwd5n" // 自己的阿里云 accessKeyID SignatureNonce := strconv.Itoa(GenerateRandNumByCount(9)) TemplateParam := url.QueryEscape(paramStr) Timestamp := url.QueryEscape(time.Now().UTC().Format("2006-01-02T15:04:05Z")) sortQueryString := fmt.Sprintf(sortQueryStringFmt, AccessKeyId, phone, url.QueryEscape(signName), SignatureNonce, templateCode, TemplateParam, Timestamp, ) urlencode := encodeLocal(sortQueryString) sign_str := fmt.Sprintf("GET&%%2F&%s", urlencode) key := []byte(token) mac := hmac.New(sha1.New, key) mac.Write([]byte(sign_str)) signature := base64.StdEncoding.EncodeToString(mac.Sum(nil)) signature = encodeLocal(signature) resp, err := http.Get("http://dysmsapi.aliyuncs.com/?Signature=" + signature + "&" + sortQueryString) if err != nil { fmt.Println(err) return err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) return err } ssr := &SendSmsReply{} if err := json.Unmarshal(body, ssr); err != nil { return err } if ssr.Code == "SignatureNonceUsed" { return SendSms(phone, paramStr, signName, templateCode) } else if ssr.Code != "OK" { return errors.New(ssr.Code) } return nil } func GenerateRandNumByCount(count int) int { rand.Seed(time.Now().Unix()) rnd := rand.Intn(9*int(exponent(10, uint64(count-1)))-1) + int(exponent(10, uint64(count-1))) return rnd } func exponent(a, n uint64) uint64 { result := uint64(1) for i := n; i > 0; i >>= 1 { if i&1 != 0 { result *= a } a *= a } return result } func SendMessageNotice(phone string, content string, signName string, templateCode string) { const token string = "IXvbHeyNLAWJHC08mg4quGYQtmf84h&" // 阿里云 accessSecret 注意这个地方要添加一个 & AccessKeyId := "LTAIZSh7LB8zkmtO" // 自己的阿里云 accessKeyID SignatureNonce := strconv.Itoa(GenerateRandNumByCount(9)) //TemplateCode := "SMS_140625198" TemplateParam := url.QueryEscape("{\"content\":\"" + content + "\"}") Timestamp := url.QueryEscape(time.Now().UTC().Format("2006-01-02T15:04:05Z")) sortQueryString := fmt.Sprintf(sortQueryStringFmt, AccessKeyId, phone, url.QueryEscape(signName), SignatureNonce, templateCode, TemplateParam, Timestamp, ) urlEncode := encodeLocal(sortQueryString) signStr := fmt.Sprintf("GET&%%2F&%s", urlEncode) key := []byte(token) mac := hmac.New(sha1.New, key) mac.Write([]byte(signStr)) signature := base64.StdEncoding.EncodeToString(mac.Sum(nil)) signature = encodeLocal(signature) resp, err := http.Get("http://dysmsapi.aliyuncs.com/?Signature=" + signature + "&" + sortQueryString) if err != nil { fmt.Println(err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) return } ssr := &SendSmsReply{} if err := json.Unmarshal(body, ssr); err != nil { return } if ssr.Code == "SignatureNonceUsed" { SendMessageNotice(phone, content, signName, templateCode) return } else if ssr.Code != "OK" { return } return }