{
"controller": <имя контроллера>,
"method": <название метода>,
"params": <JSON-объект параметров>,
"meta": <JSON-объект параметров>,
"receiver": <строковое значение>
}
receiver - нужен для более точной идентификации ответа, чтобы понять, кому он предназначается. Может быть любым строковым значением.
meta - необязательный параметр, требуется для передачи серверу значений, которые должны вернуться обратно.
{
"controller": <имя контроллера>,
"method": <название метода>,
"resCode": <код возврата>,
"result": <JSON-объект результата>,
"meta": <JSON-объект параметров>,
"receiver": <строковое значение>
}
Параметр meta в ответе присутствует только тогда, когда он был в запросе. Содержит в точности то, что было в параметре meta при запросе.
В случае ошибки вместо "result" возвращается "error" - JSON-объект формата:
{
"code": 42,
"data": {
"name": "Ivanov"
},
"message": "Some errror"
}
"resCode" добавлено для совместимости со старым протоколом, показывает результат операции. Может быть 10 (положительный результат), 0 (ошибка), либо какое-то другое значение.
Полное описание всех запросов и статусов приведено ниже.
При начальном подключении к серверу выполняется ряд процедур, описанных в разделе Подключение к серверу и завершение работы. В идеале это должно выглядеть приблизительно так:
SEND
{
"controller": "auth",
"method": "auth",
"params": {
"sid": "e10adc3949ba59abbe56e057f20f883e",
"sign": "Vovan"
},
"receiver": "4"
}
RECEIVE
{
"controller": "auth",
"method": "auth",
"receiver": "4",
"resCode": 10
}
SEND
{
"controller": "driver",
"method": "statusChanged",
"params": {
"status": 100
},
"receiver": "1"
}
RECEIVE
{
"controller": "driver",
"method": "statusChanged",
"receiver": "1",
"resCode": 10,
"result": {
"status": 100
}
}
SEND
{
"controller": "driverSession",
"method": "open",
"params": {
"build_abi": "x86_64-little_endian-lp64",
"os": "Linux Mint 19.1",
"sign": "Vovan",
"version": "1.0.84"
}
}
RECEIVE
{
"controller": "driverSession",
"method": "open",
"resCode": 10,
"result": {
"curVersion": "1.0.82",
"id": 1953786,
"isNewVersionAvailable": false,
"rst_id_group": 5,
"rst_id_owner": 2180,
"sign": "Vovan",
"sys_utc_offset": 180,
"utc_dt": 1555339345255,
"utc_offset": 180
}
}
Обязательным при каждом подключении является отправка сперва auth.auth, затем driver.open и в конце driver.statusChanged. При начальном подкючении driver.statusChanged меняется несколько раз через 100, 200 и заканчивается на 1000 после окончании синхронизации.
Если связь с сервером оборвалась, то нужно закрыть старый коннект (если он не закрывается автоматически) и по таймеру делать попытки нового подкючения каждые 5 сек, пока связь не будет установлена. При реконнекте повторную синхронизацию проводить не следуют. Серверу всё равно, какие команды ему пришлют. Если заново запросят синхронизацию, он ответит, но вообще это решает приложение, а ему достаточно просинхронизироваться только при старте. Поэтому после реконнета достаточно отправить три стандартные команды: auth.auth, driver.open, driver.statusChanged. Статус водителя отправлять тот, который текущий. Скажем, если он был занят, то отправлять 2200.
Пытаемся законнектиться...
Try to connect to 127.0.0.1:40500...
Try to connect to 127.0.0.1:40500...
Try to connect to 127.0.0.1:40500...
Try to connect to 127.0.0.1:40500...
Try to connect to 127.0.0.1:40500...
Соединение установлено!!!
SEND
{
"controller": "auth",
"method": "auth",
"params": {
"sid": "e10adc3949ba59abbe56e057f20f883e",
"sign": "Vovan"
},
"receiver": "4"
}
SEND
{
"controller": "driverSession",
"method": "open",
"params": {
"build_abi": "x86_64-little_endian-lp64",
"os": "Linux Mint 19.1",
"sign": "Vovan",
"version": "1.0.84"
}
}
RECEIVE
{
"controller": "auth",
"method": "auth",
"receiver": "4",
"resCode": 10
}
RECEIVE
{
"controller": "driverSession",
"method": "open",
"resCode": 20,
"result": {
"curVersion": "1.0.82",
"id": 1953786,
"isNewVersionAvailable": false,
"rst_id_group": 5,
"rst_id_owner": 2180,
"sign": "Vovan",
"sys_utc_offset": 180,
"utc_dt": 1555339935893,
"utc_offset": 180
}
}
Статус водителя текущий!!!
SEND
{
"controller": "driver",
"method": "statusChanged",
"params": {
"status": 2200
},
"receiver": "1"
}
RECEIVE
{
"controller": "driver",
"method": "statusChanged",
"receiver": "1",
"resCode": 10,
"result": {
"status": 2200
}
}
Каждые 20 сек на сервер отправляется запрос driverSession.ping для проверки, что сервер доступен и может адекватно отвечать. После отправки запроса запускается таймер на 5 сек. Если в течение этого времени сервер не ответил, коннект закрывается. Далее всё, как обычно. То есть по срабатыванию закрытия коннекта запускается таймер с попытками нового коннекта каждые 5 сек.
После успешного получения ответа на запрос driverSession.open сервер каждые 5 сек начнёт присылать запрос:
{
"controller": "driverSession",
"method": "ping"
}
Нужно ответить серверу запросом:
{
"controller": "driverSession",
"method": "pong"
}
Если в течение 10 сек после отправки driverSession.ping сервер не получит driverSession.pong, соединение будет разорвано.
Заключение. При любом закрытии коннекта (то ли со стороны сервера, то ли по таймауту с нашей стороны, то ли из-за пропажи интернета или плохой связи, то ли при перелогинивании), надо всегда после нового коннекта проводить процедуру инициализации из трёх запросов: auth.auth, driverSession.open, driver.statusChaged.
Требуется отправить метод sync для заданного контроллера с параметром time.
{
"controller": "orderCompletedType",
"method": "sync",
"params": {
"time": 1571748153000
},
"receiver": "8"
}
{
"controller":"orderCompletedType",
"method":"sync",
"receiver":"8",
"resCode":10,
"result":{
"removed":[
25,
27
],
"changed":[
{
"code": 2020,
"description": "",
"enabled": true,
"id": 23,
"initiator_type": "drivers",
"name": "Сломался",
"order_status": 1900,
"rst_id_company": 12,
}
]
}
}
При изменении синхронизируемых данных на сервере будут приходить события создания записей, обновления и удаления:
Параметры в этих событиях точно такие же, как в ответах на запросы синхронизации.
Пример для компаний:
{
"controller": "company",
"method": "created",
"result": {
"company_name": "Боярка",
"hexagon_grid_center": "50.455408, 30.357034",
"hexagon_radius": 1,
"id": 13,
"utc_offset": 120,
"uuid_company": "{089ad0a0-0477-44e2-9016-2ccbab532a02}",
"city": "Боярка",
"rating_company": 5,
"logo": ""
}
}
{
"controller": "company",
"method": "updated",
"result": {
"company_name": "Боярка",
"hexagon_grid_center": "50.455408, 30.357034",
"hexagon_radius": 1,
"id": 13,
"utc_offset": 120,
"uuid_company": "{089ad0a0-0477-44e2-9016-2ccbab532a02}",
"city": "Боярка",
"rating_company": 5,
"logo": ""
}
}
{
"controller": "company",
"method": "removed",
"result": {
"id": 37
}
}
{
"controller": "company",
"method": "sync",
"params": {
"time": 0
},
"receiver": "8"
}
{
"controller": "company",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"company_name": "Мухосранск",
"hexagon_grid_center": "50.455408, 30.357034",
"hexagon_radius": 1,
"id": 15,
"utc_offset": 120,
"uuid_company": "{e567a0ae-5235-4832-b2d0-27bdde5c69ec}",
"city": "Мухосранск",
"rating_company": 5,
"logo": ""
},
{
"company_name": "Боярка",
"hexagon_grid_center": "50.455408, 30.357034",
"hexagon_radius": 1,
"id": 13,
"utc_offset": 120,
"uuid_company": "{089ad0a0-0477-44e2-9016-2ccbab532a02}",
"city": "Боярка",
"rating_company": 5,
"logo": ""
},
{
"company_name": "Киев",
"hexagon_grid_center": "50.455408, 30.357034",
"hexagon_radius": 1,
"id": 12,
"utc_offset": 120,
"uuid_company": "{36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"city": "Киев",
"rating_company": 5,
"logo": ""
}
],
"removed": []
}
}
{
"controller": "zone",
"method": "sync",
"params": {
"time": 0
},
"receiver": "8"
}
{
"controller": "zone",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"color_zone": "#ce5c00",
"coords_vertex": "(50.45488103, 30.35934448),(50.45815975, 30.40603638),(50.43935869, 30.44792175),(50.42076891, 30.46337128),(50.39779498, 30.42423248),(50.42404999, 30.36518097)",
"enabled": 1,
"id": 342,
"is_default": 0,
"name": "Борщаговка",
"rst_id_company": 12,
"uuid_zone": "{eb2ae44a-679a-4a20-a2f6-ebffecc0c945}",
"zone_priority": 0
},
{
"color_zone": "#75507b",
"coords_vertex": "(50.45706687, 30.35453796),(50.49246334, 30.35659790),(50.49988887, 30.36552429),(50.47760879, 30.41221619),(50.45968974, 30.40878296)",
"enabled": 1,
"id": 343,
"is_default": 0,
"name": "Нивки",
"rst_id_company": 12,
"uuid_zone": "{55a7ed06-9fb4-4936-9952-25b5dd103eff}",
"zone_priority": 0
},
{
"color_zone": "#73d216",
"coords_vertex": "(50.42910787, 30.34681320),(50.43397387, 30.34921646),(50.43555931, 30.35367966),(50.43599666, 30.36174774),(50.43298978, 30.37217617),(50.42629193, 30.37402153),(50.42219073, 30.35505295)",
"enabled": 1,
"id": 346,
"is_default": 0,
"name": "Электронмаш",
"rst_id_company": 12,
"uuid_zone": "{6ed4a549-67ad-4baa-bfee-a799454dd74c}",
"zone_priority": 0
}
],
"removed": []
}
}
{
"controller": "tariffZone",
"method": "sync",
"params": {
"time": 0
},
"receiver": "8"
}
{
"controller": "tariffZone",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"count_km_free": 1,
"count_km_free_to_client": 0,
"count_start_sum": 1,
"count_tm_downtime_free": 1,
"count_tm_downtime_free_to_client": 0,
"count_tm_downtime_wait_on_start_free": 1,
"count_tm_up_time_free": 1,
"count_tm_up_time_free_to_client": 0,
"id": 125,
"is_default": 1,
"name": "Грабёж",
"price_min_trip": "2",
"price_set_taxi": "10",
"prices_km": "1=5",
"prices_km_on_move_penalty": "1=0",
"prices_km_on_move_to_client": "1=0",
"prices_km_on_return": "1=0",
"prices_penalty_drv_after_accepted": "1=0",
"prices_tm_on_downtime": "1=10",
"prices_tm_on_downtime_on_move_to_client": "1=5",
"prices_tm_on_downtime_penalty": "1=0",
"prices_tm_on_downtime_return": "1=9",
"prices_tm_on_up_time": "1=0",
"prices_tm_on_up_time_on_move_to_client": "1=0",
"prices_tm_on_up_time_penalty": "1=0",
"prices_tm_on_up_time_return": "1=0",
"prices_tm_wait_on_start": "1=12",
"rst_id_company": 12,
"speed_margin_km": "10=1",
"start_sum": "0.00",
"use_move_to_client_mode": 0,
"use_on_return_mode": 0,
"use_penalty_mode": 0,
"use_prices_tm_on_downtime": 1,
"use_prices_tm_on_downtime_on_move_to_client": 1,
"use_prices_tm_on_downtime_on_return": 1,
"use_prices_tm_on_downtime_penalty": 0,
"uuid_tz": "{069ecb1e-bd29-4ae7-ae82-b2ba240d3d69}"
},
{
"count_km_free": 1,
"count_km_free_to_client": 0,
"count_start_sum": 1,
"count_tm_downtime_free": 1,
"count_tm_downtime_free_to_client": 0,
"count_tm_downtime_wait_on_start_free": 1,
"count_tm_up_time_free": 1,
"count_tm_up_time_free_to_client": 0,
"id": 128,
"is_default": 1,
"name": "Default tariff of zone_08:51:18.641",
"price_min_trip": "0.00",
"price_set_taxi": "0.00",
"prices_km": "1=0",
"prices_km_on_move_penalty": "1=0",
"prices_km_on_move_to_client": "1=0",
"prices_km_on_return": "1=0",
"prices_penalty_drv_after_accepted": "1=0",
"prices_tm_on_downtime": "1=0",
"prices_tm_on_downtime_on_move_to_client": "1=0",
"prices_tm_on_downtime_penalty": "1=0",
"prices_tm_on_downtime_return": "1=0",
"prices_tm_on_up_time": "0.7=2;0.7=7",
"prices_tm_on_up_time_on_move_to_client": "1=0",
"prices_tm_on_up_time_penalty": "1=0",
"prices_tm_on_up_time_return": "1=0",
"prices_tm_wait_on_start": "1=0",
"rst_id_company": 13,
"speed_margin_km": "10=1",
"start_sum": "0.00",
"use_move_to_client_mode": 0,
"use_on_return_mode": 0,
"use_penalty_mode": 0,
"use_prices_tm_on_downtime": 0,
"use_prices_tm_on_downtime_on_move_to_client": 0,
"use_prices_tm_on_downtime_on_return": 0,
"use_prices_tm_on_downtime_penalty": 0,
"uuid_tz": "{ed421dcc-a832-4cd5-92e9-b512f6d3accc}"
},
{
"count_km_free": 1,
"count_km_free_to_client": 0,
"count_start_sum": 1,
"count_tm_downtime_free": 1,
"count_tm_downtime_free_to_client": 0,
"count_tm_downtime_wait_on_start_free": 1,
"count_tm_up_time_free": 1,
"count_tm_up_time_free_to_client": 0,
"id": 126,
"is_default": 0,
"name": "Стандарт",
"price_min_trip": "3",
"price_set_taxi": "20",
"prices_km": "1=2;2=5",
"prices_km_on_move_penalty": "1=0",
"prices_km_on_move_to_client": "1=0",
"prices_km_on_return": "1=0",
"prices_penalty_drv_after_accepted": "1=0",
"prices_tm_on_downtime": "1=0",
"prices_tm_on_downtime_on_move_to_client": "1=5",
"prices_tm_on_downtime_penalty": "1=0",
"prices_tm_on_downtime_return": "1=20",
"prices_tm_on_up_time": "0.7=2;3=9",
"prices_tm_on_up_time_on_move_to_client": "1=0",
"prices_tm_on_up_time_penalty": "1=0",
"prices_tm_on_up_time_return": "1=0",
"prices_tm_wait_on_start": "1=0;2=2",
"rst_id_company": 12,
"speed_margin_km": "10=1",
"start_sum": "30",
"use_move_to_client_mode": 0,
"use_on_return_mode": 0,
"use_penalty_mode": 0,
"use_prices_tm_on_downtime": 1,
"use_prices_tm_on_downtime_on_move_to_client": 1,
"use_prices_tm_on_downtime_on_return": 1,
"use_prices_tm_on_downtime_penalty": 0,
"uuid_tz": "{b42f7c92-2908-4012-b072-024602e009b5}"
}
],
"removed": []
}
}
{
"controller": "firstTariff",
"method": "sync",
"params": {
"time": 0
},
"receiver": "8"
}
{
"controller": "firstTariff",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"color_4_drv": "#cccccc",
"f_km_free": "0",
"f_km_free_on_move_to_client": "0",
"f_max_radius": "3",
"f_tm_downtime_free": 0,
"f_tm_downtime_free_on_move_to_client": 0,
"f_tm_downtime_wait_on_start_free": 0,
"f_tm_up_time_free": "0",
"f_tm_up_time_free_on_move_to_client": "0",
"id": 85,
"is_default": 0,
"max_dist": "4",
"note_for_driver": "0",
"rst_id_company": 12,
"tariff_enabled": 1,
"tariff_name": "Стандарт",
"type_inf_client_car_not_found": 0,
"type_inf_client_car_set": 0,
"use_color_4_drv": 0,
"uuid_ft": "{04a3b3eb-68a8-4442-9670-8c2f15458f68}"
}
],
"removed": []
}
}
{
"controller": "secondTariff",
"method": "sync",
"params": {
"time": 0
},
"receiver": "8"
}
{
"controller": "secondTariff",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"id": 3525,
"rst_id_company": 12,
"rst_id_ft": 84,
"rst_id_tz": 126,
"rst_id_zone": 342,
"uuid_st": "{2e2d79c0-4094-4da7-8634-ceee171ff671}"
},
{
"id": 3526,
"rst_id_company": 12,
"rst_id_ft": 86,
"rst_id_tz": 125,
"rst_id_zone": 342,
"uuid_st": "{bcbf7a69-5f5a-4c67-9f86-641fd95fb353}"
},
{
"id": 3527,
"rst_id_company": 12,
"rst_id_ft": 86,
"rst_id_tz": 125,
"rst_id_zone": 343,
"uuid_st": "{96e97379-4aa4-461c-9ae1-d83eb124e9a0}"
},
{
"id": 3528,
"rst_id_company": 12,
"rst_id_ft": 86,
"rst_id_tz": 125,
"rst_id_zone": 341,
"uuid_st": "{c6bfc8e8-38d7-476f-b0ae-759061ec5c71}"
},
{
"id": 3529,
"rst_id_company": 13,
"rst_id_ft": 88,
"rst_id_tz": 128,
"rst_id_zone": 345,
"uuid_st": "{87419f80-4d1b-4355-9d18-a59606c427c5}"
},
{
"id": 3530,
"rst_id_company": 12,
"rst_id_ft": 84,
"rst_id_tz": 125,
"rst_id_zone": 346,
"uuid_st": "{f35e5225-9ec9-486b-a43d-06bc551045dd}"
},
{
"id": 3532,
"rst_id_company": 12,
"rst_id_ft": 86,
"rst_id_tz": 125,
"rst_id_zone": 346,
"uuid_st": "{9862dc22-f4d2-40a7-8726-367058598b40}"
},
{
"id": 3522,
"rst_id_company": 12,
"rst_id_ft": 85,
"rst_id_tz": 125,
"rst_id_zone": 342,
"uuid_st": "{df3e7583-4389-4aa7-9f62-06a04815e17c}"
},
{
"id": 3531,
"rst_id_company": 12,
"rst_id_ft": 85,
"rst_id_tz": 126,
"rst_id_zone": 346,
"uuid_st": "{0380d1d9-c3fb-41ec-b043-0b56f7d3be23}"
}
],
"removed": []
}
}
{
"controller": "tariffScheduleSet",
"method": "sync",
"params": {
"time": 0
},
"receiver": "8"
}
{
"controller": "tariffScheduleSet",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"description_drv": "",
"enabled": 1,
"id": 107,
"is_default": 0,
"name": "Микроавтобус",
"queue_autoassign": 0,
"rst_id_company": 13,
"uuid_tss": "{d67251fa-c267-4fc5-ad54-decbf19a1635}"
},
{
"description_drv": "",
"enabled": 1,
"id": 108,
"is_default": 0,
"name": "Драйвер",
"queue_autoassign": 0,
"rst_id_company": 13,
"uuid_tss": "{1e8be2b1-ee75-4682-bef4-7fd584738a8a}"
},
{
"description_drv": "",
"enabled": 1,
"id": 102,
"is_default": 1,
"name": "Стандарт",
"queue_autoassign": 0,
"rst_id_company": 13,
"uuid_tss": "{c4e13bba-59c8-450f-a625-49a08d2d42bd}"
},
{
"description_drv": "",
"enabled": 1,
"id": 96,
"is_default": 0,
"name": "Драйвер",
"queue_autoassign": 0,
"rst_id_company": 12,
"uuid_tss": "{c4244e9b-2686-4bda-b044-a4652441c65a}"
},
{
"description_drv": "",
"enabled": 1,
"id": 94,
"is_default": 1,
"name": "Defualt order type",
"queue_autoassign": 0,
"rst_id_company": 12,
"uuid_tss": "{191e3177-c481-4c53-9904-26639f60d03a}"
},
{
"description_drv": "",
"enabled": 1,
"id": 95,
"is_default": 0,
"name": "Стандарт",
"queue_autoassign": 0,
"rst_id_company": 12,
"uuid_tss": "{a1666397-314c-413d-a4b9-8ffe302e697a}"
}
],
"removed": []
}
}
{
"controller": "tariffSchedule",
"method": "sync",
"params": {
"time": 0
},
"receiver": "8"
}
{
"controller": "tariffSchedule",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"id": 661,
"rst_id_company": 12,
"rst_id_tss": 96,
"start_time": 0,
"uuid_ts": "{0b6cd09b-b198-4428-9464-405c79aba322}",
"week_day": 1
},
{
"id": 662,
"rst_id_company": 12,
"rst_id_tss": 96,
"start_time": 0,
"uuid_ts": "{86c5bb14-a1fe-498d-b19d-3184e259d751}",
"week_day": 2
},
{
"id": 663,
"rst_id_company": 12,
"rst_id_tss": 96,
"start_time": 0,
"uuid_ts": "{e003ca39-a4b1-4df5-b8e6-a048ed833847}",
"week_day": 3
},
{
"id": 664,
"rst_id_company": 12,
"rst_id_tss": 96,
"start_time": 0,
"uuid_ts": "{4d80041e-942a-43c3-898e-f4c30a2b2a39}",
"week_day": 4
},
{
"id": 665,
"rst_id_company": 12,
"rst_id_tss": 96,
"start_time": 0,
"uuid_ts": "{2c932753-9c58-4fd7-ab4c-42ddfbc3ccb4}",
"week_day": 5
},
{
"id": 666,
"rst_id_company": 12,
"rst_id_tss": 96,
"start_time": 0,
"uuid_ts": "{095770b7-0f36-4426-987b-ddab3e50ee94}",
"week_day": 6
},
{
"id": 667,
"rst_id_company": 12,
"rst_id_tss": 96,
"start_time": 0,
"uuid_ts": "{0ae30459-8a24-45c3-8738-68f706abb4ea}",
"week_day": 7
}
],
"removed": []
}
}
{
"controller": "tariffScheduleRule",
"method": "sync",
"params": {
"time": 0
},
"receiver": "8"
}
{
"controller": "tariffScheduleRule",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"description_4_drv": "",
"id": 655,
"op_prior": 999,
"op_type": "def",
"op_var": "",
"op_var_period": 0,
"rst_id_company": 12,
"rst_id_ft": 84,
"rst_id_ts": 655,
"uuid_tsr": "{935dbdb1-e194-49dd-be40-28d7c1311559}",
"value": ""
},
{
"description_4_drv": "",
"id": 656,
"op_prior": 999,
"op_type": "def",
"op_var": "",
"op_var_period": 0,
"rst_id_company": 12,
"rst_id_ft": 84,
"rst_id_ts": 656,
"uuid_tsr": "{c3b3a411-dcbb-4564-add1-255fe8d257c5}",
"value": ""
},
{
"description_4_drv": "",
"id": 657,
"op_prior": 999,
"op_type": "def",
"op_var": "",
"op_var_period": 0,
"rst_id_company": 12,
"rst_id_ft": 84,
"rst_id_ts": 657,
"uuid_tsr": "{834a02c3-131f-4c91-8693-ec3f042ac780}",
"value": ""
},
{
"description_4_drv": "",
"id": 658,
"op_prior": 999,
"op_type": "def",
"op_var": "",
"op_var_period": 0,
"rst_id_company": 12,
"rst_id_ft": 84,
"rst_id_ts": 658,
"uuid_tsr": "{baabad14-fb6e-4db5-ace3-b87c9ef900ee}",
"value": ""
},
{
"description_4_drv": "",
"id": 659,
"op_prior": 999,
"op_type": "def",
"op_var": "",
"op_var_period": 0,
"rst_id_company": 12,
"rst_id_ft": 84,
"rst_id_ts": 659,
"uuid_tsr": "{7b953d2a-307c-4bab-b460-456d241a12a8}",
"value": ""
},
{
"description_4_drv": "",
"id": 660,
"op_prior": 999,
"op_type": "def",
"op_var": "",
"op_var_period": 0,
"rst_id_company": 12,
"rst_id_ft": 84,
"rst_id_ts": 660,
"uuid_tsr": "{a56c067b-71e9-405e-83b7-779d4b900500}",
"value": ""
}
],
"removed": []
}
}
{
"controller": "orderCompletedType",
"method": "sync",
"params": {
"time": 1571748153000
},
"receiver": "8"
}
{
"controller": "orderCompletedType",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"removed": [
25,
27
],
"changed": [
{
"code": 2020,
"description": "",
"enabled": true,
"id": 23,
"initiator_type": "drivers",
"name": "Сломался",
"order_status": 1900,
"rst_id_company": 12,
}
]
}
}
От сервера приходит сообщение order.statusChanged с параметрами заказа. Есть статус водителя (свободен, занят, на заказе), а есть статус заказа. Обычно в статусе заказа передаётся только код заказа, но человек, который эту систему придумал, решил почему-то запихать туда всё. Поэтому там может быть что угодно.
Здесь и далее order.statusChanged в запросе от сервера и в ответе могут совпадать. Чтобы различать, запрос это или ответ, нужно смотреть параметр receiver. Если этого параметра нет, то order.statusChanged является запросом от сервера. Если receiver есть, значит, это ответ на наш запрос об изменении статуса.
{
"controller": "order",
"method": "statusChanged",
"result": {
"RECEIVER_srv": "8517",
"additional_sum": "0",
"assumed_feed_time": "0",
"assumed_feed_way": "2.53",
"back_way": "0",
"calculate_route_distance": "3.091",
"calculate_route_price": "101.155",
"client_bonuses": "2236.04",
"client_name": "Вован Сидорович Щербатый",
"client_num_trips": "458",
"client_register_time": "1536304026012",
"coefficient": "1",
"debt": "100",
"distance_penalty": "0",
"drv_sign": "Vovan",
"dt_feed_time": "1568297636855",
"dt_feed_time0": "0",
"dt_feed_time1": "0",
"feed_address": "Зодчих, 7",
"feed_city": "Киев",
"feed_city_wp0": "Киев",
"feed_city_wp1": "Боярка",
"feed_is_fuzzy": "1",
"feed_is_fuzzy0": "0",
"feed_is_fuzzy1": "0",
"feed_lat": "0",
"feed_lat0": "50.4196",
"feed_lat1": "50.3077",
"feed_lon": "0",
"feed_lon0": "30.3723",
"feed_lon1": "30.3027",
"feed_note_for_driver0": "",
"feed_note_for_driver1": "",
"feed_num_house0": "7",
"feed_num_house1": "17",
"feed_num_porch0": "",
"feed_num_porch1": "",
"feed_street0": "Зодчих",
"feed_street1": "Амбулаторная",
"fto": "420",
"id": "2652",
"id_order_disp": "954",
"identifier": "0991234567",
"is_auto_assign": "1",
"is_autoassign_feed_endpoint": "0",
"is_booking": "0",
"is_cancel_reputation_penalty": "0",
"is_free": "0",
"is_user_fixed_cost": "1",
"note_drv": "",
"order_creator": "operator",
"order_creator_os": "unknown",
"order_point0": "1",
"order_point1": "2",
"order_status_srv": 800,
"payment_type": "0",
"preorder_additional_sum": "110",
"pto": "0",
"route": "[{\"lat\":50.419712,\"lon\":30.372472},{\"lat\":50.420196,\"lon\":30.371694},{\"lat\":50.420908,\"lon\":30.370587},{\"lat\":50.421192,\"lon\":30.370192},{\"lat\":50.421473,\"lon\":30.369848},{\"lat\":50.42162,\"lon\":30.369693},{\"lat\":50.421762,\"lon\":30.369545},{\"lat\":50.42204,\"lon\":30.369272},{\"lat\":50.422342,\"lon\":30.368966},{\"lat\":50.422568,\"lon\":30.368773},{\"lat\":50.422888,\"lon\":30.368512},{\"lat\":50.423093,\"lon\":30.368438},{\"lat\":50.423179,\"lon\":30.368426},{\"lat\":50.423294,\"lon\":30.368453},{\"lat\":50.423399,\"lon\":30.368529},{\"lat\":50.423572,\"lon\":30.368652},{\"lat\":50.423624,\"lon\":30.368685},{\"lat\":50.42372,\"lon\":30.368722},{\"lat\":50.423861,\"lon\":30.368765},{\"lat\":50.42394,\"lon\":30.368774},{\"lat\":50.424018,\"lon\":30.368765},{\"lat\":50.424149,\"lon\":30.368731},{\"lat\":50.424264,\"lon\":30.368677},{\"lat\":50.424482,\"lon\":30.368524},{\"lat\":50.424511,\"lon\":30.368505},{\"lat\":50.424559,\"lon\":30.368424},{\"lat\":50.313628,\"lon\":30.302825},{\"lat\":50.313456,\"lon\":30.303555},{\"lat\":50.313177,\"lon\":30.30437},{\"lat\":50.312941,\"lon\":30.304863},{\"lat\":50.312726,\"lon\":30.304885},{\"lat\":50.312426,\"lon\":30.304863},{\"lat\":50.312065,\"lon\":30.304845},{\"lat\":50.311224,\"lon\":30.304198},{\"lat\":50.311118,\"lon\":30.30411},{\"lat\":50.310873,\"lon\":30.303874},{\"lat\":50.310816,\"lon\":30.303798},{\"lat\":50.310721,\"lon\":30.303673},{\"lat\":50.310608,\"lon\":30.303583},{\"lat\":50.310501,\"lon\":30.3035},{\"lat\":50.30982,\"lon\":30.302964},{\"lat\":50.309611,\"lon\":30.302846},{\"lat\":50.309256,\"lon\":30.303218},{\"lat\":50.308521,\"lon\":30.302761},{\"lat\":50.308113,\"lon\":30.302589},{\"lat\":50.307724,\"lon\":30.302484}]",
"rst_id_terminal_cmp": 4,
"service":"[{\"abs_sum\":100,\"name\":\"Курить в салоне\",\"relative_sum\":0.1},{\"abs_sum\":40,\"name\":\"Молчаливый водитель\",\"relative_sum\":0},{\"abs_sum\":250,\"name\":\"Ведро котов в салоне\",\"relative_sum\":0.2}]"
"sum": "0",
"user_fixed_cost": "200",
"uuid_company": "{36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"uuid_ft": "{3563eace-ef3b-477d-a382-511673846ee8}",
"uuid_order0": "{e03b2c93-9abb-4eb3-8c72-ed1723876bf7}",
"uuid_order1": "{e03b2c93-9abb-4eb3-8c72-ed1723876bf7}",
"uuid_order_srv": "{e03b2c93-9abb-4eb3-8c72-ed1723876bf7}",
"uuid_tss": "{191e3177-c481-4c53-9904-26639f60d03a}",
"zn_feed_time": "180"
}
}
Затем нужно сообщить серверу, что заказ сохранён на таксе (путём установки статуса 900)
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "8",
"order_status_clt": 900,
"uuid_order_clt": "{07c1c603-52a4-4867-acb9-00606e1a5b35}"
},
"receiver": "7"
}
{
"controller": "order",
"method": "statusChanged",
"receiver": "8"
}
Самый простой вариант работы с полученным заказом - это просто его отклонить. Для этого нужно передать серверу статус 1100.
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "9",
"order_status_clt": 1100,
"uuid_order_clt": "{07c1c603-52a4-4867-acb9-00606e1a5b35}"
},
"receiver": "7"
}
{
"controller": "order",
"method": "statusChanged",
"receiver": "9"
}
Это пример совпадения названия метода. receiver есть, поэтому обрабатываем, как ответ.
После этого нужно отправить запрос завершения заказа с кодом завершения 9040.
{
"controller": "order",
"method": "completeOrder",
"params": {
"completed_code": 9040,
"uuid_order": "{a1d28776-4d87-4224-b078-ff95fcf8e867}"
},
"receiver": "1"
}
{
"controller": "order",
"method": "completeOrder",
"receiver": "1",
"result": {
"uuid_order": "{a1d28776-4d87-4224-b078-ff95fcf8e867}"
}
}
Сервер пришлёт новый статус 1300, что сервер разрешает отменить заказ (случаев, когда не разрешает, никогда не бывает): { "controller": "order", "method": "statusChanged", "result": { "RECEIVER_srv": "1026", "order_status_srv": 1300, "uuid_order_srv": "{a1d28776-4d87-4224-b078-ff95fcf8e867}" } }
Отвечаем на него традиционно: { "controller": "order", "method": "confirmStatusChanged", "params": { "RECEIVER": "1026" }, "receiver": "7" }
Начальная стадия описана в разделе Обработка заказа. Получение. Всё точно так же вплоть до отправки на сервер сообщения order.statusChanged с кодом 900. Затем, если водитель решил принять заказ, на сервер отправляется запрос об изменении статуса на 1200 (водитель принял заказ).
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "13",
"order_status_clt": 1200,
"uuid_order_clt": "{07c1c603-52a4-4867-acb9-00606e1a5b35}"
},
"receiver": "7"
}
{
"controller": "order",
"method": "statusChanged",
"receiver": "13"
}
Статус водителя нужно установить на 2000 (занят на заказе).
{
"controller": "driver",
"method": "statusChanged",
"params": {
"status": 2000
},
"receiver": "1"
}
{
"controller": "driver",
"method": "statusChanged",
"receiver": "1",
"resCode": 10,
"result": {
"status": 2000
}
}
С этого момента запускается таймер, и такс начинает периодически отправлять на сервер текущую стоимость поездки (каждые 10 сек). В некоторых тарифах засчитывается даже время движения машины до пассажира, поэтому считать сумму поездки надо всегда, начиная с того момента, как водитель принял заказ на выполнение.
{
"controller": "order",
"method": "setSum",
"params": {
"sum": 21.02,
"uuid_order": "{07c1c603-52a4-4867-acb9-00606e1a5b35}"
},
"receiver": "7"
}
Отсутствует.
Далее водитель начинает выполнять заказ и по ходу работы отправляет на сервер новые статусы заказа:
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "15",
"order_status_clt": 1700,
"uuid_order_clt": "{07c1c603-52a4-4867-acb9-00606e1a5b35}"
},
"receiver": "7"
}
{
"controller": "order",
"method": "statusChanged",
"receiver": "15"
}
Точно так же для статусов 1900, 2100, 2400, 3000.
Установка статуса 3000 означает, что заказ фактические выполнен. Нужно остановить таймер отправки на сервер запроса order.setSum и отправить на сервер последний статус 3500.
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "20",
"order_status_clt": 3500,
"sum": 57.025001525878906,
"sum_tip": 57.03,
"uuid_order_clt": "{b94cebeb-3354-4b4a-b8bb-b31efe8de471}"
},
"receiver": "7"
}
{
"controller": "order",
"method": "statusChanged",
"receiver": "20"
}
Теперь нужно отправить на сервер статистику о поездке по зонам.
{
"controller": "order",
"method": "completeOrder",
"params": {
"amt_free_km0": "0",
"amt_free_km1": "0",
"amt_free_km2": "0",
"amt_free_tm_down_time0": "0",
"amt_free_tm_down_time1": "0",
"amt_free_tm_down_time2": "0",
"amt_free_tm_up_time0": "0",
"amt_free_tm_up_time1": "0",
"amt_free_tm_up_time2": "0",
"amt_km0": "0",
"amt_km1": "0",
"amt_km2": "0",
"amt_km_free_on_move_to_client0": "0",
"amt_km_free_on_move_to_client1": "0",
"amt_km_free_on_move_to_client2": "0",
"amt_km_on_move_penalty0": "0",
"amt_km_on_move_penalty1": "0",
"amt_km_on_move_penalty2": "0",
"amt_km_on_move_to_client0": "0",
"amt_km_on_move_to_client1": "0",
"amt_km_on_move_to_client2": "0",
"amt_km_on_return0": "0",
"amt_km_on_return1": "0",
"amt_km_on_return2": "0",
"amt_penalty_drv_after_accepted0": "0",
"amt_penalty_drv_after_accepted1": "0",
"amt_penalty_drv_after_accepted2": "0",
"amt_tm_on_downtime0": "0",
"amt_tm_on_downtime1": "0",
"amt_tm_on_downtime2": "0",
"amt_tm_on_downtime_common0": "0",
"amt_tm_on_downtime_common1": "0",
"amt_tm_on_downtime_common2": "0",
"amt_tm_on_downtime_common_return0": "0",
"amt_tm_on_downtime_common_return1": "0",
"amt_tm_on_downtime_common_return2": "0",
"amt_tm_on_downtime_on_move_to_client0": "0",
"amt_tm_on_downtime_on_move_to_client1": "0",
"amt_tm_on_downtime_on_move_to_client2": "0",
"amt_tm_on_downtime_penalty0": "0",
"amt_tm_on_downtime_penalty1": "0",
"amt_tm_on_downtime_penalty2": "0",
"amt_tm_on_downtime_return0": "0",
"amt_tm_on_downtime_return1": "0",
"amt_tm_on_downtime_return2": "0",
"amt_tm_on_up_time0": "0",
"amt_tm_on_up_time1": "0",
"amt_tm_on_up_time2": "5",
"amt_tm_on_up_time_on_move_to_client0": "0",
"amt_tm_on_up_time_on_move_to_client1": "0",
"amt_tm_on_up_time_on_move_to_client2": "1",
"amt_tm_on_up_time_penalty0": "0",
"amt_tm_on_up_time_penalty1": "0",
"amt_tm_on_up_time_penalty2": "0",
"amt_tm_on_up_time_return0": "0",
"amt_tm_on_up_time_return1": "0",
"amt_tm_on_up_time_return2": "0",
"amt_tm_up_time_free_on_move_to_client0": "0",
"amt_tm_up_time_free_on_move_to_client1": "0",
"amt_tm_up_time_free_on_move_to_client2": "0",
"amt_tm_wait_on_start0": "0",
"amt_tm_wait_on_start1": "0",
"amt_tm_wait_on_start2": "0",
"completed_code": 9000,
"dt_client_update0": "0",
"dt_client_update1": "0",
"dt_client_update2": "0",
"dt_utc_last_update0": "1544779321636",
"dt_utc_last_update1": "1544779321637",
"dt_utc_last_update2": "1544779342313",
"min_trip0": "0",
"min_trip1": "0",
"min_trip2": "1",
"price_tm_on_downtime0": "0",
"price_tm_on_downtime1": "0",
"price_tm_on_downtime2": "0",
"price_tm_on_downtime_return0": "0",
"price_tm_on_downtime_return1": "0",
"price_tm_on_downtime_return2": "0",
"rst_id_owner0": "2",
"rst_id_owner1": "2",
"rst_id_owner2": "2",
"rst_id_user_locked0": "1",
"rst_id_user_locked1": "1",
"rst_id_user_locked2": "1",
"rst_id_zone0": "11",
"rst_id_zone1": "12",
"rst_id_zone2": "13",
"set_taxi0": "0",
"set_taxi1": "0",
"set_taxi2": "1",
"start_sum0": "0",
"start_sum1": "0",
"start_sum2": "0",
"sum": "57.025001525878906",
"sum_speed_margin_km0": "0",
"sum_speed_margin_km1": "0",
"sum_speed_margin_km2": "0",
"uuid_order": "{07c1c603-52a4-4867-acb9-00606e1a5b35}",
"uuid_st0": "{0fd5d900-b32b-465c-a822-513e29cfefac}",
"uuid_st1": "{2e2d79c0-4094-4da7-8634-ceee171ff671}",
"uuid_st2": "{48919405-d9fe-4549-9bb7-de4f8f731ba5}"
},
"receiver": "1"
}
{
"controller": "order",
"method": "completeOrder",
"receiver": "1",
"result": {
"uuid_order": "{07c1c603-52a4-4867-acb9-00606e1a5b35}"
}
}
Напоследок надо перевести статус водителя в 1000, то есть снова свободен.
{
"controller": "driver",
"method": "statusChanged",
"params": {
"status": 1000
},
"receiver": "1"
}
{
"controller": "driver",
"method": "statusChanged",
"receiver": "1",
"resCode": 10,
"result": {
"status": 1000
}
}
Иногда бывает, что заказ отменяется не водителем, а диспетчерской службой, когда он находится у водителя на выполнении. Тогда приходит запрос order.confirmCompleteOrder (описан выше). Нужно ответить серверу и вывести сообщение, что заказ завершён с кодом completed_code (из запроса), после чего остановить таймер отправки order.setSum и отправить на сервер запрос driver.statusChanged со статусом 1000.
Когда водителю приходит заказ, запускается таймер таймаута, в течение которого он этот заказ может или принять, или отказаться. Если машина движется, то таймаут 45 сек, иначе 30 Движение машины определяется так: если скорость больше 1.38 м/с, то есть 5 км/ч, то машина движется, иначе стоит.
Типичные ситуации при получения заказа уже описыны выше, но теперь можно обобщить с учётом наступления таймаута.
Пришёл заказ
RECEIVE
{
"controller": "order",
"method": "statusChanged",
"result": {
"RECEIVER_srv": "1063",
"additional_sum": "0",
"assumed_feed_time": "0",
"assumed_feed_way": "0",
"back_way": "0",
"client_name": "Вован Сидорович Щербатый",
"coefficient": "1.5",
"distance_penalty": "0",
"drv_sign": "Vovan",
"dt_feed_time": "1547195931467",
"dt_feed_time0": "0",
"feed_address": "Зодчих, 7",
"feed_city": "Киев",
"feed_city_wp0": "Киев",
"feed_is_fuzzy": "1",
"feed_is_fuzzy0": "1",
"feed_lat": "0",
"feed_lat0": "50.4196",
"feed_lon": "0",
"feed_lon0": "30.3723",
"feed_note_for_driver0": "",
"feed_num_house0": "7",
"feed_num_porch0": "",
"feed_street0": "Зодчих",
"fto": "420",
"id_order_disp": "143",
"identifier": "0991234567",
"is_auto_assign": "0",
"is_booking": "0",
"is_cancel_reputation_penalty": "0",
"is_free": "0",
"note_drv": "",
"order_creator": "operator",
"order_creator_os": "unknown",
"order_point0": "1",
"order_status_srv": 800,
"payment_type": "0",
"preorder_additional_sum": "110",
"pto": "0",
"rst_id_terminal_cmp": 4,
"sum": "0",
"uuid_company": "{36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"uuid_ft": "{3563eace-ef3b-477d-a382-511673846ee8}",
"uuid_order0": "{18c728de-87f2-40a9-b50f-267fbed3fef1}",
"uuid_order_srv": "{18c728de-87f2-40a9-b50f-267fbed3fef1}",
"uuid_tss": "{191e3177-c481-4c53-9904-26639f60d03a}",
"zn_feed_time": "120"
}
}
Подтверждаем, чтобы больше его не присылали.
SEND
{
"controller": "order",
"method": "confirmStatusChanged",
"params": {
"RECEIVER": "1063"
},
"receiver": "7"
}
Отсылаем статус 900, что заказ поступил на такс
SEND
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "63",
"order_status_clt": 900,
"uuid_order_clt": "{18c728de-87f2-40a9-b50f-267fbed3fef1}"
},
"receiver": "7"
}
Сервер обработал
RECEIVE
{
"controller": "order",
"method": "statusChanged",
"receiver": "63"
}
..........
Проходит 30 или 45 сек. Никто ничего не нажимает.
Такс выводит сообщение, что время принятия заказа истекло, и когда водила нажмёт ОК, то уберёт заказ с экрана. И одновременно, сразу после вывода диалога (или до этого), отправляет статус 1105, что заказ пропущен.
SEND
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "64",
"order_status_clt": 1105,
"uuid_order_clt": "{18c728de-87f2-40a9-b50f-267fbed3fef1}"
},
"receiver": "7"
}
Сервер обрабатывает
RECEIVE
{
"controller": "order",
"method": "statusChanged",
"receiver": "64"
}
Такс устанавливает статус водителя в 2100. Новые заказы он теперь принимать не будет, пока не водитель не поставит статус 1000.
SEND
{
"controller": "driver",
"method": "statusChanged",
"params": {
"status": 2100
},
"receiver": "1"
}
Сервер обработал запрос
RECEIVE
{
"controller": "driver",
"method": "statusChanged",
"receiver": "1",
"resCode": 10,
"result": {
"status": 2100
}
}
С этого момента водила в пролёте для заказов, пока не догадается поменять свой статус.
Если заказ завершается в статусе 3500, то завершение состоит из двух этапов:
Если заказ завершается в ином статусе, тогда делается запрос только из пункта 2.
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "464",
"order_status_clt": 3500,
"sum": 0,
"sum_tip": 32.8,
"uuid_order_clt": "{9178e61c-5e85-4f77-91c8-28f9559b1bd6}"
},
"receiver": "7"
}
{
"controller": "order",
"method": "statusChanged",
"receiver": "464"
}
В качестве receiver сервер вернул посланное ему RECEIVER_clt.
Сразу после этого на сервер нужно отправить новый статус водителя 1000, то есть свободен для следующих заказов.
{
"controller": "driver",
"method": "statusChanged",
"params": {
"status": 1000
},
"receiver": "1"
}
{
"controller": "driver",
"method": "statusChanged",
"receiver": "1",
"resCode": 10,
"result": {
"status": 1000
}
}
Расчёт делается по таймеру, каждую секунду. В старом таксе для этого использовался отдельный поток, который непрерывно работает на всём протяжении выполнения заказа, пока он не будет завершён. В процессе работы потока в нём выполняется бесконечный цикл, в котором делается какой-то расчёт, затем поток засыпает на 1 секунду, после чего цикл начинается сначала. Прерывается цикл установкой триггера, когда считать больше не нужно (водитель завершил заказ, отменил или загрузил другой). Упрощённо это выглядит так (псевдо-С++):
double price = 0
bool stop = false
// Запускаем в отдельном потоке.
while (!stop) {
price += veryBigCalcFunction()
sleep(1)
}
По мере рассчёта мы забираем price, показываем на экране и отправляем на сервер. Для выхода из цикла устанавливаем в основном потоке stop = true. sleep(1) нужен, чтобы процессор не бегал по циклу, тратя на это все свободные ресурсы, а занимался этим один раз в секунду.
Теперь подробно.
Все расчёты в старом таксе делает класс TaxCounter. Это что-то наподобие синглтона. При загрузке заказа в память такса (путём создания нового или получения из базы) происходит инициализация TaxCounter. Сперва там выключается расчёт предыдущего заказа (установкой флага stop = true) на случай, если предыдущий был не завершён, а просто заменён другим. Затем туда передаётся id заказа (здесь и далее я буду употреблять id, хотя вместо него можно использовать и uuid) и его статус. По этому id загружаются данные firstTariff, но не из основной таблицы, полученной в результате синхронизации, а из той, где сохраняются снапшоты данных для каждого заказа (описанные в разделе документации "Снапшоты тарифов и зон для заказа"). Точно таким же образом по этому id загружатся копии secondTariff, сохранённые для этого заказа.
Количество записей secondTariff будет столько же, сколько зон у компании. Нужно пройтись по ним циклом, проинициализировать структуру данных (в старом таксе она называется TZItem), в которой будут храниться текущие значения расчётных параметров по каждой зоне, после чего записать её в массив.
При инициализации каждого TZItem происходит следующее:
В TZItem загружаются из СНАПШОТОВ (!!!) заказа параметры secondTariff, zone и tariffZone. Также загружается полигон (список координат) зоны и записи TZA для этой зоны.
TZA - это таблица в базе (в старом таксе называется tbl_order_tza), куда сохраняются расчётные данные текущей суммы заказа. При создании заказа в таблицу TZA добавляется столько записей, сколько в тарифе зон, и пока машина едет через зоны, в строки таблицы сохраняются накопленные расчётные значения. Если такс был перезапущен или был загружен другой заказ, то можно продолжить расчёт с предыдущего места, просто загрузив в TZItem расчётные данные TZA, сохранённые в базе ранее. Текущие значения TZA сохраняются в базу при каждом изменении статуса заказа.
Далее в TZItem заполняются данные для tariffZone (из загруженного ранее снапшота):
Utils::tariffString2map(m_tz.model()->getValue("speed_margin_km"), speed_margin_km);
Utils::tariffString2map(m_tz.model()->getValue("prices_km"), prices_km);
Utils::tariffString2map(m_tz.model()->getValue("prices_km_on_return"), prices_km_on_return);
Utils::tariffString2map(m_tz.model()->getValue("prices_km_on_move_to_client"), prices_km_on_move_to_client);
Utils::tariffString2map(m_tz.model()->getValue("prices_km_on_move_penalty"), prices_km_on_move_penalty);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_wait_on_start"), prices_tm_wait_on_start);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_on_up_time"), prices_tm_on_up_time);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_on_downtime"), prices_tm_on_downtime);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_on_up_time_return"), prices_tm_on_up_time_return);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_on_downtime_return"), prices_tm_on_downtime_return);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_on_up_time_on_move_to_client"), prices_tm_on_up_time_on_move_to_client);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_on_downtime_on_move_to_client"), prices_tm_on_downtime_on_move_to_client);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_on_up_time_penalty"), prices_tm_on_up_time_penalty);
Utils::tariffString2map(m_tz.model()->getValue("prices_tm_on_downtime_penalty"), prices_tm_on_downtime_penalty);
Utils::tariffString2map(m_tz.model()->getValue("prices_penalty_drv_after_accepted"), prices_penalty_drv_after_accepted);
speed_margin_km, prices_km и прочие - это мапы типа QMap<double,double>. В них конвертируется строка вида 1=0;2=1.5 из значений tariffZone. Ключём будет число до =, значением - число после =. В приведённом выше примере в мапе будет два double значения.
Расшифровывается эта строка следующим образом: 1=0 - до 1 км стоимость 0 грн. 2=1.5 - от 1 до 2 км - стоимость 1.5 грн. за км. больше 2 км - тоже 1.5 грн за км.
То есть правильно это интерпретировать так: до 1 км пути цена бесплата, а свыше - по 1.5 грн. за км. Чаще всего это относится к случаям, когда водитель едет к клиенту по нестандартной местности. Скажем, в лесу или в зоне АТО. Чтобы было не так страшно ехать, клиент оплатит даже тот километраж, который накрутил водила, пока к нему добирался.
Аналогично со временем. Строка вроде 5=0;6=1.5 будет означать: 5=0 - до 5 мин - бесплатно (например, ожидание клиента, пока тот соизволит погрузиться в машину) 6=1.5 - до 6 мин - 1.5 грн. за мин. И, поскольку, третьего параметра нет, то от 6 до бесконечности - тоже 1,5 грн. за мин.
И напоследок обнуляются переменные, в которые будет записываться расчёт:
resultes["set_taxi"] = 0.0;
resultes["min_trip"] = 0.0;
resultes["start_sum"] = 0.0;
resultes["speed_margin_km"] = 0.0;
resultes["km"] = 0.0;
resultes["km_on_return"] = 0.0;
resultes["km_on_move_to_client"] = 0.0;
resultes["km_on_move_penalty"] = 0.0;
resultes["tm_wait_on_start"] = 0.0;
resultes["tm_on_up_time"] = 0.0;
resultes["tm_on_downtime"] = 0.0;
resultes["tm_on_up_time_return"] = 0.0;
resultes["tm_on_downtime_return"] = 0.0;
resultes["tm_on_up_time_on_move_to_client"] = 0.0;
resultes["tm_on_downtime_on_move_to_client"] = 0.0;
resultes["tm_on_up_time_penalty"] = 0.0;
resultes["tm_on_downtime_penalty"] = 0.0;
resultes["penalty_drv_after_accepted"] = 0.0;
current_prices["speed_margin_km"] = 0.0;
current_prices["km"] = 0.0;
current_prices["km_on_return"] = 0.0;
current_prices["km_on_move_to_client"] = 0.0;
current_prices["km_on_move_penalty"] = 0.0;
current_prices["tm_wait_on_start"] = 0.0;
current_prices["tm_on_up_time"] = 0.0;
current_prices["tm_on_downtime"] = 0.0;
current_prices["tm_on_up_time_return"] = 0.0;
current_prices["tm_on_downtime_return"] = 0.0;
current_prices["tm_on_up_time_on_move_to_client"] = 0.0;
current_prices["tm_on_downtime_on_move_to_client"] = 0.0;
current_prices["tm_on_up_time_penalty"] = 0.0;
current_prices["tm_on_downtime_penalty"] = 0.0;
current_prices["penalty_drv_after_accepted"] = 0.0;
resultes и current_prices - это тоже мапы.
Ещё в цикле инициализации списка TZtem делается проверка параметра is_default на 1 по снапшоту зоны. Такой TZtem становится текущим и дефолтовым. Возможно, это и не нужно вообще.
Инициализация закончена.
Расчёт делится на две части - стоимость километра пути и стоимость минуты пути. В начале цикла с датчика считываются GPS-координаты (latitude, longitude) и устанавливается статус заказа. Эти показатели общие для обоих частей расчёта.
По GPS-координатам определяется, в какой зоне находится машина. Зона представляет из себя полигон координат, находящихся в параметре coords_vertex снапшота zone. Делается это тупым перебором всех TZItem в списке и проверкой, попадает ли координата GPS внутрь полигона зоны. Если так получилось, что координата попала в несколько зон одновременно (скажем, есть большая зона, а в ней несколько маленьких - тогда мы сразу будем в друх зонах, большой и какой-то маленькой), то текущей зоной выберется та, которая обладает наивысшим приоритетом, то есть лежит в слоях зон выше всех. Приоритет содержится в параметре zone_priority из снапшота зоны. Такой TZItem становится текущим и все расчёты делаются только с ним.
Если зона изменилась по сравнению с прошлой координатой, то нужно отобразить на экране новую текущую зону и сделать текущим другой TZItem.
Затем проверяется, не слишком ли низкая скорость у машины (параметр наподобие speed с датчика GPS). Если speed < 1.38 м/с (5 км/ч), то координата игнорируется. Также, если установлен статус заказа 2600 или 2601 (водитель поставил заказ на паузу), то расчёт прекращается.
Если уже есть предыдущая координата, то вычисляется дельта между предыдущей и текущей.
Затем в расчёте старого такса стоит загадочный код:
if (delta_dist > 0.5) {//increased from 0.2 to 0.5 08.06.18
delta_dist = 0;
points.clear();
}
Пока непонятно, что это означает. Похоже, если расстояние между соседними точками больше 500 метров, то дельта обнуляется и все точки тоже обнуляются. Как следствие, вычисление между ними уже не проводится.
Дальше будет фигурировать мапа total_amt, которая находится в TaxCounter (на самом деле в классе TZSet, а он уже непосредственно в TaxCounter, но это почти одно и то же). У total_amt имеются следующие поля (взято из обнуления мапы, функция totalAmt2Zero(); это из другого места, будет описано ниже):
total_amt["amt_km_free_on_move_to_client"] = 0.0;
total_amt["amt_tm_up_time_free_on_move_to_client"] = 0;
total_amt["amt_free_km"] = 0.0;
total_amt["amt_free_tm_up_time"] = 0;
total_amt["amt_free_tm_down_time"] = 0;
total_amt["amt_km"] = 0.0;
total_amt["amt_km_on_return"] = 0.0;
total_amt["amt_km_on_move_to_client"] = 0.0;
total_amt["amt_km_on_move_penalty"] = 0.0;
total_amt["amt_tm_wait_on_start"] = 0;
total_amt["amt_tm_on_up_time"] = 0;
total_amt["amt_tm_on_downtime"] = 0;
total_amt["amt_tm_on_downtime_common"] = 0;
total_amt["price_tm_on_downtime"] = 0;
total_amt["amt_tm_on_up_time_return"] = 0;
total_amt["amt_tm_on_downtime_return"] = 0;
total_amt["amt_tm_on_downtime_common_return"] = 0;
total_amt["price_tm_on_downtime_return"] = 0;
total_amt["amt_tm_on_up_time_on_move_to_client"] = 0;
total_amt["amt_tm_on_downtime_on_move_to_client"] = 0;
total_amt["amt_tm_on_up_time_penalty"] = 0;
total_amt["amt_tm_on_downtime_penalty"] = 0;
total_amt["amt_penalty_drv_after_accepted"] = 0;
По сути это те же параметры, что снапшотах firstTariff и tariffZone, собранные в кучу, только с префиксом amt. То есть, если в firstTariff указаны единицы измерения, скажем, f_km_free_on_move_to_client = 1.5 грн. за км, то в том же amt_km_free_on_move_to_client, после того, как водитель проехал 3 км, будет значение 4,5 (3 * 1.5).
Проверяется статус заказа. Проще сперва показать код старого такса, а потом попробовать его прокомментировать.
if ("1700" == order_status) {//mode: move to client
if ((tz_set->m_order_ft.model()->getValue("f_km_free_on_move_to_client").toFloat() >
tz_set->getTotalAmtTS().value("amt_km_free_on_move_to_client").toFloat())
) {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_km_free_on_move_to_client", delta_dist);
}
else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_km_on_move_to_client", delta_dist);
}
}
else if ("2400" == order_status) {//(start mode with client)
if ((tz_set->m_order_ft.model()->getValue("f_km_free").toFloat() >
tz_set->getTotalAmtTS().value("amt_free_km").toFloat())
&& ("1" == tz_set->cur_tzi->m_tz.model()->getValue("count_km_free")) ) {//free km handling
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_free_km", delta_dist);
}
else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_km", delta_dist);
}
}
else if ("2800" == order_status) {//Back way
if ((tz_set->m_order_ft.model()->getValue("f_km_free").toFloat() >
tz_set->getTotalAmtTS().value("amt_free_km").toFloat()) &&
("1" == tz_set->cur_tzi->m_tz.model()->getValue("count_km_free")) ) {//free km handling
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_free_km", delta_dist);
} else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_km_on_return", delta_dist);
}
}
Если статус 1700 (движение к клиенту), то берётся f_km_free_on_move_to_client из снапшота firstTariff и сравнивается с amt_km_free_on_move_to_client из мапы total_amt. Если f_km_free_on_move_to_client больше, то к amt_km_free_on_move_to_client добавляется дельта. А если меньше, то дельта добавляется к amt_km_on_move_to_client. Физический смысл этой операции таков: пока машина не превысила лимит бесплатной поездки до клиента, указанного в f_km_free_on_move_to_client, то считаются свободные (то есть бесплатные) километры пути в amt_km_free_on_move_to_client, иначе считаются платные километры в amt_km_on_move_to_client.
Если статус 2400 (водила везёт клиента), то всё точно так же, как в предыдущем случае, только делается дополнительная проверка на count_km_free. Я так понимаю, клиент тоже может несколько первых километров ехать бесплатно, но это опционально и может быть включено/выключено флагом count_km_free.
Если статус 2800 (водила везёт клиента обратно), то аналогично прошлому случаю, только платные километры записываются в amt_km_on_return.
Все показатели записываются в TZItem текущей зоны, по которой едет машина, разумеется.
В том же цикле, но чуть дальше, считаются свободные или несвободные минуты пути. Сперва снова код. Здесь всё уже немного посерьёзнее.
delta_tm = qint64 ((el_timer.elapsed() - prev_tick) * 0.001);
prev_tick = el_timer.elapsed();
if ("1700" == order_status) {//mode: move to client
if (tz_set->m_order_ft.model()->getValue("f_tm_up_time_free_on_move_to_client").toLongLong() >
tz_set->getTotalAmtTS().value("amt_tm_up_time_free_on_move_to_client").toLongLong()
) {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_up_time_free_on_move_to_client", delta_tm);
}
else {
if ("1" == tz_set->cur_tzi->m_tz.model()->getValue("use_prices_tm_on_downtime_on_move_to_client")) {
if (isMoving()) {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_up_time_on_move_to_client", delta_tm);
}
else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_downtime_on_move_to_client", delta_tm);
}
}
else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_up_time_on_move_to_client", delta_tm);
}
}
}
else if ("2200" == order_status ||
"2300" == order_status) {//mode: on place
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_wait_on_start", delta_tm);
}
else if ("2400" == order_status) {//(start mode with client)
if ("1" == tz_set->cur_tzi->m_tz.model()->getValue("use_prices_tm_on_downtime")) {
if (isMoving()) {//uptime
//save common price of dontime before reset
tz_set->cur_tzi->m_tza.addDeltaValueTS("price_tm_on_downtime",
tz_set->cur_tzi->getResultesTS().value("tm_on_downtime").toFloat());
tz_set->cur_tzi->m_tza.addDeltaValueTS("price_tm_on_downtime_return",
tz_set->cur_tzi->getResultesTS().value("tm_on_downtime_return").toFloat());
//reset 'amt_tm_on_downtime' and 'amt_tm_on_downtime_return'
tz_set->cur_tzi->m_tza.setValueTS("amt_tm_on_downtime", "0");
tz_set->cur_tzi->m_tza.setValueTS("amt_tm_on_downtime_return", "0");
if (( qint64(tz_set->m_order_ft.model()->getValue("f_tm_up_time_free").toFloat()*60) >
tz_set->getTotalAmtTS().value("amt_free_tm_up_time").toLongLong() ) &&
("1" == tz_set->cur_tzi->m_tz.model()->getValue("count_tm_up_time_free")) ) {//free up tm handling
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_free_tm_up_time", delta_tm);
}
else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_up_time", delta_tm);
}
}
else {//downtime
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_downtime", delta_tm);
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_downtime_common", delta_tm);
//REMOVE IT LATER!!!!
// if (tz_set->cur_tzi->m_tza.getValueTS("amt_tm_on_downtime").toLongLong()>65) {
// tz_set->cur_tzi->m_tza.addDeltaValueTS("price_tm_on_downtime",
// tz_set->cur_tzi->getResultesTS().value("tm_on_downtime").toFloat());
// tz_set->cur_tzi->m_tza.setValueTS("amt_tm_on_downtime", "0");
// }
}
}
else {
if ( (qint64(tz_set->m_order_ft.model()->getValue("f_tm_up_time_free").toFloat()*60) >
tz_set->getTotalAmtTS().value("amt_free_tm_up_time").toLongLong() ) &&
("1" == tz_set->cur_tzi->m_tz.model()->getValue("count_tm_up_time_free")) ) {//free up tm handling
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_free_tm_up_time", delta_tm);
} else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_up_time", delta_tm);
}
}
} else if ("2800" == order_status) {//back way
if ("1" == tz_set->cur_tzi->m_tz.model()->getValue("use_prices_tm_on_downtime_on_return")) {
if (isMoving()) {//uptime
//save common price of dontime before reset
tz_set->cur_tzi->m_tza.addDeltaValueTS("price_tm_on_downtime",
tz_set->cur_tzi->getResultesTS().value("tm_on_downtime").toFloat());
tz_set->cur_tzi->m_tza.addDeltaValueTS("price_tm_on_downtime_return",
tz_set->cur_tzi->getResultesTS().value("tm_on_downtime_return").toFloat());
//reset 'amt_tm_on_downtime' and 'amt_tm_on_downtime_return'
tz_set->cur_tzi->m_tza.setValueTS("amt_tm_on_downtime", "0");
tz_set->cur_tzi->m_tza.setValueTS("amt_tm_on_downtime_return", "0");
if (( qint64(tz_set->m_order_ft.model()->getValue("f_tm_up_time_free").toFloat()*60) >
tz_set->getTotalAmtTS().value("amt_free_tm_up_time").toLongLong() ) &&
("1" == tz_set->cur_tzi->m_tz.model()->getValue("count_tm_up_time_free")) ) {//free up tm handling
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_free_tm_up_time", delta_tm);
} else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_up_time_return", delta_tm);
}
} else {//downtime
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_downtime_return", delta_tm);
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_downtime_common_return", delta_tm);
//REMOVE IT LATER!!!!
// if (tz_set->cur_tzi->m_tza.getValueTS("amt_tm_on_downtime_return").toLongLong()>40) {
// tz_set->cur_tzi->m_tza.addDeltaValueTS("price_tm_on_downtime_return",
// tz_set->cur_tzi->getResultesTS().value("tm_on_downtime_return").toFloat());
// tz_set->cur_tzi->m_tza.setValueTS("amt_tm_on_downtime_return", "0");
// }
}
} else {
if ( (qint64(tz_set->m_order_ft.model()->getValue("f_tm_up_time_free").toFloat()*60) >
tz_set->getTotalAmtTS().value("amt_free_tm_up_time").toLongLong() ) &&
("1" == tz_set->cur_tzi->m_tz.model()->getValue("count_tm_up_time_free")) ) {//free up tm handling
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_free_tm_up_time", delta_tm);
} else {
tz_set->cur_tzi->m_tza.addDeltaValueTS("amt_tm_on_up_time_return", delta_tm);
}
}
}
Вместо delta_dist здесь фигурирует delta_tm. Таймер el_timer запускается до начала цикла, и потом каждый цикл с него снимаются показания и записывается дельта времени в delta_dist.
Расчёт аналогичен, как для километров, только больше вариантов. Проверка на isMoving() показывает, движется ли машина. Как было показано в разделе "Отправка координат на сервер", is_moving = spd < 1.38 ? 0 : 1.
В самом конце цикла, когда собраны показания по километражу и времени, вычисляются итоговые суммы. Вот пример из старого такса:
float total_price = 0.0;
mtx_total_amt.lock();
totalAmt2Zero();
QSharedPointer<TZItem> tzi;
foreach (tzi, lst_tzi) {
{//calculate total amount
total_amt["amt_km_free_on_move_to_client"] = total_amt["amt_km_free_on_move_to_client"].toFloat()
+ tzi->m_tza.getValueTS("amt_km_free_on_move_to_client").toFloat();
total_amt["amt_tm_up_time_free_on_move_to_client"] = total_amt["amt_tm_up_time_free_on_move_to_client"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_up_time_free_on_move_to_client").toLongLong();
total_amt["amt_free_km"] = total_amt["amt_free_km"].toFloat()
+ tzi->m_tza.getValueTS("amt_free_km").toFloat();
total_amt["amt_free_tm_up_time"] = total_amt["amt_free_tm_up_time"].toLongLong()
+ tzi->m_tza.getValueTS("amt_free_tm_up_time").toLongLong();
total_amt["amt_free_tm_down_time"] = total_amt["amt_free_tm_down_time"].toLongLong()
+ tzi->m_tza.getValueTS("amt_free_tm_down_time").toLongLong();
total_amt["amt_km"] = total_amt["amt_km"].toFloat()
+ tzi->m_tza.getValueTS("amt_km").toFloat();
total_amt["amt_km_on_return"] = total_amt["amt_km_on_return"].toFloat()
+ tzi->m_tza.getValueTS("amt_km_on_return").toFloat();
total_amt["amt_km_on_move_to_client"] = total_amt["amt_km_on_move_to_client"].toFloat()
+ tzi->m_tza.getValueTS("amt_km_on_move_to_client").toFloat();
total_amt["amt_km_on_move_penalty"] = total_amt["amt_km_on_move_penalty"].toFloat()
+ tzi->m_tza.getValueTS("amt_km_on_move_penalty").toFloat();
total_amt["amt_tm_wait_on_start"] = total_amt["amt_tm_wait_on_start"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_wait_on_start").toLongLong();
total_amt["amt_tm_on_up_time"] = total_amt["amt_tm_on_up_time"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_up_time").toLongLong();
total_amt["amt_tm_on_downtime"] = total_amt["amt_tm_on_downtime"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_downtime").toLongLong();
total_amt["amt_tm_on_downtime_common"] = total_amt["amt_tm_on_downtime_common"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_downtime_common").toLongLong();
total_amt["price_tm_on_downtime"] = total_amt["price_tm_on_downtime"].toFloat()
+ tzi->m_tza.getValueTS("price_tm_on_downtime").toFloat();
total_amt["amt_tm_on_up_time_return"] = total_amt["amt_tm_on_up_time_return"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_up_time_return").toLongLong();
total_amt["amt_tm_on_downtime_return"] = total_amt["amt_tm_on_downtime_return"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_downtime_return").toLongLong();
total_amt["amt_tm_on_downtime_common_return"] = total_amt["amt_tm_on_downtime_common_return"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_downtime_common_return").toLongLong();
total_amt["price_tm_on_downtime_return"] = total_amt["price_tm_on_downtime_return"].toFloat()
+ tzi->m_tza.getValueTS("price_tm_on_downtime_return").toFloat();
total_amt["amt_tm_on_up_time_on_move_to_client"] = total_amt["amt_tm_on_up_time_on_move_to_client"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_up_time_on_move_to_client").toLongLong();
total_amt["amt_tm_on_downtime_on_move_to_client"] = total_amt["amt_tm_on_downtime_on_move_to_client"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_downtime_on_move_to_client").toLongLong();
total_amt["amt_tm_on_up_time_penalty"] = total_amt["amt_tm_on_up_time_penalty"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_up_time_penalty").toLongLong();
total_amt["amt_tm_on_downtime_penalty"] = total_amt["amt_tm_on_downtime_penalty"].toLongLong()
+ tzi->m_tza.getValueTS("amt_tm_on_downtime_penalty").toLongLong();
total_amt["amt_penalty_drv_after_accepted"] = total_amt["amt_penalty_drv_after_accepted"].toLongLong()
+ tzi->m_tza.getValueTS("amt_penalty_drv_after_accepted").toLongLong();
}
total_price += tzi->calculatePrice();
}
return total_price;
Несмотря на угрожающие размеры, код довольно простой.
Выглядит код этой функции так:
double res=0, dummy;
QMutexLocker locker(&mtx_resultes);
QMutexLocker locker1(&mtx_current_prices);
resultes["set_taxi"] = ("1" == m_tza.getValueTS("set_taxi") ) ?
m_tz.model()->getValue("price_set_taxi").toFloat() : 0.0;
resultes["min_trip"] = ("1" == m_tza.getValueTS("min_trip") ) ?
m_tz.model()->getValue("price_min_trip").toFloat() : 0.0;
resultes["start_sum"] = ("1" == m_tza.getValueTS("start_sum") ) ?
m_tz.model()->getValue("start_sum").toFloat() : 0.0;
resultes["speed_margin_km"] = 0.0;
{
resultes["km"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_km").toFloat(),
prices_km, dummy);
current_prices["km"] = dummy;
}
{
resultes["km_on_return"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_km_on_return").toFloat(),
prices_km_on_return, dummy);
current_prices["km_on_return"] = dummy;
}
{
resultes["km_on_move_to_client"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_km_on_move_to_client").toFloat(),
prices_km_on_move_to_client, dummy);
current_prices["km_on_move_to_client"] = dummy;
}
{
resultes["km_on_move_penalty"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_km_on_move_penalty").toFloat(),
prices_km_on_move_penalty, dummy);
current_prices["km_on_move_penalty"] = dummy;
}
{
resultes["tm_wait_on_start"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_tm_wait_on_start").toFloat() / 60,
prices_tm_wait_on_start, dummy);
current_prices["tm_wait_on_start"] = dummy;
}
{
resultes["tm_on_up_time"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_tm_on_up_time").toFloat() / 60,
prices_tm_on_up_time, dummy);
current_prices["tm_on_up_time"] = dummy;
}
{
resultes["tm_on_downtime"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_tm_on_downtime").toFloat() / 60,
prices_tm_on_downtime, dummy);
current_prices["tm_on_downtime"] = dummy;
}
{
resultes["tm_on_up_time_return"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_tm_on_up_time_return").toFloat() / 60,
prices_tm_on_up_time_return, dummy);
current_prices["tm_on_up_time_return"] = dummy;
}
{
resultes["tm_on_downtime_return"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_tm_on_downtime_return").toFloat() / 60,
prices_tm_on_downtime_return, dummy);
current_prices["tm_on_downtime_return"] = dummy;
}
{
resultes["tm_on_up_time_on_move_to_client"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_tm_on_up_time_on_move_to_client").toFloat() / 60,
prices_tm_on_up_time_on_move_to_client, dummy);
current_prices["tm_on_up_time_on_move_to_client"] = dummy;
}
{
resultes["tm_on_downtime_on_move_to_client"] = Utils::priceByMapInterval(m_tza.getValueTS("amt_tm_on_downtime_on_move_to_client").toFloat() / 60,
prices_tm_on_downtime_on_move_to_client, dummy);
current_prices["tm_on_downtime_on_move_to_client"] = dummy;
}
for (QVariantMap::const_iterator i = resultes.cbegin(); i!=resultes.cend(); ++i) {
res += i->toFloat();
}
res += m_tza.getValueTS("price_tm_on_downtime").toFloat();
res += m_tza.getValueTS("price_tm_on_downtime_return").toFloat();
return res;
Толкование.
resultes и current_prices - это мапы типа QVariantMap. То есть мапа, в которой ключом является QString, а значением QVariant (любое значение). Фактически, значением является double.
В set_taxi, min_trip и start_sum значения из снапшота tariffZone записываются в тех случаях, когда установлен соответствующий флаг в снапшоте TZA. Иначе записывается 0.
Предназначение функции Utils::priceByMapInterval() туманно. Расшифровать её пока не удалось. Вот её код:
double Utils::priceByMapInterval(double fValue
, const QMap<double, double> &map
, double &fCurPrice) {
double fPrice = 0.0
, fPreviosKey = 0.0;
QMap<double, double>::const_iterator i = map.constBegin();
while (i != map.constEnd()) {
if ( (fValue - (i.key() - fPreviosKey)) > 0 ) {
fPrice += (i.key() - fPreviosKey) * i.value();
fValue -= (i.key() - fPreviosKey);
fPreviosKey = i.key();
}
else {
fPrice += fValue * i.value();
fValue = 0;
break;
}
++i;
}
//count remains by last price
if (0 < fValue) {
--i;//go to last value
fPrice += fValue * i.value();
}
fCurPrice = i.value();
return fPrice;
}
Результирущее расчётное значение суммы (total_price) нужно умножить на coefficient и сложить с additional_sum, preorder_additional_sum, которые должны указываться в заказе. Обычно coefficient == 1, additional_sum == 0.
Во время синхронизации такс получает таблицы для firstTariff, secondTariff, zone и tariffZone. При каждом запуске такса эти таблицы обновляются во время синхронизации. Однако, если был принят в обработку заказ из службы такси или создан свободный заказ, то значения тарифов и зон, которые к нему были привязаны, должны остаться неизменными на всём протяжении выполнения заказа (иногда заказ может быть забронирован на несколько дней вперёд), даже в том случае, если у самой службы такси они уже изменились (вследствие инфляции, например, или каких-то праздников). Данные же, полученные при синхронизации, обновятся и будут больше не соответствовать под заказу.
Чтобы этого избежать, в старом таксе были четыре таблицы tbl_order_ft, tbl_order_st, tbl_order_zn и tbl_order_tz, в которые копировались записи для firstTariff, secondTariff, zone и tariffZone соответственно в привязке к конкретному заказу (rst_id_order). Это значит, что, когда в таблицу заказов добавляется новый заказ, то в tbl_order_ft добавляется новая запись, куда копируются данные для firstTariff (по uuid_ft), к которому привязан заказ. Точно также в secondTariff добавляется несколько записей, куда копируются все данные secondTariff (по uuid_st), связанные с заказом, а потом в zone и tariffZone.
С этого момента все данные из firstTariff, secondTariff, zone и tariffZone, которые нужны заказу (для отображения на экране или расчёте суммы поездки) будут браться из этих таблиц по rst_id_order (или uuid_order, если удобнее искать по этому полю). ЭТО КАСАЕТСЯ ТОЛЬКО ЗАКАЗА!!! В остальных случаях, когда показывается на экране список тарифов или зон, они должны браться из обычных таблиц со свежими обновлёнными данными.
Регистрация проводится в два этапа. Сперва отправляются данные на сервер, потом они подтверждаются ответом на телефонный звонок.
Для отправки данных водителя сначала нужно получить некоторые регистрационные данные от сервера:
http://localhost:5001/driver/getRegData
{
"RES": "10",
"result": {
"car_body_types": [
{
"code": "minibus",
"name": "Микроавтобус"
},
{
"code": "sedan",
"name": "Седан"
},
{
"code": "universal",
"name": "Универсал"
}
],
"car_brands": [
{
"code": "volvo",
"name": "Volvo"
},
{
"code": "volkswagen",
"name": "Volkswagen"
}
],
"car_colors": [
{
"code": "white",
"name": "Белый",
"rgb_code": "#FFFFFF"
},
{
"code": "orange",
"name": "Оранжевый",
"rgb_code": "#FFA500"
}
],
"cities": [
"Боярка",
"Ирпень"
]
}
}
После ввода водителем всех данных регистрационные данные отправляются по урлу
http://localhost:5001/driver/trSignUp?params=
{
"def_city": "Боярка",
"first_name": "Вован",
"last_name": "Щербатый",
"middle_name": "Сидорович",
"car_brand_code": "jaguar",
"body_type_code": "sedan",
"car_color_code": "lightblue",
"model": "XF",
"car_identifier": "666",
"car_year": "2000",
"car_place_amount": "42",
"phone": "0992223322",
"identification_code": "7743013901",
"password": "123456",
"recommender": "0121",
"mode": "sms"
}
Проверить оба пароля на совпадение, и если не совпадают, то выдать ошибку "Passwords doesn't match".
После отправки запроса в ответ придёт JSON либо с сигнатурой, либо с ошибкой. Если в течение 5 сек ответа не будет никакого, то выдать ошибку "Timeout HTTP request".
Вариант с сигнатурой:
{
"RES": "10",
"signature": "{d9f95f92-ae91-4bbc-bb5c-3edec6ce8da6}"
}
Вариант с ошибкой:
{
"ERRCODE": "512",
"RES": "0",
"id": ""
}
Коды возможных ошибок:
Если была получена сигнатура и регистрация была по звонку, то каждые 2 сек начинаем отправлять на сервер запрос:
http://localhost:5001/driver/trGetSign?params={"signature":"{0a330718-5f37-4cc7-9167-5ab34df80ff2}"}
В signature передать то, что получили в ответе на прошлый запрос trSignUp.
Теперь водителю на указанный телефон должен прийти звонок, на который нужно ответить и нажать ту цифру, которую скажет робот. Обычно это 1. Пока это не будет сделано, сервер на каждый запрос таймера будет возвращать ошибку с кодом 517 - номер ещё не потверждён.
{
"ERRCODE": "517",
"RES": "0",
"id": ""
}
Когда номер будет подтверждён, сервер вернёт логин и пароль:
{
"RES": "10",
"sign": "2310",
"pwd": "123456"
}
Если по истечение 5 мин по-прежнему возвращается ошибка 517, то вывести сообщение "Timeout to confirm phone number" и завершить процесс регистрации.
Если регистрация была по SMS, тогда один раз отправить запрос:
http://localhost:5001/driver/trGetSign?params={"signature":"{0a330718-5f37-4cc7-9167-5ab34df80ff2}","code":"344635"}
В запросе должен быть параметр code с кодом, который пришёл в SMS. Дальше всё точно так же, как для регистрации по звонку, за исключением того, что не будет приходить ошибки с кодом 517.
Процедура аналогична регистрации водителя в системе.
На первом этапе отправляется запрос на сброс пароля.
http://localhost:5001/driver/resetPassword?params={"phone":"0991234567","password":"123456"}
Вместо localhost подставить адрес сервера.
Сервер позвонит по номеру телефона водителя с предложением ввести цифру 1 для подтверждения. Одновременно придёт ответ:
{
"RES": "10",
"signature": "{d9f95f92-ae91-4bbc-bb5c-3edec6ce8da6}"
}
Используя сигнатуру, нужно по таймеру каждые 2 сек делать запрос:
http://localhost:5001/driver/getResetPasswordResult?params={"signature":"{d9f95f92-ae91-4bbc-bb5c-3edec6ce8da6}"}
Вместо localhost подставить адрес сервера.
Варианты ответа:
{
"RES": "10",
}
Водитель нажал кнопку 1, сброс пароля успешно завершён. В остальных случаях будет ответ с ошибкой вида:
{
"ERRCODE": "612",
"RES": "0",
"id": "0"
}
В случае, когда водитель зарегистрировался, но ни разу не подключался к серверу в течение 10 дней, либо не выходил на связь в течение трёх месяцев после последнего подключения, аккаунт переносится в архив. Его позывной при этом удаляется. При желании можно попросить сервер вернуть аккаунт из архива.
На первом этапе передаётся номер телефона водителя, чтобы проверить, возможна ли вообще разархивация.
http://localhost:5001/driver/getUnarchiveCode?params={"phone":"0991234567"}
{
"RES": "10",
"signature": "{d9f95f92-ae91-4bbc-bb5c-3edec6ce8da6}"
}
* 700 - Номер телефона не найден.
* 701 - Аккаунт не находится в архиве.
* 702 - Аккаунт заблокирован.
Если ошибки не было, то на указанный номер телефона будет отправлен код подвержения. Нужно дождаться кода, взять сигнатуру из ответа и отправить запрос с указанием сигнатуры и кода из SMS:
http://localhost:5001/driver/unarchive?params={"signature":"{d9f95f92-ae91-4bbc-bb5c-3edec6ce8da6}","code":"344635"}
{
"RES": "10",
"sign": "2310"
}
Сервер вернёт новый позывной водителя. Одновременно отправит этот же позывной в SMS на телефон водителя.
* 703 - Время для подтверждения истекло (даётся 5 мин).
* 704 - Код подтверждения не совпадает.
Чат может находиться в четырёх состояниях, которые указываются через параметр complete_stage в запросах групп чатов
Состояния 2 и 3 водитель вряд ли когда-нибудь увидит. Оно нужно больше для диспетчерской, потому что завершённый чат у водителя удаляется.
Возможны два варианта завершения чата:
Завершить можно только персональный чат.
Когда приходит запрос о завершении от диспетчерской, тогда параметр complete_stage = 1. При этом придёт системное сообщение в чат, что начата подготовка к завершению.
Когда водитель хочет сам завершить какой-то чат, он просто отправляет запрос chatGroup.complete с теми же параметрами, после чего ему придёт уведомление об удалении группы чата, а в диспетчерскую поступит системное сообщение, что водитель завершил чат.
http://localhost:5001/driver/crash?params={"sign":"3285"}
В теле запроса передать базу данных в формате Base64.
Ответ:
{
"RES": "10"
}
{
"controller": "auth",
"method": "auth",
"params": {
"sid": "e10adc3949ba59abbe56e057f20f883e",
"phone": "0991234567"
},
"receiver": "4"
}
sid - это пароль, преобразованный в хэш MD5. На Qt программа выглядит так (data - исходное строковое значение):
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(data.toUtf8(), data.toUtf8().length());
return QString(md5.result().toHex().constData());
Таким образом, нужно преобразовать строку в md5, затем в UTF-8 и затем в hex-строку.
{
"controller": "auth",
"method": "auth",
"resCode": 10,
"result": {
"sign": "0001"
}
}
"resCode" = 10 показывает, что авторизация прошла успешно.
В случае неуспеха коды ошибок для resCode:
{
"controller": "driver",
"method": "statusChanged",
"params": {
"status": 100,
"time": 1611841410007
},
"receiver": "1"
}
{
"controller": "driver",
"method": "statusChanged",
"receiver": "1",
"resCode": 10,
"result": {
"status": 100
}
}
{
"controller": "driverSession",
"method": "open",
"params": {
"build_abi": "x86_64-little_endian-lp64",
"os": "Ubuntu 18.04.1 LTS",
"sign": "Vovan",
"version": "1.0.83"
}
}
{
"controller": "driverSession",
"method": "open",
"resCode": 10,
"result": {
"curVersion": "1.0.82",
"id": 1952572,
"isNewVersionAvailable": false,
"rst_id_group": 5,
"rst_id_owner": 2180,
"sign": "Vovan",
"sys_utc_offset": 180,
"utc_dt": 1539758956427,
"utc_offset": 180
}
}
{
"controller": "driverSession",
"method": "close",
"params": {
"type_close": 3
}
}
type_close всегда 3. В коде нигде не описано, какие могут быть варианты, поэтому, скорее всего, 3 означает "по инициативе клиента".
{
"controller": "driverSession",
"method": "close",
"params": {
"type_close": 3
}
}
{
"controller": "driverSession",
"method": "closed"
}
После получения уведомления произойдёт обрыв коннекта сервером. Нужно перестать делать реконнект до следующего залогинивания, вывести сообщение, что сессия закрыта сервером, и выйти из приложения после нажатия ОК.
{
"controller": "driverSession",
"method": "ping",
"receiver": "3"
}
{
"controller": "driverSession",
"method": "ping",
"receiver": "3"
}
Используется для проверки работоспособности сервера. Должен отправляться по таймеру каждые 30 сек.
{
"controller": "driverShift",
"method": "begin",
"params": {
"expected_complete_time": 1593681300000,
"odometer": 143495
},
"receiver": "42"
}
{
"controller": "driverShift",
"method": "begin",
"resCode": 10,
"receiver": "42"
}
В случае возвращения кода ошибки 220 в ответе будет дополнительный параметр data с указанием личных данных водителя, который не закрыл смену с этой же машиной.
{
"error": {
"code": 220,
"data": {
"sign": "3285"
"first_name": "Василий",
"middle_name": "Иванович",
"last_name": "Пупкин",
}
}
}
{
"controller": "driverShift",
"method": "complete",
"params": {
"odometer": 143472,
"refueling": {
"gas": {
"cash": 34.5,
"cashless": 123.1,
"liter": 350
},
"petrol": {
"cash": 41.2,
"cashless": 70.1,
"liter": 220
}
},
"washing": {
"cash": 230.2,
"cashless": 30.7,
"cost": 12.4
},
"incidental_expenses": 432.9,
"description": "Пробил колесо"
},
"receiver": "42"
}
{
"controller": "driverShift",
"method": "complete",
"resCode": 10,
"receiver": "42"
}
{
"controller": "driverShift",
"method": "getCurrent"
}
{
"controller": "driverShift",
"method": "getCurrent",
"resCode": 10,
"result": {
"begin_time": 1594275893320,
"expected_complete_time": 1593681300000
}
}
Если begin_time = 0 и expected_complete_time = 0, то сейчас нет начатой, но незаконченной смены.
{
"controller": "driverShift",
"method": "completed"
}
{
"controller": "driverSession",
"method": "subscribe",
"params": {
"type": "map"
},
"receiver": "18"
}
Подписки на события сохраняются на сервере в базе данных. Если сервер будет перезапущен, то все данные по подпискам будут восстановлены и продолжат использоваться в рабочем режиме.
{
"controller": "driverSession",
"method": "subscribe",
"resCode": 10,
"receiver": "18"
}
{
"controller": "driverSession",
"method": "unsubscribe",
"params": {
"type": "map"
},
"receiver": "18"
}
Параметры такие же, как в driverSession.subscribe.
{
"controller": "driverSession",
"method": "unsubscribe",
"resCode": 10,
"receiver": "18"
}
{
"controller": "driver",
"method": "updateCoord",
"params": {
"alt": 0,
"course": 0,
"dt_utc_coords": 1541402207761,
"h_accuracy": 0,
"is_moving": 1,
"lat": 35.5623,
"lon": 67.7345,
"spd": 2,
"v_accuracy": 0,
"note": "This is coordinate"
},
"receiver": "1"
}
Отсутствует
{
"controller": "driver",
"method": "setFixedLocation",
"params": {
"is_fixed": true,
"lat": 43.415784,
"lon": 32.018608
},
"receiver": "1"
}
{
"controller": "driver",
"method": "setFixedLocation",
"receiver": "1",
"resCode": 10
}
{
"controller": "driver",
"method": "balanceChanged",
"result": {
"balance": 530.02
}
}
{
"controller": "driver",
"method": "lowBalance",
"receiver": "1"
}
{
"controller": "driver",
"method": "lowBalance",
"receiver": "1",
"result": {
"is_low_balance": "yes",
"balance": "-250.4",
"low_balance": 0
}
}
{
"controller": "driver",
"method": "lowBalanceOccurred",
"result": {
"balance": -4910.54,
"low_balance": 0
}
}
Те же, что в ответе запроса driver.lowBalance
{
"controller": "driver",
"method": "sos",
"params": {
"lat": 43.3452,
"lon": 12.8434
},
"receiver": "1"
}
{
"controller": "driver",
"method": "sos",
"resCode": 10
}
{
"controller": "driver",
"method": "sosToAll",
"result": {
"lat": 50.4217,
"lon": 30.3697,
"sign": "Vovan"
}
}
{
"controller": "driver",
"method": "onlineDriverStatistic",
"receiver": "1"
}
{
"controller": "driver",
"method": "onlineDriverStatistic",
"receiver": "1",
"resCode": 10,
"result": {
"amount_busy_driver": "1",
"amount_free_driver": "0"
}
}
{
"controller": "driver",
"method": "online",
"result": {
"drivers": "[{\"course\":0,\"latitude\":50.421727,\"longitude\":30.369668,\"sign\":\"1001\",\"status\":1000},{\"course\":0,\"latitude\":50.4323,\"longitude\":30.3793,\"sign\":\"1015\",\"status\":2200}]"
}
}
Уведомление приходит от сервера каждые 10 сек при наличии подписки запросом driverSession.subscribe с параметром type = "map".
{
"controller": "driver",
"method": "getProfile",
"receiver": "1"
}
{
"controller": "driver",
"method": "getProfile",
"receiver": "1",
"resCode": 10,
"result": {
"car_body_type_code": "minibus",
"car_brand_code": "jaguar",
"car_color_code": "lightblue",
"car_identifier": "666",
"car_model": "XF",
"car_place_amount": "42",
"car_year": "2000",
"first_name": "Вован",
"last_name": "Щербатый",
"middle_name": "Сидорович",
"phone": "0992121667",
"phone2": "0634445566",
"identification_code": "7743013901",
"fcm_token": "",
"rst_id_car": 24,
"rst_id_car_company": 18
}
}
{
"controller": "driver",
"method": "updateProfile",
"params": {
"phone2": "0634445566",
"identification_code": "7743013901",
"fcm_token":""
},
"receiver": "1"
}
После отправки этого запроса данные в базу не вносятся до тех пор, пока они не будут утверждены. Поэтому, если в промежутке между отправкой этого запроса и его утверждением выполнить запрос driver.getProfile, то будут получены старые данные.
{
"controller": "driver",
"method": "updateProfile",
"receiver": "1",
"resCode": 10
}
{
"controller": "driver",
"method": "deleteProfile",
"params": {
"reason": "Я устал, я ухожу"
},
"receiver": "1"
}
{
"controller": "driver",
"method": "deleteProfile",
"receiver": "1",
"resCode": 10
}
{
"controller": "driver",
"method": "profileUpdated",
"result": {
"car_body_type_code": "minibus",
"car_brand_code": "jaguar",
"car_color_code": "lightblue",
"car_identifier": "666",
"car_model": "XF",
"car_place_amount": "42",
"car_year": "2000",
"first_name": "Вован",
"last_name": "Щербатый",
"middle_name": "Сидорович",
"phone": "0991234567",
"phone2": "0634445566",
"fcm_token":"",
"rst_id_car": 24,
"rst_id_car_company": 18
}
}
Такие же, как в ответе запроса driver.getProfile. В настоящее время уведомление отправляется только при изменении параметра rst_id_car_company.
{
"controller": "driver",
"method": "updateProfileNotify",
"result": {
"approve": true
}
}
Уведомление приходит на такс, когда администраторы подтвердили или отклонили изменения профиля, выполненное запросом driver.updateProfile
Требуется для отображения аккаунта.
{
"controller": "driver",
"method": "info",
"receiver": "1"
}
{
"controller": "driver",
"method": "info",
"receiver": "1",
"resCode": 10,
"result": {
"approveness": {
"identification_code": "1234567891",
"car_model": "DZ"
},
"HURD_UPDATE": 0,
"additional_abs": "1=0",
"additional_percent": "1=0",
"alt": "0",
"alt_lv": "0",
"balance": "1089.14",
"blocked": "0",
"body_type_code": "pickup",
"body_type_name": "Пикап",
"brand_code": "daewoo",
"brand_name": "Daewoo",
"cancel_per_day": "0",
"car_identifier": "33432633",
"car_model": "запор",
"car_place_amount": "5",
"car_year": "1990",
"checked": "0",
"city_name": "Боярка",
"color_code": "brown",
"color_name": "Коричневый",
"color_rgb_code": "#8B4513",
"course": "0",
"distance_penalty": "1=0",
"dt_del": "0",
"dt_last_update_com_inf": "1540893167503",
"dt_utc_coords": "1541487499101",
"dt_utc_insert": "1539758542386",
"dt_utc_last_update": "1541488231572",
"dt_utc_status": "1541488231572",
"enabled_additional_payment": "0",
"enabled_distance_penalty": "0",
"enabled_low_balance": "0",
"first_name": "Вован",
"h_accuracy": "0",
"id": 2180,
"id_owner_modify": "2180",
"identification_code": "7743013901",
"inner_note": "",
"is_del": "0",
"is_moving": "1",
"is_stealth": "0",
"last_name": "Щербатый",
"lat": "0",
"lat_lv": "0",
"lon": "0",
"lon_lv": "0",
"low_balance": "0",
"middle_name": "Сидорович",
"override_group_additinal_payment": "0",
"override_group_distance_penalty": "0",
"override_group_low_balance": "0",
"pass_check_ver": "0",
"phone": "0991234567",
"rating": "2.33333",
"rating_count": "3",
"recommender":"0121",
"reputation":"4.8",
"rst_id_bank_card":44,
"rst_id_body_types": 8,
"rst_id_car_brands": 10,
"rst_id_car_colors": 8,
"rst_id_city": 4,
"rst_id_group": 5,
"rst_id_user_locked": 1,
"sex": "0",
"sign": "Vovan",
"spd": "2",
"status": "1000",
"status_string": "",
"system_note": "",
"trunk_volume": "666",
"use_utc_offset": "0",
"use_utc_offset_string": "",
"utc_offset": "180",
"v_accuracy": "0"
}
}
{
"controller": "driver",
"method": "getSettings",
"receiver": "1"
}
{
"controller": "driver",
"method": "getSettings",
"receiver": "1",
"resCode": 10,
"result": {
"settings": {
"value1": 42,
"value2": 43
}
}
}
{
"controller": "driver",
"method": "updateSettings",
"params": {
"settings": {
"value1": 42,
"value2": 43
}
},
"receiver": "1"
}
{
"controller": "driver",
"method": "updateSettings",
"receiver": "1",
"resCode": 10
}
{
"controller": "driver",
"method": "getConfirmCode",
"receiver": "1"
}
{
"controller": "driver",
"method": "getConfirmCode",
"result": {
"code": 436412
},
"resCode": 10,
"receiver": "1"
}
В случае успешно выполненного запроса на основной телефон водителя придёт sms с кодом подтверждения точно такой же, как в параметре code. Имея этот код, водитель по идее должен получить возможность изменить пароль через запрос driver.changePassword. Или выполнять другие методы, требующие подтверждеения по SMS.
{
"controller": "driver",
"method": "changePassword",
"params": {
"password": "e10adc3949ba59abbe56e057f20f883e"
},
"receiver": "1"
}
{
"controller": "driver",
"method": "changePassword",
"resCode": 10,
"receiver": "1"
}
{
"controller": "driver",
"method": "getRaiseReputationCost",
"receiver": "1"
}
{
"controller": "driver",
"method": "getRaiseReputationCost",
"result": {
"cost": 30
},
"resCode": 10,
"receiver": "1"
}
Выполнять этот метод надо после того, как получили код в ответе на запрос driver.getConfirmCode
{
"controller": "driver",
"method": "raiseReputation",
"receiver": "1"
}
{
"controller": "driver",
"method": "raiseReputation",
"resCode": 10,
"receiver": "1"
}
{
"controller": "driver",
"method": "getRaiseReputationStart",
"receiver": "1"
}
{
"controller": "driver",
"method": "getRaiseReputationStart",
"result": {
"time": 1593671763522
},
"resCode": 10,
"receiver": "1"
}
{
"controller": "driver",
"method": "getReputationLog",
"params": {
"last_time": 1677621600000
},
"receiver": "11"
}
{
"controller": "driver",
"method": "getReputationLog",
"receiver": "11",
"result": [
{
"delta": 0.1,
"dt_utc_insert": 1677218693243,
"note": "Для 2 в последовательности завершённых заказов (последний заказ 3695)",
"reputation": 5
},
{
"delta": -0.1,
"dt_utc_insert": 1673335538368,
"note": "Для 2 в последовательности отменённых заказов (последний заказ 3549)",
"reputation": 3.9
}
]
}
Список отсортирован по убыванию (самые новые данные вверху)
{
"controller": "driver",
"method": "reputationChanged",
"result": {
"reputation": 4.9
}
}
{
"controller": "driver",
"method": "getRatingLog",
"params": {
"last_time": 1677621600000
},
"receiver": "11"
}
{
"controller": "driver",
"method": "getRatingLog",
"receiver": "11",
"result": [
{
"delta": 0.03,
"dt_utc_insert": 1677218693243,
"note": "Заказ 3764: Очень хороший человек",
"rating": 4.1,
"score": 5
},
{
"delta": -0.03,
"dt_utc_insert": 1673335538368,
"note": "Заказ 3766: Не машина, а гроб на колёсах!!!",
"rating": 3.9,
"score": 1
}
]
}
Список отсортирован по убыванию (самые новые данные вверху)
{
"controller": "driver",
"method": "ratingChanged",
"result": {
"rating": 3.7
}
}
{
"controller": "driverDuty",
"method": "getGroups",
"receiver": "19"
}
{
"controller": "driverDuty",
"method": "getGroups",
"receiver": "19",
"result": [
{
"city": "Киев",
"hours_amount": 12,
"id": 12,
"month": 9,
"name": "Киевские",
"rst_id_company": 12,
"selected_duty_amount": 2,
"start_time": 480,
"total_duty_amount": 2,
"year": 2020
},
{
"city": "Боярка",
"hours_amount": 12,
"id": 13,
"month": 9,
"name": "Боярские",
"rst_id_company": 13,
"selected_duty_amount": 0,
"start_time": 0,
"total_duty_amount": 2,
"year": 2020
},
{
"city": "Киев",
"hours_amount": 12,
"id": 12,
"month": 10,
"name": "Киевские",
"rst_id_company": 12,
"selected_duty_amount": 0,
"start_time": 480,
"total_duty_amount": 2,
"year": 2020
}
]
}
В списке возвращаются только те группы, в которые был добавлен водитель, разбитые по месяцам. В противном случае список будет пустой. Если месяц принадлежит одной и той же группе, то id группы будет одинаковый, но с разными year и month.
Просмотр месяца для дежурств.
{
"controller": "driverDuty",
"method": "getCalendar",
"params": {
"rst_id_group": 12,
"year": 2020,
"month": 9
},
"receiver": "19"
}
{
"controller": "driverDuty",
"method": "getCalendar",
"receiver": "19",
"result": [
{
"date": 1598907600000,
"id": 2,
"selected": 1
},
{
"date": 1598994000000,
"id": 3,
"selected": 0
},
{
"date": 1599080400000,
"id": 4,
"selected": 1
},
{
"date": 1599166800000,
"id": 5,
"selected": 0
},
{
"date": 1599598800000,
"id": 10,
"selected": 0
},
{
"date": 1600117200000,
"id": 16,
"selected": 1
},
{
"date": 1600203600000,
"id": 17,
"selected": 0
},
{
"date": 1601413200000,
"id": 31,
"selected": 0
}
]
}
В списке возвращаются дни месяца от 1 до 28...31, но только те, которые можно выбрать или развыбрать запросом driverDuty.select. Все остальные дни уже, стало быть, разобраны другими водителями.
{
"controller": "driverDuty",
"method": "select",
"params": {
"rst_id_calendar": 3,
"mode": 0
},
"receiver": "19"
}
{
"controller": "driverDuty",
"method": "select",
"receiver": "19",
"resCode": 10
}
{
"controller": "driverDuty",
"method": "check",
"receiver": "19"
}
{
"controller": "driverDuty",
"method": "check",
"receiver": "19",
"resCode": 10,
"result": {
"value": 1
}
}
{
"controller": "dtc",
"method": "connect",
"params": {
"rst_id_car": 12,
"rst_id_company": 11
},
"receiver": "3"
}
{
"controller": "dtc",
"method": "connect",
"receiver": "3",
"resCode": 10
}
{
"controller": "dtc",
"method": "connectResolution",
"result": [
{
"uuid_tss": "{a1666397-314c-413d-a4b9-8ffe302e697a}",
"rst_id_car": 12,
},
{
"uuid_tss": "{191e3177-c481-4c53-9904-26639f60d03a}",
"rst_id_car": 12,
}
]
}
{
"controller": "dtc",
"method": "getConnectState",
"params": {
"rst_id_car": 12,
"uuid_tss": [
"{a1666397-314c-413d-a4b9-8ffe302e697a}",
"{191e3177-c481-4c53-9904-26639f60d03a}"
]
},
"receiver": "3"
}
{
"controller": "dtc",
"method": "getConnectState",
"result": [
{
"uuid_tss": "{a1666397-314c-413d-a4b9-8ffe302e697a}",
"enabled": true
},
{
"uuid_tss": "{191e3177-c481-4c53-9904-26639f60d03a}",
"enabled": false
}
],
"receiver": "3"
}
Запрос dtc.connect имеет смысл запрашивать только для тарифов, у которых enabled = false. Если у тарифа enabled = true, то такой тариф будет проигнорирован сервером.
{
"controller": "dtc",
"method": "getAllow",
"params": {
"rst_id_car": 12,
"rst_id_company": 11
},
"receiver": "3"
}
{
"controller": "dtc",
"method": "getAllow",
"result": {
"allow": true
},
"receiver": "3"
}
{
"controller": "dtc",
"method": "getList",
"params": {
"rst_id_car": 12,
"rst_id_company": 11
},
"receiver": "21"
}
{
"controller": "dtc",
"method": "getList",
"receiver": "21",
"result": [
{
"accepted": "1",
"drv_sign": "Vovan",
"dt_utc_insert": "1540295809323",
"dt_utc_last_update": "1541001109045",
"enabled": "1",
"id": 158584,
"rst_id_user_locked": 1,
"rst_id_car": 12,
"uuid_company": "{36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"uuid_tss": "{191e3177-c481-4c53-9904-26639f60d03a}"
},
{
"accepted": "1",
"drv_sign": "Vovan",
"dt_utc_insert": "1540295749314",
"dt_utc_last_update": "1541423047137",
"enabled": "1",
"id": 158583,
"rst_id_user_locked": 1,
"rst_id_car": 12,
"uuid_company": "{36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"uuid_tss": "{a1666397-314c-413d-a4b9-8ffe302e697a}"
}
]
}
Возвращаются только те записи, для которых tariffScheduleSet.enabled = 1
{
"controller": "dtc",
"method": "changeConnection",
"params": {
"accepted": "1",
"id": 158583
},
"receiver": "21"
}
{
"controller": "dtc",
"method": "changeConnection",
"receiver": "21",
"resCode": 10,
"result": {
"accepted": "1",
"id": 158583
}
}
{
"controller": "driverCommissionProgram",
"method": "getAll",
"receiver": "42"
}
{
"controller": "driverCommissionProgram",
"method": "getAll",
"receiver": "42",
"result": [
{
"active": true,
"current_order_count": 4,
"dt_utc_begin": 1736409655702,
"dt_utc_end": 1736719199999,
"min_rating": 3,
"min_reputation": 3,
"name": "Старая программа",
"program_commission_abs": 0,
"program_commission_rel": 0,
"program_order_count": 5,
"schedule": [
{
"end_date": 1736719199999,
"end_time": 1439,
"mode": 0,
"start_date": 1736409655702,
"start_time": 0,
"week": 0
}
],
"standard_commission_abs": -1,
"standard_commission_rel": -1
},
{
"active": false,
"current_order_count": 0,
"dt_utc_begin": 1736597349640,
"dt_utc_end": 1736719199999,
"min_rating": 1.5,
"min_reputation": 1.5,
"name": "Новая программа",
"program_commission_abs": 40,
"program_commission_rel": 3,
"program_order_count": 5,
"schedule": [
{
"end_date": 1736719199999,
"end_time": 1439,
"mode": 1,
"start_date": 1736597349640,
"start_time": 780,
"week": 16
}
],
"standard_commission_abs": 200,
"standard_commission_rel": 12
}
]
}
{
"controller": "driverCommissionProgram",
"method": "getCurrent",
"receiver": "42"
}
{
"controller": "driverCommissionProgram",
"method": "getCurrent",
"receiver": "42",
"resCode": 10,
"result": {
"current_order_count": 4,
"dt_utc_begin": 1736409655702,
"dt_utc_end": 1736719199999,
"enabled": true,
"min_rating": 3,
"min_reputation": 3,
"name": "Старая программа",
"program_commission_abs": 0,
"program_commission_rel": 0,
"program_order_count": 5,
"schedule": [
{
"end_date": 1736719199999,
"end_time": 1439,
"mode": 0,
"start_date": 1736409655702,
"start_time": 0,
"week": 0
}
],
"standard_commission_abs": -1,
"standard_commission_rel": -1
}
}
{
"controller": "driverVipStatus",
"method": "getTariffs",
"receiver": "42"
}
{
"controller": "driverVipStatus",
"method": "getTariffs",
"receiver": "42",
"resCode": 10,
"result": {
"tariffs": {
"day": 70,
"month": 700,
"week": 350
}
}
}
{
"controller": "driverVipStatus",
"method": "getAll",
"receiver": "42"
}
{
"controller": "driverVipStatus",
"method": "getAll",
"receiver": "42",
"result": [
{
"days": 2,
"dt_end": 0,
"dt_start": 0,
"id": 5
},
{
"days": 1,
"dt_end": 1770069599999,
"dt_start": 1770114275000,
"id": 6
}
]
}
{
"controller": "driverVipStatus",
"method": "getCurrent",
"receiver": "42"
}
{
"controller": "driverVipStatus",
"method": "getCurrent",
"receiver": "42",
"resCode": 10,
"result": {
"dt_end": 1770069599999
}
}
{
"controller": "driverVipStatus",
"method": "use",
"params": {
"id": 6
},
"receiver": "42"
}
{
"controller": "driverVipStatus",
"method": "use",
"receiver": "42",
"resCode": 10
}
{
"controller": "driverVipStatus",
"method": "set",
"params": {
"term": 0
},
"receiver": "42"
}
{
"controller": "driverVipStatus",
"method": "set",
"receiver": "42",
"resCode": 10
}
{
"controller": "driverVipStatus",
"method": "created",
"result": {
"days": 1,
"id": 18
}
}
{
"controller": "driverVipStatus",
"method": "removed",
"result": {
"id": 17
}
}
{
"controller": "order",
"method": "createFree",
"params": {
"uuid_ft": "{04a3b3eb-68a8-4442-9670-8c2f15458f68}"
},
"receiver": "7"
}
{
"controller": "order",
"method": "createFree",
"receiver": "7",
"resCode": 10
}
Одновременно от сервера должно прийти сообщение с характеристиками заказа
{
"controller": "order",
"method": "statusChanged",
"result": {
"RECEIVER_srv": "2",
"additional_sum": "0",
"assumed_feed_time": "0",
"assumed_feed_way": "0",
"back_way": "0",
"client_name": "Free order",
"coefficient": "1",
"debt": 100,
"distance_penalty": "0",
"drv_sign": "Vovan",
"dt_feed_time": "1541425211065",
"feed_address": "n/a",
"feed_city": "",
"feed_is_fuzzy": "1",
"feed_lat": "0",
"feed_lon": "0",
"fto": "0",
"id_order_disp": "1",
"identifier": "n/a",
"is_auto_assign": "0",
"is_booking": "0",
"is_free": "1",
"is_user_fixed_cost": "1",
"note_drv": "",
"order_creator": "mobile",
"order_creator_os": "android",
"order_status_srv": 800,
"payment_type": "0",
"preorder_additional_sum": "110",
"pto": "0",
"rst_id_terminal_cmp": 4,
"sum": "0",
"user_fixed_cost": "200",
"uuid_company": "{36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"uuid_ft": "{04a3b3eb-68a8-4442-9670-8c2f15458f68}",
"uuid_order_srv": "{9178e61c-5e85-4f77-91c8-28f9559b1bd6}",
"uuid_tss": "{4b3cd9c4-a746-40ee-abc3-7b268bc33ab5}",
"zn_feed_time": "120"
}
}
Водитель должен подтвердить этот заказ
{
"controller": "order",
"method": "confirmStatusChanged",
"params": {
"RECEIVER": "2"
},
"receiver": "7"
}
Нужно это для того, чтобы сервер не присылал бесконечно этот заказ и понял, что клиент его уже принял и обработал.
{
"controller": "driver",
"method": "clearUncompletedFreeOrders",
"receiver": "1"
}
{
"controller": "driver",
"method": "clearUncompletedFreeOrders",
"receiver": "1",
"resCode": 10
}
Сервер удаляет незавершённые свободные заказы на сервере, если есть.
Запрос производится после подключения к серверу и открытия сессии, как описано в разделе Подключение к серверу и завершение работы. Перед тем, как сделать запрос к серверу, нужно выполнить чистку таких заказов в собственной базе данных. Делается это SQL-запросом:
DELETE FROM tbl_orders WHERE is_free = 1 and is_completed = 0
{
"controller": "driver",
"method": "listOfOrders",
"params": {
"_check_uncompleted_orders": "1",
"limit": 1,
"query": [
{
"condition": "and",
"expressions": [
{
"condition": "and",
"operation": "=",
"role": "is_completed",
"value": "0"
},
{
"condition": "and",
"operation": "=",
"role": "is_free",
"value": "1"
}
]
}
]
},
"receiver": "1"
}
{
"controller": "driver",
"method": "listOfOrders",
"receiver": "1",
"resCode": 10,
"result": {
"_check_uncompleted_orders": "1",
"query": []
}
}
Запрос отправляется при переходе на экран со списком бронированных заказов. После получения ответа нужно проверить массив query. Если там есть хоть одно значение, и статус водителя не busy, то нужно вывести сообщение "Booking orders do not available with uncompleted free orders" и запретить показ списка бронированных заказов. Список бронированных заказов, таким образом, будет показываться только в статусе free и при отсутствии свободных заказов.
{
"controller": "bookingOrder",
"method": "getListAvailableBookingOrder",
"receiver": "8"
}
{
"controller": "bookingOrder",
"method": "getListAvailableBookingOrder",
"receiver": "8",
"result": [
{
"additional_sum": 0,
"assumed_feed_time": 0,
"assumed_feed_way": 0,
"back_way": 0,
"between_points": [
{
"feed_address": "Хрещатик",
"feed_city": "Киев",
"feed_is_fuzzy": 0,
"feed_lat": 50.4693056817449,
"feed_lon": 30.4177093505859,
"feed_note_for_driver": "",
"number": 2
}
],
"calculate_route_distance": 3.091,
"calculate_route_price": 27.5,
"client_bonuses": 0,
"client_name": "Вован Сидорович Щербатый",
"client_num_trips": 1439,
"client_register_time": 1536304026012,
"coefficient": 1.1,
"company_code": "",
"company_name": "Киев",
"debt": 100,
"distance_penalty": 0,
"dt_feed_time": 1638447210998,
"ep_feed_address": "Амбулаторная, 11",
"ep_feed_city": "Боярка",
"ep_feed_is_fuzzy": 0,
"ep_feed_lat": 50.3082,
"ep_feed_lon": 30.3028,
"ep_feed_note_for_driver": "",
"ep_number": 3,
"feed_address": "Зодчих, 42",
"feed_city": "Киев",
"feed_is_fuzzy": 0,
"feed_lat": 50.4319,
"feed_lon": 30.3617,
"feed_note_for_driver": "",
"fto": 420,
"id": 2652,
"id_order_disp": 3279,
"identifier": "0991234567",
"is_user_fixed_cost": 1,
"note_drv": "",
"order_creator": "operator",
"order_creator_os": "unknown",
"payment_type": 0,
"preorder_additional_sum": 110,
"pto": 0,
"service":"[{\"abs_sum\":100,\"name\":\"Курить в салоне\",\"relative_sum\":0.1},{\"abs_sum\":40,\"name\":\"Молчаливый водитель\",\"relative_sum\":0},{\"abs_sum\":250,\"name\":\"Ведро котов в салоне\",\"relative_sum\":0.2}]"
"tariff_name": "Стандарт",
"user_fixed_cost": 200,
"uuid_company": "{36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"uuid_ft": "{04a3b3eb-68a8-4442-9670-8c2f15458f68}",
"uuid_order": "{395c9275-5db2-4b40-bc10-6d09954091ed}",
"uuid_order_srv": "{395c9275-5db2-4b40-bc10-6d09954091ed}",
"uuid_tss": "{a1666397-314c-413d-a4b9-8ffe302e697a}",
"zn_feed_time": 120
}
]
}
{
"controller": "bookingOrder",
"method": "created",
"result": {
"additional_sum": 0,
"assumed_feed_time": 0,
"assumed_feed_way": 0,
"back_way": 0,
"between_points": [
{
"feed_address": "Хрещатик",
"feed_city": "Киев",
"feed_is_fuzzy": 0,
"feed_lat": 50.4693056817449,
"feed_lon": 30.4177093505859,
"feed_note_for_driver": "",
"number": 2
}
],
"calculate_route_distance": 3.091,
"calculate_route_price": 27.5,
"client_bonuses": 0,
"client_name": "Вован Сидорович Щербатый",
"client_num_trips": 1439,
"client_register_time": 1536304026012,
"coefficient": 1.1,
"company_code": "",
"company_name": "Киев",
"debt": 100,
"distance_penalty": 0,
"dt_feed_time": 1638447210998,
"ep_feed_address": "Амбулаторная, 11",
"ep_feed_city": "Боярка",
"ep_feed_is_fuzzy": 0,
"ep_feed_lat": 50.3082,
"ep_feed_lon": 30.3028,
"ep_feed_note_for_driver": "",
"ep_number": 3,
"feed_address": "Зодчих, 42",
"feed_city": "Киев",
"feed_is_fuzzy": 0,
"feed_lat": 50.4319,
"feed_lon": 30.3617,
"feed_note_for_driver": "",
"fto": 420,
"id": 2652,
"id_order_disp": 3279,
"identifier": "0991234567",
"is_user_fixed_cost": 1,
"note_drv": "",
"order_creator": "operator",
"order_creator_os": "unknown",
"payment_type": 0,
"preorder_additional_sum": 110,
"pto": 0,
"service":"[{\"abs_sum\":100,\"name\":\"Курить в салоне\",\"relative_sum\":0.1},{\"abs_sum\":40,\"name\":\"Молчаливый водитель\",\"relative_sum\":0},{\"abs_sum\":250,\"name\":\"Ведро котов в салоне\",\"relative_sum\":0.2}]"
"tariff_name": "Стандарт",
"user_fixed_cost": 200,
"uuid_company": "{36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"uuid_ft": "{04a3b3eb-68a8-4442-9670-8c2f15458f68}",
"uuid_order": "{395c9275-5db2-4b40-bc10-6d09954091ed}",
"uuid_order_srv": "{395c9275-5db2-4b40-bc10-6d09954091ed}",
"uuid_tss": "{a1666397-314c-413d-a4b9-8ffe302e697a}",
"zn_feed_time": 120
}
}
{
"controller": "bookingOrder",
"method": "removed",
"result": {
"uuid": "{a2733a04-550b-46bf-a6ab-250aaa048c3a}"
}
}
uuid - uuid заказа
{
"controller": "bookingOrder",
"method": "makeBooking",
"params": {
"uuid_order": "{d802a212-0196-446b-b29d-10032c63bff3}"
},
"receiver": "8"
}
{
"controller": "bookingOrder",
"method": "makeBooking",
"receiver": "8",
"resCode": 10
}
{
"controller": "bookingOrder",
"method": "cancelBooking",
"params": {
"uuid_order": "{d802a212-0196-446b-b29d-10032c63bff3}"
},
"receiver": "8"
}
{
"controller": "bookingOrder",
"method": "cancelBooking",
"receiver": "8",
"resCode": 10
}
{
"controller": "order",
"method": "getList",
"params": {
"filter": 0,
"last_date": 1760043600000
},
"receiver": "11"
}
{
"controller": "order",
"method": "getList",
"receiver": "11",
"result": [
{
"additional_sum": 0,
"assumed_feed_time": 0,
"assumed_feed_way": 0,
"back_way": 0,
"between_points": [],
"calculate_route_distance": 23.7098,
"calculate_route_price": 2521.6914,
"client_bonuses": 0,
"client_name": "Вован Сидорович Щербатый",
"client_num_trips": 1775,
"client_register_time": 1536304026012,
"coefficient": 1.5,
"company_code": "",
"company_name": "Боярка",
"debt": 100,
"distance_penalty": 0,
"dt_complete": 1760438171786,
"dt_feed_time": 1760083842603,
"ep_feed_address": "Крещатик, 2",
"ep_feed_city": "Киев",
"ep_feed_is_fuzzy": 0,
"ep_feed_lat": 50.4647,
"ep_feed_lon": 30.4774,
"ep_feed_note_for_driver": "",
"ep_number": 2,
"feed_address": "Белогородская, 40",
"feed_city": "Боярка",
"feed_is_fuzzy": 0,
"feed_lat": 50.3278,
"feed_lon": 30.2929,
"feed_note_for_driver": "",
"fto": 420,
"id": 3777,
"id_order_disp": 4840,
"identifier": "0991234567",
"is_user_fixed_cost": 1,
"note_drv": "",
"order_creator": "operator",
"order_creator_os": "unknown",
"payment_type": 0,
"preorder_additional_sum": 0,
"pto": 0,
"service": "[]",
"status": 3500,
"sum": 118,
"tariff_name": "Стандарт",
"user_fixed_cost": 200,
"uuid_company": "{089ad0a0-0477-44e2-9016-2ccbab532a02}",
"uuid_ft": "{c105ed51-f45a-43f6-8ea7-8f7a85e64dbf}",
"uuid_order": "{53afc456-0069-4377-aee6-a34b87e995fb}",
"uuid_order_srv": "{53afc456-0069-4377-aee6-a34b87e995fb}",
"uuid_tss": "{c4e13bba-59c8-450f-a625-49a08d2d42bd}",
"zn_feed_time": 180
}
]
}
Точно такие же, как у bookingOrder.getListAvailableBookingOrder и bookingOrder.created, но дополнительно присутствуют параметры:
{
"controller": "order",
"method": "statusChanged",
"params": {
"RECEIVER_clt": "456",
"order_status_clt": 900,
"uuid_order_clt": "{9178e61c-5e85-4f77-91c8-28f9559b1bd6}",
"time": 1611841410007
},
"receiver": "7"
}
{
"controller": "order",
"method": "statusChanged",
"receiver": "456"
}
Вместо receiver, который послал клиент (в примере это 7) сервер прислал обратно RECEIVER_clt (456). Парадокс. А просто receiver было утеряно.
{
"controller": "order",
"method": "setDriverFto",
"params": {
"fto": 7,
"order_uuid": "{9178e61c-5e85-4f77-91c8-28f9559b1bd6}"
},
"receiver": "6"
}
{
"controller": "order",
"method": "setDriverFto",
"receiver": "6",
"resCode": 10
}
{
"controller": "order",
"method": "setSum",
"params": {
"sum": 0,
"uuid_order": "{9178e61c-5e85-4f77-91c8-28f9559b1bd6}"
},
"receiver": "7"
}
Отсутствует.
{
"controller": "order",
"method": "setPaidWaiting",
"params": {
"id": 3899,
"state": 1,
"wait_sum": 15
},
"receiver": "6"
}
{
"controller": "order",
"method": "setPaidWaiting",
"receiver": "6",
"resCode": 10
}
{
"controller": "order",
"method": "getRoute",
"params": {
"uuid_order": "{9178e61c-5e85-4f77-91c8-28f9559b1bd6}"
},
"receiver": "7"
}
{
"controller": "order",
"method": "getRoute",
"receiver": "7",
"result": {
"route": "[{\"lat\":50.419712,\"lon\":30.372472},{\"lat\":50.420196,\"lon\":30.371694},{\"lat\":50.420908,\"lon\":30.370587},{\"lat\":50.421192,\"lon\":30.370192},{\"lat\":50.421473,\"lon\":30.369848},{\"lat\":50.42162,\"lon\":30.369693},{\"lat\":50.421762,\"lon\":30.369545},{\"lat\":50.42204,\"lon\":30.369272},{\"lat\":50.422342,\"lon\":30.368966},{\"lat\":50.422568,\"lon\":30.368773},{\"lat\":50.422888,\"lon\":30.368512},{\"lat\":50.423093,\"lon\":30.368438},{\"lat\":50.423179,\"lon\":30.368426},{\"lat\":50.423294,\"lon\":30.368453},{\"lat\":50.423399,\"lon\":30.368529},{\"lat\":50.423572,\"lon\":30.368652},{\"lat\":50.423624,\"lon\":30.368685},{\"lat\":50.42372,\"lon\":30.368722},{\"lat\":50.423861,\"lon\":30.368765},{\"lat\":50.42394,\"lon\":30.368774},{\"lat\":50.424018,\"lon\":30.368765},{\"lat\":50.424149,\"lon\":30.368731},{\"lat\":50.424264,\"lon\":30.368677},{\"lat\":50.424482,\"lon\":30.368524},{\"lat\":50.424511,\"lon\":30.368505},{\"lat\":50.424572,\"lon\":30.368491},{\"lat\":50.424636,\"lon\":30.368476},{\"lat\":50.42473,\"lon\":30.36847},{\"lat\":50.424797,\"lon\":30.368483},{\"lat\":50.424867,\"lon\":30.368532},{\"lat\":50.42492,\"lon\":30.368609},{\"lat\":50.424959,\"lon\":30.368702},{\"lat\":50.424985,\"lon\":30.368765},{\"lat\":50.425216,\"lon\":30.36964},{\"lat\":50.425995,\"lon\":30.372586},{\"lat\":50.308521,\"lon\":30.302761},{\"lat\":50.308228,\"lon\":30.302637}]"
}
}
Если в точках адресов заказа меньше двух валидных, то массив вернётся пустой.
{
"controller": "order",
"method": "completeOrder",
"params": {
"completed_code": 9000,
"sum": "0",
"uuid_order": "{9178e61c-5e85-4f77-91c8-28f9559b1bd6}"
},
"receiver": "1"
}
{
"controller": "order",
"method": "completeOrder",
"receiver": "1",
"result": {
"uuid_order": "{9178e61c-5e85-4f77-91c8-28f9559b1bd6}"
}
}
Сообщение от сервера, что статус заказа поменялся на стороне сервера. Обычно свидетельствует о завершении заказа диспетчерской или клиентом через приложение
{
"controller": "order",
"method": "completeOrder",
"result": {
"completed_code": 1050,
"uuid_order": "{d1ba8f23-11be-4e1a-9e75-a889a19c6b5a}"
}
}
{
"controller": "order",
"method": "confirmCompleteOrder",
"params": {
"uuid_order": "{d1ba8f23-11be-4e1a-9e75-a889a19c6b5a}"
},
"receiver": "7"
}
Сообщение от сервера о том, как прошёл процесс перевода средств с банковской карты клиента на карту водителя.
{
"controller": "order",
"method": "fondyPayment",
"result": {
"amount": 5243,
"error_code": 1000,
"error_message": "General decline",
"id_order_disp": 2388,
"uuid": "{8d0b1214-a00d-4556-8b01-00de905bb50b}"
}
}
В случае успеха операции error_code будет 0, а error_message пустым.
Fondy присылает описание ошибок на английском языке. Если нужно показывать водителю на русском, то можно по коду ошибки взять описание согласно таблице кодов отказа API Fondy.
{
"controller": "order",
"method": "checkCompletedCodes",
"params": {
"orders": [
"{34cd0162-a42f-4d40-af65-0c7d819e97e9}",
"{8e7ee8f8-10c5-4614-8d08-368dc09db236}",
"{7e6e9b36-7f17-4447-85dd-caa0a72da75c}"
]
},
"receiver": "9"
}
{
"controller": "order",
"method": "checkCompletedCodes",
"receiver": "9",
"result": [
{
"assigned: false",
"completed_code": 0,
"uuid": "{34cd0162-a42f-4d40-af65-0c7d819e97e9}"
},
{
"assigned: true",
"completed_code": 9000,
"uuid": "{7e6e9b36-7f17-4447-85dd-caa0a72da75c}"
},
{
"assigned: true",
"completed_code": 1050,
"uuid": "{8e7ee8f8-10c5-4614-8d08-368dc09db236}"
}
]
}
{
"controller": "order",
"method": "getClientPhoto",
"params": {
"id": 12
},
"receiver": "6"
}
{
"controller": "order",
"method": "getClientPhoto",
"result": {
"photo": "OlxSHIOciplYaG4wKOopWO4GnfdUetStADt0pDQhJ5bp2p3y809wewm0baYYyBTzkDrUikYw1CpxvdCuQLuFSqTxSAfKT74pxIVPeiIBxnJpOCpwQKQ7j"
}
"receiver": "6",
"resCode": 10
}
{
"controller": "order",
"method": "ignoreClient",
"params": {
"order_uuid": "{42aef8e1-2ad5-46a9-9021-7f15ec643540}"
},
"receiver": "6"
}
{
"controller": "order",
"method": "ignoreClient",
"receiver": "6",
"resCode": 10
}
Клиент, который сделал заказ, будет добавлен в список игнора водителя, и заказы от него водителю приходить не будут ни по автоназначению, ни вручную.
{
"controller": "order",
"method": "setClientRating",
"params": {
"uuid": "{42aef8e1-2ad5-46a9-9021-7f15ec643540}",
"rating": 4
},
"receiver": "6"
}
{
"controller": "order",
"method": "setClientRating",
"receiver": "6",
"resCode": 10
}
{
"controller": "driver",
"method": "listOfOrders",
"params": {
"limit": 1,
"query": [
{
"condition": "and",
"expressions": [
{
"condition": "and",
"operation": "=",
"role": "is_completed",
"value": "0"
},
{
"condition": "and",
"operation": "=",
"role": "is_booking",
"value": "0"
}
]
}
]
},
"receiver": "1"
}
{
"controller": "driver",
"method": "listOfOrders",
"receiver": "1",
"resCode": 10,
"result": {
"query": []
}
}
{
"controller": "driver",
"method": "remainAmountFreeCancelOrder",
"receiver": "1"
}
{
"controller": "driver",
"method": "remainAmountFreeCancelOrder",
"receiver": "1",
"resCode": 10,
"result": {
"amount_penalties_last_day": "0",
"cancel_per_day": "6",
"enabled_distance_penalty": "yes"
}
}
{
"controller": "order",
"method": "sendStat",
"receiver": "1",
"params": {
"uuid": "{e2a7af6f-6c15-4751-b266-6e3f4391bfa5}",
"sum": 45.6,
"set_taxi": 12,
"min_trip": 7.9,
"start_sum": 5,
"wait_sum": 15,
"distance": 2.3,
"bonuses": 20,
"coefficient": 1.15,
"total_amount": {
"amt_km_free_on_move_to_client": 0,
"amt_tm_up_time_free_on_move_to_client": 0,
"amt_free_km": 0,
"amt_free_tm_up_time": 0,
"amt_free_tm_down_time": 0,
"amt_km": 0,
"amt_km_on_return": 0,
"amt_km_on_move_to_client": 0,
"amt_km_on_move_penalty": 0,
"amt_tm_wait_on_start": 0,
"amt_tm_on_up_time": 0,
"amt_tm_on_downtime": 0,
"amt_tm_on_downtime_common": 0,
"price_tm_on_downtime": 0,
"amt_tm_on_up_time_return": 0,
"amt_tm_on_downtime_return": 0,
"amt_tm_on_downtime_common_return": 0,
"price_tm_on_downtime_return": 0,
"amt_tm_on_up_time_on_move_to_client": 0,
"amt_tm_on_downtime_on_move_to_client": 0,
"amt_tm_on_up_time_penalty": 0,
"amt_tm_on_downtime_penalty": 0,
"amt_penalty_drv_after_accepted": 0
},
"zone_amount": [
{
"rst_id_zone": 7,
"zone_name": "Кладбище",
"amt_km_free_on_move_to_client": 0,
"amt_tm_up_time_free_on_move_to_client": 0,
"amt_free_km": 0,
"amt_free_tm_up_time": 0,
"amt_free_tm_down_time": 0,
"amt_km": 0,
"amt_km_on_return": 0,
"amt_km_on_move_to_client": 0,
"amt_km_on_move_penalty": 0,
"amt_tm_wait_on_start": 0,
"amt_tm_on_up_time": 0,
"amt_tm_on_downtime": 0,
"amt_tm_on_downtime_common": 0,
"amt_tm_on_up_time_return": 0,
"amt_tm_on_downtime_return": 0,
"amt_tm_on_downtime_common_return": 0,
"amt_tm_on_up_time_on_move_to_client": 0,
"amt_tm_on_downtime_on_move_to_client": 0,
"amt_tm_on_up_time_penalty": 0,
"amt_tm_on_downtime_penalty": 0,
"amt_penalty_drv_after_accepted": 0,
"sum_km": 0,
"sum_km_on_return": 0,
"sum_km_on_move_to_client": 0,
"sum_km_on_move_penalty": 0,
"sum_tm_wait_on_start": 0,
"sum_tm_on_up_time": 0,
"sum_tm_on_downtime": 0,
"price_tm_on_downtime": 0,
"sum_tm_on_up_time_return": 0,
"sum_tm_on_downtime_return": 0,
"price_tm_on_downtime_return": 0,
"sum_tm_on_up_time_on_move_to_client": 0,
"sum_tm_on_downtime_on_move_to_client": 0,
"sum_tm_on_up_time_penalty": 0,
"sum_tm_on_downtime_penalty": 0,
"sum_penalty_drv_after_accepted": 0,
"set_taxi": 0,
"start_sum": 0,
"min_trip": 0
},
{
"rst_id_zone": 9,
"zone_name": "Морг",
"amt_km_free_on_move_to_client": 0,
"amt_tm_up_time_free_on_move_to_client": 0,
"amt_free_km": 0,
"amt_free_tm_up_time": 0,
"amt_free_tm_down_time": 0,
"amt_km": 0,
"amt_km_on_return": 0,
"amt_km_on_move_to_client": 0,
"amt_km_on_move_penalty": 0,
"amt_tm_wait_on_start": 0,
"amt_tm_on_up_time": 0,
"amt_tm_on_downtime": 0,
"amt_tm_on_downtime_common": 0,
"amt_tm_on_up_time_return": 0,
"amt_tm_on_downtime_return": 0,
"amt_tm_on_downtime_common_return": 0,
"amt_tm_on_up_time_on_move_to_client": 0,
"amt_tm_on_downtime_on_move_to_client": 0,
"amt_tm_on_up_time_penalty": 0,
"amt_tm_on_downtime_penalty": 0,
"amt_penalty_drv_after_accepted": 0,
"sum_km": 0,
"sum_km_on_return": 0,
"sum_km_on_move_to_client": 0,
"sum_km_on_move_penalty": 0,
"sum_tm_wait_on_start": 0,
"sum_tm_on_up_time": 0,
"sum_tm_on_downtime": 0,
"price_tm_on_downtime": 0,
"sum_tm_on_up_time_return": 0,
"sum_tm_on_downtime_return": 0,
"price_tm_on_downtime_return": 0,
"sum_tm_on_up_time_on_move_to_client": 0,
"sum_tm_on_downtime_on_move_to_client": 0,
"sum_tm_on_up_time_penalty": 0,
"sum_tm_on_downtime_penalty": 0,
"sum_penalty_drv_after_accepted": 0,
"set_taxi": 0,
"start_sum": 0,
"min_trip": 0
}
]
}
}
{
"controller": "order",
"method": "sendStat",
"receiver": "1",
"resCode": 10
}
{
"controller": "order",
"method": "getStat",
"params": {
"id": 3778
},
"receiver": "11"
}
{
"controller": "order",
"method": "getStat",
"receiver": "11",
"resCode": 10,
"result": {
"min_trip": 15,
"set_taxi": 60,
"start_sum": 25,
"wait_sum": 15,
"distance": 2.3,
"bonuses": 20,
"sum": 90,
"total_amount": {
"amt_free_km": 0,
"amt_free_tm_down_time": 0,
"amt_free_tm_down_time_to_client": 0,
"amt_free_tm_down_time_wait_on_start": 0,
"amt_free_tm_up_time": 0,
"amt_km": 0,
"amt_km_free_on_move_to_client": 0,
"amt_km_on_move_penalty": 0,
"amt_km_on_move_to_client": 0,
"amt_km_on_return": 0,
"amt_penalty_drv_after_accepted": 0,
"amt_tm_on_downtime": 0,
"amt_tm_on_downtime_common": 0,
"amt_tm_on_downtime_common_return": 0,
"amt_tm_on_downtime_on_move_to_client": 0,
"amt_tm_on_downtime_penalty": 0,
"amt_tm_on_downtime_return": 0,
"amt_tm_on_up_time": 3,
"amt_tm_on_up_time_on_move_to_client": 24,
"amt_tm_on_up_time_penalty": 0,
"amt_tm_on_up_time_return": 0,
"amt_tm_up_time_free_on_move_to_client": 0,
"amt_tm_wait_on_start": 0,
"price_tm_on_downtime": 0,
"price_tm_on_downtime_return": 0
},
"zone_amount": [
{
"amt_free_km": 0,
"amt_free_tm_down_time": 0,
"amt_free_tm_down_time_to_client": 0,
"amt_free_tm_down_time_wait_on_start": 0,
"amt_free_tm_up_time": 0,
"amt_km": 0,
"amt_km_free_on_move_to_client": 0,
"amt_km_on_move_penalty": 0,
"amt_km_on_move_to_client": 0,
"amt_km_on_return": 0,
"amt_penalty_drv_after_accepted": 0,
"amt_tm_on_downtime": 0,
"amt_tm_on_downtime_common": 0,
"amt_tm_on_downtime_common_return": 0,
"amt_tm_on_downtime_on_move_to_client": 0,
"amt_tm_on_downtime_penalty": 0,
"amt_tm_on_downtime_return": 0,
"amt_tm_on_up_time": 3,
"amt_tm_on_up_time_on_move_to_client": 24,
"amt_tm_on_up_time_penalty": 0,
"amt_tm_on_up_time_return": 0,
"amt_tm_up_time_free_on_move_to_client": 0,
"amt_tm_wait_on_start": 0,
"min_trip": 1,
"price_tm_on_downtime": 0,
"price_tm_on_downtime_return": 0,
"rst_id_zone": 57,
"set_taxi": 1,
"start_sum": 1,
"sum_km": 0,
"sum_km_on_move_penalty": 0,
"sum_km_on_move_to_client": 0,
"sum_km_on_return": 0,
"sum_penalty_drv_after_accepted": 0,
"sum_tm_on_downtime": 0,
"sum_tm_on_downtime_on_move_to_client": 0,
"sum_tm_on_downtime_penalty": 0,
"sum_tm_on_downtime_return": 0,
"sum_tm_on_up_time": 0.1,
"sum_tm_on_up_time_on_move_to_client": 0,
"sum_tm_on_up_time_penalty": 0,
"sum_tm_on_up_time_return": 0,
"sum_tm_wait_on_start": 0,
"zone_name": "Стандарт(Старая Боярка)"
},
{
"amt_free_km": 0,
"amt_free_tm_down_time": 0,
"amt_free_tm_down_time_to_client": 0,
"amt_free_tm_down_time_wait_on_start": 0,
"amt_free_tm_up_time": 0,
"amt_km": 0,
"amt_km_free_on_move_to_client": 0,
"amt_km_on_move_penalty": 0,
"amt_km_on_move_to_client": 0,
"amt_km_on_return": 0,
"amt_penalty_drv_after_accepted": 0,
"amt_tm_on_downtime": 0,
"amt_tm_on_downtime_common": 0,
"amt_tm_on_downtime_common_return": 0,
"amt_tm_on_downtime_on_move_to_client": 0,
"amt_tm_on_downtime_penalty": 0,
"amt_tm_on_downtime_return": 0,
"amt_tm_on_up_time": 0,
"amt_tm_on_up_time_on_move_to_client": 0,
"amt_tm_on_up_time_penalty": 0,
"amt_tm_on_up_time_return": 0,
"amt_tm_up_time_free_on_move_to_client": 0,
"amt_tm_wait_on_start": 0,
"min_trip": 0,
"price_tm_on_downtime": 0,
"price_tm_on_downtime_return": 0,
"rst_id_zone": 58,
"set_taxi": 0,
"start_sum": 0,
"sum_km": 0,
"sum_km_on_move_penalty": 0,
"sum_km_on_move_to_client": 0,
"sum_km_on_return": 0,
"sum_penalty_drv_after_accepted": 0,
"sum_tm_on_downtime": 0,
"sum_tm_on_downtime_on_move_to_client": 0,
"sum_tm_on_downtime_penalty": 0,
"sum_tm_on_downtime_return": 0,
"sum_tm_on_up_time": 0,
"sum_tm_on_up_time_on_move_to_client": 0,
"sum_tm_on_up_time_penalty": 0,
"sum_tm_on_up_time_return": 0,
"sum_tm_wait_on_start": 0,
"zone_name": "Стандарт(Новая Боярка)"
}
]
}
}
{
"controller": "order",
"method": "sync",
"params": {
"time": 1607420614445
},
"receiver": "8"
}
{
"controller": "order",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"coefficient": 1.5,
"cost": 84.3,
"uuid": "{24a427f5-990f-4024-9491-e01f45e65e68}"
}
]
}
}
В ответе возвращаются не все поля из заказа, а те, которые могут измениться, и которые приходят в уведомлении order.updated
{
"controller": "order",
"method": "updated",
"result": {
"coefficient": 1.5,
"cost": 84.3,
"uuid": "{41e53ae7-3d9e-48d2-9718-4c66fb787877}"
}
}
Все параметры, как в ответе запроса order.sync
{
"controller": "order",
"method": "setComplaint",
"params": {
"uuid": "{42aef8e1-2ad5-46a9-9021-7f15ec643540}",
"complaint": "Коллаборант"
},
"receiver": "6"
}
{
"controller": "order",
"method": "setComplaint",
"receiver": "6",
"resCode": 10
}
{
"controller": "order",
"method": "waypointsUpdated",
"result": {
"id": 3914,
"cost": 120,
"waypoints": [
{
"feed_city": "Боярка",
"feed_lat": 50.3177,
"feed_lon": 30.298,
"feed_note_for_driver": "Фора",
"feed_num_house": "1",
"feed_num_porch": "1",
"feed_street": "Садовая",
"order_point": 2
},
{
"feed_city": "Боярка",
"feed_lat": 50.3451,
"feed_lon": 30.2809,
"feed_note_for_driver": "Эпицентр",
"feed_num_house": "2",
"feed_num_porch": "1",
"feed_street": "Магистральная",
"order_point": 3
}
]
}
}
Адреса в списке приведены без первого, то есть начиная со второго - то, что нужно утвердить.
Получение обновлённого маршрута на тот случай, если было пропущено уведомление order.waypointsUpdated. Выполнять запрос имеет смысл, когда на таксе загружен заказ, созданный в клиентском приложении (иначе мы не будем знать нужный id), и статус заказа 2400 или больше. То есть при загрузке заказа на экран, если статус подходящий, либо при реконнекте, если подобный заказ уже загружен.
{
"controller": "order",
"method": "getUpdatedWaypoints",
"params": {
"id": 3913
},
"receiver": "11"
}
{
"controller": "order",
"method": "getUpdatedWaypoints",
"receiver": "11",
"resCode": 10,
"result": {
"approve_status": 1,
"cost": 120,
"waypoints": [
{
"feed_city": "Боярка",
"feed_lat": 50.3177,
"feed_lon": 30.298,
"feed_note_for_driver": "Фора",
"feed_num_house": "1",
"feed_num_porch": "1",
"feed_street": "Садовая",
"order_point": 2
},
{
"feed_city": "Боярка",
"feed_lat": 50.3451,
"feed_lon": 30.2809,
"feed_note_for_driver": "Эпицентр",
"feed_num_house": "2",
"feed_num_porch": "1",
"feed_street": "Магистральная",
"order_point": 3
}
]
}
}
{
"controller": "order",
"method": "approveWaypoints",
"params": {
"id": 3914,
"approved": false
},
"receiver": "11"
}
{
"controller": "order",
"method": "approveWaypoints",
"receiver": "11",
"resCode": 10
}
{
"controller": "order",
"method": "servicesUpdated",
"result": {
"cost": 448,
"id": 3935,
"note_drv": "Молчаливый водитель: 40 грн.\nВедро котов в салоне: 290 грн. + 20%"
}
}
Получение обновлённых доп. услуг на тот случай, если было пропущено уведомление order.servicesUpdated. Условия отправки запроса такие же, как в запросе order.getUpdatedWaypoints
{
"controller": "order",
"method": "getUpdatedServices",
"params": {
"id": 3935
},
"receiver": "11"
}
{
"controller": "order",
"method": "getUpdatedServices",
"receiver": "11",
"resCode": 10,
"result": {
"cost": 448,
"note_drv": "Молчаливый водитель: 40 грн.\nВедро котов в салоне: 290 грн. + 20%"
}
}
{
"controller": "dbl",
"method": "getList",
"params": {
"start_date": 1690837200000,
"end_date": 1692623601316
},
"receiver": "18"
}
{
"controller": "dbl",
"method": "getList",
"receiver": "18",
"result": [
{
"balance": "1120.72",
"bg_name": "Операции по заказам",
"bt_name": "Списание",
"dt_utc_insert": "1560240004067",
"dt_utc_insert_formated": "",
"dt_utc_insert_time_formated": "",
"dt_utc_last_update": "1560240004067",
"id": 1488029,
"note": "Order=489, rate=10.00%+0.00, sum=12.00, company={36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"rst_id_bg": 3,
"rst_id_bt": 5,
"rst_id_owner": 2180,
"rst_id_user_created": 1,
"rst_id_user_locked": 1,
"sign_user_created": "",
"trn_key": "{9cdb89e0-b2c9-4010-a4e6-ab1167757ec9}",
"value": "-1.2"
},
{
"balance": "1121.92",
"bg_name": "Операции по заказам",
"bt_name": "Списание",
"dt_utc_insert": "1560239701622",
"dt_utc_insert_formated": "",
"dt_utc_insert_time_formated": "",
"dt_utc_last_update": "1560239701622",
"id": 1488028,
"note": "Order=488, rate=10.00%+0.00, sum=12.00, company={36d9e2c0-0f91-48d0-907b-86aa97795e4d}",
"rst_id_bg": 3,
"rst_id_bt": 5,
"rst_id_owner": 2180,
"rst_id_user_created": 1,
"rst_id_user_locked": 1,
"sign_user_created": "",
"trn_key": "{fc703dc5-44fa-42cd-82ac-674a2ca3b29a}",
"value": "-1.2"
}
]
}
{
"controller": "paymentSysAccComp",
"method": "getPaymentAccountInfo",
"receiver": "139"
}
{
"controller": "paymentSysAccComp",
"method": "getPaymentAccountInfo",
"receiver": "139",
"resCode": 10,
"result": {
"def_payment_value": "100",
"fee_nt_abs": "0",
"fee_nt_percent": "0.25",
"fee_payment_system_abs": "0",
"fee_payment_system_percent": "2.75",
"id_payment_account": "11"
}
}
{
"controller": "paymentSysDriversPaymentsLog",
"method": "addPayment",
"params": {
"amount": 1,
"rst_id_payments_system_acc_comp": 11
},
"receiver": "140"
}
{
"controller": "paymentSysDriversPaymentsLog",
"method": "addPayment",
"receiver": "140",
"resCode": 10,
"result": {
"data": "ewogICAgImFjdGlvbiI6ICJwYXkiLAogICAgImFtb3VudCI6ICIxIiwKICAgICJjdXJyZW5jeSI6ICJVQUgiLAogICAgImN1c3RvbWVyIjogIjIxODAiLAogICAgImRlc2NyaXB0aW9uIjogIlJlY2hhcmdlIGJhbGFuY2Ugb2YgJ1ZvdmFuJyIsCiAgICAiZXhwaXJlZF9kYXRlIjogIjIwMTgtMTEtMDYgMDc6MzE6MTMiLAogICAgImxhbmd1YWdlIjogInVrIiwKICAgICJvcmRlcl9pZCI6ICJ7Y2JmMWJjMzQtOTBjMi00OGJkLWEyNjgtYjMxM2VhNjkxNDQ2fSIsCiAgICAicGF5dHlwZXMiOiAiY2FyZCIsCiAgICAicHVibGljX2tleSI6ICJpMTEyMjkyNzg3NjAiLAogICAgInZlcnNpb24iOiAzCn0K",
"signature": "FrW+rkmlp9iM8cDsiwBNr2nImos="
}
}
Запрос отправляется, когда вводитель ввёл значение amount и нажал кнопку пополнения. Когда приходит ответ, производится перевод на экран со встроенным в приложение браузером, где запускается html-файл с кодом:
<head>
<script src="request.js"></script>
</head>
<body onload="">
<form id="form" method="POST" action="https://www.liqpay.ua/api/3/checkout"
accept-charset="utf-8">
<input type="hidden" id="data" name="data" />
<input type="hidden" id="signature" name="signature" />
</form>
Sending request...
</body>
Содержимое request.js
function sendRequest(data, signature) {
document.getElementById('data').value = data
document.getElementById('signature').value = signature
document.getElementById('form').submit()
}
data и signature передаются в функцию sendRequest из ответа на этот запрос.
Проще говоря, нужно выполнить http-запрос на URL https://www.liqpay.ua/api/3/checkout, как будто мы делаем это из формы. Все дальнейшие действия производятся во встроенном в экран браузере. Сервер liqpay вернёт страницу для ввода реквизитов карты, после чего нужно будет там же нажать кнопку заплатить.
Два этапа. Сперва запрос driverBalanceTransfer.prepareTransfer. Затем, когда придёт пароль в смс, запрос driverBalanceTransfer.applyTransfer
{
"controller": "driverBalanceTransfer",
"method": "prepareTransfer",
"params": {
"amount_credit": "7",
"sign_acceptor": "Vovan"
},
"receiver": "36"
}
{
"controller": "driverBalanceTransfer",
"method": "prepareTransfer",
"receiver": "36",
"resCode": 10,
"result": {
"additional_info": {
"amount_credit": "7",
"amount_debit": "6.86",
"dt_utc_timeout": "1559038970650",
"percent": "0.02",
"sign_acceptor": "Vovan",
"trn_key": "{8cccd66d-c352-4a33-821c-2570612c20e7}"
},
"amount_credit": "7",
"amount_debit": "6.86",
"dt_utc_timeout": "1559038970650",
"percent": "0.02",
"sign_acceptor": "Vovan",
"trn_key": "{8cccd66d-c352-4a33-821c-2570612c20e7}"
}
}
{
"controller": "driverBalanceTransfer",
"method": "applyTransfer",
"params": {
"password": "0010",
"trn_key": "{c0aceef9-de35-4279-822a-b52f887cbd07}"
},
"receiver": "183"
}
{
"controller": "driverBalanceTransfer",
"method": "applyTransfer",
"receiver": "183",
"resCode": 10
}
{
"controller": "media",
"method": "create",
"params": {
"tag": "car_inside_back",
"rst_id_car": 12,
"data": "OlxSHIOciplYaG4wKOopWO4GnfdUetStADt0pDQhJ5bp2p3y809wewm0baYYyBTzkDrUikYw1CpxvdCuQLuFSqTxSAfKT74pxIVPeiIBxnJpOCpwQKQ7j1"
},
"receiver": "10"
}
{
"controller": "media",
"method": "create",
"receiver": "10",
"resCode": 10,
"result": {
"uuid": "{a1666397-314c-413d-a4b9-8ffe302e697a}"
}
}
{
"controller": "media",
"method": "getList",
"params": {
"skip_data": true,
"rst_id_car": 1230
},
"receiver": "11"
}
{
"controller": "media",
"method": "getList",
"receiver": "11",
"result": [
{
"approved": false,
"id": 12,
"uuid": "{a1666397-314c-413d-a4b9-8ffe302e697a}",
"tag": "car_inside_back",
"rst_id_car": 12,
"data": "OlxSHIOciplYaG4wKOopWO4GnfdUetStADt0pDQhJ5bp2p3y809wewm0baYYyBTzkDrUikYw1CpxvdCuQLuFSqTxSAfKT74pxIVPeiIBxnJpOCpwQKQ7j1"
},
{
"approved": true,
"id": 13,
"uuid": "{07c1c603-52a4-4867-acb9-00606e1a5b35}",
"tag": "car_inside_front",
"rst_id_car": 12,
"data": "0YPQttC1INC90LXQsdC+INC+0YHQtdC90YzRjiDQtNGL0YjQsNC70L4sINC60L7RgNC+0YfQtSDRgdGC0LDQvdC+0LLQuNC70YHRjyDQtNC10L3RjA=="
}
]
}
{
"controller": "media",
"method": "getInfo",
"params": {
"id": 6
},
"receiver": "11"
}
{
"controller": "media",
"method": "getInfo",
"receiver": "10",
"resCode": 10,
"result": {
"approved": true,
"uuid": "{07c1c603-52a4-4867-acb9-00606e1a5b35}",
"tag": "car_inside_front",
"rst_id_car": 12,
"data": "0YPQttC1INC90LXQsdC+INC+0YHQtdC90YzRjiDQtNGL0YjQsNC70L4sINC60L7RgNC+0YfQtSDRgdGC0LDQvdC+0LLQuNC70YHRjyDQtNC10L3RjA=="
}
}
{
"controller": "media",
"method": "approveNotify",
"result": {
"rst_id_car": 12,
"tags": [
"car_outside_left",
"car_data_sheet_2"
]
}
}
{
"controller": "media",
"method": "removed",
"result": {
"uuid": "{ef22ca94-90a3-455c-8107-260d8ef044c8}"
}
}
Выполнять нужно при запуске такса и каждом реконнекте.
{
"controller": "media",
"method": "sync",
"params": {
"time": 1571748153000
},
"receiver": "8"
}
{
"controller": "media",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"removed": [
"{c7948086-5da9-4cb2-89c3-86366f5f3f70}",
"{2aa27951-b2b2-455f-a476-76807cef0599}"
]
}
}
{
"controller": "car",
"method": "getList",
"receiver": "42"
}
{
"controller": "car",
"method": "getList",
"receiver": "42",
"result": [
{
"id": 4,
"approved": true,
"brand_code": "jaguar",
"body_type_code": "sedan",
"color_code": "lightblue",
"model": "XF",
"identifier": "AI 1960 BX",
"logo": "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABi2lDQ1BHSU1QIGJ1aWx0LWluIHNSR0IAACiRfZE9SMNQ",
"year": "2022",
"place_amount": "4",
"is_active": true
}
]
}
{
"controller": "car",
"method": "getInfo",
"params": {
"id": 4
},
"receiver": "1"
}
{
"controller": "car",
"method": "getInfo",
"receiver": "1",
"resCode": 10,
"result": {
"approved": true,
"body_type_code": "sedan",
"brand_code": "bmw",
"color_code": "green",
"id": 4,
"identifier": "АІ 6125 АХ",
"logo": "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABi2lDQ1BHSU1QIGJ1aWx0LWluIHNSR0IAACiRfZE9SMNQ",
"is_active": false,
"model": "318i",
"place_amount": 4,
"year": 1999
}
}
{
"controller": "car",
"method": "create",
"params": {
"brand_code": "jaguar",
"body_type_code": "sedan",
"color_code": "lightblue",
"model": "XF",
"identifier": "AI 1960 BX",
"year": "2022",
"place_amount": "4"
},
"receiver": "42"
}
{
"controller": "car",
"method": "create",
"receiver": "42",
"resCode": 10,
"result": {
"id": 2
}
}
{
"controller": "car",
"method": "remove",
"params": {
"id": 5
},
"receiver": "42"
}
{
"controller": "car",
"method": "remove",
"receiver": "42",
"resCode": 10
}
{
"controller": "car",
"method": "select",
"params": {
"id": 5
},
"receiver": "42"
}
{
"controller": "car",
"method": "select",
"receiver": "42",
"resCode": 10
}
{
"controller": "bankCard",
"method": "getFondyAccount",
"receiver": "42"
}
{
"controller": "bankCard",
"method": "getFondyAccount",
"result": {
"login": "1433359",
"password": "QMWBRUkJzhDJ4E1v5o0YCZykoHc5S5qI"
},
"receiver": "42"
}
{
"controller": "bankCard",
"method": "create",
"params": {
"mask": "444455XXXXXX1111",
"token": "a41087ed7ce6d8a3e659549d0e1978393ddc266"
},
"receiver": "42"
}
{
"controller": "bankCard",
"method": "create",
"receiver": "42",
"resCode": 10,
"result": {
"id": 2
}
}
{
"controller": "bankCard",
"method": "getList",
"receiver": "42"
}
{
"controller": "bankCard",
"method": "getList",
"receiver": "42",
"result": [
{
"id": 4,
"mask": "444455XXXXXX1111",
"selected": false,
"token": "a41087ed7ce6d8a3e659549d0e1978393ddc266"
},
{
"id": 3,
"mask": "444455XXXXXX6666",
"selected": true,
"token": "15c146efea24b702319e47e340fa4b3ab21b9d33"
}
]
}
{
"controller": "bankCard",
"method": "remove",
"params": {
"id": 5
},
"receiver": "42"
}
{
"controller": "bankCard",
"method": "remove",
"receiver": "42",
"resCode": 10
}
Если была удалена банковская карта, установленная в текущую запросом bankCard.select, то в случае, если флаг использования текущей карты для безналичных оплат был установлен в true запросом bankCard.use, этот флаг будет сброшен в false.
{
"controller": "bankCard",
"method": "select",
"params": {
"id": 5
},
"receiver": "42"
}
Если установить id в 1, то выбор будет снят. Если до этого был установлен флаг использования банковской карты для безналичных оплат запросом bankCard.use, то этот флаг тоже будет снят.
{
"controller": "bankCard",
"method": "select",
"receiver": "42",
"resCode": 10
}
{
"controller": "bankCard",
"method": "use",
"params": {
"value": true
},
"receiver": "42"
}
{
"controller": "bankCard",
"method": "use",
"receiver": "42",
"resCode": 10
}
{
"controller": "bankCard",
"method": "getUse",
"receiver": "42"
}
{
"controller": "bankCard",
"method": "getUse",
"result": {
"use": true
},
"receiver": "42",
"resCode": 10
}
{
"controller": "chatGroup",
"method": "created",
"result": {
"id": 3,
"id_order_disp": 4000,
"name": "Объявления",
"destination_type": "common",
"complete_stage": 0,
"recipient": 0
}
}
{
"controller": "chatGroup",
"method": "updated",
"result": {
"id": 3,
"id_order_disp": 4000,
"name": "Объявления",
"destination_type": "common",
"complete_stage": 0
}
}
{
"controller": "chatGroup",
"method": "removed",
"result": {
"id": 3
}
}
Выполнять нужно при запуске такса и каждом реконнекте.
{
"controller": "chatGroup",
"method": "sync",
"params": {
"current": [
9,
15
],
"time": 1571748153000
},
"receiver": "8"
}
{
"controller": "chatGroup",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"id": 9,
"id_order_disp": 4000,
"name": "Штрафы+",
"destination_type": "common",
"complete_stage": 0,
"recipient": 0
}
],
"removed": [
5
]
}
}
Завершение чата по запросу от диспетчерской или по собственной инициативе.
{
"controller": "chatGroup",
"method": "complete",
"params": {
"id": 24,
"note": "Всё зашибись!",
"resolved": true
},
"receiver": "42"
}
{
"controller": "chatGroup",
"method": "complete",
"receiver": "42",
"resCode": 10
}
Продолжить чат по запросу от диспетчерской о завершении.
{
"controller": "chatGroup",
"method": "continue",
"params": {
"id": 24
},
"receiver": "42"
}
{
"controller": "chatGroup",
"method": "continue",
"receiver": "42",
"resCode": 10
}
Такие же, как в запросе chatGroup.complete
{
"controller": "chatGroup",
"method": "create",
"params": {
"order_uuid": "{f66b6537-166d-438a-8e24-0dd6062d6f11}",
"recipient": 1
},
"receiver": "42"
}
{
"controller": "chatGroup",
"method": "create",
"receiver": "42",
"result": {
"complete_stage": 0,
"destination_type": "personal",
"id": 214,
"id_order_disp": 4151,
"name": "Chat #214",
"recipient": 1
}
}
{
"controller": "chat",
"method": "created",
"result": {
"id": 10,
"dt_utc_insert": 1584954999614,
"is_sys": 0,
"message": "Кто потерял колесо, обратитесь в депо",
"rst_id_group": 10,
"sender": "user",
"user_sign": "Олеся_12"
}
}
{
"controller": "chat",
"method": "removed",
"result": {
"id": 10
}
}
Выполнять нужно при запуске такса и каждом реконнекте.
{
"controller": "chat",
"method": "sync",
"params": {
"current_groups": [
9,
15
],
"time": 1571748153000
},
"receiver": "8"
}
{
"controller": "chat",
"method": "sync",
"receiver": "8",
"resCode": 10,
"result": {
"changed": [
{
"dt_utc_insert": 1584954999614,
"id": 2,
"is_readed": 0,
"is_sys": 0,
"message": "Комиссия за заказ увеличена до 10%",
"rst_id_group": 10,
"sender": "user",
"user_sign": ""
},
{
"dt_utc_insert": 1584955036979,
"id": 3,
"is_readed": 0,
"is_sys": 0,
"message": "Желаю, чтобы все!",
"rst_id_group": 9,
"sender": "user",
"user_sign": ""
},
{
"dt_utc_insert": 1584955138863,
"id": 5,
"is_readed": 0,
"is_sys": 0,
"message": "Поздравляем с днём водителя!",
"rst_id_group": 10,
"sender": "user",
"user_sign": ""
}
],
"removed": [
6,
9
]
}
}
{
"controller": "chat",
"method": "read",
"params": {
"id": 12
},
"receiver": "42"
}
{
"controller": "chat",
"method": "read",
"receiver": "42",
"resCode": 10
}
{
"controller": "chat",
"method": "reply",
"params": {
"id": 12
},
"receiver": "42"
}
Будет создана новая группа, куда будет скопировано это сообщение. id новой группы возвращается в ответе в параметре rst_id_group.
Будут отправлены уведомления chatGroup.created и chat.created.
{
"controller": "chat",
"method": "reply",
"receiver": "42",
"resCode": 10,
"result": {
"rst_id_group": 23
}
}
{
"controller": "chat",
"method": "create",
"params": {
"rst_id_group": 3,
"message": "Привет, Мир!"
},
"receiver": "42"
}
{
"controller": "chat",
"method": "create",
"receiver": "42",
"resCode": 10,
"result": {
"dt_utc_insert": 1587103003634,
"id": 15,
"is_readed": 0,
"message": "Привет, Мир!",
"is_sys": 0,
"rst_id_group": 3,
"sender": "driver"
}
}
{
"controller": "company",
"method": "getPersonal",
"params": {
"id": 42
},
"receiver": "42"
}
{
"controller": "company",
"method": "getPersonal",
"receiver": "42",
"resCode": 10,
"result": {
"about": "",
"additional_conditions": "",
"additional_payments": "",
"contract_offer": "",
"city": "",
"address": "",
"commission": "",
"logo": "/9j/4AAQSkZJRgABAQEAYABgAAD",
"tariffs": [
{
"description": "Отвезти клиента на его собственном авто",
"name": "Драйвер"
},
{
"description": "",
"name": "Стандарт"
}
],
"phone": "",
"schedule": ""
}
}
{
"controller": "company",
"method": "getCoefficients",
"receiver": "18"
}
{
"controller": "company",
"method": "getCoefficients",
"receiver": "18",
"result": [
{
"cell": [
0,
-2
],
"coefficient": 1.4,
"color": "#FFFF00",
"id": 12,
"order_count": 4
}
]
}
Ответ возвращает список шестиугольников с координатами cell, в которых коэффициент заказа coefficient больше 1. В одной компании может быть несколько таких шестиугольников.
Отправляется водителям, которые подключены к тарифам компании, у которых изменился динамический коэффициент заказа.
{
"controller": "company",
"method": "coefficientChanged",
"result": {
"cell": [
0,
-2
],
"coefficient": 1.4,
"color": "#FFFF00",
"id": 12,
"order_count": 4
}
}
Аналогично, как в ответе на запрос company.getCoefficients, только отправляется один элемент из списка, то есть шестиугольник компании, в котором что-то изменилось.
{
"controller": "zone",
"method": "getCoefficients",
"receiver": "18"
}
{
"controller": "zone",
"method": "getCoefficients",
"receiver": "18",
"result": [
{
"coefficient": 1.3,
"color": "#FFFF00",
"id": 342,
"rst_id_tss": 95
},
{
"coefficient": 1.3,
"color": "#FFFF00",
"id": 343,
"rst_id_tss": 95
},
{
"coefficient": 1.3,
"color": "#FFFF00",
"id": 346,
"rst_id_tss": 95
}
]
}
Список верхнего уровня - зоны:
* id - id зоны.
* rst_id_tss - id типа заказа, у которого is_default = 1.
* coefficient - динамический коэффициент заказа, который будет применяться для этого типа заказа в данной зоне.
* color - цвет зоны в зависимости от коэффициента. Для коэффициента 1.0 цвет будет белый, но он не имеет значения, потому что такие зоны нужно отрисовывать полностью прозрачными.
Отправляется водителям, которые подключены к типам заказа, у которых изменился динамический коэффициент заказа.
{
"controller": "zone",
"method": "coefficientChanged",
"result": {
"coefficient": 1.6,
"color": "#FFA07A",
"id": 346,
"rst_id_tss": 95
}
}
Аналогично, как в ответе на запрос zone.getCoefficients, только отправляется один элемент из списка, то есть зона, у которой что-то изменилось.