# 接口使用指南
# 请求数据格式
- 当接口需要POST方式请求,请求数据推荐使用form-data格式,而不是x-www-form-urlencoded。 当接口需要GET方式请求时, 请求数据需要放置在url参数中。
 
# 数据返回格式
- 接口返回数据结构和header类型 所有接口返回格式均为json,Content-type:application/json;charset=utf-8
 
# 公共参数
- 以下公共参数为所有接口必须携带的参数。
 
# 使用GET方式请求的接口
Query
| 参数名称 | 是否必须 | 示例 | 备注 | 
|---|---|---|---|
| app_key | 是 | 商户app_key | |
| rand_str | 是 | 32位随机字符串,不可重复 | |
| request_time | 是 | 当前秒级时间戳,需要与服务器标准时间相差不超过3分钟 | |
| sign | 是 | 验证加密字符串 | 
- 以上参数均为必填项
 - GET方式请求接口时,以上参数需要生成QueryParam拼接到要请求的url中
 - 参数rand_str应当在每次请求时随机生产32位字符串,不使用重复值
 - 参数request_time应当保证时间戳与服务器标准时间尽量保持小的误差
 - 参数sign生成算法: md5(app_key+md5(app_secret+"dolit-cloud-openapi-v1"+rand_str) + request_time),app_secret是指您的商户秘钥,可登录您的商户后台查看。
 - GET方式调用示例
 
<?php
$app_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  //您的商户app_key
$rand_str = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //生产32位随机字符串
$app_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; //您的商户秘钥app_secret
$request_time = time();
$sign = md5($app_key + md5($app_secret+"dolit-cloud-openapi-v1"+$rand_str) + $request_time)));
$params_arr = array(
	"app_key" => $app_key,
	"rand_str" => $rand_str,
	"request_time" => $request_time,
	"sign" => $sign,
);
$params = http_build_query($params_arr);
$base_url = "http://xxx.com/xxx?";
$req_url = $base_url+$params;
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $req_url);
$res = curl_exec($curl);
curl_close($curl);
echo $res;
# 使用POST方式请求的接口
# 公共Header
Headers
| 参数名称 | 参数值 | 是否必须 | 示例 | 备注 | 
|---|---|---|---|---|
| Content-Type | multipart/form-data; boundary={cal when sent} | 是 | 支持application/x-www-form-urlencoded类型 | 
Body
| 参数名称 | 是否必须 | 示例 | 备注 | 
|---|---|---|---|
| app_key | 是 | 商户app_key | |
| rand_str | 是 | 32位随机字符串,不可重复 | |
| request_time | 是 | 当前秒级时间戳,需要与服务器标准时间相差不超过3分钟 | |
| sign | 是 | 验证加密字符串 | 
- 以上参数均为必填项
 - POST方式请求接口时,以上参数需要通过post方式发送到服务端。支持x-www-form-urlencoded或者form-data两种请求方式
 - 参数rand_str应当在每次请求时随机生产32位字符串,不使用重复值
 - 参数request_time应当保证时间戳与服务器标准时间尽量保持小的误差
 - 参数sign生成算法: md5(app_key+md5(app_secret+"dolit-cloud-openapi-v1"+rand_str) + request_time),app_secret是指您的商户秘钥,可登录您的商户后台查看。
 
# 接口使用场景说明
- 云流化系统对接第三方系统集成,实现对服务器,内容,流路的管理
 - 按需按场景生成串流访问地址:
 
 1 动态分配服务资源,实现用时动态启动,闲置时关闭资源。
 2 对于预启动的资源,自动搜索指定资源的空闲流路。
