API-V5 接口说明-通用接口标准

通用接口标准

传输协议标准

  • “海量ADP大数据平台”提供在线的互联网服务,为开发者提供http/https接口,方便开发者与平台进行交互。
  • 服务器提供http/https形式的访问接口,通过POST的方式,以JSON格式传递参数。
  • 采用同步请求响应的模式提供返回数据。请求方将参数存放在规定的参数名中,发送给目标接口URL,接口的后端服务响应后会将结果返回给请求方。

数据格式标准

  • 所有API接口统一采用 POST JSON 的请求方式
  • 所有API接口返回内容统一采用 JSON 数据格式
  • 文本编码统一为 utf-8
  • 客户端请求 "Content-Type" 需为 "application/json"
  • 服务端返回 "Content-Type" 均为 "application/json"

访问接口标准

  • 接口支持HTTP/HTTPS协议
  • 接口仅支持POST方法进行调用
  • 请求参数仅支持 JSON 格式的 BODY 内容
  • 请求包含:公共参数 + 具体服务的特定参数

公共参数说明

  • 公共参数的功能主要为身份认证,防止非法请求通过API访问系统功能
  • 公共参数均在 HTTP HEADER 中,服务器通过 HEADER 中的信息进行身份认证
  • 公共参数有如下几个:
参数名称 参数格式 参数描述 是否必需 备注
hl_appkey 字符串 用户appkey 由海量提供的用户身份识别码,参与认证签名计算
hl_time 字符串 当前时间 当前北京时间,参与认证签名计算,格式为 “yyyy-mm-dd HH:MM:SS”
hl_sign 字符串 认证签名 安全加密认证的参数, 请查看下面的具体说明
  • 注意:上面参数均为系统保留字,请不要在其他参数中使用上述名称
  • 以上三个参数每个接口都要使用,hl_sign 认证签名的生成方法,请参考后面章节
  • [非必需]建议发送http请求访问接口时,Headers中设置 "Accept-Encoding:gzip"

 关于认证签名的生成

  • 每次调用 API 接口时,需要提供一个 hl_sign 认证签名参数,用于认证此次请求的合法性
  • 海量会为每位客户提供一个 appkey 及与其对应的一组密钥(secret)
  • 客户端发起请求前,需要利用这组密钥来生成 hl_sign 的加密签名字符串,与请求一同提交给服务器

