راهنمای PHP برای API ارز
دریافت نرخ ارز با PHP از وبسرویس و API سرویکس
اتصال امن PHP 8.2 به وبسرویس و API نرخ ارز سرویکس را با cURL، نگهداری سمت سرور API Key، timeout، اعتبارسنجی JSON، کنترل تازگی و retry محدود پیادهسازی و تست کنید.
این راهنما قرارداد احرازشده supported-assets سرویکس را با PHP 8.2 یا جدیدتر پیادهسازی میکند. نمونه کامل و بدون وابستگی Composer در مسیر docs/examples/php، لایه HTTP را از اعتبارسنجی قرارداد جدا کرده است تا همه مسیرهای موفق و ناموفق بدون تماس با production تست شوند.
کد را فقط روی سرور، queue worker، job زمانبندیشده یا CLI قابل اعتماد و با افزونه cURL اجرا کنید. API Key یا response احرازشده سرویکس نباید وارد کد مرورگر، URL، HTML عمومی، analytics، گزارش خطا یا log عمومی شود.
تنظیم سمت سرور
export SERVIX_API_KEY="<your-servix-api-key>"
export SERVIX_ASSET_CODE="USD_RLS"
php -l docs/examples/php/src/ServixApiClient.php
php docs/examples/php/tests/ServixApiClientTest.php
php docs/examples/php/example.php
ServixApiClient::fromEnvironment() کلید را هنگام شروع process میخواند. برای توسعه و production کلید جدا بسازید، دسترسی به environment یا secret manager را محدود کنید و بعد از احتمال افشا کلید را فوری لغو کنید.
ارسال درخواست با cURL
transport تستشده redirect را میبندد، timeout اتصال و کل درخواست را مشخص میکند، فقط protocolهای HTTP و HTTPS را میپذیرد و status، header امن و body را به validator میدهد. API Key فقط در header درخواست قرار میگیرد.
<?php
$handle = curl_init(
$baseUrl . '/api/v1/assets/supported',
);
$responseHeaders = [];
curl_setopt_array($handle, [
CURLOPT_CONNECTTIMEOUT_MS => 3_000,
CURLOPT_TIMEOUT_MS => 10_000,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'X-API-Key: ' . $apiKey,
],
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS | CURLPROTO_HTTP,
CURLOPT_RETURNTRANSFER => true,
]);
$body = curl_exec($handle);
if ($body === false) {
throw new ServixNetworkException(
'Servix network request failed.',
);
}
$status = (int) curl_getinfo(
$handle,
CURLINFO_RESPONSE_CODE,
);
curl_close($handle);
try {
$payload = json_decode(
$body,
true,
64,
JSON_THROW_ON_ERROR,
);
} catch (JsonException $exception) {
throw new ServixSchemaException(
'Servix returned malformed JSON.',
);
}
بررسی دسترسی و تازگی
$asset = null;
foreach ($payload['assets'] ?? [] as $candidate) {
if (is_array($candidate)
&& ($candidate['code'] ?? null) === $assetCode) {
$asset = $candidate;
break;
}
}
if ($asset === null) {
throw new ServixUnavailableException();
}
foreach (['providerSupported', 'latestValueAvailable', 'stale'] as $field) {
if (!array_key_exists($field, $asset)
|| !is_bool($asset[$field])) {
throw new ServixSchemaException();
}
}
if (!$asset['providerSupported']
|| !$asset['latestValueAvailable']) {
throw new ServixUnavailableException();
}
if ($asset['stale']
|| ($asset['availabilityStatus'] ?? null) !== 'FRESH') {
throw new ServixStaleDataException();
}
if ((!is_int($asset['latestValue'])
&& !is_float($asset['latestValue']))
|| !is_finite((float) $asset['latestValue'])) {
throw new ServixSchemaException();
}
نسخه کامل HTTPS، HTTP محدود به loopback تست، شکل asset code، timezone در businessTime، هماهنگی تازگی، عدد finite و request ID امن را هم پیش از ساخت AssetQuote immutable بررسی میکند.
قرارداد response احرازشده
{
"code": "USD_RLS",
"providerSupported": true,
"latestValueAvailable": true,
"latestValue": "<protected-market-value>",
"businessTime": "<source-timestamp>",
"availabilityStatus": "FRESH",
"stale": false
}
businessTime زمان خود داده است. وضعیتهای STALE، MISSING و UNKNOWN را حالتهای واقعی محصول بدانید. برای داده unavailable صفر نسازید و مقدار قدیمی را بدون برچسب stale استفاده نکنید. کدهای پایانیافته به _RLS ریالی هستند؛ تبدیل به تومان را در لایه نمایش خودتان انجام دهید.
خطای HTTP و retry محدود
| وضعیت | رفتار PHP |
|---|---|
| خطای اتصال یا timeout در cURL | حداکثر سه بار با فاصله نمایی retry کنید و بعد فقط دسته خطای امن را برگردانید. |
| 400، 401، 403، 404 | درخواست بدون تغییر را retry نکنید؛ request، API Key، دسترسی حساب یا asset code را اصلاح کنید. |
| 429 | سهمیه روزانه تمام شده است؛ polling را تا پنجره بعدی متوقف کنید. |
| 500، 502، 503، 504 | retry محدود خطای موقت را اجرا کنید و بعد امن fail شوید. |
| JSON یا قرارداد خراب | response را رد کنید؛ نوع فیلد را حدس نزنید و مقدار ساختگی نسازید. |
تستها یک transport ساختگی تزریق میکنند و URL، header، timeout، mapping موفق، backoff شبکه و 5xx، رفتار 401 و 429، JSON خراب، boolean ناقص، داده stale و unavailable، asset ناشناخته و تنظیم ناامن را میسنجند. هیچ کلید واقعی یا response بازار production برای تست لازم نیست.
cache و ادامه مسیر
فقط response احرازشده و معتبر را در بکاند cache کنید و businessTime را کنار آن نگه دارید. cache را میان کاربران مشترک کنید، TTL را کوتاهتر از پنجره تازگی قابل قبول بگذارید و برای هر مرورگر polling جدا نسازید. احراز هویت، نمادهای پشتیبانیشده، خطا و سهمیه، راهنمای Spring Boot و راهنمای Python را هم ببینید.
ساخت حساب و فعالسازی دسترسی API · مقایسه پلنها و سهمیه روزانه