GO API

最近更新时间:2020-07-29 11:39:50

腾讯云 API 全新升级3.0 ,该版本进行了性能优化且全地域部署、支持就近和按地域接入、访问时延下降显著,接口描述更加详细、错误码描述更加全面、SDK增加接口级注释,让您更加方便快捷的使用腾讯云产品。这里针对 GO API 调用方式进行简单说明。
现已支持云服务器(CVM)、云硬盘(CBS)、私有网络(VPC)、云数据库(TencentDB)等 腾讯云产品,后续会支持其他的云产品接入,敬请期待。

了解请求结构

1. 服务地址(endpoint)

API 支持就近地域接入(例如:cvm 产品域名为 cvm.tencentcloudapi.com),也支持指定地域域名访问(例如:广州地域的域名为 cvm.ap-guangzhou.tencentcloudapi.com),各地域参数见下文公共参数中的地域列表,详情请参见各产品的“请求结构”文档说明判断是否支持该地域。

注意:

对时延敏感的业务,建议指定带地域的域名。

2. 通信协议

腾讯云 API 的所有接口均通过 HTTPS 进行通信,提供高安全性的通信通道。

3. 请求方法

支持的 HTTP 请求方法:

  • POST(推荐)
  • GET

POST 请求支持的 Content-Type 类型:

  • application/json(推荐),必须使用签名方法 v3(TC3-HMAC-SHA256)。
  • application/x-www-form-urlencoded,必须使用签名方法 v1(HmacSHA1 或 HmacSHA256)。
  • multipart/form-data(仅部分接口支持),必须使用签名方法 v3(TC3-HMAC-SHA256)。

GET 请求的请求包大小不得超过32KB。POST 请求使用签名方法 v1(HmacSHA1、HmacSHA256)时不得超过1MB。POST 请求使用签名方法 v3(TC3-HMAC-SHA256)时支持10MB。

4. 字符编码

均使用 UTF-8 编码。

公共参数

说明:

公共参数是用于标识用户和接口签名的参数,每次请求均需要携带这些参数,才能正常发起请求。

签名方法 V3 公共参数

签名方法 v3 (有时也称作 TC3-HMAC-SHA256)相比签名方法 v1 (有些文档可能会简称签名方法),更安全,支持更大的请求包,支持 POST JSON 格式,性能有一定提升,推荐使用该签名方法计算签名。使用方法见下文 “签名方法介绍” 。