# 接口对接流程说明
- 使用API接口列表中
云应用相关创建云应用接口创建云应用,接口返回值中url即为web链接地址 - SDK对接可使用API接口列表中
资源调度获取当前应用流路接口获取当前应用最佳访问路径 
# API接口请求示例
# Node.js
const crypto = require('crypto');
const querystring = require('querystring');
const axios = require('axios');
const app_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  // 您的商户app_key
const rand_str = crypto.randomBytes(32).toString('hex'); // 生产32位随机字符串
const app_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // 您的商户秘钥app_secret
const request_time = Math.floor(Date.now() / 1000); // 获取当前时间戳(秒)
// 计算签名
const signStr = `${app_key}${crypto.createHash('md5').update(`${app_secret}dolit-cloud-openapi-v1${rand_str}`).digest('hex')}${request_time}`;
const sign = crypto.createHash('md5').update(signStr).digest('hex');
// 构建请求参数
const params_arr = {
    app_key,
    rand_str,
    request_time,
    sign,
};
// URL 编码参数
const params = querystring.stringify(params_arr);
// 定义请求URL
const base_url = "http://xxx.com/xxx?";
const req_url = base_url + params;
// 发起 HTTP 请求
axios.get(req_url)
    .then((response) => {
        console.log(response.data);
    })
    .catch((error) => {
        console.error(error);
    });
# Golang
引入文件
- 将
cloud.go文件引入到项目的根目录下,也可自行修改packge,以放入其他包下。 - 执行
go mod tidy下载所需依赖 
cloud.go
package cloud
import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"github.com/gogf/gf/util/gconv"
	"go.uber.org/zap"
	"io"
	"math/rand"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)
