1.1 - 系统关系

avatar

1.2 - 接入流程

avatar

1.3 - 接口规范

1.3.1 - 频控策略

  • 所有接口限制每个最高频率 50 次/秒

1.3.2 - 认证 token

  • 描述:获取企业下account_id账号对应的access_token,用于请求其他接口数据。 access_token 默认 24 小时 过期,refresh_token 默认 24 * 7 小时 过期

1.3.3 - 获取token

  • 接口:/open-apis/auth/v1/app-access-token/internal
  • 方法:GET
  • 请求头:application/json; charset=utf-8
  • 描述:获取企业下account_id账号对应的access_token,用于请求其他接口数据
  • 请求参数
{
    "app_key": "rcmt_id1",
    "expires": 1649819247, 
    "signature": "2F014C6A34C0ECFB522E2D52DF51B2BAAF97944EF9A2901115AB9912E59ACD35"
}
  • 参数说明
参数类型举例备注
app_keystringrcmt_id1应用唯一标识,由人才码头运营创建
expiresstring1649819247当前时间+60秒的10位时间戳 // 60s 过期
signaturestring2F014C6A34C0ECFB522E2D52DF51B2BA
AF97944EF9A2901115AB9912E59ACD35
签名

1.3.4 - 签名方法

  • 描述:对app_key,expires,app_secret 基于sha256 加密
  • 示例代码「php」:
class Signature
{
    /*
     * @param $path:去除根域名后的相对路径,这里的 $path 需要带上 '/'
     * @param $parameters: 接口传递参数,需要除开「expires, signature 」这2个参数
     * @param $secret:秘钥
     * @param $delay:过期时间,不要设置太长,否则会有一定的安全隐患
     */
    public static function sign($path, $parameters = [], $secret, $delay = 60)
    {
        $expiration = Carbon::now()->addRealSeconds($delay)->getTimestamp();
        $parameters['expires'] = $expiration;

        ksort($parameters);

        $signature = static::hash($path, $parameters, $secret, false);
        $parameters['signature'] = $signature;

        return $parameters;
    }

    public static function hash($path, $parameters, $secret, $sort = true)
    {
        if ($sort) {
            ksort($parameters);
        }

        $original = sprintf('/%s?%s', trim($path, '/'), Arr::query($parameters));

        return hash_hmac('sha256', $original, $secret);
    }
}
  • 示例代码「java」:
    public static final String SIGNATURE = "signature";
    public static final String EXPIRES = "expires";
    
    /**
      * url:去除根域名后的相对路径,注意传入的路径最前面需要带上 '/',否则会导致签名失败
      * 时间戳:需要转换为'秒'再加入到map
      * kSort():注意生成后的参数是否是按照字母顺序排序的
      */
    public static void adaptSignature(String secretKey,String url, Map<String, String> map) {
        String currentTimeMills = (System.currentTimeMillis() + 60 * 1000)/1000 + "";
        map.put(EXPIRES, currentTimeMills);
        String signStr = kSort(map);
        String encodeUrl = String.format("%s?%s", url, signStr);
        String signature = sha256_HMAC(encodeUrl, secretKey).toLowerCase();
        map.put(SIGNATURE, signature);
    }
    
    public static String kSort(Map<String, String> map) {
        StringBuilder sb = new StringBuilder();
        String[] key = new String[map.size()];
        int index = 0;
        for (String k : map.keySet()) {
            key[index] = k;
            index++;
        }
        Arrays.sort(key);
        for (String s : key) {
            sb.append(s).append("=").append(map.get(s)).append("&");
        }
        sb = new StringBuilder(sb.substring(0, sb.length() - 1));
        sb = new StringBuilder(URLEncoder.encode(sb.toString(), "UTF-8"));
        sb = new StringBuilder(sb.toString()
                .replace("%3D", "=")
                .replace("%26", "&")
                .replaceAll("\\+", "%20")
        );
        return sb.toString();
    }

    public static String sha256_HMAC(String data, String secret) {
        Mac sha256HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        sha256HMAC.init(secret_key);
        return byteArrayToHexString(sha256HMAC.doFinal(data.getBytes())).toLowerCase();
    }

    private static String byteArrayToHexString(byte[] b) {
        StringBuilder resultSb = new StringBuilder();
        for (byte value : b) {
            resultSb.append(byteToHexString(value));
        }
        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D",
            "E", "F"};

// 备注:1、考虑对特殊json包含空格、等号、&符号等进行转义  2、requestBody也要进行转义
  • 返回值
{
    "data": {
        "access_token": "234243xwer134",
        // 用户接口鉴权
        "refresh_token": "eyJhcHBLZXkiOiIxMjM0",
        //刷新token
        "expire": 86400
        // 过期秒数
    },
    "msg": "success",
    "error_code": 0
}

1.3.5 - 刷新token

  • 接口:/open-apis/auth/v1/app-access-token/refresh
  • 方法:GET
  • 请求头:application/json; charset=utf-8
  • 描述:根据refresh_token获取新的有效token
  • 请求参数
参数类型举例备注
refresh_tokenstringeyJhcHBLZXkiOiIxMjM0由3.2.1 获取token时获得
  • 返回值
{
    "data": {
        "access_token": "234243xwer134",
        // 用户接口鉴权
        "refresh_token": "eyJhcHBLZXkiOiIxMjM0",
        //刷新token
        "expire": 7140
        // 过期秒数
    },
    "msg": "success",
    "error_code": 0
}

1.3.6 - 调试方式

  • API调用时,需要将 access token 放入请求Header中,使用语法Authorization:Bearer <access token> 进行调用。下面是一个调用API查询企业标品-岗位-列表的示例,需要注意的是,示例中的 access_token 需要替换为有效的访问凭证(access token)。
$ curl --request GET 'https://open.rencaimatou.com/open-apis/company/v1/accounts/s232123/industry-jobs' \
--header 'Content-Type: application/json; charset=utf-8' \
--header 'Authorization:Bearer <实际的 access token>'
上次更新:
Contributors: 顾金鹤, PeikyLiu