参数名称 类型 必选 描述
X-TC-Action String 操作的接口名称。取值参考接口文档中输入参数公共参数 Action 的说明。例如云服务器的查询实例列表接口,取值为 DescribeInstances。
X-TC-Region String - 地域参数,用来标识希望操作哪个地域的数据。接口接受的地域取值参考接口文档中输入参数公共参数 Region 的说明。注意:某些接口不需要传递该参数,接口文档中会对此特别说明,此时即使传递该参数也不会生效。
X-TC-Timestamp Integer 当前 UNIX 时间戳,可记录发起 API 请求的时间。例如 1529223702。注意:如果与服务器时间相差超过5分钟,会引起签名过期错误。
X-TC-Version String 操作的 API 的版本。取值参考接口文档中入参公共参数 Version 的说明。例如云服务器的版本 2017-03-12。
Authorization String HTTP 标准身份认证头部字段,例如: TC3-HMAC-SHA256 Credential=AKIDEXAMPLE/Date/service/tc3_request, SignedHeaders=content-type;host, Signature=72e494ea8**a96525168
其中:
  • TC3-HMAC-SHA256:签名方法,目前固定取该值。
  • Credential:签名凭证,AKIDEXAMPLE 是 SecretId。
  • Date 是 UTC 标准时间的日期,取值需要和公共参数 X-TC-Timestamp 换算的 UTC 标准时间日期一致。
  • service 为产品名,通常为域名前缀,例如域名 cvm.tencentcloudapi.com 意味着产品名是 cvm。本产品取值为 cvm。
  • SignedHeaders:参与签名计算的头部信息,content-type 和 host 为必选头部。
  • Signature:签名摘要,计算过程详见下文。
  • X-TC-Token String 临时证书所用的 Token ,需要结合临时密钥一起使用。临时密钥和 Token 需要到访问管理服务调用接口获取。长期密钥不需要 Token。

    签名方法 V1 公共参数

    使用签名方法 v1(有时会称作 HmacSHA256 和 HmacSHA1),公共参数需要统一放到请求串中。

    参数名称 类型 必选 描述
    Action String 操作的接口名称。取值参考接口文档中输入参数公共参数 Action 的说明。例如云服务器的查询实例列表接口,取值为 DescribeInstances 。
    Region String - 地域参数,用来标识希望操作哪个地域的数据。接口接受的地域取值参考接口文档中输入参数公共参数 Region 的说明。注意:某些接口不需要传递该参数,接口文档中会对此特别说明,此时即使传递该参数也不会生效。
    Timestamp Integer 当前 UNIX 时间戳,可记录发起 API 请求的时间。例如1529223702,如果与当前时间相差过大,会引起签名过期错误。
    Nonce Integer 随机正整数,与 Timestamp 联合起来,用于防止重放攻击。
    SecretId String 云API密钥 上申请的标识身份的 SecretId,一个 SecretId 对应唯一的 SecretKey,而 SecretKey 会用来生成请求签名 Signature。
    Signature String 请求签名,用来验证此次请求的合法性,需要用户根据实际的输入参数计算得出。具体计算方法参见下文“签名方法介绍” 。
    Version String 操作的 API 的版本。取值参考接口文档中入参公共参数 Version 的说明。例如云服务器的版本 2017-03-12。
    SignatureMethod String 签名方式,目前支持 HmacSHA256 和 HmacSHA1。只有指定此参数为 HmacSHA256 时,才使用 HmacSHA256 算法验证签名,其他情况均使用 HmacSHA1 验证签名。
    Token String 临时证书所用的 Token ,需要结合临时密钥一起使用。临时密钥和 Token 需要到访问管理服务调用接口获取。长期密钥不需要 Token 。

    地域列表

    由于各个产品支持地域不同,具体详情请参考各产品文档中的地域列表。
    例如,您可以参考云服务器的 地域列表

    GO API 调用方式

    腾讯云 API 会对每个请求进行身份验证,用户需要使用安全凭证,经过特定的步骤对请求进行签名(Signature),每个请求都需要在公共请求参数中指定该签名结果并以指定的方式和格式发送请求。

    假设用户的 SecretId 和 SecretKey 分别是:AKIDz8krbsJ5**********mLPx3EXAMPLEGu5t9xGAR***********EXAMPLE。用户想查看广州区云服务器名为“未命名”的主机状态,只返回一条数据。则请求可能为:

    curl -X POST https://cvm.tencentcloudapi.com \
    -H "Authorization: TC3-HMAC-SHA256 Credential=AKIDz8krbsJ5**********mLPx3EXAMPLE/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host, Signature=72e494ea8******************************************a96525168" \
    -H "Content-Type: application/json; charset=utf-8" \
    -H "Host: cvm.tencentcloudapi.com" \
    -H "X-TC-Action: DescribeInstances" \
    -H "X-TC-Timestamp: 1551113065" \
    -H "X-TC-Version: 2017-03-12" \
    -H "X-TC-Region: ap-guangzhou" \
    -d '{"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}'

    步骤1:申请安全凭证

    本文使用的安全凭证为密钥,密钥包括 SecretId 和 SecretKey。每个用户最多可以拥有两对密钥。

    • SecretId:用于标识 API 调用者身份,可以简单类比为用户名。
    • SecretKey:用于验证 API 调用者的身份,可以简单类比为密码。
    注意:

    用户必须严格保管安全凭证,避免泄露,否则将危及财产安全。如已泄漏,请立刻禁用该安全凭证。

    前往 API密钥管理 页面,即可进行获取。如下图所示:

    步骤2:

    1. 获取 API 3.0 V3 版本签名

    签名方法 v3 (TC3-HMAC-SHA256)功能上覆盖了以前的签名方法 v1,而且更安全,支持更大的请求,支持 json 格式,性能有一定提升,推荐使用该签名方法计算签名。

    注意:

    首次接触,建议使用 API Explorer 中的“签名串生成”功能,选择签名版本为“ API 3.0 签名 v3 ”,可以生成签名过程进行验证,也可直接生成 SDK 代码。推荐使用腾讯云 API 配套的7种常见的编程语言 SDK,已经封装了签名和请求过程,均已开源,支持 PythonJavaPHPGoNodeJS.NETC++

    云 API 支持 GET 和 POST 请求。对于 GET 方法,只支持 Content-Type: application/x-www-form-urlencoded 协议格式。对于POST方法,目前支持 Content-Type: application/json 以及 Content-Type: multipart/form-data 两种协议格式,json 格式绝大多数接口均支持,multipart 格式只有特定接口支持,此时该接口不能使用 json 格式调用,参考具体业务接口文档说明。推荐使用 POST 请求,因为两者的结果并无差异,但 GET 请求只支持 32 KB 以内的请求包。

    下面以 查看实例列表 接口为例,分步骤介绍签名的计算过程。我们选择该接口是因为:

    1. 云服务器默认已开通,该接口很常用;
    2. 该接口是只读的,不会改变现有资源的状态;
    3. 接口覆盖的参数种类较全,可以演示包含数据结构的数组如何使用。

    1. 拼接规范请求串

    CanonicalRequest =
        HTTPRequestMethod + '\n' +
        CanonicalURI + '\n' +
        CanonicalQueryString + '\n' +
        CanonicalHeaders + '\n' +
        SignedHeaders + '\n' +
        HashedRequestPayload
    字段名称 解释
    HTTPRequestMethod HTTP 请求方法(GET、POST )。此示例取值为 POST
    CanonicalURI URI 参数,API 3.0 固定为正斜杠(/)。
    CanonicalQueryString 发起 HTTP 请求 URL 中的查询字符串,对于 POST 请求,固定为空字符串"",对于 GET 请求,则为 URL 中问号(?)后面的字符串内容,例如:Limit=10&Offset=0。 注意:CanonicalQueryString 需要参考 RFC3986 进行 URLEncode,字符集 UTF8,推荐使用编程语言标准库,所有特殊字符均需编码,大写形式。
    CanonicalHeaders 参与签名的头部信息,至少包含 host 和 content-type 两个头部,也可加入自定义的头部参与签名以提高自身请求的唯一性和安全性。 拼接规则:头部 key 和 value 统一转成小写,并去掉首尾空格,按照 key:value\n 格式拼接;多个头部,按照头部 key(小写)的 ASCII 升序进行拼接。此示例计算结果是 content-type:application/json; charset=utf-8\nhost:cvm.tencentcloudapi.com\n。 注意:content-type 必须和实际发送的相符合,有些编程语言网络库即使未指定也会自动添加 charset 值,如果签名时和发送时不一致,服务器会返回签名校验失败。
    SignedHeaders 参与签名的头部信息,说明此次请求有哪些头部参与了签名,和 CanonicalHeaders 包含的头部内容是一一对应的。content-type 和 host 为必选头部。 拼接规则:头部 key 统一转成小写;多个头部 key(小写)按照 ASCII 升序进行拼接,并且以分号(;)分隔。此示例为 content-type;host
    HashedRequestPayload 请求正文(Requestpayload,即 body,此示例为 {"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]})的哈希值,计算伪代码为 Lowercase(HexEncode(Hash.SHA256(RequestPayload))),即对 HTTP 请求正文做 SHA256 哈希,然后十六进制编码,最后编码串转换成小写字母。对于 GET 请求,RequestPayload 固定为空字符串。此示例计算结果是 35e9c5b0e3ae67532d3c9f17ead6c90222632e5b1ff7f6e89887f1398934f064

    根据以上规则,示例中得到的规范请求串如下:

    POST
    /
    
    content-type:application/json; charset=utf-8
    host:cvm.tencentcloudapi.com
    
    content-type;host
    35e9c5b0e3ae67532d3c9f17ead6c90222632e5b1ff7f6e89887f1398934f064

    2. 拼接待签名字符串

    按如下格式拼接待签名字符串:

    StringToSign =
        Algorithm + \n +
        RequestTimestamp + \n +
        CredentialScope + \n +
        HashedCanonicalRequest
    字段名称 解释
    Algorithm 签名算法,目前固定为 TC3-HMAC-SHA256
    RequestTimestamp 请求时间戳,即请求头部的公共参数 X-TC-Timestamp 取值,取当前时间 UNIX 时间戳,精确到秒。此示例取值为 1551113065
    CredentialScope 凭证范围,格式为 Date/service/tc3_request,包含日期、所请求的服务和终止字符串(tc3_request)。Date 为 UTC 标准时间的日期,取值需要和公共参数 X-TC-Timestamp 换算的 UTC 标准时间日期一致;service 为产品名,必须与调用的产品域名一致。此示例计算结果是 2019-02-25/cvm/tc3_request。
    HashedCanonicalRequest 前述步骤拼接所得规范请求串的哈希值,计算伪代码为 Lowercase(HexEncode(Hash.SHA256(CanonicalRequest)))。此示例计算结果是 5ffe6a04c0664d6b969fab9a13bdab201d63ee709638e2749d62a09ca18d7031
    注意:

    1. Date 必须从时间戳 X-TC-Timestamp 计算得到,且时区为 UTC+0。如果加入系统本地时区信息,例如东八区,将导致白天和晚上调用成功,但是凌晨时调用必定失败。假设时间戳为 1551113065,在东八区的时间是 2019-02-26 00:44:25,但是计算得到的 Date 取 UTC+0 的日期应为 2019-02-25,而不是 2019-02-26。
    2. Timestamp 必须是当前系统时间,且需确保系统时间和标准时间是同步的,如果相差超过五分钟则必定失败。如果长时间不和标准时间同步,可能导致运行一段时间后,请求必定失败,返回签名过期错误。

    根据以上规则,示例中得到的待签名字符串如下:

    TC3-HMAC-SHA256
    1551113065
    2019-02-25/cvm/tc3_request
    5ffe6a04c0664d6b969fab9a13bdab201d63ee709638e2749d62a09ca18d7031

    3.计算签名(伪代码)

    secretDate := hmacsha256(date, "TC3"+secretKey)
    secretService := hmacsha256(service, secretDate)
    secretSigning := hmacsha256("tc3_request", secretService)
    signature := hex.EncodeToString([]byte(hmacsha256(string2sign, secretSigning)))
    fmt.Println(signature)

    派生出的密钥 SecretDateSecretServiceSecretSigning 是二进制的数据,可能包含不可打印字符,此处不展示中间结果。

    字段名称 解释
    secretKey 原始的 secretKey,即 Gu5t9xGAR***********EXAMPLE
    date 即 Credential 中的 Date 字段信息(标准时间)。此示例取值为 2019-02-25
    service 即 Credential 中的 Service 字段信息。此示例取值为 cvm

    此示例计算结果是 72e494ea8******************************************a96525168

    4. 拼接 Authorization

    按如下格式拼接 Authorization:

        authorization := fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s",
            algorithm,
            secretId,
            credentialScope,
            signedHeaders,
            signature)
        fmt.Println(authorization)
    字段名称 解释
    algorithm 签名方法,固定为 TC3-HMAC-SHA256
    secretId 密钥对中的 SecretId,即 AKIDz8krbsJ5**********mLPx3EXAMPLE
    credentialScope 见上文,凭证范围。此示例计算结果是 2019-02-25/cvm/tc3_request
    signedHeaders 见上文,参与签名的头部信息。此示例取值为 content-type;host
    signature 签名值。此示例计算结果是 72e494ea8******************************************a96525168

    根据以上规则,示例中得到的值为:

    TC3-HMAC-SHA256 Credential=AKIDz8krbsJ5**********mLPx3EXAMPLE/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host, Signature=72e494ea8******************************************a96525168

    最终完整的调用信息如下:

    POST https://cvm.tencentcloudapi.com/
    Authorization: TC3-HMAC-SHA256 Credential=AKIDz8krbsJ5**********mLPx3EXAMPLE/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host, Signature=72e494ea8******************************************a96525168
    Content-Type: application/json; charset=utf-8
    Host: cvm.tencentcloudapi.com
    X-TC-Action: DescribeInstances
    X-TC-Version: 2017-03-12
    X-TC-Timestamp: 1551113065
    X-TC-Region: ap-guangzhou
    
    {"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}

    5. API 3.0 签名 V3示例

    package main
    
    import (
        "crypto/hmac"
        "crypto/sha256"
        "encoding/hex"
        "fmt"
        "time"
    )
    
    func sha256hex(s string) string {
        b := sha256.Sum256([]byte(s))
        return hex.EncodeToString(b[:])
    }
    
    func hmacsha256(s, key string) string {
        hashed := hmac.New(sha256.New, []byte(key))
        hashed.Write([]byte(s))
        return string(hashed.Sum(nil))
    }
    
    func main() {
        secretId := "AKIDz8krbsJ5**********mLPx3EXAMPLE"
        secretKey := "Gu5t9xGAR***********EXAMPLE"
        host := "cvm.tencentcloudapi.com"
        algorithm := "TC3-HMAC-SHA256"
        service := "cvm"
        version := "2017-03-12"
        action := "DescribeInstances"
        region := "ap-guangzhou"
        //var timestamp int64 = time.Now().Unix()
        var timestamp int64 = 1551113065
    
        // step 1: build canonical request string
        httpRequestMethod := "POST"
        canonicalURI := "/"
        canonicalQueryString := ""
        canonicalHeaders := "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n"
        signedHeaders := "content-type;host"
        payload := `{"Limit": 1, "Filters": [{"Values": ["\u672a\u547d\u540d"], "Name": "instance-name"}]}`
        hashedRequestPayload := sha256hex(payload)
        canonicalRequest := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s",
            httpRequestMethod,
            canonicalURI,
            canonicalQueryString,
            canonicalHeaders,
            signedHeaders,
            hashedRequestPayload)
        fmt.Println(canonicalRequest)
    
        // step 2: build string to sign
        date := time.Unix(timestamp, 0).UTC().Format("2006-01-02")
        credentialScope := fmt.Sprintf("%s/%s/tc3_request", date, service)
        hashedCanonicalRequest := sha256hex(canonicalRequest)
        string2sign := fmt.Sprintf("%s\n%d\n%s\n%s",
            algorithm,
            timestamp,
            credentialScope,
            hashedCanonicalRequest)
        fmt.Println(string2sign)
    
        // step 3: sign string
        secretDate := hmacsha256(date, "TC3"+secretKey)
        secretService := hmacsha256(service, secretDate)
        secretSigning := hmacsha256("tc3_request", secretService)
        signature := hex.EncodeToString([]byte(hmacsha256(string2sign, secretSigning)))
        fmt.Println(signature)
    
        // step 4: build authorization
        authorization := fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s",
            algorithm,
            secretId,
            credentialScope,
            signedHeaders,
            signature)
        fmt.Println(authorization)
    
        curl := fmt.Sprintf(`curl -X POST https://%s\
     -H "Authorization: %s"\
     -H "Content-Type: application/json; charset=utf-8"\
     -H "Host: %s" -H "X-TC-Action: %s"\
     -H "X-TC-Timestamp: %d"\
     -H "X-TC-Version: %s"\
     -H "X-TC-Region: %s"\
     -d '%s'`, host, authorization, host, action, timestamp, version, region, payload)
        fmt.Println(curl)
    }

    2. 获取 API 3.0 V1 版本签名

    签名方法 v1 简单易用,但是功能和安全性都不如签名方法 v3,推荐使用签名方法 v3。

    注意:

    首次接触,建议使用 API Explorer 中的“签名串生成”功能,选择签名版本为“ API 3.0 签名 v1 ”,可以生成签名过程进行验证,并提供了部分编程语言的签名示例,也可直接生成 SDK 代码。推荐使用腾讯云 API 配套的 7 种常见的编程语言 SDK,已经封装了签名和请求过程,均已开源,支持 PythonJavaPHPGoNodeJS.NETC++

    以云服务器查看可用区列表(DescribeInstances)请求为例,当用户调用这一接口时,其请求参数可能如下:

    参数名称 中文 参数值
    Action 方法名 DescribeInstances
    SecretId 密钥 ID AKIDz8krbsJ5**********mLPx3EXAMPLE
    Timestamp 当前时间戳 1465185768
    Nonce 随机正整数 11886
    Region 实例所在区域 ap-guangzhou
    InstanceIds.0 待查询的实例 ID ins-09dx96dg
    Offset 偏移量 0
    Limit 最大允许输出 20
    Version 接口版本号 2017-03-12

    1. 对参数排序

    首先对所有请求参数按参数名的字典序( ASCII 码)升序排序。

    注意:

    1. 只按参数名进行排序,参数值保持对应即可,不参与比大小。
    2. 按 ASCII 码比大小,如 InstanceIds.2 要排在 InstanceIds.12 后面,不是按字母表,也不是按数值。用户可以借助编程语言中的相关排序函数来实现这一功能,如 PHP 中的 ksort 函数。

    上述示例参数的排序结果如下:

    {
        'Action' : 'DescribeInstances',
        'InstanceIds.0' : 'ins-09dx96dg',
        'Limit' : 20,
        'Nonce' : 11886,  
        'Offset' : 0,
        'Region' : 'ap-guangzhou',
        'SecretId' : 'AKIDz8krbsJ5**********mLPx3EXAMPLE',
        'Timestamp' : 1465185768,
        'Version': '2017-03-12',
    }

    使用程序设计语言开发时,可对上面示例中的参数进行排序,得到的结果一致即可。

    2. 拼接规范请求串

    此步骤生成请求字符串。将把上一步排序好的请求参数格式化成“参数名称=参数值”的形式,如对 Action 参数,其参数名称为 "Action" ,参数值为 "DescribeInstances" ,因此格式化后就为 Action=DescribeInstances 。

    注意:

    “参数值”为原始值而非 url 编码后的值。

    然后将格式化后的各个参数用"&"拼接在一起,最终生成的请求字符串为:

    Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5**********mLPx3EXAMPLE&Timestamp=1465185768&Version=2017-03-12

    3. 拼接待签名字符串

    此步骤生成签名原文字符串。 签名原文字符串由以下几个参数构成:

    1. 请求方法: 支持 POST 和 GET 方式,这里使用 GET 请求,注意方法为全大写。
    2. 请求主机:查看实例列表(DescribeInstances)的请求域名为:cvm.tencentcloudapi.com。实际的请求域名根据接口所属模块的不同而不同,详见各接口说明。
    3. 请求路径: 当前版本云API的请求路径固定为 / 。
    4. 请求字符串: 即上一步生成的请求字符串。

    签名原文串的拼接规则为:请求方法 + 请求主机 +请求路径 + ? + 请求字符串

    示例的拼接结果为:

    GETcvm.tencentcloudapi.com/?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5**********mLPx3EXAMPLE&Timestamp=1465185768&Version=2017-03-12

    4. 计算签名(伪代码)

    此步骤生成签名串。 首先使用 HMAC-SHA1 算法对上一步中获得的签名原文字符串进行签名,然后将生成的签名串使用 Base64 进行编码,即可获得签名串。

    hashed := hmac.New(sha1.New, []byte(secretKey))
    hashed.Write(buf.Bytes())
    
    fmt.Println(base64.StdEncoding.EncodeToString(hashed.Sum(nil)))

    5. 获取调用信息并发送请求

    # 实际调用,成功后如果是消费接口会产生计费(此处以Python语言为例发送get请求)
    resp = requests.get("https://" + endpoint, params=data)
    print(resp.url)
    最终得到的请求串为:
    https://cvm.tencentcloudapi.com/?Nonce=11886&SecretId=AKIDz8krbsJ5**********mLPx3EXAMPLE&Limit=20&Version=2017-03-12&Offset=0&Action=DescribeInstances&Timestamp=1465185768&Region=ap-guangzhou&Signature=EliP9YW3pW28FpsEdkXt%2F%2BWcGeI%3D&InstanceIds.0=ins-09dx96dg
    字段名称 解释
    endpoint 服务地址, 例如:cvm.tencentcloudapi.com
    data API 3.0 签名 V1 所举示例接口参数,注意 这里需要将计算的签名已键值对的形式加入data中
    注意:

    由于示例中的密钥是虚构的,时间戳也不是系统当前时间,因此如果将此 url 在浏览器中打开或者用 curl 等命令调用时会返回鉴权错误:签名过期。为了得到一个可以正常返回的 url ,需要修改示例中的 SecretId 和 SecretKey 为真实的密钥,并使用系统当前时间戳作为 Timestamp 。

    为了更清楚的解释签名过程,下面以 Python 语言为例,将上述的签名过程具体实现。请求的域名、调用的接口和参数的取值都以上述签名过程为准,代码只为解释签名过程,并不具备通用性,实际开发请尽量使用 SDK 。

    6. 签名串编码

    生成的签名串并不能直接作为请求参数,需要对其进行 URL 编码。

    如上一步生成的签名串为 Eli*****************cGeI= ,最终得到的签名串请求参数(Signature)为:EliP***********************eI%3D,它将用于生成最终的请求 URL。

    注意:

    • 如果用户的请求方法是 GET,或者请求方法为 POST 同时 Content-Type 为 application/x-www-form-urlencoded,则发送请求时所有请求参数的值均需要做 URL 编码,参数键和=符号不需要编码。非 ASCII 字符在 URL 编码前需要先以 UTF-8 进行编码。
    • 有些编程语言的网络库会自动为所有参数进行 urlencode,在这种情况下,就不需要对签名串进行 URL 编码了,否则两次 URL 编码会导致签名失败。
    • 其他参数值也需要进行编码,编码采用 RFC 3986。使用 %XY 对特殊字符例如汉字进行百分比编码,其中 XY 为十六进制字符(0-9 和大写字母 A-F),使用小写将引发错误。

    7. API 3.0 签名 V1示例

    注意:

    此处只到计算签名部分,如需获得最终请求串,需要在参数 params 里加上下面所得到的签名键值。

    package main
    
    import (
        "bytes"
        "crypto/hmac"
        "crypto/sha1"
        "encoding/base64"
        "net/url"
        "fmt"
        "sort"
    )
    
    func main() {
        secretId := "AKIDz8krbsJ5**********mLPx3EXAMPLE"
        secretKey := "Gu5t9xGAR***********EXAMPLE"
        endpoint := "cvm.tencentcloudapi.com"
        params := map[string]string{
            "Nonce":         "11886",
            "Timestamp":     "1465185768",
            "Region":        "ap-guangzhou",
            "SecretId":      secretId,
            "Version":       "2017-03-12",
            "Action":        "DescribeInstances",
            "InstanceIds.0": "ins-09dx96dg",
            "Limit":         "20",
            "Offset":        "0",
        }
    
        var buf bytes.Buffer
        buf.WriteString("GET")
        buf.WriteString(endpoint)
        buf.WriteString("/")
        buf.WriteString("?")
    
        // sort keys by ascii asc order
        keys := make([]string, 0, len(params))
        for k, _ := range params {
            keys = append(keys, k)
        }
        sort.Strings(keys)
    
        for i := range keys {
            k := keys[i]
            buf.WriteString(k)
            buf.WriteString("=")
            buf.WriteString(params[k])
            buf.WriteString("&")
        }
        buf.Truncate(buf.Len() - 1)
    
        hashed := hmac.New(sha1.New, []byte(secretKey))
        hashed.Write(buf.Bytes())
    
        signature := base64.StdEncoding.EncodeToString(hashed.Sum(nil))
        fmt.Println(base64.StdEncoding.EncodeToString(hashed.Sum(nil)))
        final_signature := url.QueryEscape(signature)
        fmt.Println(final_signature)
    }

    签名失败

    存在以下签名失败的错误码,请根据实际情况处理。

    错误码 错误描述
    AuthFailure.SignatureExpire 签名过期。Timestamp 与服务器接收到请求的时间相差不得超过五分钟。
    AuthFailure.SecretIdNotFound 密钥不存在。请到控制台查看密钥是否被禁用,是否少复制了字符或者多了字符。
    AuthFailure.SignatureFailure 签名错误。可能是签名计算错误,或者签名与实际发送的内容不相符合,也有可能是密钥 SecretKey 错误导致的。
    AuthFailure.TokenFailure 临时证书 Token 错误。
    AuthFailure.InvalidSecretId 密钥非法(不是云 API 密钥类型)。

    返回结果

    正确返回结果

    以云服务器的接口查看实例状态列表(DescribeInstancesStatus)2017-03-12 版本为例,若调用成功,其可能的返回如下为:

    {
        "Response": {
            "TotalCount": 0,
            "InstanceStatusSet": [],
            "RequestId": "b5b41468-520d-4192-b42f-595cc34b6c1c"
        }
    }
    • Response 及其内部的 RequestId 是固定的字段,无论请求成功与否,只要 API 处理了,则必定会返回。
    • RequestId 用于一个 API 请求的唯一标识,如果 API 出现异常,可以联系我们,并提供该 ID 来解决问题。
    • 除了固定的字段外,其余均为具体接口定义的字段,不同的接口所返回的字段参见接口文档中的定义。此例中的 TotalCountInstanceStatusSet 均为 DescribeInstancesStatus 接口定义的字段,由于调用请求的用户暂时还没有云服务器实例,因此 TotalCount 在此情况下的返回值为 0, InstanceStatusSet 列表为空。

    错误返回结果

    若调用失败,其返回值示例如下为:

    {
        "Response": {
            "Error": {
                "Code": "AuthFailure.SignatureFailure",
                "Message": "The provided credentials could not be validated. Please check your signature is correct."
            },
            "RequestId": "ed93f3cb-f35e-473f-b9f3-0d451b8b79c6"
        }
    }
    • Error 的出现代表着该请求调用失败。Error 字段连同其内部的 CodeMessage 字段在调用失败时是必定返回的。
    • Code 表示具体出错的错误码,当请求出错时可以先根据该错误码在公共错误码和当前接口对应的错误码列表里面查找对应原因和解决方案。
    • Message 显示出了这个错误发生的具体原因,随着业务发展或体验优化,此文本可能会经常保持变更或更新,用户不应依赖这个返回值。
    • RequestId 用于一个 API 请求的唯一标识,如果 API 出现异常,可以联系我们,并提供该 ID 来解决问题。

    公共错误码

    返回结果中如果存在 Error 字段,则表示调用 API 接口失败。 Error 中的 Code 字段表示错误码,所有业务都可能出现的错误码为公共错误码,下表列出了公共错误码。

    错误码 错误描述
    AuthFailure.InvalidSecretId 密钥非法(不是云 API 密钥类型)。
    AuthFailure.MFAFailure MFA 错误。
    AuthFailure.SecretIdNotFound 密钥不存在。
    AuthFailure.SignatureExpire 签名过期。
    AuthFailure.SignatureFailure 签名错误。
    AuthFailure.TokenFailure token 错误。
    AuthFailure.UnauthorizedOperation 请求未 CAM 授权。
    DryRunOperation DryRun 操作,代表请求将会是成功的,只是多传了 DryRun 参数。
    FailedOperation 操作失败。
    InternalError 内部错误。
    InvalidAction 接口不存在。
    InvalidParameter 参数错误。
    InvalidParameterValue 参数取值错误。
    LimitExceeded 超过配额限制。
    MissingParameter 缺少参数错误。
    NoSuchVersion 接口版本不存在。
    RequestLimitExceeded 请求的次数超过了频率限制。
    ResourceInUse 资源被占用。
    ResourceInsufficient 资源不足。
    ResourceNotFound 资源不存在。
    ResourceUnavailable 资源不可用。
    UnauthorizedOperation 未授权操作。
    UnknownParameter 未知参数错误。
    UnsupportedOperation 操作不支持。
    UnsupportedProtocol HTTPS 请求方法错误,只支持 GET 和 POST 请求。
    UnsupportedRegion 接口不支持所传地域。
    目录