签名生成方法

  • 客户端请求包括以下三部分:请求接口的 URL地址,公共参数(HEADER内),具体服务特定参数(JSON内)
  • 海量API v5 接口统一使用的地址前缀为 https://api.hylanda.com/v5/
  • 下面以 https://api.hylanda.com/v5/xuanzhi/media/publish_count 接口(炫知媒体发稿量)为例,介绍生成步骤:
  • 首先,假设您已经从海量获得了appkey及secret,如下

     appkey : 123456789012345467890
     secret : HZUQs7gLxQ1nFT0rKdSu0YuilGkkMF2T
    
  • 确定要调用的接口URL路径(完整URL去除域名),例如上述接口URL路径为 /v5/xuanzhi/media/publish_count

  • 将当前时间格式化为字符串(北京时间精确到秒),作为 hl_time 参数的值
  • 将接口的 公共参数 及 POST-JSON字符串 罗列出来(不含hl_sign),即 hl_appkey、hl_time、json 三者,例如如下形式(还是以炫知媒体发稿量接口为例):

     hl_appkey     : 123456789012345467890
     hl_time       : 2021-12-01 16:55:48
     json          : {"date": "2021-11-06", "name": "新华网", "type": "standard_media_name"}
    
  • 将 “参数名” 和 “参数值” 使用 “&” 和 “=” 做字符串拼接(注意:要保持上面的顺序),像这样:

    hl_appkey=xxxxxxx&hl_time=xxxxxxxx&json=xxxxxxxxx

    请注意:上述字符串拼接好后,不需要再进行其他处理,输出一个码制为UTF-8的字符串即可

    重要:json部分有空格换行也不要紧,原样拼入上述字符串即可,但一旦拼好了,拼入字符串的这部分json,必须和最终POST的json一模一样,不能在POST时再追加或删减任何字符,包括空格、换行等

    上例中,拼接后的字符串如下:
    hl_appkey=123456789012345467890&hl_time=2021-12-01 16:55:48&json={"date": "2021-11-06", "name": "新华网", "type": "standard_media_name"}

  • 在字符串前面拼接上URL路径,并加上 “?” 符号连接,像这样:

    /v5/xuanzhi/media/publish_count?hl_appkey=123456789012345467890&hl_time=2021-12-01 16:55:48&json={"date": "2021-11-06", "name": "新华网", "type": "standard_media_name"}

  • 在字符串尾部直接拼接上密钥(secret),像这样:

    /v5/xuanzhi/media/publish_count?hl_appkey=123456789012345467890&hl_time=2021-12-01 16:55:48&json={"date": "2021-11-06", "name": "新华网", "type": "standard_media_name"}HZUQs7gLxQ1nFT0rKdSu0YuilGkkMF2T

    (这里假设 “HZUQs7gLxQ1nFT0rKdSu0YuilGkkMF2T” 是您的密钥)

  • 将上述整个字符串计算 MD5 值,作为 hl_sign 参数的值,加入请求参数中(若MD5函数需要unicode转码,像python之类,使用 UTF-8 转码即可)

     temp_string = '/v5/xuanzhi/media/publish_count?hl_appkey=123456789012345467890&hl_time=2021-12-01 16:55:48&json={"date": "2021-11-06", "name": "新华网", "type": "standard_media_name"}HZUQs7gLxQ1nFT0rKdSu0YuilGkkMF2T'
     hl_sign=md5(temp_string)
     ----计算MD5得出:
     hl_sign=f2b1add46f07dfe07a8231195f581f76        
     ----请注意:此`hl_sign`值有效期为`hl_time`开始的300秒内
    
  • POST JSON标准方式,输入公共参数和服务特定参数,发送给指定 API 接口即可:

     POST https://api.hylanda.com/v5/xuanzhi/media/publish_count
     HEADERS: 'Content-Type: application/json'
              'hl_appkey: 123456789012345467890'
              'hl_time: 2021-12-01 16:55:48'
              'hl_sign: f2b1add46f07dfe07a8231195f581f76'
     BODY: {"date": "2021-11-06", "name": "新华网", "type": "standard_media_name"}
    

请注意:无论任何情况下,请保护您的密钥(secret),不要在网络上明文传输,或发送给任何单位和个人,由此产生的损失将由泄密方承担。

通用返回信息

海量API接口的返回信息体的基本JSON结构如下

{
  "res":0,  //返回码,正常一般返回0,非零为各种异常情况,有时特殊接口会使用特殊返回值
  "msg":"服务返回信息",
  "特定服务其他返回字段":""
}

通用错误返回信息说明

HTTP Code HTTP Response Body Description
401 {
"res": 401,
"msg": "data truncated (数据出错)"
}
传输的数据错误,
可能是通讯过程出现问题,尝试重试解决
401 {
"res": 401,
"msg": "no JSON (未收到 POST JSON 数据)"
}
服务器没有收到接口参数数据,
请检查客户端参数
403 {
"res": 401,
"msg": "validate clock failed (请求时间字段不存在或不合法)"
}
请检查hl_time参数,
服务器仅响应hl_time在最近300秒内的请求;
也有可能是POST方式错误,
服务器没有接到hl_time字段
403 {
"res": 403,
"msg": "missing signature field (缺少认证所需签名字段)"
}
请检查hl_appkey,hl_time,hl_sign参数
是否漏发,请补全后重试
403 {
"res": 403,
"msg": "missing credential (未找到该用户的证书)"
}
请检查hl_appkey字段是否填错,
系统没有找到对应用户的证书
403 {
"res": 403,
"msg": "signature not same (签名校验失败)"
}
hl_sign签名校验失败,
请检查hl_sign的生成逻辑是否有误
200 {
"res": -1,
"msg": "您没有调用此接口的权限"
}
授权信息无权访问此接口,请与相关人员确认您是否有权调用

