Skip to main content

公共请求头验签说明


易荟通OPEN API 是使用 HTTP 并遵循 REST 原则设计的 Web 服务接口,您可以使用几乎任何客户端和任何编程语言与 REST API 进行交互。通过发送简单的 HTTP POST 请求就可以轻松接入使用。

统一请求格式#

BASE URL:#

    https://gateway.yihuitong.top

URL 格式:#

    /coll-openapi/{resource}/{function}
说明:#
  • {resource}为资源名,通常对应一类 API
  • {function}为该资源提供的操作方法

比如获取呼叫状态的 url 为:https://gateway.yihuitong.top/coll-openapi/call/record/callReport 表示调用呼叫的状态方法,返回 json 格式的字符串。 我们目前已经提供的接口,请参考 API。

HTTP 头信息:#

    Accept:application/json;charset=utf-8;    Content-Type:application/json;charset=utf-8;    X-SIGNATURE: $signature;    X-APIKEY: $APIKEY;    X-TIMESTAMP: $timestamp;    X-NONCE: $nonce;
**说明#

上面带 $ 符号参数为变量对应下面表格说明

变量名称说明
$signature变量是接口验签值计算公式 signature = HMAC-SHAx-HEX(secret_key, signing_string) 从公式可以看出,想要获得签名需要得到 secret_key 和 signing_string 两个参数。 其中 secret_key 从 控制台->账号设置->APIKEY->secretKey 获取,signing_string 的计算公式为 signing_string = HTTP Method + \n + HTTP URI + \n + $APIKEY + \n + $timestamp + \n + $nonce + \n + canonical_query_string + \n + json_body
$APIKEY变量从 控制台->账号设置->APIKEY->apikey 获取
$timestamp当前接口请求时的时间戳(精度到秒级) 跟易荟通服务器时间相差不能超过10秒
$nonce变量是防重机制,请求时上次当前请求唯一ID; 推荐: 32-UUID、分布式ID
  1. HTTP Method:指 HTTP 协议中定义的 GET、PUT、POST 等请求方法,必须使用全大写的形式。
  2. HTTP URI:要求必须以“/”开头,不以“/”开头的需要补充上,空路径为“/”。
  3. APIKEY: 请求头中的 X-APIKEY
  4. timestamp: 请求头中的 X-TIMESTAMP
  5. nonce: 请求头中的 X-NONCE
  6. canonical_query_string: 是对于 URL 中的 query( query 即 URL 中 ? 后面的 key1=valve1&key2=valve2 字符串)或者 Content-Type:application/x-www-form-urlencoded 的时候 body 里面的值,进行编码后的结果参数需要进行 url encode 编码 url_encode(key) + "=" + url_encode(value) 的形式,每一项转换后,以 key 按照字典顺序( ASCII 码由小到大)排序,并使用 & 符号连接起来,生成相应的 canonical_query_string 。 如果 没有query,canonical_query_string + \n 就不需要拼接上去
  7. json_body: POST 请求 Content-Type:application/json 的时候 json_body 就是 body 中的json请求数据
  8. HMAC-SHAx-HEX: 加密算法是 HmacSHA256 。 加密完后的字节数组需要在通过 Base64 进行编码
代码案例:#

根据下面的案例算出来headers的值是: {X-NONCE=bc9efee185e64ab9bc0b07a2785c4660, X-TIMESTAMP=1626856279, X-SIGNATURE=HB78nqGoplcCgZGInTYzEPjGyVy9/sm1uxQotqxo/6s=, X-APIKEY=123456789}

import java.io.UnsupportedEncodingException;import java.net.URLEncoder;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.TreeMap;import java.util.stream.Collectors;
import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import javax.xml.bind.DatatypeConverter;

import com.alibaba.fastjson.JSON;
public class SignatureCase {            public static void main(String[] args) {        @SuppressWarnings("unused")        String callReportUrl = "https://gateway.yihuitong.top/coll-openapi/call/record/callReport";        String nonce = "bc9efee185e64ab9bc0b07a2785c4660";        Integer timestamp = 1626856279;        String apikey = "123456789";        String secretKey = "1234567890";        String method = "GET";        String path = "/coll-openapi/call/record/callReport";        String contentType = "";                        Map<String, Object> parameters = new HashMap<>();        parameters.put("callId","1234");                        StringBuilder sb = new StringBuilder();        sb.append(method).append("\n")        .append(path).append("\n")        .append(apikey).append("\n")        .append(timestamp).append("\n")        .append(nonce).append("\n");                        if(parameters!=null && !parameters.isEmpty()) {            if("json".equals(contentType) ) {                sb.append(JSON.toJSONString(parameters)).append("\n");            }else {                String canonical_query_string = formatUrlMap(parameters, true, false);                sb.append(canonical_query_string).append("\n");            }                    }                try {            Mac hasher = Mac.getInstance("HmacSHA256");            hasher.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));            byte[] hash = hasher.doFinal(sb.toString().getBytes());                                    Map<String,String> headers = new HashMap<String, String>();            headers.put("X-SIGNATURE", DatatypeConverter.printBase64Binary(hash));            headers.put("X-APIKEY", apikey);            headers.put("X-TIMESTAMP", timestamp.toString());            headers.put("X-NONCE", nonce);                                    System.out.println(headers +": "+ headers);                    } catch (NoSuchAlgorithmException | InvalidKeyException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }            }        public static String formatUrlMap(Map<String, Object> paraMap,boolean urlEncode,boolean keyToLower) {        if(paraMap==null || paraMap.isEmpty()) {            return null;        }               if(!(paraMap instanceof TreeMap)) {           paraMap = new TreeMap<String, Object>(paraMap);       }                return paraMap.entrySet().stream().map(entry -> {            String key = entry.getKey();            Object value = entry.getValue();            if(urlEncode) {                try {                    key = URLEncoder.encode(key, "utf-8");                } catch (UnsupportedEncodingException e) {                    e.printStackTrace();                }                if(value!=null && !"".equals(value.toString())) {                    try {                        value = URLEncoder.encode(value.toString(), "utf-8");                    } catch (UnsupportedEncodingException e) {                        e.printStackTrace();                    }                }                if (keyToLower) {                    key = key.toLowerCase();                }            }            return key + "=" + value;        }).collect(Collectors.joining("&"));            }    }