更新时间:2024-11-14 GMT+08:00
分享

Go

样例

发送短信示例发送分批短信示例接受状态报告示例接收上行短信示例

环境要求

go1.17.1,IntelliJ IDEA 2021.1.3安装插件(Go 211.7628.1)

  • 发送短信为单模板群发短信示例,发送分批短信为多模板群发短信示例。
  • 本文档所述Demo在提供服务的过程中,可能会涉及个人数据的使用,建议您遵从国家的相关法律采取足够的措施,以确保用户的个人数据受到充分的保护。
  • 本文档所述Demo仅用于功能演示,不允许客户直接进行商业使用。
  • 本文档信息仅供参考,不构成任何要约或承诺。

参考API签名SDK与demo,点击下载其中的SDK与Demo。将下列代码样例替换demo.go文件内容即可。

由于使用的是go1.17, 请将首层go.mod文件内容修改为:
module huaweicloud.com/apig/go/signer

require huaweicloud.com/apig/signer v0.0.0

replace huaweicloud.com/apig/signer v0.0.0 => ./core

go 1.12

发送短信示例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
package main

import (
   "bytes"
   "crypto/tls"
   "fmt"
   core "huaweicloud.com/apig/signer"
   "io/ioutil"
   "net/http"
   "net/url"
)

func main() {
   //必填,请参考"开发准备"获取如下数据,替换为实际值
   appInfo := core.Signer{
      // 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;
      Key:    "c8RWg3ggEcyd4D3p94bf3Y7x1Ile", //App Key
      Secret: "q4Ii87Bh************80SfD7Al", //App Secret
   }
   apiAddress := "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1" //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
   sender := "csms12345678"                                    //国内短信签名通道号
   templateId := "8ff55eac1d0b478ab3c06c3c6a492300"               //模板ID

   //条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
   
   signature := "华为云短信测试" //签名名称

   //必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔
   receiver := "+86151****6789" //短信接收人号码

   //选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
   statusCallBack := ""

   /*
    * 选填,使用无变量模板时请赋空值 string templateParas = "";
    * 单变量模板示例:模板内容为"您的验证码是${1}"时,templateParas可填写为"[\"369751\"]"
    * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,templateParas可填写为"[\"3\",\"人民公园正门\"]"
    * 模板中的每个变量都必须赋值,且取值不能为空
    * 查看更多模板规范和变量规范:产品介绍>短信模板须知和短信变量须知
    */
   templateParas := "[\"369751\"]" //模板变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。

   body := buildRequestBody(sender, receiver, templateId, templateParas, statusCallBack, signature)
   resp, err := post(apiAddress, []byte(body), appInfo)

   if err != nil {
      return
   }
   fmt.Println(resp)
}

/**
 * sender,receiver,templateId不能为空
 */
func buildRequestBody(sender, receiver, templateId, templateParas, statusCallBack, signature string) string {
   param := "from=" + url.QueryEscape(sender) + "&to=" + url.QueryEscape(receiver) + "&templateId=" + url.QueryEscape(templateId)
   if templateParas != "" {
      param += "&templateParas=" + url.QueryEscape(templateParas)
   }
   if statusCallBack != "" {
      param += "&statusCallback=" + url.QueryEscape(statusCallBack)
   }
   if signature != "" {
      param += "&signature=" + url.QueryEscape(signature)
   }
   return param
}

func post(url string, param []byte, appInfo core.Signer) (string, error) {
   if param == nil || appInfo == (core.Signer{}) {
      return "", nil
   }

   // 代码样例为了简便,设置了不进行证书校验,请在商用环境自行开启证书校验。
   tr := &http.Transport{
      TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   }
   client := &http.Client{Transport: tr}

   req, err := http.NewRequest("POST", url, bytes.NewBuffer(param))
   if err != nil {
      return "", err
   }

   // 对请求增加内容格式,固定头域
   req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
   // 对请求进行HMAC算法签名,并将签名结果设置到Authorization头域。
   appInfo.Sign(req)

   fmt.Println(req.Header)
   // 发送短信请求
   resp, err := client.Do(req)
   if err != nil {
      fmt.Println(err)
   }

   // 获取短信响应
   defer resp.Body.Close()
   body, err := ioutil.ReadAll(resp.Body)
   if err != nil {
      return "", err
   }
   return string(body), nil
}

发送分批短信示例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main

import (
   "bytes"
   "crypto/tls"
   "encoding/json"
   "fmt"
   core "huaweicloud.com/apig/signer"
   "io/ioutil"
   "net/http"
)

