π API ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ
ΠΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ
api.html
30.05.2026 15:03
11.82 KB
/resources/docs/developer/api.html
Π‘ΡΡΠ»ΠΊΠΈ
π API ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ
ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° API ΡΠΈΡΡΠ΅ΠΌΡ
Π‘ΠΈΡΡΠ΅ΠΌΠ° DEXA ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΡΠ½ΠΈΠ²Π΅ΡΡΠ°Π»ΡΠ½ΡΡ ΡΠΈΡΡΠ΅ΠΌΡ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΉ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π²Π½Π΅ΡΠ½ΠΈΠΌΠΈ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°ΠΌΠΈ ΠΊΡΡΡΠΎΠ².
Π’Π°Π±Π»ΠΈΡΠ° exchange_apis
| ΠΠΎΠ»Π΅ | Π’ΠΈΠΏ | ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ | ΠΡΠΈΠΌΠ΅Ρ |
|---|---|---|---|
| name | VARCHAR(255) | ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ | Rapira API |
| base_url | VARCHAR(500) | ΠΠ°Π·ΠΎΠ²ΡΠΉ URL API | https://api.rapira.net |
| endpoint | VARCHAR(255) | ΠΠ½Π΄ΠΏΠΎΠΈΠ½Ρ Π΄Π»Ρ Π·Π°ΠΏΡΠΎΡΠ° | /v1/rates |
| method | ENUM('GET','POST') | HTTP ΠΌΠ΅ΡΠΎΠ΄ | GET |
| field_mapping | JSON | ΠΠ°ΠΏΠΏΠΈΠ½Π³ ΠΏΠΎΠ»Π΅ΠΉ ΠΎΡΠ²Π΅ΡΠ° | {"symbol_field": "pair"} |
| pair_format | JSON | Π€ΠΎΡΠΌΠ°Ρ Π²Π°Π»ΡΡΠ½ΡΡ ΠΏΠ°Ρ | {"from_separator": "_"} |
| authentication_type | VARCHAR(50) | Π’ΠΈΠΏ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ | api_key |
| api_key | TEXT | ΠΠ»ΡΡ API (ΡΠΈΡΡΡΠ΅ΡΡΡ) | encrypted_data |
Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ
Π§Π΅ΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ
- ΠΠ΅ΡΠ΅ΠΉΠ΄ΠΈΡΠ΅ Π² API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ β Π‘ΠΎΠ·Π΄Π°ΡΡ
- ΠΠ°ΠΏΠΎΠ»Π½ΠΈΡΠ΅ ΠΏΠΎΠ»Ρ:
- ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ Π΄Π»Ρ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ
- Base URL (ΠΏΠΎΠ»Π½ΡΠΉ Π°Π΄ΡΠ΅Ρ Π±Π΅Π· ΡΠ½Π΄ΠΏΠΎΠΈΠ½ΡΠ°)
- Endpoint (ΠΏΡΡΡ ΠΊ API)
- HTTP ΠΌΠ΅ΡΠΎΠ΄ (GET ΠΈΠ»ΠΈ POST)
- Π’ΠΈΠΏ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ
- ΠΠ»ΡΡΠΈ Π΄ΠΎΡΡΡΠΏΠ°
- ΠΠ°ΡΡΡΠΎΠΉΡΠ΅ ΠΌΠ°ΠΏΠΏΠΈΠ½Π³ ΠΏΠΎΠ»Π΅ΠΉ (JSON)
- ΠΡΠΎΡΠ΅ΡΡΠΈΡΡΠΉΡΠ΅ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
- Π‘ΠΎΡ ΡΠ°Π½ΠΈΡΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ
Π§Π΅ΡΠ΅Π· ΠΌΠΈΠ³ΡΠ°ΡΠΈΡ/ΡΠΈΠ΄Ρ
// ΠΡΠΈΠΌΠ΅Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ
ExchangeApi::create([
'name' => 'Binance Public API',
'base_url' => 'https://api.binance.com',
'endpoint' => '/api/v3/ticker/price',
'method' => 'GET',
'field_mapping' => json_encode([
'data_path' => null,
'symbol_field' => 'symbol',
'rate_path' => 'price',
'is_simple_array' => false
]),
'pair_format' => json_encode([
'from_separator' => '',
'to_separator' => '',
'reverse' => false
]),
'authentication_type' => 'none',
'is_active' => true,
'priority' => 1
]);
Field Mapping
JSON ΡΡΡΡΠΊΡΡΡΠ° Π΄Π»Ρ ΠΌΠ°ΠΏΠΏΠΈΠ½Π³Π° ΠΏΠΎΠ»Π΅ΠΉ API ΠΎΡΠ²Π΅ΡΠ°:
{
"data_path": "data.tickers", // ΠΡΡΡ ΠΊ ΠΌΠ°ΡΡΠΈΠ²Ρ Π΄Π°Π½Π½ΡΡ
"symbol_field": "symbol", // ΠΠΎΠ»Π΅ Ρ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠΌ Π²Π°Π»ΡΡΠ½ΠΎΠΉ ΠΏΠ°ΡΡ
"rate_path": "close", // ΠΡΡΡ ΠΊ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΊΡΡΡΠ°
"bid_path": "bid", // ΠΡΡΡ ΠΊ Π»ΡΡΡΠ΅ΠΉ ΡΠ΅Π½Π΅ ΠΏΠΎΠΊΡΠΏΠΊΠΈ
"ask_path": "ask", // ΠΡΡΡ ΠΊ Π»ΡΡΡΠ΅ΠΉ ΡΠ΅Π½Π΅ ΠΏΡΠΎΠ΄Π°ΠΆΠΈ
"volume_path": "volume", // ΠΡΡΡ ΠΊ ΠΎΠ±ΡΠ΅ΠΌΡ ΡΠΎΡΠ³ΠΎΠ²
"change_path": "chg", // ΠΡΡΡ ΠΊ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΡΠ΅Π½Ρ
"high_path": "high", // ΠΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½Π°Ρ ΡΠ΅Π½Π°
"low_path": "low", // ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½Π°Ρ ΡΠ΅Π½Π°
"is_simple_array": false, // ΠΡΠΎΡΡΠΎΠΉ ΠΌΠ°ΡΡΠΈΠ² ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ²
"delimiter": ",", // Π Π°Π·Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ Π΄Π»Ρ CSV
"has_header": true, // ΠΡΡΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Π² CSV
"orderbook_endpoint": "/market/exchange-plate-mini",
"orderbook_symbol_format": "{from}/{to}",
"orderbook_bid_path": "bid.items",
"orderbook_ask_path": "ask.items",
"orderbook_price_field": "price",
"orderbook_amount_field": "amount"
}
Pair Format
ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΡΠΎΡΠΌΠ°ΡΠ° Π²Π°Π»ΡΡΠ½ΡΡ ΠΏΠ°Ρ:
{
"from_separator": "/", // Π Π°Π·Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ ΠΌΠ΅ΠΆΠ΄Ρ Π²Π°Π»ΡΡΠ°ΠΌΠΈ
"to_separator": "_", // ΠΠ»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π½ΡΠΉ ΡΠ°Π·Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ
"reverse": false, // Π Π΅Π²Π΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ ΠΏΠ°ΡΡ (USDT/BTC β BTC/USDT)
"prefix": "", // ΠΡΠ΅ΡΠΈΠΊΡ Π΄Π»Ρ ΡΠΈΠΌΠ²ΠΎΠ»Π°
"suffix": "" // Π‘ΡΡΡΠΈΠΊΡ Π΄Π»Ρ ΡΠΈΠΌΠ²ΠΎΠ»Π°
}
Π’ΠΈΠΏΡ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ
| Π’ΠΈΠΏ | ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ | ΠΠΎΠ»Ρ | ΠΡΠΈΠΌΠ΅Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° |
|---|---|---|---|
| none | ΠΠ΅Π· Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ | - | - |
| api_key | ΠΠ»ΡΡ Π² ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ΅ Π·Π°ΠΏΡΠΎΡΠ° | api_key | ?api_key=xxx |
| bearer | Bearer ΡΠΎΠΊΠ΅Π½ | api_key | Authorization: Bearer xxx |
| basic | Basic Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ | api_key, secret_key | Authorization: Basic base64 |
ΠΡΠΈΠΌΠ΅ΡΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΉ
ΠΡΠΈΠΌΠ΅Ρ 1: Binance Public API
ΠΠ°Π·Π²Π°Π½ΠΈΠ΅: Binance Spot Prices
Base URL: https://api.binance.com
Endpoint: /api/v3/ticker/price
ΠΠ΅ΡΠΎΠ΄: GET
ΠΠ°ΠΏΠΏΠΈΠ½Π³: {
"data_path": null,
"symbol_field": "symbol",
"rate_path": "price",
"is_simple_array": true
}
Π€ΠΎΡΠΌΠ°Ρ ΠΏΠ°ΡΡ: {
"from_separator": "",
"to_separator": "",
"reverse": false
}
ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ: none
ΠΡΠΈΠΌΠ΅Ρ 2: Rapira.net Ρ API ΠΊΠ»ΡΡΠΎΠΌ
ΠΠ°Π·Π²Π°Π½ΠΈΠ΅: Rapira Exchange API
Base URL: https://api.rapira.net
Endpoint: /v1/rates
ΠΠ΅ΡΠΎΠ΄: GET
ΠΠ°ΠΏΠΏΠΈΠ½Π³: {
"data_path": "data",
"symbol_field": "pair",
"rate_path": "rate",
"bid_path": "bid",
"ask_path": "ask",
"volume_path": "volume_24h",
"is_simple_array": false
}
Π€ΠΎΡΠΌΠ°Ρ ΠΏΠ°ΡΡ: {
"from_separator": "_",
"to_separator": "_",
"reverse": false
}
ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ: api_key
API Key: Π²Π°Ρ_ΠΊΠ»ΡΡ_rapira
ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΠΎΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ API
Π‘Π΅ΡΠ²ΠΈΡ UniversalApiService
ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠ΅ΡΠ²ΠΈΡ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ API:
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΡΡΡΠΎΠ² Ρ API
$apiService = new UniversalApiService();
$result = $apiService->fetchRates($apiConfig);
// Π’Π΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ API
$testResult = $apiService->testApi($apiConfig, $useTestData);
// ΠΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΊΡΡΡΠΎΠ² ΠΈΠ· ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠ³ΠΎ API
$externalRateService = new ExternalRateService();
$updatedCount = $externalRateService->updateRatesFromSpecificApi($api);
ΠΠΎΠ½ΡΡΠΎΠ»Π»Π΅Ρ ApiConfigController
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ:
test()- ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈquickTest()- Π±ΡΡΡΡΡΠΉ ΡΠ΅ΡΡ Π±Π΅Π· ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ
toggleActive() - Π°ΠΊΡΠΈΠ²Π°ΡΠΈΡ/Π΄Π΅Π°ΠΊΡΠΈΠ²Π°ΡΠΈΡ API
ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠ²Π΅ΡΠΎΠ²
Π£ΡΠΏΠ΅ΡΠ½ΡΠΉ ΠΎΡΠ²Π΅Ρ
{
"success": true,
"rates": [
{
"from": "USDT",
"to": "RUB",
"rate": 92.45,
"bid": 92.40,
"ask": 92.50,
"source": "binance"
}
],
"count": 150,
"timestamp": "2024-01-15T12:30:45Z"
}
ΠΡΠΈΠ±ΠΊΠ°
{
"success": false,
"error": "API connection failed",
"message": "Could not connect to https://api.binance.com",
"code": "CONNECTION_ERROR",
"retry_count": 3
}
ΠΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³
ΠΠ»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ API Π²Π΅Π΄Π΅ΡΡΡ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΠ°:
- success_count - ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΡΠΏΠ΅ΡΠ½ΡΡ Π·Π°ΠΏΡΠΎΡΠΎΠ²
- error_count - ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΎΡΠΈΠ±ΠΎΠΊ
- last_success_at - Π²ΡΠ΅ΠΌΡ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ ΡΡΠΏΠ΅Ρ Π°
- last_error_at - Π²ΡΠ΅ΠΌΡ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅ΠΉ ΠΎΡΠΈΠ±ΠΊΠΈ
- last_error_message - ΡΠ΅ΠΊΡΡ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅ΠΉ ΠΎΡΠΈΠ±ΠΊΠΈ
ΠΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅
ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ ΠΊΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ:
- ΠΠΎΡΡΡΠΏΠ½ΡΠ΅ Π²Π°Π»ΡΡΡ ΠΊΡΡΠΈΡΡΡΡΡΡ Π½Π° 24 ΡΠ°ΡΠ°
- ΠΡΡΡΡ ΠΊΡΡΠΈΡΡΡΡΡΡ ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ ΠΈΠ½ΡΠ΅ΡΠ²Π°Π»Ρ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ
- ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ API Π½Π΅ ΠΊΡΡΠΈΡΡΡΡΡΡ (ΡΠ°ΡΡΠΎ ΠΌΠ΅Π½ΡΡΡΡΡ)
ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ
Π‘ΠΈΡΡΠ΅ΠΌΠ° ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ:
- Π’Π°ΠΉΠΌΠ°ΡΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ (Π½Π°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌΡΠ΅)
- ΠΠΎΠ²ΡΠΎΡΠ½ΡΠ΅ ΠΏΠΎΠΏΡΡΠΊΠΈ (retry_count)
- ΠΠ»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π½ΡΠ΅ API (fallback)
- ΠΠ°Π»ΠΈΠ΄Π°ΡΠΈΡ ΠΎΡΠ²Π΅ΡΠΎΠ²
- ΠΠ΅Π³ΡΠ°Π΄Π°ΡΠΈΡ ΡΠ΅ΡΠ²ΠΈΡΠ°
ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ ΠΏΠ°ΡΡΠ½Π΅ΡΠ°ΠΌΠΈ
ΠΠ°ΠΆΠ΄ΡΠΉ ΠΏΠ°ΡΡΠ½Π΅Ρ ΠΌΠΎΠΆΠ΅Ρ ΠΈΠΌΠ΅ΡΡ ΡΠ²ΠΎΠΉ API:
// ΠΠ°Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ API ΠΏΠ°ΡΡΠ½Π΅ΡΡ
$partner = Partner::find(1);
$partner->api_id = $apiConfig->id;
$partner->save();
// ΠΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΊΡΡΡΠΎΠ² ΠΏΠ°ΡΡΠ½Π΅ΡΠ°
$rateUpdateService = new RateUpdateService();
$result = $rateUpdateService->updatePartnerRatesFromApi($partner->id, $apiConfig);
ΠΠ°ΠΆΠ½ΠΎ: ΠΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠ΅ΡΠ΅ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ Π²ΡΠ΅ ΡΠ²ΡΠ·Π°Π½Π½ΡΠ΅ ΠΏΠ°ΡΡΠ½Π΅ΡΡ.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>π API ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; padding: 20px; max-width: 1200px; margin: 0 auto; }
h1 { color: #2c3e50; border-bottom: 2px solid #eee; padding-bottom: 10px; margin-bottom: 20px; }
h2 { color: #34495e; border-bottom: 1px solid #eee; padding-bottom: 5px; margin-top: 30px; }
h3 { color: #7f8c8d; margin-top: 25px; }
p { margin-bottom: 15px; }
ul, ol { margin-bottom: 15px; padding-left: 20px; }
li { margin-bottom: 5px; }
code { background-color: #f8f9fa; padding: 2px 6px; border-radius: 4px; font-family: monospace; }
pre { background-color: #f8f9fa; padding: 15px; border-radius: 8px; overflow-x: auto; border: 1px solid #dee2e6; }
.endpoint { background-color: #e9ecef; padding: 10px; border-radius: 5px; margin: 10px 0; }
table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
th, td { padding: 12px; border: 1px solid #dee2e6; }
th { background-color: #f8f9fa; }
</style>
</head>
<body>
<h1>π API ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ</h1>
<h2>ΠΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠ° API ΡΠΈΡΡΠ΅ΠΌΡ</h2>
<p>Π‘ΠΈΡΡΠ΅ΠΌΠ° DEXA ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΡΠ½ΠΈΠ²Π΅ΡΡΠ°Π»ΡΠ½ΡΡ ΡΠΈΡΡΠ΅ΠΌΡ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΉ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π²Π½Π΅ΡΠ½ΠΈΠΌΠΈ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ°ΠΌΠΈ ΠΊΡΡΡΠΎΠ².</p>
<h3>Π’Π°Π±Π»ΠΈΡΠ° exchange_apis</h3>
<table>
<thead>
<tr>
<th>ΠΠΎΠ»Π΅</th>
<th>Π’ΠΈΠΏ</th>
<th>ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅</th>
<th>ΠΡΠΈΠΌΠ΅Ρ</th>
</tr>
</thead>
<tbody>
<tr>
<td>name</td>
<td>VARCHAR(255)</td>
<td>ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ</td>
<td>Rapira API</td>
</tr>
<tr>
<td>base_url</td>
<td>VARCHAR(500)</td>
<td>ΠΠ°Π·ΠΎΠ²ΡΠΉ URL API</td>
<td>https://api.rapira.net</td>
</tr>
<tr>
<td>endpoint</td>
<td>VARCHAR(255)</td>
<td>ΠΠ½Π΄ΠΏΠΎΠΈΠ½Ρ Π΄Π»Ρ Π·Π°ΠΏΡΠΎΡΠ°</td>
<td>/v1/rates</td>
</tr>
<tr>
<td>method</td>
<td>ENUM('GET','POST')</td>
<td>HTTP ΠΌΠ΅ΡΠΎΠ΄</td>
<td>GET</td>
</tr>
<tr>
<td>field_mapping</td>
<td>JSON</td>
<td>ΠΠ°ΠΏΠΏΠΈΠ½Π³ ΠΏΠΎΠ»Π΅ΠΉ ΠΎΡΠ²Π΅ΡΠ°</td>
<td>{"symbol_field": "pair"}</td>
</tr>
<tr>
<td>pair_format</td>
<td>JSON</td>
<td>Π€ΠΎΡΠΌΠ°Ρ Π²Π°Π»ΡΡΠ½ΡΡ
ΠΏΠ°Ρ</td>
<td>{"from_separator": "_"}</td>
</tr>
<tr>
<td>authentication_type</td>
<td>VARCHAR(50)</td>
<td>Π’ΠΈΠΏ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ</td>
<td>api_key</td>
</tr>
<tr>
<td>api_key</td>
<td>TEXT</td>
<td>ΠΠ»ΡΡ API (ΡΠΈΡΡΡΠ΅ΡΡΡ)</td>
<td>encrypted_data</td>
</tr>
</tbody>
</table>
<h2>Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ</h2>
<h3>Π§Π΅ΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ</h3>
<ol>
<li>ΠΠ΅ΡΠ΅ΠΉΠ΄ΠΈΡΠ΅ Π² <strong>API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ β Π‘ΠΎΠ·Π΄Π°ΡΡ</strong></li>
<li>ΠΠ°ΠΏΠΎΠ»Π½ΠΈΡΠ΅ ΠΏΠΎΠ»Ρ:
<ul>
<li>ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ Π΄Π»Ρ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ</li>
<li>Base URL (ΠΏΠΎΠ»Π½ΡΠΉ Π°Π΄ΡΠ΅Ρ Π±Π΅Π· ΡΠ½Π΄ΠΏΠΎΠΈΠ½ΡΠ°)</li>
<li>Endpoint (ΠΏΡΡΡ ΠΊ API)</li>
<li>HTTP ΠΌΠ΅ΡΠΎΠ΄ (GET ΠΈΠ»ΠΈ POST)</li>
<li>Π’ΠΈΠΏ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ</li>
<li>ΠΠ»ΡΡΠΈ Π΄ΠΎΡΡΡΠΏΠ°</li>
</ul>
</li>
<li>ΠΠ°ΡΡΡΠΎΠΉΡΠ΅ ΠΌΠ°ΠΏΠΏΠΈΠ½Π³ ΠΏΠΎΠ»Π΅ΠΉ (JSON)</li>
<li>ΠΡΠΎΡΠ΅ΡΡΠΈΡΡΠΉΡΠ΅ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅</li>
<li>Π‘ΠΎΡ
ΡΠ°Π½ΠΈΡΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ</li>
</ol>
<h3>Π§Π΅ΡΠ΅Π· ΠΌΠΈΠ³ΡΠ°ΡΠΈΡ/ΡΠΈΠ΄Ρ</h3>
<pre><code>// ΠΡΠΈΠΌΠ΅Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ
ExchangeApi::create([
'name' => 'Binance Public API',
'base_url' => 'https://api.binance.com',
'endpoint' => '/api/v3/ticker/price',
'method' => 'GET',
'field_mapping' => json_encode([
'data_path' => null,
'symbol_field' => 'symbol',
'rate_path' => 'price',
'is_simple_array' => false
]),
'pair_format' => json_encode([
'from_separator' => '',
'to_separator' => '',
'reverse' => false
]),
'authentication_type' => 'none',
'is_active' => true,
'priority' => 1
]);</code></pre>
<h2>Field Mapping</h2>
<p>JSON ΡΡΡΡΠΊΡΡΡΠ° Π΄Π»Ρ ΠΌΠ°ΠΏΠΏΠΈΠ½Π³Π° ΠΏΠΎΠ»Π΅ΠΉ API ΠΎΡΠ²Π΅ΡΠ°:</p>
<pre><code>{
"data_path": "data.tickers", // ΠΡΡΡ ΠΊ ΠΌΠ°ΡΡΠΈΠ²Ρ Π΄Π°Π½Π½ΡΡ
"symbol_field": "symbol", // ΠΠΎΠ»Π΅ Ρ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠΌ Π²Π°Π»ΡΡΠ½ΠΎΠΉ ΠΏΠ°ΡΡ
"rate_path": "close", // ΠΡΡΡ ΠΊ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΊΡΡΡΠ°
"bid_path": "bid", // ΠΡΡΡ ΠΊ Π»ΡΡΡΠ΅ΠΉ ΡΠ΅Π½Π΅ ΠΏΠΎΠΊΡΠΏΠΊΠΈ
"ask_path": "ask", // ΠΡΡΡ ΠΊ Π»ΡΡΡΠ΅ΠΉ ΡΠ΅Π½Π΅ ΠΏΡΠΎΠ΄Π°ΠΆΠΈ
"volume_path": "volume", // ΠΡΡΡ ΠΊ ΠΎΠ±ΡΠ΅ΠΌΡ ΡΠΎΡΠ³ΠΎΠ²
"change_path": "chg", // ΠΡΡΡ ΠΊ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΡΠ΅Π½Ρ
"high_path": "high", // ΠΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½Π°Ρ ΡΠ΅Π½Π°
"low_path": "low", // ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½Π°Ρ ΡΠ΅Π½Π°
"is_simple_array": false, // ΠΡΠΎΡΡΠΎΠΉ ΠΌΠ°ΡΡΠΈΠ² ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ²
"delimiter": ",", // Π Π°Π·Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ Π΄Π»Ρ CSV
"has_header": true, // ΠΡΡΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Π² CSV
"orderbook_endpoint": "/market/exchange-plate-mini",
"orderbook_symbol_format": "{from}/{to}",
"orderbook_bid_path": "bid.items",
"orderbook_ask_path": "ask.items",
"orderbook_price_field": "price",
"orderbook_amount_field": "amount"
}</code></pre>
<h2>Pair Format</h2>
<p>ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΡΠΎΡΠΌΠ°ΡΠ° Π²Π°Π»ΡΡΠ½ΡΡ
ΠΏΠ°Ρ:</p>
<pre><code>{
"from_separator": "/", // Π Π°Π·Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ ΠΌΠ΅ΠΆΠ΄Ρ Π²Π°Π»ΡΡΠ°ΠΌΠΈ
"to_separator": "_", // ΠΠ»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π½ΡΠΉ ΡΠ°Π·Π΄Π΅Π»ΠΈΡΠ΅Π»Ρ
"reverse": false, // Π Π΅Π²Π΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ ΠΏΠ°ΡΡ (USDT/BTC β BTC/USDT)
"prefix": "", // ΠΡΠ΅ΡΠΈΠΊΡ Π΄Π»Ρ ΡΠΈΠΌΠ²ΠΎΠ»Π°
"suffix": "" // Π‘ΡΡΡΠΈΠΊΡ Π΄Π»Ρ ΡΠΈΠΌΠ²ΠΎΠ»Π°
}</code></pre>
<h2>Π’ΠΈΠΏΡ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ</h2>
<table>
<thead>
<tr>
<th>Π’ΠΈΠΏ</th>
<th>ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅</th>
<th>ΠΠΎΠ»Ρ</th>
<th>ΠΡΠΈΠΌΠ΅Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°</th>
</tr>
</thead>
<tbody>
<tr>
<td>none</td>
<td>ΠΠ΅Π· Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>api_key</td>
<td>ΠΠ»ΡΡ Π² ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ΅ Π·Π°ΠΏΡΠΎΡΠ°</td>
<td>api_key</td>
<td>?api_key=xxx</td>
</tr>
<tr>
<td>bearer</td>
<td>Bearer ΡΠΎΠΊΠ΅Π½</td>
<td>api_key</td>
<td>Authorization: Bearer xxx</td>
</tr>
<tr>
<td>basic</td>
<td>Basic Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ</td>
<td>api_key, secret_key</td>
<td>Authorization: Basic base64</td>
</tr>
</tbody>
</table>
<h2>ΠΡΠΈΠΌΠ΅ΡΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΉ</h2>
<h3>ΠΡΠΈΠΌΠ΅Ρ 1: Binance Public API</h3>
<pre><code>ΠΠ°Π·Π²Π°Π½ΠΈΠ΅: Binance Spot Prices
Base URL: https://api.binance.com
Endpoint: /api/v3/ticker/price
ΠΠ΅ΡΠΎΠ΄: GET
ΠΠ°ΠΏΠΏΠΈΠ½Π³: {
"data_path": null,
"symbol_field": "symbol",
"rate_path": "price",
"is_simple_array": true
}
Π€ΠΎΡΠΌΠ°Ρ ΠΏΠ°ΡΡ: {
"from_separator": "",
"to_separator": "",
"reverse": false
}
ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ: none</code></pre>
<h3>ΠΡΠΈΠΌΠ΅Ρ 2: Rapira.net Ρ API ΠΊΠ»ΡΡΠΎΠΌ</h3>
<pre><code>ΠΠ°Π·Π²Π°Π½ΠΈΠ΅: Rapira Exchange API
Base URL: https://api.rapira.net
Endpoint: /v1/rates
ΠΠ΅ΡΠΎΠ΄: GET
ΠΠ°ΠΏΠΏΠΈΠ½Π³: {
"data_path": "data",
"symbol_field": "pair",
"rate_path": "rate",
"bid_path": "bid",
"ask_path": "ask",
"volume_path": "volume_24h",
"is_simple_array": false
}
Π€ΠΎΡΠΌΠ°Ρ ΠΏΠ°ΡΡ: {
"from_separator": "_",
"to_separator": "_",
"reverse": false
}
ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ: api_key
API Key: Π²Π°Ρ_ΠΊΠ»ΡΡ_rapira</code></pre>
<h2>ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΠΎΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ API</h2>
<h3>Π‘Π΅ΡΠ²ΠΈΡ UniversalApiService</h3>
<p>ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠ΅ΡΠ²ΠΈΡ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ API:</p>
<pre><code>// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΡΡΡΠΎΠ² Ρ API
$apiService = new UniversalApiService();
$result = $apiService->fetchRates($apiConfig);
// Π’Π΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ API
$testResult = $apiService->testApi($apiConfig, $useTestData);
// ΠΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΊΡΡΡΠΎΠ² ΠΈΠ· ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠ³ΠΎ API
$externalRateService = new ExternalRateService();
$updatedCount = $externalRateService->updateRatesFromSpecificApi($api);</code></pre>
<h3>ΠΠΎΠ½ΡΡΠΎΠ»Π»Π΅Ρ ApiConfigController</h3>
<p>ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ:</p>
<ul>
<li><code>test()</code> - ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ</li>
<li><code>quickTest()</code> - Π±ΡΡΡΡΡΠΉ ΡΠ΅ΡΡ Π±Π΅Π· ΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΡ</li>
<code>toggleActive()</code> - Π°ΠΊΡΠΈΠ²Π°ΡΠΈΡ/Π΄Π΅Π°ΠΊΡΠΈΠ²Π°ΡΠΈΡ API</li>
</ul>
<h2>ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠ²Π΅ΡΠΎΠ²</h2>
<h3>Π£ΡΠΏΠ΅ΡΠ½ΡΠΉ ΠΎΡΠ²Π΅Ρ</h3>
<pre><code>{
"success": true,
"rates": [
{
"from": "USDT",
"to": "RUB",
"rate": 92.45,
"bid": 92.40,
"ask": 92.50,
"source": "binance"
}
],
"count": 150,
"timestamp": "2024-01-15T12:30:45Z"
}</code></pre>
<h3>ΠΡΠΈΠ±ΠΊΠ°</h3>
<pre><code>{
"success": false,
"error": "API connection failed",
"message": "Could not connect to https://api.binance.com",
"code": "CONNECTION_ERROR",
"retry_count": 3
}</code></pre>
<h2>ΠΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³</h2>
<p>ΠΠ»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ API Π²Π΅Π΄Π΅ΡΡΡ ΡΡΠ°ΡΠΈΡΡΠΈΠΊΠ°:</p>
<ul>
<li><strong>success_count</strong> - ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΡΠΏΠ΅ΡΠ½ΡΡ
Π·Π°ΠΏΡΠΎΡΠΎΠ²</li>
<li><strong>error_count</strong> - ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΎΡΠΈΠ±ΠΎΠΊ</li>
<li><strong>last_success_at</strong> - Π²ΡΠ΅ΠΌΡ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ ΡΡΠΏΠ΅Ρ
Π°</li>
<li><strong>last_error_at</strong> - Π²ΡΠ΅ΠΌΡ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅ΠΉ ΠΎΡΠΈΠ±ΠΊΠΈ</li>
<li><strong>last_error_message</strong> - ΡΠ΅ΠΊΡΡ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅ΠΉ ΠΎΡΠΈΠ±ΠΊΠΈ</li>
</ul>
<h2>ΠΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅</h2>
<p>ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ ΠΊΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ:</p>
<ul>
<li>ΠΠΎΡΡΡΠΏΠ½ΡΠ΅ Π²Π°Π»ΡΡΡ ΠΊΡΡΠΈΡΡΡΡΡΡ Π½Π° 24 ΡΠ°ΡΠ°</li>
<li>ΠΡΡΡΡ ΠΊΡΡΠΈΡΡΡΡΡΡ ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ ΠΈΠ½ΡΠ΅ΡΠ²Π°Π»Ρ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ</li>
<li>ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ API Π½Π΅ ΠΊΡΡΠΈΡΡΡΡΡΡ (ΡΠ°ΡΡΠΎ ΠΌΠ΅Π½ΡΡΡΡΡ)</li>
</ul>
<h2>ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ</h2>
<p>Π‘ΠΈΡΡΠ΅ΠΌΠ° ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ:</p>
<ol>
<li>Π’Π°ΠΉΠΌΠ°ΡΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ (Π½Π°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌΡΠ΅)</li>
<li>ΠΠΎΠ²ΡΠΎΡΠ½ΡΠ΅ ΠΏΠΎΠΏΡΡΠΊΠΈ (retry_count)</li>
<li>ΠΠ»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π½ΡΠ΅ API (fallback)</li>
<li>ΠΠ°Π»ΠΈΠ΄Π°ΡΠΈΡ ΠΎΡΠ²Π΅ΡΠΎΠ²</li>
<li>ΠΠ΅Π³ΡΠ°Π΄Π°ΡΠΈΡ ΡΠ΅ΡΠ²ΠΈΡΠ°</li>
</ol>
<h2>ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ ΠΏΠ°ΡΡΠ½Π΅ΡΠ°ΠΌΠΈ</h2>
<p>ΠΠ°ΠΆΠ΄ΡΠΉ ΠΏΠ°ΡΡΠ½Π΅Ρ ΠΌΠΎΠΆΠ΅Ρ ΠΈΠΌΠ΅ΡΡ ΡΠ²ΠΎΠΉ API:</p>
<pre><code>// ΠΠ°Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ API ΠΏΠ°ΡΡΠ½Π΅ΡΡ
$partner = Partner::find(1);
$partner->api_id = $apiConfig->id;
$partner->save();
// ΠΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΊΡΡΡΠΎΠ² ΠΏΠ°ΡΡΠ½Π΅ΡΠ°
$rateUpdateService = new RateUpdateService();
$result = $rateUpdateService->updatePartnerRatesFromApi($partner->id, $apiConfig);</code></pre>
<blockquote>
<p><strong>ΠΠ°ΠΆΠ½ΠΎ:</strong> ΠΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ API ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠ΅ΡΠ΅ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ Π²ΡΠ΅ ΡΠ²ΡΠ·Π°Π½Π½ΡΠ΅ ΠΏΠ°ΡΡΠ½Π΅ΡΡ.</p>
</blockquote>
</body>
</html>