لجلب أسعار الذهب المباشرة في PHP، أرسل طلب GET إلى api.goldprice.dev/v1/spot/XAU-USD-SPOT باستخدام cURL المدمجة، وضع مفتاح API في ترويسة X-API-Key. لا تحتاج إلى Composer. فك ترميز JSON، وأبقِ الأسعار كنصوص، واستخدم BCMath للحساب العشري الدقيق. خزّن كل رمز لمدة 60 ثانية. تشمل الخطة المجانية 5,000 طلب شهريا دون بطاقة ائتمان. اختُبر في يونيو 2026 على PHP 8.3.
احصل على مفتاح API من goldprice.dev
أنشئ حسابا مجانيا على goldprice.dev/onboarding. بعد تأكيد بريدك الإلكتروني، تعرض لوحة التحكم مفتاحا يبدأ بـ ga_live_. احفظه في متغير بيئة:
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_hereتشمل الخطة المجانية 5,000 طلب شهريا وأسعار الذهب الفورية بـ 31 عملة. لا تحتاج إلى بطاقة ائتمان.
تحقق من الإضافات المطلوبة
لا تحتاج إلى حزم Composer. يتضمن PHP 8 كلا من curl وjson، وbcmath إضافة قياسية للحساب العشري الدقيق. تحقق من تفعيل الإضافات الثلاث:
php -m | grep -E '^(curl|json|bcmath)$'# curl# json# bcmath <- if missing, install php8.3-bcmath (or enable in php.ini)اكتب عميل goldprice
احفظ هذا الكود باسم goldprice.php. تخزّن spot() كل رمز لمدة 60 ثانية في مصفوفة ساكنة، وتعيد المحاولة حتى 3 مرات عند 429 بتأخير متزايد أسيا. تعيد المصفوفة بعد فك الترميز مع إبقاء الأسعار كنصوص لتتمكن BCMath من إجراء الحساب بدقة.
<?php// php: goldprice.php, native cURL + BCMath, no Composer// curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOTdeclare(strict_types=1);const API_BASE = 'https://api.goldprice.dev';const TIMEOUT = 5; // secondsconst TTL = 60; // secondsfinal class RateLimitedException extends RuntimeException {}final class GoldpriceClient{ private string $apiKey; /** @var array<string, array{data: array, expires: int}> */ private static array $cache = []; public function __construct() { $key = getenv('GOLDPRICE_API_KEY'); if ($key === false || $key === '') { throw new RuntimeException('GOLDPRICE_API_KEY not set'); } $this->apiKey = $key; } /** * Fetch live spot price. Cached 60s per symbol, retries 3x on 429. * Prices stay as strings for BCMath. */ public function spot(string $symbol = 'XAU-USD-SPOT'): array { $now = time(); if (isset(self::$cache[$symbol]) && self::$cache[$symbol]['expires'] > $now) { return self::$cache[$symbol]['data']; } for ($attempt = 0; $attempt < 3; $attempt++) { try { $data = $this->fetch($symbol); self::$cache[$symbol] = ['data' => $data, 'expires' => $now + TTL]; return $data; } catch (RateLimitedException) { sleep(1 << $attempt); // 1s, 2s, 4s } } throw new RateLimitedException('goldprice: 429 after 3 retries'); } private function fetch(string $symbol): array { $ch = curl_init(API_BASE . '/v1/spot/' . rawurlencode($symbol)); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => TIMEOUT, CURLOPT_HTTPHEADER => ['X-API-Key: ' . $this->apiKey], ]); $body = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($code === 429) { throw new RateLimitedException('rate limited'); } if ($code !== 200 || $body === false) { throw new RuntimeException("goldprice: unexpected status {$code}"); } return json_decode((string) $body, true, 512, JSON_THROW_ON_ERROR); }}$client = new GoldpriceClient();$r = $client->spot('XAU-USD-SPOT');// Prices are strings; use BCMath for exact math (e.g. price for 5 oz):$fiveOz = bcmul($r['price'], '5', 4);printf("%s-%s: %s (computed %s)\n", $r['symbol'], $r['quote_currency'], $r['price'], $r['computed_at']);printf("5 troy oz = %s %s\n", $fiveOz, $r['quote_currency']);شغّل الكود
شغّل الملف عبر CLI من الطرفية التي صدّرت فيها GOLDPRICE_API_KEY. يرسل الاستدعاء الأول طلبا إلى API. تعيد استدعاءات spot() اللاحقة داخل العملية نفسها خلال 60 ثانية المصفوفة المخزّنة. التخزين الساكن خاص بكل عملية. استخدم APCu أو Redis لمشاركته بين الطلبات تحت PHP-FPM.
php goldprice.php# XAU-USD: 4012.75 (computed 2026-10-23T07:00:18.221118+00:00)# 5 troy oz = 20063.7500 USDغيّر العملة أو المعدن
صيغة الرموز هي METAL-CURRENCY-SPOT. مرّر رمزا بأي من العملات الفورية الـ 31 إلى spot(). يُخزّن كل رمز مستقلا في المصفوفة الساكنة. صفحة تعرض 5 رموز ترسل بحد أقصى 5 طلبات عند غياب التخزين المؤقت، وتعيد استخدامها عند العرض التالي خلال مدة التخزين.
$client = new GoldpriceClient();// USD spot, default$client->spot('XAU-USD-SPOT');$client->spot('XAU-INR-SPOT');$client->spot('XAU-EUR-SPOT');// Silver in USD$client->spot('XAG-USD-SPOT');النتيجة المتوقعة
{ "symbol": "XAU", "quote_currency": "USD", "unit": "troy_ounce", "contract_type": "spot", "price": "4012.75", "is_stale": false, "computed_at": "2026-10-23T07:00:18.221118+00:00"}تعرض CLI سطرين: الرمز والعملة والسعر والطابع الزمني، ثم ناتج ضرب BCMath لكمية 5 أونصات تروي. يستخدم الكود اللاحق المصفوفة بعد فك الترميز، وتبقى الأسعار كنصوص.
أخطاء شائعة
| الرمز | ما يظهر لك | الحل |
|---|---|---|
| 401 | RuntimeException: goldprice: unexpected status 401 | مفتاح API مفقود أو غير صالح. تحقق من وصول المتغير إلى PHP: php -r 'echo getenv("GOLDPRICE_API_KEY");'. لا تُشارك متغيرات بيئة CLI مع PHP-FPM، لذا اضبط المفتاح عبر fastcgi_param أو مدير العمليات. إن كان فارغا، انسخه مجددا من لوحة التحكم. |
| 429 | تعيد المحاولات الثلاث مع التأخير الرمز 429، ثم يُطرح RateLimitedException | بلغت حد الطلبات في الدقيقة. يمنع التخزين المؤقت لمدة 60 ثانية ذلك مع الطلبات المنتظمة. تحت PHP-FPM، التخزين الساكن خاص بكل طلب، لذا استخدم APCu عبر apcu_fetch / apcu_store لمشاركته بين الطلبات. للاستخدام المكثف المستمر، راجع الخطط المدفوعة في /pricing. |
| N/A | تظهر أخطاء تقريب عند تحويل الأسعار إلى float لإجراء الحساب | لا تحوّل السعر إلى (float) قبل الحساب، لأن الأعداد العائمة في PHP تفقد الدقة عند الجمع. أبقِ القيمة بالنص الذي تعيده API، واستخدم bcadd وbcmul وbccomp مع تحديد عدد المنازل العشرية صراحة. فعّل إضافة bcmath إذا كانت هذه الدوال غير معرّفة. |
خطوات إضافية
- استبدل التخزين الساكن بـ
apcu_store/apcu_fetchليخدم جلب واحد جميع عمليات PHP-FPM العاملة طوال 60 ثانية - أضف الدالة
bars()لاستدعاء/v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=...واعرض الصفوف في مخطط باستخدام محرك القوالب - غلّف
spot()بخدمة بسيطة في Laravel أو Symfony، وسجّلها في الحاوية لحقن الاعتماديات - أضف فحص
If-None-Match/ ETag عند الاستعلام عن الرمز نفسه من عمليات عاملة عديدة لتجاوز البيانات التي لم تتغير - نسّق الأسعار للعرض باستخدام
bcdivوعوامل التحويل من أونصة تروي إلى الغرام لعرض سعر التجزئة لكل غرام