func main() {
   //必填,请参考"开发准备"获取如下数据,替换为实际值
   apiAddress := "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendDiffSms/v1" //APP接入地址(在控制台"应用管理"页面获取)+接口访问URI
   // 认证用的appKey和appSecret硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;
   appKey := "c8RWg3ggEcyd4D3p94bf3Y7x1Ile"                                         //APP_Key
   appSecret := "q4Ii87Bh************80SfD7Al"                                      //APP_Secret
   sender := "csms12345678"                                                         //国内短信签名通道号
   templateId1 := "8ff55eac1d0b478ab3c06c3c6a492300"                                //模板ID1
   templateId2 := "8ff55eac1d0b478ab3c06c3c6a492300"                                //模板ID2

   //条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
   
   signature1 := "华为云短信测试" //签名名称1
   signature2 := "华为云短信测试" //签名名称2

   //必填,全局号码格式(包含国家码),示例:+8615123456789,多个号码之间用英文逗号分隔
   receiver1 := []string{"+86151****6789", "+86152****7890"} //模板1的接收号码
   receiver2 := []string{"+86151****6789", "+86152****7890"} //模板2的接收号码

   //选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
   statusCallBack := ""

   /**
    * 选填,使用无变量模板时请赋空值 templateParas := []string{}
    * 单变量模板示例:模板内容为"您的验证码是${1}"时,templateParas可填写为[]string{"369751"}
    * 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,templateParas可填写为[]string{{"3","人民公园正门"}
    * ${DATE}${TIME}变量不允许取值为空,${TXT_20}变量可以使用英文空格或点号替代空值,${NUM_6}变量可以使用0替代空值
    * 查看更多模板规范和变量规范:产品介绍>短信模板须知和短信变量须知
    */
   templateParas1 := []string{"123456"} //模板1变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。
   templateParas2 := []string{"234567"} //模板2变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。

   item1 := initDiffSms(receiver1, templateId1, templateParas1, signature1)
   item2 := initDiffSms(receiver2, templateId2, templateParas2, signature2)

   item := []map[string]interface{}{item1, item2}
   body := buildRequestBody(sender, item, statusCallBack)

   appInfo := core.Signer{
      Key:    appKey, //App Key
      Secret: appSecret, //App Secret
   }
   resp, err := post(apiAddress, []byte(body), appInfo)
   if err != nil {
      return
   }
   fmt.Println(resp)
}

func buildRequestBody(sender string, item []map[string]interface{}, statusCallBack string) []byte {
   body := make(map[string]interface{})
   body["smsContent"] = item
   body["from"] = sender
   if statusCallBack != "" {
      body["statusCallback"] = statusCallBack
   }
   res, _ := json.Marshal(body)
   return res
}

func initDiffSms(reveiver []string, templateId string, templateParas []string, signature string) map[string]interface{} {
   diffSms := make(map[string]interface{})
   diffSms["to"] = reveiver
   diffSms["templateId"] = templateId
   if templateParas != nil && len(templateParas) > 0 {
      diffSms["templateParas"] = templateParas
   }
   if signature != "" {
      diffSms["signature"] = signature
   }
   return diffSms
}

func post(url string, param []byte, appInfo core.Signer) (string, error) {
   if param == nil || appInfo == (core.Signer{}) {
      return "", nil
   }

   // 代码样例为了简便,设置了不进行证书校验,请在商用环境自行开启证书校验。
   tr := &http.Transport{
      TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
   }
   client := &http.Client{Transport: tr}

   req, err := http.NewRequest("POST", url, bytes.NewBuffer(param))
   if err != nil {
      return "", err
   }

   // 对请求增加内容格式,固定头域
   req.Header.Add("Content-Type", "application/json")
   // 对请求进行HMAC算法签名,并将签名结果设置到Authorization头域。
   appInfo.Sign(req)

   fmt.Println(req.Header)
   // 发送短信请求
   resp, err := client.Do(req)
   if err != nil {
      fmt.Println(err)
   }

   // 获取短信响应
   defer resp.Body.Close()
   body, err := ioutil.ReadAll(resp.Body)
   if err != nil {
      return "", err
   }
   return string(body), nil
}

接收状态报告

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
    "fmt"
    "net/url"
    "strings"
)

func main() {
    // 短信平台上报状态报告数据样例(urlencode)
    //success_body := "sequence=1&total=1&updateTime=2018-10-31T08%3A43%3A41Z&source=2&smsMsgId=2ea20735-f856-4376-afbf-570bd70a46ee_11840135&status=DELIVRD";
    failed_body := "sequence=1&total=1&updateTime=2018-10-31T08%3A43%3A41Z&source=2&smsMsgId=2ea20735-f856-4376-afbf-570bd70a46ee_11840135&status=E200027";
    //onSmsStatusReport(success_body);
    onSmsStatusReport(failed_body);
}

func onSmsStatusReport(data string) {
    ss, _ := url.QueryUnescape(data)
    params := strings.Split(ss, "&")
    keyValues := make(map[string]string)
    for i := range params {
        temp := strings.Split(params[i],"=")
        keyValues[temp[0]] = temp[1];
    }
    status := keyValues["status"];
    if status == "DELIVRD" {
        fmt.Println("Send sms success. smsMsgId: " + keyValues["smsMsgId"])
    } else {
        fmt.Println("Send sms failed. smsMsgId: " + keyValues["smsMsgId"])
        fmt.Println("Failed status:  " + keyValues["status"])
    }
}

接收上行短信

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
    "fmt"
    "net/url"
    "strings"
)

func main() {
    upData := "from=%2B86151****6789&to=1069***2019&body=***********&smsMsgId=9692b5be-c427-4525-8e73-cf4a6ac5b3f7";
    onSmsUpData(upData);
}

func onSmsUpData(data string) {
    ss, _ := url.QueryUnescape(data)
    params := strings.Split(ss, "&")
    keyValues := make(map[string]string)
    for i := range params {
        temp := strings.Split(params[i],"=")
        keyValues[temp[0]] = temp[1];
    }
    body := keyValues["body"];
    fmt.Println("Sms up data. Body: " + body)
}

相关文档