var (
	appKey, appSecret, baseUrl string
	RequestUserParam           url.Values
)
type CloudClient struct {
	client http.Client
	//Writer *multipart.Writer
}
// 新增云应用请求参数
type InsertCloudApp struct {
	AppName               string          `json:"app_name" binding:"required"`                 //应用名称
	AppModeNo             string          `json:"app_mode_no" binding:"required"`              //应用模板编号ID
	ExePath               string          `json:"exe_path" binding:"required"`                 //应用路径
	ViewPath              string          `json:"view_path"`                                   //视图路径
	Args                  string          `json:"args"`                                        //参数
	Mark                  string          `json:"mark"`                                        //备注
	PreStartStreamerCount int             `json:"pre_start_streamer_count" binding:"required"` //预启动数量(1.针对启动加载慢的应用程序,可设置提前启动,用户访问无需加载立即进入。2.预启动数量最大不能超过累计流路数)
	StreamerCount         int             `json:"streamer_count" binding:"required"`           //流路数(流路数取决于机器性能,性能越好可开流路数越多)
	AppData               []InsertAppData `json:"app_data" binding:"required"`                 //服务器列表json字符串
}
type InsertAppData struct {
	Peer                  string `json:"peer" binding:"required"`                     //服务器IP,如果局域网IP和公网IP都需要,参数如示例;如果只有局域网IP或公网IP,则如:10.0.0.21
	ExePath               string `json:"exe_path" binding:"required"`                 //应用路径
	ViewPath              string `json:"view_path"`                                   //视图路径
	Args                  string `json:"args"`                                        //参数
	PreStartStreamerCount int    `json:"pre_start_streamer_count" binding:"required"` //预启动数量(1.针对启动加载慢的应用程序,可设置提前启动,用户访问无需加载立即进入。2.预启动数量最大不能超过累计流路数)
	StreamerCount         int    `json:"streamer_count" binding:"required"`           //流路数(流路数取决于机器性能,性
}
// 获取列表请求参数
type CloudListParam struct {
	Page       int    `json:"page"`
	Limit      int    `json:"limit"`
	CateName   string `json:"cate_name"`
	AppCode    string `json:"app_code"`
	Status     string `json:"status"`
	AppCateNo  string `json:"app_cate_no"`
	ComputerNo string `json:"computer_no"`
}
// 修改云应用请求参数
type EditCloudApp struct {
	AppCateNo             string        `json:"app_cate_no" binding:"required "`             //应用编号ID(添加应用或应用列表获取)
	Name                  string        `json:"name" binding:"required"`                     //应用名称
	AppModeNo             string        `json:"app_mode_no" binding:"required"`              //应用模板编号ID
	Path                  string        `json:"path" binding:"required"`                     //应用路径
	ViewProcess           string        `json:"view_process"`                                //视图路径
	Args                  string        `json:"args"`                                        //参数
	PreStartStreamerCount int           `json:"pre_start_streamer_count" binding:"required"` //预启动数量
	StreamerCount         int           `json:"streamer_count" binding:"required"`           //流路数
	AppData               []EditAppData `json:"app_data" binding:"required"`                 //服务器列表json字符串
}
type EditAppData struct {
	AppNo                 string `json:"app_no"`                                      //应用主键ID
	ComputerNo            string `json:"computer_no" binding:"required"`              //服务器ID
	Path                  string `json:"path" binding:"required"`                     //应用路径
	ViewProcess           string `json:"view_process"`                                //视图路径
	Args                  string `json:"args"`                                        //参数
	PreStartStreamerCount int    `json:"pre_start_streamer_count" binding:"required"` //预启动数量
	StreamerCount         int    `json:"streamer_count" binding:"required"`           //流路数
}
// 删除请求参数
type DeleteAppData struct {
	AppCateNos string `json:"app_cate_nos" binding:"required"` //应用ID,多个之间用英文逗号拼接
}
// 启用禁用请求参数
type AbleCloudData struct {
	Status     int    `json:"status" binding:"required"`       //状态,1启用,2禁用
	AppCateNos string `json:"app_cate_nos" binding:"required"` //应用ID,多个之间用英文逗号拼接
}
func (CR *CloudClient) DoGet(url string, data interface{}) string {
	paramUrl := setParams(data).Encode()
	reqUrl := baseUrl + url + "?" + paramUrl
	resp, err := CR.client.Get(reqUrl)
	if err != nil {
		zap.L().Error("Get请求异常:" + err.Error())
	}
	defer resp.Body.Close()
	bytes, _ := io.ReadAll(resp.Body)
	return string(bytes)
}
func (CR *CloudClient) DoPost(url string, data interface{}) string {
	params := setParams(data)
	reqUrl := baseUrl + url
	resp, err := CR.client.Post(reqUrl, "application/x-www-form-urlencoded", strings.NewReader(params.Encode()))
	if err != nil {
		zap.L().Error("Post请求异常 : " + err.Error())
	}
	defer resp.Body.Close()
	bytes, _ := io.ReadAll(resp.Body)
	return string(bytes)
}
// 获取请求客户端
func GetCloudClient(AppKey, AppSecret, BaseUrl string) CloudClient {
	appKey = AppKey
	appSecret = AppSecret
	baseUrl = BaseUrl
	tr := http.Transport{DisableKeepAlives: true}
	client := http.Client{Transport: &tr}
	cloudClient := CloudClient{
		client: client,
	}
	return cloudClient
}
// 获得随机字符串
func RandString(len int) string {
	rand.Seed(time.Now().UnixNano())
	randBytes := make([]byte, len/2)
	rand.Read(randBytes)
	return fmt.Sprintf("%x", randBytes)
}
// Post请求客户密钥封装
func requestKey(appKey string, appSecret string, randStr string) url.Values {
	requestTime := strconv.Itoa(int(time.Now().Unix()))
	sign := Md5Tool(appKey + Md5Tool(appSecret+"dolit-cloud-openapi-v1"+randStr) + requestTime)
	requestBody := url.Values{}
	//www-form格式
	requestBody.Set("app_key", appKey)
	requestBody.Set("rand_str", randStr)
	requestBody.Set("request_time", requestTime)
	requestBody.Set("sign", sign)
	return requestBody
}
func Md5Tool(data string) string {
	t := md5.New()
	io.WriteString(t, data)
	return fmt.Sprintf("%x", t.Sum(nil))
}
// 解析用户参数
func setParams(data interface{}) url.Values {
	randStr := RandString(32)
	RequestUserParam = requestKey(appKey, appSecret, randStr)
	jsonData, _ := json.Marshal(data)
	var jsonMap map[string]interface{}
	json.Unmarshal(jsonData, &jsonMap)
	for k, v := range jsonMap {
		RequestUserParam.Set(k, gconv.String(v))
	}
	return RequestUserParam
}
说明
- 通过
GetCloudClient(AppKey, AppSecret, BaseUrl)获取cloudClient。 - 根据需要创建所需的请求参数
 - 通过
