# Доступ
# Прежде чем получить доступ
- Убедитесь, что соответствующие права для доступа через API включены. Неавторизованные попытки доступа через API могут привести к приостановке действия учетной записи.
- Убедитесь, что ограничение на частоту подключений настроено правильно. Превышение ограничения приведет к временной приостановке.
- Примите надлежащие меры по предотвращению повторного входа, поскольку проблемы с сетью могут привести к множественным вызовам, что в свою очередь приведет к дублирующимся сообщениям вызовов, отправляемым получающим доступ, что может негативно сказаться на пользователях.
- Выполняйте проверку отправляемых данных, чтобы избежать их фальсификации или потери.
- Пользователи могут получить только информацию о водителях в своем таксопарке.
# Запрос доступа к соответствующим ключам
Для запроса ключей доступа и ключей дешифрации перейдите на веб-сайт fleet > «Учетная запись» > «open api». Ключи будут предоставлены после того, как ваш запрос будет одобрен проверяющим.
# Порталы API
Производственная среда:
https://open-jelly-ru.didiglobal.com/
Среда песочницы:
https://open-jelly-ru-sim.didiglobal.com
# Служебные запросы
Производственная среда:
// Управление балансом водителей
curl -X POST
-H "Content-Type: application/json"
-H "Authorization: bearer {cid}|{access_token}"
-d 'json {
"fleet_id": 10000000000000,
"driver_id": 50000000000000,
"location_country": "RU",
"lang": "ru-RU"
}'
'https://open-jelly-ru.didiglobal.com/biz/fleet/open-api/drivers/getBalance'
2
3
4
5
6
7
8
9
10
11
Среда песочницы:
// Управление балансом водителей
curl -X POST
-H "Content-Type: application/json"
-H "Authorization: bearer {cid}|{access_token}"
-d 'json {
"fleet_id": 10000000000000,
"driver_id": 50000000000000,
"location_country": "RU",
"lang": "ru-RU"
}'
'https://open-jelly-ru-sim.didiglobal.com/biz/fleet/open-api/drivers/getBalance'
2
3
4
5
6
7
8
9
10
11
Примечание
Для запроса к служебному API требуется domain + "/biz" + api_url Не забудьте "/biz"
# Проверка безопасности
Метод: POST
URL: /oauth/token
Функция: Oauth2.0-проверка
Запрашиваемые параметры:
| Название параметра | Тип | Описание |
|---|---|---|
| grant_type | string | Режим запроса. Поддерживаются только два режима.. i.Режим клиента: client_credentials ii.Обновитьtoken: refresh_token |
| scope | string | Список запрашиваемых прав доступа. |
| _ | string | Текущее время, формат — «2006-01-02T15:04:05-0700», 10 мин. Не проверяется в тестовой среде |
| nostr | string | Случайная строка, 6 симв., сочетание цифр и букв (без учета регистра) |
| refresh_token | string | Поле refresh_token появляется при запросе token (Требуется для обновления) |
Диапазоны значений Scope
| Значение Scope | Описание |
|---|---|
| fleet | fleet функции |
token запроса:
curl -X POST -H "Content-Type: application/json"
-H "Authorization: Bearer {cid}|{sign}"
-d '{"grant_type":"client_credentials","_":"2016-07-01T10:00:00+0800""nostr":"123abc"}'
'https://open-jelly-ru.didiglobal.com/oauth/token'
2
3
4
token обновления:
curl -X POST -H "Authorization: Bearer {cid}|{sign}"
-H "Content-Type: application/json"
-d '{"grant_type":"refresh_token","refresh_token":"43713d0303-49c60a08fe-835c9fc1fe","_":"2016-07-01T11:00:00+0800","nostr":"123abc"}'
'https://open-jelly-ru.didiglobal.com/oauth/token'
2
3
4
Нормальный ответ:
| Название параметра | Тип | Описание |
|---|---|---|
| access_token | string | Токен доступа token, Должен быть предоставлен header при запросе к другим API. Сразу несколько token могут одновременно быть активны на платформе |
| refresh_token | string | token обновления, который используется, когда истекает срок действия access_token. Этот token может быть действителен только один раз. После обновления будет назначен новый refresh_token. У токена нет фиксированной даты окончания срока действия |
| expires_in_second | int | access_token — срок действия (секунды). |
| token_type | string | token — тип,bearer/mac. Поддерживается только тип bear. |
| scope | string | token Уровень доступа токена (тот же, что и запрашиваемый уровень) |
Примечание
Ограничение на частоту запросов token: платформа <= 10 раз/день; обновление <= 10 раз/день. После превышения ограничения учетная запись будет приостановлена на 24 ч.
Возвращенный результат:
Статус http
- 200 обозначает, что запрос действителен
- Не 200 указывает на ошибку запроса
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
{
"access_token": "didiCB5DEFD8086CE8EAC49CFDCFFA3BF94E66BFC287113521F868B9257E8782D0DB978B81A04133BA5968D9B15B6A4655A9B3B8E7E856ED69BC1FF5848DC784C5080523D74F1AA6B2AC310219BAD3CDE24DF60E61A83B67565B0FC63DE417858FF4",
"refresh_token": "bd01a0d243-e4a056f463-138c7a00fd",
"expires_in_second": 259200,
"token_type": "bearer",
"scope": "calling_car"
}
2
3
4
5
6
7
Описание:
- Формат данных запроса должен быть json
- header должен содержать id и подпись получающего доступ. Authorization: bearer {cid}|{sign}. bearer представляет собой тип token. cid — назначенный id получающего доступ, связанный с подписью sign через "|"
- Алгоритм подписи
Версия php
function generalCreateSign( $aData = array(), $sKey = '' )
{
if ( empty( $aData ) || ! is_string( $sKey ) ) { //Данные подписи не могут быть пустыми, и key должен быть строкой
return FALSE;
}
ksort( $aData ); //Данные подписи упорядочиваются по значению ключа в алфавитном порядке
$str = '';
foreach ( $aData as $k => $v ) {
if ( empty( $v ) && $v !== 0 ) { //Пустое значение ключа не используется в подписи
continue;
}
if ( is_array( $v ) ) {
$v = json_encode( $v );
}
$str .= trim( $k ) . '=' . trim( $v ) . '&'; //Ключ1=Значение1&Ключ2=Значение2...
}
$str = trim( $str, '&' ); //Удалить символы & с обоих концов строки
return md5( md5( $str ) . $sKey ); //2 раза md5, key — это подпись, назначенная принадлежащему получателю key
}
Версия golang
func generalCreateSign(req GetTokenReq, clientSecret string) string {
reqData := map[string]string{}
keys := []string{}
t := reflect.TypeOf(req)
v := reflect.ValueOf(req)
for i := 0; i < t.NumField(); i++ {
tag := t.Field(i).Tag.Get("json")
value := v.Field(i).String() // req Все поля типа string
reqData[tag] = value
keys = append(keys, tag)
}
// Упорядочить в алфавитном порядке
sort.Strings(keys)
sign := ""
for _, k := range keys {
if reqData[k] == "" {
continue
}
// k1=v1&k2=v2...
sign += strings.TrimSpace(k) + "=" + strings.TrimSpace(reqData[k]) + "&"
}
sign = strings.Trim(sign, "&")
withSecret := fmt.Sprintf("%x", md5.Sum([]byte(sign))) + clientSecret
return fmt.Sprintf("%x", md5.Sum([]byte(withSecret)))
}
Версия c#
public static string GenerateMD5(string txt)
{
byte[] buffer = Encoding.Default.GetBytes(txt);
byte[] newBuffer = MD5.Create().ComputeHash(buffer);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < newBuffer.Length; i++)
{
sb.Append(newBuffer[i].ToString("x2"));
}
return sb.ToString();
}
public static string GeneralCreateSign(IDictionary parameters, string secret)
{
IDictionary sortedParams = new SortedDictionary(parameters);
IEnumerator> iterator = sortedParams.GetEnumerator();
StringBuilder strBuilder = new StringBuilder();
while (iterator.MoveNext())
{
string key = iterator.Current.Key;
string value = iterator.Current.Value;
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
{
strBuilder.Append(key).Append("=").Append(value).Append("&");
}
}
string finalString = strBuilder.ToString().Trim('&');
string result = GenerateMD5(GenerateMD5(finalString) + secret);
return result;
}
Версия java
public static String Md5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
byte s[] = MessageDigest.getInstance("md5").digest(str.getBytes("UTF8"));
String Md5String = "";
for (int i = 0; i < s.length; i++) {
Md5String += Integer.toHexString((0x000000FF & s[i]) | 0xFFFFFF00).substring(6);
}
return Md5String;
}
public static Map sortMapByKey(Map map) {
if (map == null || map.isEmpty()) {
return null;
}
Map sortMap = new TreeMap(new Comparator() {
public int compare(String obj1, String obj2) {
return obj1.compareTo(obj2);//Упорядочить по возрастанию
}
});
sortMap.putAll(map);
return sortMap;
}
public static String CreateSign(Map params, String key) throws Exception {
if (key.isEmpty() || params.isEmpty()){
throw new Exception("sign key is empty or param is empty");
}
// Упорядочить
params = sortMapByKey(params);
Iterator> it = params.entrySet().iterator();
String sign = "";
while (it.hasNext()){
Map.Entry entry = it.next();
String k = entry.getKey();
String v = entry.getValue();
if (!v.isEmpty()){
sign+=k.trim()+"="+v.trim()+"&";
}
}
// Убрать конечные &
sign = sign.substring(0,sign.length()-1);
// md5
return Md5(Md5(sign)+key) ;
}