最近更新时间:2023.09.14 18:17:03
首次发布时间:2023.03.10 15:26:17
火山引擎云手机-iPaaS支持通过 HTTP 或 HTTPS 协议将账号业务下云手机实例资源的状态变动等事件消息推送到接入方提供的 URL 回调地址。接入方在接收到消息后,可按照下述消息内容格式做进一步处理或消费。
接入云手机-iPaaS回调服务需要完成以下配置:
配置业务维度的回调消息接收地址:接入方需提供公网可访问的 URl 回调地址,并在云手机业务维度配置并订阅了相关事件的回调消息(可通过火山引擎 云手机控制台 > 业务管理 > 功能配置 页面进行配置;详细信息,参考 控制台指南)。
配置用于鉴权的 AccessKey 和 SecretKey(AK、SK),请求时会通过 AK、SK 计算出签名,接入方可以自行验证(可通过火山引擎 云手机控制台 > 业务管理 > 功能配置 页面进行配置;详细信息,参考 控制台指南)。
首次推送失败后(非成功响应),回调服务将每隔1秒重推消息。若重试3次仍未成功,将停止推送,超时时长为5秒。
字段 | 类型 | 说明 | 示例 |
---|---|---|---|
iPaaS-Auth | String | 请求的签名,格式为:
对于签名方法的详细说明,参考 附件 中的说明 | auth-v1/ak_example/1648211879/1800/ea4349f93a9f37a960f562ef55bf180419cac83ff302479d416503082d4f0dac |
application/json | String | application/json |
格式:json
字段 | 类型 | 说明 |
---|---|---|
id | String | 回调消息标识 ID(msgid) |
event_type | String | 回调事件类型,枚举值说明:
|
event_async_task | []String | 当 event_type 为 AsyncTask 时,则为必填,参考以下 AsyncTaskEvent 结构说明 |
event_instance_status | []String | 当 event_type 为 InstanceStatus 时,则为必填,参考以下 InstanceStatusEvent 结构说明 |
AsyncTaskEvent 结构说明
字段 | 类型 | 说明 |
---|---|---|
instance_id | String | 实例 ID |
host_id | String | 云机 ID |
global_task_id | String | 全局任务 ID,由平台生成 |
task_status | Int | 任务状态:
|
task_type | String | 任务类型,枚举值说明,参考以下 任务类型说明 |
content | String | 任务或事件内容描述 |
start_time | String | 开始时间戳(任务创建时间) |
end_time | String | 结束时间戳 |
任务类型说明
枚举值 | 含义 |
---|---|
ApkInstall | 安装应用 |
ApkControl | 管理应用 |
SecurityGroupBind | 安全组绑定 |
SecurityGroupUnbind | 安全组解绑 |
AdbKeyBind | 密钥对绑定 |
AdbKeyUnbind | 密钥对解绑 |
PushFile | 推送文件到实例 |
PullFile | 从实例拉取文件 |
ExecCmd | 执行命令 |
PowerUp | 实例开机 |
PowerDown | 实例关机 |
WarmReboot | 实例重启(热重启) |
ColdReboot | 强制重启(冷重启) |
Update | 升级实例 |
ResetFactory | 实例恢复出厂设置 |
ResetInstance | 实例重置 |
参考示例:
{ "id": "13579xyz24680", "event_type": "AsyncTask", "event_async_task": { "instance_id":"i-1748455288xxxxxx", "host_id":"h-1248455288xxxxxx", "global_task_id":"t-7187279730302xxxxxx", "task_type":"ResetFactory", "task_status":200, "content": "instance reset factory success", "start_time":1672143930, "end_time":1672143938 } }
InstanceStatusEvent 结构说明
字段 | 类型 | 说明 |
---|---|---|
instance_id | String | 实例 ID |
from_status | Integer | 变化前的实例状态码;状态码说明,参考以下 Status 具体定义 |
from_status_str | String | 变化前的实例状态说明 |
to_status | Integer | 变化后的实例状态码,状态码说明,参考以下 Status 具体定义 |
to_status_str | String | 变化后的实例状态码说明 |
Status 具体定义
状态码(status) | 状态说明(status_str) | 含义 |
---|---|---|
256 | Running | 运行中 |
259 | Shutdown | 已关机 |
261 | Initializing | 初始化中 |
513 | ShuttingDown | 关机中 |
515 | Booting | 开机中 |
514 | Rebooting | 重启中 |
519 | ColdRebooting | 强制重启中 |
516 | Upgrading | 升级中 |
517 | Resetting | 重置中 |
518 | ResetToFactoryHandling | 恢复出厂设置中 |
528 | ModifyCritConfigRebootHandling | 配置变更,设备重启中 |
1024 | Fault | 异常状态 |
1025 | InitFailed | 初始化失败 |
参考示例:
{ "id": "13579xyz24680", "event_type": "InstanceStatus", "event_instance_status": { "instance_id": "i-1776357725xxxxxx", "from_status": 519, "from_status_str": "ColdRebooting", "to_status": 256, "to_status_str": "Running" } }
字段 | 类型 | 说明 |
---|---|---|
code | Int32 | 业务返回码:
|
msg | String | 错误信息 |
接收到请求后,执行以下验证过程:
可选项,建议按照如下方式进行检查操作: 检查时间戳,如果不符合以下条件直接返回403(防重放攻击):timestamp - 5分钟 < 服务器接收到请求时间 < timestamp + expiretime + 5分钟
。
必选项: 通过 AK 找到对应的 SK,使用相同的摘要算法生成认证字符串,并与用户请求中包含的认证字符串进行比对。
如果认证字符串相同,系统认为用户合法,并执行后续的用户权限验证的相关操作。
如果认证字符串不同,系统将忽略该操作并返回 HTTP code 403。
字段 | 含义 |
---|---|
auth_ver | 鉴权版本,目前支持 auth-v1 |
access_key | AK,用于标示用户,在配置回调服务时,通过平台工具生成,或者由用户自行提供 |
secret_key | SK,用于生成认证字符串的密钥,必须保密,用户通过一定机制获取,只有发送和接收双方知道,各自本地保存,不在请求中传递。在配置回调服务时,通过平台工具生成,或者由用户自行提供 |
timestamp | 请求发送时间 |
expiretime | 超时时间,单位:秒 |
按以下流程生成认证字符串(可参考后面的代码示例):
以 $auth_ver/$access_key/$timestamp/$expiretime
为认证字符串前缀。
使用 基于sha256的HMAC摘要算法,以 secret_key
为 key, 对认证字符串前缀生成摘要 sign_key
。
POST 请求:保证不被篡改的参数放入请求的 body 部分,序列化生成 sign_content
,用同样的摘要算法,以上一步得到的 sign_key
对 sign_content
生成摘要 signature
。
最终的认证字符串为:
$auth_ver/$access_key/$timestamp/$expiretime/$signature
iPaaS-Auth:$auth_ver/$access_key/$timestamp/$expiretime/$signature
import ( "crypto/hmac" "crypto/sha256" "fmt" "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(ver string, ak string, sk string, signContent []byte) string { expiration := 1800 signKeyInfo := fmt.Sprintf("%s/%s/%d/%d", ver, ak, time.Now().Unix(), expiration) signKey := sha256HMAC([]byte(sk), []byte(signKeyInfo)) signature := sha256HMAC(signKey, signContent) return fmt.Sprintf("%v/%v", signKeyInfo, string(signature)) }
import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public static String Sha256HMAC(String key, byte[] data) throws Exception { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); sha256_HMAC.init(keySpec); byte[] hash = sha256_HMAC.doFinal(data); byte[] hexChars = new byte[hash.length * 2]; for ( int j = 0; j < hash.length; j++ ) { byte[] s = String.format("%02x", hash[j] & 0xFF).getBytes(); hexChars[j * 2] = s[0]; hexChars[j * 2 + 1] = s[1]; } return new String(hexChars); } public static String Sign(String ver, String ak, String sk, byte[] data) throws Exception { int expiration = 1800; long timestamp = System.currentTimeMillis() / 1000L; String signKeyInfo = String.format("%s/%s/%d/%d", ver, ak, timestamp, expiration); String signKey = Sha256HMAC(sk, signKeyInfo.getBytes()); String signature = Sha256HMAC(signKey, data); return String.format("%s/%s", signKeyInfo, signature); }