cloudClient执行DoGet或DoGet发起请求,并填入接口地址及相应的请求参数。 
综合示例
func main() {
	AppKey := "xxxxxxxxxxxxxxxxxxxxx"    // 商户的 app_key
	AppSecret := "xxxxxxxxxxxxxxxxxxxxx" // 商户的秘钥
    BaseUrl := "xxxxxxxxxxxxxxxxxxxxx"	
	cloudClient := GetCloudClient(AppKey, AppSecret, BaseUrl)
	var result string
    
	//获取云应用列表
	result = cloudClient.DoGet("/open/v1/app_cloud/list", CloudListParam{
		1,		//分页-当前页码
		10,		//分页-每页数量
		"",		//应用名称(模糊搜索)
		"",		//应用code(模糊搜索)
		"",		//应用状态:1正常,2停用
		"",		//应用ID
		"",		//服务器ID
	})
	fmt.Println(result)
	//禁用启用云应用
	result = cloudClient.DoPost("/open/v1/app_cloud/disable_batch", AbleCloudData{
		Status:     2,											//状态
		AppCateNos: "xxxxxxxxxxxxxxxxxxx,xxxxxxxxxxxxxxxxxxx", //云应用id,多个云应用之间用逗号隔开
	})
	fmt.Println(result)
    
    
	//一键新增云应用
	result = cloudClient.DoPost("/open/v1/app_cloud/add_common", InsertCloudApp{
		AppName:               "example",		//应用名称
		AppModeNo:             "xxxxxxxxxxxxxxxxxxx",		//	应用模板编号ID
		ExePath:               "F:\\pp.exe",//应用路径
		ViewPath:              "",				//视图路径
		Args:                  "",				//参数
		Mark:                  "",				//备注
		PreStartStreamerCount: 1,				//预启动数量
		StreamerCount:         1,				//流路数
		AppData: []InsertAppData{{				//服务器列表
			Peer:                  "XX.XX.XX.XX,XX.XX.XX.XX",	//服务器IP
			ExePath:               "",			//应用路径
			ViewPath:              "",			//视图路径
			Args:                  "",			//参数
			PreStartStreamerCount: 1,			//预启动数量
			StreamerCount:         1,			//流路数
		}},
	})
	fmt.Println(result)
    
    
    //删除云应用
	result = cloudClient.DoPost("/open/v1/app_cloud/del_batch", DeleteAppData{
		AppCateNos: "xxxxxxxxxxxxxxxxxxx",	//应用id
	})
	fmt.Println(result)
    
	//编辑云应用
	result = cloudClient.DoPost("/open/v1/app_cloud/edit", EditCloudApp{
		AppCateNo:             "xxxxxxxxxxxxxxxxxxx",	//应用编号ID
		Name:                  "exampleName",			//应用名称
		AppModeNo:             "xxxxxxxxxxxxxxxxxxx",	//应用模板编号ID
		Path:                  "F:\\pp.exe",//应用路径
		ViewProcess:           "F:\\pp.exe",//视图路径
        Args:				   "",						//参数
		PreStartStreamerCount: 3,						//预启动数量
		StreamerCount:         3,						//流路数
		AppData: []EditAppData{{						//服务器列表
			AppNo:                 "xxxxxxxxxxxxxxxxxxx",	//应用主键ID
			ComputerNo:            "xxxxxxxxxxxxxxxxxxx",	//服务器ID
			Path:                  "",						//应用路径
			ViewProcess:           "",						//视图路径
            Args:				   "",						//参数
			PreStartStreamerCount: 0,						//预启动数量
			StreamerCount:         0,						//流路数
		}},
	})
	fmt.Println(result)
}
- 关于请求参数
 
