var body = keyValues.body; // 上行短信发送的内容 console.log('Sms up data. Body: ', body);
}
onSmsUpData(updata);
相关推荐
相关文档 相关产品
● 代码样例:Java/PHP/Python/C#/Go
●
发送短信API
●
发送分批短信API
●
接收状态报告API
●
接收上行短信API
●
调测问题处理
语音通话 隐私保护通话
3.6 Go
样例
发送短信、发送分批短信
接收状态报告、接收上行短信
环境要求 go1.11及以上版本引用库
github.com/satori/go.uuid
须知
● 本文档所述Demo在提供服务的过程中,可能会涉及个人数据的使用,建议您遵从 国家的相关法律采取足够的措施,以确保用户的个人数据受到充分的保护。
● 本文档所述Demo仅用于功能演示,不允许客户直接进行商业使用。
● 本文档信息仅供参考,不构成任何要约或承诺。
发送短信
package main import ( "bytes"
"crypto/sha256"
"crypto/tls"
"encoding/base64"
"fmt"
"github.com/satori/go.uuid"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
)
//无需修改,用于格式化鉴权头域,给"X-WSSE"参数赋值
const WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s
\",Created=\"%s\""
//无需修改,用于格式化鉴权头域,给"Authorization"参数赋值
const AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""
func main() {
//必填,请参考"开发准备"获取如下数据,替换为实际值
apiAddress := "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1" //APP接入地址 (在控制台"应用管理"页面获取)+接口访问URI
appKey := "c8RWg3ggEcyd4D3p94bf3Y7x1Ile" //APP_Key appSecret := "q4Ii87BhST9vcs8wvrzN80SfD7Al" //APP_Secret
sender := "csms12345678" //国内短信签名通道号或国际/港澳台短信通道号 templateId := "8ff55eac1d0b478ab3c06c3c6a492300" //模板ID
//条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板 类型一致的签名名称
//国际/港澳台短信不用关注该参数 signature := "华为云短信测试" //签名名称
//必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔 receiver := "+86151****6789,+86152****7890" //短信接收人号码
//选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告 statusCallBack := ""
/*
* 选填,使用无变量模板时请赋空值 string templateParas = "";
* 单变量模板示例:模板内容为"您的验证码是${1}"时,templateParas可填写为"[\"369751\"]"
* 双变量模板示例:模板内容为"您有${1}件快递请到${2}领取"时,templateParas可填写为"[\"3\",\"人民公园正 门\"]"
* 模板中的每个变量都必须赋值,且取值不能为空 * 查看更多模板和变量规范:产品介绍>模板和变量规范 */
templateParas := "[\"369751\"]" //模板变量,此处以单变量验证码短信为例,请客户自行生成6位验证码,并 定义为字符串类型,以杜绝首位0丢失的问题(例如:002569变成了2569)。
body := buildRequestBody(sender,receiver,templateId,templateParas,statusCallBack,signature) headers := make(map[string]string)
headers["Content-Type"] = "application/x-www-form-urlencoded"
headers["Authorization"] = AUTH_HEADER_VALUE;
headers["X-WSSE"] = buildWsseHeader(appKey, appSecret);
resp, err := post(apiAddress, []byte(body),headers) 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, headers map[string]string)(string,error) { 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 }
for key, header := range headers { req.Header.Set(key, header) }
resp, err := client.Do(req) defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil {
return "", err }
return string(body), nil;
}
func buildWsseHeader(appKey,appSecret string)string { var cTime = time.Now().Format("2006-01-02T15:04:05Z") var nonce = uuid.NewV4().String()
nonce = strings.ReplaceAll(nonce,"-","") h := sha256.New()
h.Write([]byte(nonce + cTime + appSecret))
passwordDigestBase64Str := base64.StdEncoding.EncodeToString(h.Sum(nil))
return fmt.Sprintf(WSSE_HEADER_FORMAT,appKey,passwordDigestBase64Str,nonce, cTime);
}
发送分批短信
package main import ( "bytes"
"crypto/sha256"
"crypto/tls"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/satori/go.uuid"
"io/ioutil"
"net/http"
"strings"
"time"
)
//无需修改,用于格式化鉴权头域,给"X-WSSE"参数赋值
const WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s
\",Created=\"%s\""
//无需修改,用于格式化鉴权头域,给"Authorization"参数赋值
const AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""
func main() {
//必填,请参考"开发准备"获取如下数据,替换为实际值
url := "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendDiffSms/v1" //APP接入地址(在控 制台"应用管理"页面获取)+接口访问URI
appKey := "c8RWg3ggEcyd4D3p94bf3Y7x1Ile" //APP_Key appSecret := "q4Ii87BhST9vcs8wvrzN80SfD7Al" //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) headers := make(map[string]string)
headers["Content-Type"] = "application/json;charset=utf-8"
headers["Authorization"] = AUTH_HEADER_VALUE;
headers["X-WSSE"] = buildWsseHeader(appKey, appSecret);
resp, err := post(url,body,headers) 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, headers map[string]string)(string,error) { 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 }
for key, header := range headers { req.Header.Set(key, header) }
resp, err := client.Do(req) defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil {
return "", err }
return string(body), nil;
}
func buildWsseHeader(appKey,appSecret string)string { var cTime = time.Now().Format("2006-01-02T15:04:05Z") var nonce = uuid.NewV4().String()
nonce = strings.ReplaceAll(nonce,"-","") h := sha256.New()
h.Write([]byte(nonce + cTime + appSecret))
passwordDigestBase64Str := base64.StdEncoding.EncodeToString(h.Sum(nil))
return fmt.Sprintf(WSSE_HEADER_FORMAT,appKey,passwordDigestBase64Str,nonce, cTime);
}
接收状态报告
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"])
} }
接收上行短信
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) }
相关推荐
相关文档 相关产品
● 代码样例:Java/PHP/Python/C#/Node.js
●
发送短信API
●
发送分批短信API
●
接收状态报告API
●
接收上行短信API
●
调测问题处理
语音通话
隐私保护通话
4 API 错误码
说明
本章节为调用API错误返回的错误码全集,数量较多,建议您使用快捷键Ctrl+F在界面进行搜 索,找到您需要的错误码处理建议。
404 问题处理
若调用接口时返回了404响应,请检查APP接入地址和访问URI(详见开发准备)是否
都填写正确,且拼接成了完整的请求URL,如“https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1”。
错误码处理
调用发送短信/发送分批短信接口会产生接口调用错误码,响应示例如下:
注:一个请求响应只有一个code,一个手机号码对应一个status。
HTTP/1.1 200 OK
Date: Mon, 06 Aug 2018 11:59:50 GMT Server: WebServer
Content-Type: application/json;charset=UTF-8 Content-Length: 224
{ "code":"000000", "description":"Success", "result":
[{
"originTo":"+8618612345678", "createTime":"2018-08-06T11:59:50Z", "from":"1069031221280000001",
"smsMsgId":"4b4b34e7-1a9e-42ac-b309-d10997148905_85496076", "status":"000000"
}]
}
code参数处理
参数取值 说明 处理建议
000000 请求成功。 接口调用成功,请等待短信状态报告。
参数取值 说明 处理建议 E000000 表示系统异常,一般是
请求格式异常,短信平 台无法解析。
● 请检查短信模板,变量部分用{},而不是 ();重新申请模板
● 请参考代码样例检查“templateParas”参 数值引号使用是否合理:
–
发送短信API中,“templateParas”参
数为字符串类型,参数值需要加引号,每个模板变量值都需要加引号,请合理 使用转义字符或单引号/双引号嵌套。
示例:templateParas='["3","人民公园 正门"]'
–
发送分批短信API中,
“templateParas”参数为字符串数组 类型,参数值无需加引号,每个数组元 素(即模板变量)都需要加引号。示 例:templateParas=["3","人民公园正 门"]
● 请检查请求消息体编码格式是否正确:
–
发送短信API中,请求Body参数是
URLEncode字符串。
–
发送分批短信API中,请求Body参数是
Json字符串。
E000001 HTTP消息头未找到
Authorization字段 请检查HTTP消息头中是否携带了 Authorization字段。
E000002 Authorization字段中未
找到realm属性 请检查Authorization字段中的是否携带了 realm属性。
E000003 Authorization字段中未
找到profile属性 请检查Authorization字段中的是否携带了 profile属性。
E000004 Authorization中realm
属性值应该为“SDP” 请检查Authorization字段中的realm属性值是 否为“SDP”。
E000005 Authorization中profile 属性值应该为
“UsernameToken”
请检查Authorization字段中的profile属性值 是否为“UsernameToken”。
E000006 Authorization中type属
性值应该为“Appkey” 请检查Authorization字段中的type属性值是 否为“Appkey”。
E000007 Authorization字段中未
找到type属性 请检查Authorization字段中是否携带了type 属性。
E000008 Authorization中没有携
带WSSE 请检查Authorization字段中是否携带了 WSSE。
E000020 HTTP头未找到X-WSSE
字段 请检查HTTP消息头中是否携带了X-WSSE字 段。
参数取值 说明 处理建议 E000021 X-WSSE字段中未找到
UserName属性 请检查X-WSSE字段中的是否携带了 UserName属性。
E000022 X-WSSE字段中未找到
Nonce属性 请检查X-WSSE字段中的是否携带了Nonce属 性。
E000023 X-WSSE字段中未找到
Created属性 请检查X-WSSE字段中的是否携带了Created属 性。
E000024 X-WSSE字段中未找到
PasswordDigest属性 请检查X-WSSE字段中的是否携带了 PasswordDigest属性。
E000025 Created属性格式错误 请检查X-WSSE字段中的Created属性格式是否 正确。
E000026 X-WSSE字段中未找到
UsernameToken属性 请检查X-WSSE字段中的是否携带了 UsernameToken属性。
E000027 非法请求 根据API接口文档的参数描述和要求,检查请 求携带的参数是否都合法。
E000040 ContentType值应该为 application/x-www-form-urlencoded
请检查ContentType头域的取值是否为
“application/x-www-form-urlencoded”。
E000101 鉴权失败 请检查Authorization和X-WSSE参数的填写是 否正确。
E000102 app_key无效 请检查请求携带的app_key填写是否正确。
如app_key填写正确,建议检查app接入地址 是否正确(从控制台“应用管理”获取)。
E000103 app_key不可用 请联系管理员确认该app_key状态是否正常。
E000104 app_secret无效 请检查请求携带的app_secret填写是否正确。
E000105 PasswordDigest无效 请检查请求携带的PasswordDigest填写是否 正确。
E000106 app_key没有调用本API
的权限 请联系管理员确认该app_key是否具有“短信 能力开放”能力。
E000109 用户状态未激活 请联系管理员激活用户。
E000110 时间超出限制 请确认X-WSSE鉴权时,生成随机数的时间
(Created)与发送请求时的本地时间不能相 差太大(具体差值请与管理员确认)。
请确认服务器的本地时间是否正确,建议不要 与北京时间相差大于8小时。
请检查随机数生成时间(Created)的代码实 现,以Java为例,将格式字符串中的YYYY改 为yyyy。请参考发送短信API。
参数取值 说明 处理建议
E000111 用户名或密码错误 系统找不到app_key对应的用户信息,请联系 管理员处理。
E000112 用户状态已冻结 若是因账户欠费冻结,请参考华为云账户充值 完成充值,到账后自动解冻。
若是因业务违规冻结,请整改业务后联系运营 经理申请解冻。
E000503 参数格式错误 请检查参数格式是否正确。
E000510 短信发送失败,描述见
参数status 请参考status参数处理,修改后重新发送。
E000620 对端app IP不在白名单
列表中 联系管理员检查IP白名单是否配置正确。
列表中 联系管理员检查IP白名单是否配置正确。