You need to enable JavaScript to run this app.
导航
回调服务接入指南
最近更新时间:2024.11.21 19:55:44首次发布时间:2022.09.09 09:13:30
复制全文
我的收藏
有用
有用
无用
无用
开通服务
  1. 登录云手机控制台。
  2. 选择目标业务卡片,点击进入业务
  3. 在左侧导航栏选择功能配置,进入回调配置页面。
  4. 点击添加配置填写回调相关信息:
    • 回调事件:你希望接收的回调事件。当前支持回调的事件详情请参考回调事件参考
    • 回调 URL:接收回调请求的 URL 地址。
    • 回调鉴权密钥:用于鉴权的 AccessKey(AK)和 SecretKey(SK),请求时会通过鉴权密钥计算出签名,接入方可以自行验证。

      请注意区分回调鉴权密钥(AccessKey/SecretKey)和火山引擎API访问密钥(Access Key ID/Secret Access Key)。此处的回调鉴权密钥可点击“自动生成密钥”由系统自动生成。

回调请求格式

服务端回调机制基于 HTTP 协议,通过 POST 请求将数据发送至预设的回调地址。

  • 接口协议:使用标准的 HTTP 协议进行数据传输。
  • 请求方式:采用 POST 方法发起请求。
  • 字符编码格式:统一使用 UTF-8 编码。
  • 传值方式:通过请求的 Body 部分传递数据,支持灵活的数据格式

Header 参数

/ {version}/{access_key}/{timestamp}/{expire_time}
SignKeyInfo: v1/ak_example/1648211879/180
// Signature
Signature: ea4349f93a9f37a960f562ef55bf180419cac83ff302479d416503082dxxxxxx
text
字段
类型
示例
说明
SignKeyInfoString请求方的身份信息
{version}/{access_key}/{timestamp}/{expire_time}
  • version: 版本信息
  • access_key: 请求方身份密钥
  • timestamp: 请求时的时间戳,unix 时间戳,秒级
  • expiration:过期时间,秒级
  • v1/ak_example/1648211879/180
    回调接收方应利用提供的 access_key(示例中的 ak_example),在本地数据库中检索与之关联的 secret_key。
    SignatureString根据 SignKeyInfo 和储存在用户的 SecretKey 计算出的签名ea4349f93a9f37a960f562ef55bf180419cac83ff302479d416503082dxxxxxx

    说明

    从 Header 的 SignKeyInfo 中:

    • 解析出 {timestamp} 和 {expire_time},通过当前时间是否处于 {timestamp}+{expire_time} 内来校验该请求的时效性,过期可直接忽略,以防重放攻击。
    • 解析出 {access_key},查找对应的 secret_key,通过签名计算方法中的 sha256HMAC 算法计算出签名,和请求的 Signature 比较是否一致,如果不一致说明请求被篡改,应当拒绝。

    Body 参数

    字段类型说明
    product_idString业务 ID
    event_typeString事件类型,参考回调事件参考
    event_idString事件 ID,具有唯一性,可用于去重
    event_timeInt64事件产生时间,UTC 时间,单位:秒
    event_dataObject事件具体内容,JSON 格式,参考回调事件参考
    签名计算方法

    云手机提供 Golang、Java、PHP 三种语言的算法示例,你可以参考以下示例,对回调进行验证。

    注意

    以下各语言示例中的 ak、sk 需传入控制台开通回调服务时填写的回调鉴权密钥(AccessKey/SecretKey),而非账号下火山引擎API访问密钥(Access Key ID/Secret Access Key)。
    alt

    package main
    
    import (
        "crypto/hmac"
        "crypto/sha256"
        "fmt"
        "strconv"
        "strings"
        "time"
    )
    
    func sha256HMAC(key []byte, data []byte) []byte {
        mac := hmac.New(sha256.New, key)
        mac.Write(data)
        return []byte(fmt.Sprintf("%x", mac.Sum(nil)))
    }
    
    func Sign(signKeyInfo string, sk string, body []byte) string {
        // expiration := 1800
        // signKeyInfo := fmt.Sprintf("%s/%s/%d/%d", ver, ak, time.Now().Unix(), expiration)
        signKey := sha256HMAC([]byte(sk), []byte(signKeyInfo))
        signResult := sha256HMAC(signKey, body)
        return string(signResult)
    }
    
    func main() {
    
        //控制台回调配置的ak、sk
        var ak = "ak"
        var sk = "sk"
        //从header参数中获取
        var signKeyInfo string
        var signature string
    
        //获取接受到http请求的body
        var bodyPayload []byte
    
        signInfos := strings.Split(signKeyInfo, "/")
        if len(signInfos) != 4 {
            panic("signKeyInfo error")
        }
    
        //请求过期
        timestamp, _ := strconv.ParseInt(signInfos[2], 10, 64)
        expiration, _ := strconv.ParseInt(signInfos[3], 10, 64)
        
        if time.Now().Unix() > timestamp+expiration {
            panic("timestamp or expiration error")
        }
    
        signatureCal := Sign(signKeyInfo, sk, bodyPayload)
    
        //签名不通过
        if signature != signatureCal {
            panic("signature error")
        }
        fmt.Printf("ak: %s SignKeyInfo:%s\n", ak, signKeyInfo)
        fmt.Printf("Signature:%s\n", signature)
    }
    返回格式
    字段类型说明

    code

    Int32

    返回码:

    • 0(成功)

    • 其它(失败,错误码待约定)

    messageString错误信息
    错误码
    Code说明
    1000请求参数错误
    2000鉴权失败