本包仅定义了操作云应用的部分接口的请求类型,如有需要,请自行定义其他请求类型,也可使用map类型来代替,具体示例如下:
注意:此处的app_data的数据为数组类型,是由于本包内部已经将其转为json字符串,故不必特地将其转为string类型。
package main
import "fmt"
func main() {
	AppKey := "xxxxxxxxxxxxxxxxxxxxx"    // 商户的 app_key
	AppSecret := "xxxxxxxxxxxxxxxxxxxxx" // 商户的秘钥
    BaseUrl := "xxxxxxxxxxxxxxxxxxxxx"	
	cloudClient := GetCloudClient(AppKey, AppSecret, BaseUrl)
    //使用map封装新建请求
	response := cloudClient.DoPost("/open/v1/app_cloud/add_common", map[string]interface{}{
		"app_name":                 "MapAddExample",
		"app_mode_no":              "xxxxxxxxxxxxxxxxxxxxx",
		"exe_path":                 "F:\\pp.exe",
		"view_path":                "",
		"args":                     "",
		"mark":                     "",
		"pre_start_streamer_count": 1,
		"streamer_count":           3,
		"app_data": []map[string]interface{}{{
			"peer":                     "XX.XX.XX.XX,XX.XX.XX.XX",
			"exe_path":                 "",
			"view_path":                "",
			"args":                     "",
			"pre_start_streamer_count": 1,
			"streamer_count":           1,
		}, {
			"peer":                     "XX.XX.XX.XX,XX.XX.XX.XX",
			"exe_path":                 "",
			"view_path":                "",
			"args":                     "",
			"pre_start_streamer_count": 1,
			"streamer_count":           1,
		}, {
			"peer":                     "XX.XX.XX.XX,XX.XX.XX.XX",
			"exe_path":                 "",
			"view_path":                "",
			"args":                     "",
			"pre_start_streamer_count": 1,
			"streamer_count":           1,
		}},
	})
	fmt.Println(response) 
	
}
API
DoGet
接口说明
- 本接口主要适用于点量云流化管理系统的对外接口发起Get请求
 - 在接口中放入接口地址以及相应的请求参数
 
请求参数
| 参数名称 | 参数类型 | 是否必须 | 示例 | 备注 | 
|---|---|---|---|---|
| url | string | 是 | /open/v1/app_cloud/xxxxx | 对外接口地址 | 
| data | interface{} | 是 | CloudListParam,map等 | 请求参数-类型为结构体或map[string]interface{} | 
返回数据
| 名称 | 类型 | 默认值 | 备注 | 其他信息 | 
|---|---|---|---|---|
| response | string | 服务器返回结果 | 
示例
func main() {
	//根据app_key和app_secret获得CloudClient
	cloudClient := GetCloudClient("xxxxxxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxx","xxxxxxxxxxxxxxxxxxxxx")
	//使用CloudClient发起Get请求
	response := cloudClient.DoGet("/open/v1/app_cloud/list", CloudListParam{
		1,
		10,
		"",
		"",
		"",
		"",
		"",
	})
	//
	fmt.Println(result)
}
- DoPost
 
接口说明
- 本接口主要适用于点量云流化管理系统的对外接口发起Post请求
 - 在接口中放入接口地址以及相应的请求参数
 
请求参数
| 参数名称 | 参数类型 | 是否必须 | 示例 | 备注 | 
|---|---|---|---|---|
| url | string | 是 | /open/v1/app_cloud/xxxxx | 对外接口地址 | 
| data | interface{} | 是 | CloudListParam,map等 | 请求参数-类型为结构体或map[string]interface{} | 
返回数据
| 名称 | 类型 | 默认值 | 备注 | 其他信息 | 
|---|---|---|---|---|
| response | string | 服务器返回结果 | 
示例
func main() {
	//根据app_key和app_secret获得CloudClient
	cloudClient := GetCloudClient("xxxxxxxxxxxxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxx","xxxxxxxxxxxxxxxxxxxxx")
	//使用CloudClient发起Post请求
	response := cloudClient.DoPost("/open/v1/app_cloud/add_common", InsertCloudApp{
		AppName:               "example",
		AppModeNo:             "xxxxxxxxxxxxxxxxxxxxx",
		ExePath:               "F:\\pp.exe",
		ViewPath:              "F:\\pp.exe",
		Args:                  "",
		Mark:                  "",
		PreStartStreamerCount: 1,
		StreamerCount:         1,
		AppData: []InsertAppData{{
			Peer:                  "XX.XX.XX.XX,XX.XX.XX.XX",
			ExePath:               "",
			ViewPath:              "",
			Args:                  "",
			PreStartStreamerCount: 0,
			StreamerCount:         0,
		},
		},
	})
	fmt.Println(result)
}
# Java
Jar包与API请求示例详细说明文档请点击下载 Java版本对接文档 (opens new window)
引入文件
- 将
CloudClient.jar文件引入到项目中。 
说明
- 通过
new CloudClient(appKey,appSecret,baseUrl)获取CloudClient。 - 根据需要创建所需的请求参数
 - 通过
CloudClient执行DoGet或DoGet发起请求。 
API接口列表 →