调用接口的代码样例(python3)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created by chy on 2020/12/29 18:04
"""
本代码仅供向客户演示海量APIv5的调用方法
代码可以任意截取、复制到您的系统中
但本代码仅供演示调用方法,所用函数、库等并不一定是最优的,请使用此代码的开发人员根据自己系统的特点自行修改
"""

import datetime
import hashlib
import json
import requests

if __name__ == "__main__":
    appkey = "这里填写你的appkey"
    secret = "这里填写你的密钥"
    # api_path 这里填写您要调用的api相对路径(不包含域名的部分) 这里只是个例子,请不要照搬
    api_path = "/v5/xuanzhi/media/publish_count" 
    url = "https://api.hylanda.com"+api_path
    headers = {
        "Content-Type": "application/json",
        "hl_appkey": appkey,
        "hl_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
    data = {
        # 这里填写您要调用的API的参数,参数名和参数值都请参考对应的接口说明里写,这里只是一个例子,请不要照搬
        "date": "2021-11-06",
        "name": "新华网",
        "type": "standard_media_name"
    }
    #将json对象dumps成为字符串
    str_data_json = json.dumps(data, ensure_ascii=False)
    #拼接用来计算md5的字符串
    str_temp = f"{api_path}?hl_appkey={headers['hl_appkey']}&hl_time={headers['hl_time']}&json={str_data_json}" + secret
    #计算md5
    m = hashlib.md5()
    m.update(str_temp.encode("utf8"))
    #将算好的md5放进headers中
    headers["hl_sign"] = m.hexdigest()
    #开始请求接口
    resp = requests.post(url, str_data_json.encode("utf-8"), headers=headers, timeout=30)
    print(resp.status_code)
    if resp is not None:
        print( resp.json())

调用接口的代码样例(JAVA)

"""
本代码仅供向客户演示海量APIv5的调用方法
代码可以任意截取、复制到您的系统中
但本代码仅供演示调用方法,所用函数、库等并不一定是最优的,请使用此代码的开发人员根据自己系统的特点自行修改
"""

/**
 * 计算sign值类
 */
import com.alibaba.fastjson.JSONObject;
import java.security.MessageDigest;
import java.util.Map;
import java.util.TreeMap;

public class ApiV5SignUtil {

    public static String API_HOST = "https://api.hylanda.com";
    public static String APPKEY   = "这里填写你的appkey";
    public static String SECRET   = "这里填写你的密钥";

    /**
     * url为api除去域名的地址,如 /v5/xuanzhi/analysis/profile
     *
     */
    public static String getSign(String url, String hl_time, JSONObject param) {
        String sign_str = url + "?hl_appkey=" + APPKEY + "&hl_time=" + hl_time + "&json=" + param + SECRET;
        return MD5(sign_str).toLowerCase();
    }

    public final static String MD5(String s) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        try {
            byte[] btInput = s.getBytes("UTF-8");
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}


/**

 * 请求样例类
 */
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 *  <dependency>
 *        <groupId>com.squareup.okhttp3</groupId>
 *      <artifactId>okhttp</artifactId>
 *      <version>4.9.0</version>
 *  </dependency>
 * 
 */
public class HttpUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    private static OkHttpClient getClient() {
        return new OkHttpClient.Builder().readTimeout(60, TimeUnit.SECONDS).build();
    }

    public static String postJsonV5(String sub_url, JSONObject params) {

        RequestBody body = RequestBody.create(params.toJSONString(), MediaType.get("application/json; charset=utf-8"));
        String hl_time   = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        String hl_sign   = ApiV5SignUtil.getSign(sub_url, hl_time, params);

        Request request = new Request.Builder()
                .url(ApiV5SignUtil.API_HOST + sub_url)
                .header("hl_appkey", ApiV5SignUtil.APPKEY)
                .header("hl_time",   hl_time)
                .header("hl_sign",   hl_sign)
                .post(body)
                .build();

        try(Response response = getClient().newCall(request).execute()) {

            if (response.code() == 200)
                return response.body().string();
            else
                logger.error("--- http请求失败, code: " + response.code() + ", url: " + sub_url + ", params: " + params);
        }
        catch (IOException e){

            logger.error("--- http请求异常: ", e);
        }

        return "";
    }
}

results matching ""

    No results matching ""