واجهة API لأسعار الذهب في PHP: cURL وGuzzle ورمز قصير في WordPress
استخدم واجهة API لأسعار الذهب في PHP عبر cURL أو Guzzle، ثم أضف إلى WordPress رمزًا قصيرًا [gold_price] مع transients وWP-Cron، أو اختر ودجة بلا شيفرة.
واجهة API لأسعار الذهب في PHP: الأساسيات
تمنح واجهة API لأسعار الذهب شيفرة PHP لديك سعر الذهب الحالي بصيغة JSON، لأسعار المنتجات أو لسطر سعر في سمة أو لتقرير يومي. يغطي هذا الدرس PHP العادية مع cURL، وعميل HTTP المسمى Guzzle، وWordPress، حيث يضع رمز قصير [gold_price] مخزَّن مؤقتًا يحدّثه WP-Cron السعرَ في أي مقالة أو صفحة. ويستخدم MetalAPI، وهي واجهة REST بصيغة JSON للمعادن الثمينة والمعادن الصناعية والطاقة والعملات والعملات المشفرة.
تحتاج إلى مفتاح API من لوحة تحكم MetalAPI. تبدأ المفاتيح بـ mk_live_، وتتضمن خطة Free مئة طلب شهريًا مع تحديث يومي للأسعار، دون بطاقة ائتمان. أبقِ المفتاح خارج شيفرتك: في متغير بيئة مع PHP العادية، أو في wp-config.php مع WordPress.
كل نقطة نهاية هي طلب GET تحت https://metalapi.com/api/v1. أرسل المفتاح في ترويسة X-API-Key (أو بصيغة Authorization: Bearer) بدلًا من معامل الاستعلام api_key، حتى يبقى خارج سجلات الوصول. وهذه استجابة من /latest بالقيم النموذجية من التوثيق:
{
"success": true,
"timestamp": 1792834892,
"date": "2026-10-24",
"base": "USD",
"rates": {
"XAU": 0.0002501319,
"USDXAU": 3997.89,
"EUR": 0.8925,
"USDEUR": 1.1204
},
"rate_limit": { "...": "..." }
}rates.USDXAU هو سعر أونصة تروي واحدة من الذهب بالدولار؛ وrates.XAU هو مقلوبه، أي عدد الأونصات لكل دولار، فلا تعرضه أبدًا على أنه سعر. وrates.USDEUR هو سعر يورو واحد بالدولار، وتستخدمه إضافة WordPress للتحويل. وtimestamp هو وقت بيانات السعر بثواني Unix.
كيف تحصل على سعر الذهب في PHP باستخدام cURL
يأتي امتداد cURL مع كل تثبيت لـ PHP تقريبًا. ترسل هذه الدالة المفتاح في ترويسة، وتضبط المهل الزمنية، وتحوّل أعطال الشبكة وأخطاء الواجهة إلى استثناءات:
<?php
// PHP 8+ with the curl extension. Run: METALAPI_KEY=mk_live_... php gold.php
function metalapi(string $path, array $params = []): array
{
$ch = curl_init('https://metalapi.com/api/v1/' . $path . '?' . http_build_query($params));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . getenv('METALAPI_KEY')],
]);
$body = curl_exec($ch);
if ($body === false) {
throw new RuntimeException('Network error: ' . curl_error($ch));
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$data = json_decode($body, true);
if (empty($data['success'])) {
$code = $data['error']['code'] ?? $status;
$info = $data['error']['info'] ?? "HTTP $status";
throw new RuntimeException("MetalAPI $code: $info", $code);
}
return $data;
}
$data = metalapi('latest', ['base' => 'USD', 'currencies' => 'XAU']);
printf("Gold: %.2f USD per troy oz\n", $data['rates']['USDXAU']);
printf("Time: %s UTC\n", gmdate('Y-m-d H:i', $data['timestamp']));مع القيم النموذجية يطبع Gold: 3997.89 USD per troy oz. ورمز الاستثناء هو رمز الخطأ في MetalAPI: أعد محاولة 104 (الحد لكل دقيقة) بعد انقضاء عدد ثواني Retry-After، و500 أو 503 مع تراجع تدريجي، لكن أصلح سبب رموز مثل 102 (مفتاح غير صالح) أو 105 (استُنفدت الحصة الشهرية) أو 106 (نقطة النهاية غير مشمولة في خطتك). ويسرد دليل معالجة الأخطاء جميع الرموز.
استخدام Guzzle بدلًا من cURL
في مشروع Composer، يؤدي Guzzle المهمة نفسها في أسطر أقل. أبقِ الشرطة المائلة في نهاية base_uri واطلب مسارات نسبية مثل latest، لأن Guzzle يحلّ /latest نسبةً إلى جذر النطاق. وعطّل http_errors، حتى تُرجع استجابات الخطأ جسم JSON من MetalAPI بدلًا من إطلاق استثناء:
<?php
// composer require guzzlehttp/guzzle
require __DIR__ . '/vendor/autoload.php';
$client = new GuzzleHttp\Client([
'base_uri' => 'https://metalapi.com/api/v1/',
'timeout' => 10,
'http_errors' => false,
'headers' => ['X-API-Key' => (string) getenv('METALAPI_KEY')],
]);
$res = $client->get('latest', ['query' => ['base' => 'EUR', 'currencies' => 'XAU', 'unit' => 'gram']]);
$data = json_decode((string) $res->getBody(), true);
if (empty($data['success'])) {
$code = $data['error']['code'] ?? $res->getStatusCode();
throw new RuntimeException("MetalAPI $code: " . ($data['error']['info'] ?? $res->getReasonPhrase()), $code);
}
printf("Gold: %.2f EUR per gram\n", $data['rates']['EURXAU']);ما زالت المهل الزمنية وأعطال الشبكة الأخرى تطلق ConnectException، لذا التقطه حيث يجب ألا يعطّل الفشلُ الصفحة.
سعر الذهب في WordPress: رمز قصير [gold_price] مخزَّن مؤقتًا
داخل WordPress، استخدم بدلًا من ذلك wp_remote_get() من واجهة HTTP المدمجة. وتُبقي قاعدتان في التصميم الرمز القصير سريعًا ومنخفض التكلفة:
- لا تستدعِ الواجهة أثناء عرض الصفحة. تحتفظ الإضافة بالأسعار في transient يحدّثه WP-Cron في الخلفية. ولا يتسبب الزوار في إرسال طلب إلا حين يكون الـ transient مفقودًا، كما يحدث مباشرةً بعد التفعيل.
- اطلب كل العملات في استدعاء واحد. مع عملة الأساس
USDوcurrencies=XAU,EUR,GBP، تحتوي الاستجابة على سعر الذهب وسعر كل عملة بالدولار من اللقطة نفسها، فيكون سعر الذهب باليوروUSDXAU ÷ USDEUR، وتُشتق الغرامات من 31.1034768 غرامًا لكل أونصة تروي. ويغطي طلب واحد لكل تحديث جميع العملات والوحدات.
قد تختفي الـ transients قبل انتهاء صلاحيتها، مثلًا حين تحذفها ذاكرة تخزين مؤقت دائمة للكائنات (persistent object cache)، لذا تحتفظ الإضافة أيضًا بآخر أسعار صالحة في خيار (option). وإذا فشل التحديث، تسجّل الخطأ وتقدّم تلك النسخة لمدة خمس دقائق. أضف أولًا المفتاح إلى wp-config.php، فوق السطر الذي يطلب التوقف عن التعديل:
define( 'METALAPI_KEY', 'mk_live_your_key_here' );ثم احفظ الإضافة باسم wp-content/plugins/metalapi-gold-price/metalapi-gold-price.php وفعّلها من الإضافات (Plugins):
<?php
/**
* Plugin Name: MetalAPI Gold Price
* Description: [gold_price] shortcode, cached in a transient and refreshed by WP-Cron.
* Requires PHP: 8.0
*/
defined( 'ABSPATH' ) || exit;
const MGP_INTERVAL = 600; // seconds. Standard: 600, Lite: 3600, Free: 86400
const MGP_CURRENCIES = [ 'EUR', 'GBP' ]; // besides USD, every currency your shortcodes use
const MGP_GRAMS = [ 'troy_oz' => 31.1034768, 'gram' => 1, 'kilogram' => 1000 ];
function mgp_refresh(): ?array {
if ( ! defined( 'METALAPI_KEY' ) ) {
return null;
}
$url = add_query_arg(
[ 'base' => 'USD', 'currencies' => implode( ',', [ 'XAU', ...MGP_CURRENCIES ] ) ],
'https://metalapi.com/api/v1/latest'
);
$res = wp_remote_get( $url, [ 'timeout' => 8, 'headers' => [ 'X-API-Key' => METALAPI_KEY ] ] );
$data = is_wp_error( $res ) ? null : json_decode( wp_remote_retrieve_body( $res ), true );
if ( empty( $data['success'] ) ) {
error_log( 'MetalAPI refresh failed: ' . ( is_wp_error( $res ) ? $res->get_error_message() : wp_remote_retrieve_body( $res ) ) );
$last = get_option( 'mgp_prices_last' );
if ( $last ) {
set_transient( 'mgp_prices', $last, 5 * MINUTE_IN_SECONDS ); // back off, keep the last good prices
}
return $last ?: null;
}
$per_oz = [ 'USD' => $data['rates']['USDXAU'] ];
foreach ( MGP_CURRENCIES as $cur ) {
if ( ! empty( $data['rates'][ "USD$cur" ] ) ) {
$per_oz[ $cur ] = $data['rates']['USDXAU'] / $data['rates'][ "USD$cur" ];
}
}
$prices = [ 'per_oz' => $per_oz, 'time' => $data['timestamp'] ];
set_transient( 'mgp_prices', $prices, 2 * MGP_INTERVAL ); // survives one late cron run
update_option( 'mgp_prices_last', $prices, false ); // fallback if the transient is evicted
return $prices;
}
function mgp_prices(): ?array {
return get_transient( 'mgp_prices' ) ?: mgp_refresh();
}
add_shortcode( 'gold_price', function ( $atts ): string {
$a = shortcode_atts( [ 'currency' => 'USD', 'unit' => 'troy_oz', 'decimals' => 2 ], $atts, 'gold_price' );
$cur = strtoupper( $a['currency'] );
$unit = strtolower( $a['unit'] );
$p = mgp_prices();
if ( ! $p || ! isset( $p['per_oz'][ $cur ] ) || ! array_key_exists( $unit, MGP_GRAMS ) ) {
return '';
}
$price = $p['per_oz'][ $cur ] / MGP_GRAMS['troy_oz'] * MGP_GRAMS[ $unit ];
return sprintf(
'<span class="gold-price">%s %s / %s</span> <small>%s</small>',
esc_html( number_format_i18n( $price, absint( $a['decimals'] ) ) ),
esc_html( $cur ),
esc_html( str_replace( '_', ' ', $unit ) ),
esc_html( wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $p['time'] ) )
);
} );
// WP-Cron: refresh in the background once per interval.
add_filter( 'cron_schedules', function ( array $schedules ): array {
$schedules['mgp_interval'] = [ 'interval' => MGP_INTERVAL, 'display' => 'MetalAPI refresh' ];
return $schedules;
} );
add_action( 'mgp_refresh_event', 'mgp_refresh' );
register_activation_hook( __FILE__, function (): void {
if ( ! wp_next_scheduled( 'mgp_refresh_event' ) ) {
wp_schedule_event( time(), 'mgp_interval', 'mgp_refresh_event' );
}
} );
register_deactivation_hook( __FILE__, function (): void {
wp_clear_scheduled_hook( 'mgp_refresh_event' );
} );استخدمه في أي مقالة أو صفحة أو مكوّن رمز قصير (Shortcode) بالصيغة [gold_price] أو [gold_price currency="EUR" unit="gram"]. ومع الأسعار النموذجية، يعرض الثاني 114.72 EUR / gram: إذ يعطي 3997.89 ÷ 1.1204 القيمة 3,568.27 يورو لكل أونصة تروي، والقسمة على 31.1034768 تعطي سعر الغرام. والعملة غير المدرجة في MGP_CURRENCIES لا تطبع شيئًا، لذا أدرج كل عملة تستخدمها رموزك القصيرة.
تحديث أسعار الذهب باستخدام WP-Cron
يجدول خطاف التفعيل التحديث بالفترة المخصصة المسجَّلة عبر cron_schedules، ويزيله إلغاء التفعيل. اضبط MGP_INTERVAL على فترة التحديث في خطتك، أو على فترة أطول حين تتطلب الحصة ذلك:
| الخطة | MGP_INTERVAL | الطلبات في شهر من 31 يومًا | الحصة الشهرية |
|---|---|---|---|
| Free (تحديثات يومية) | 86400 | 31 | 100 |
| Lite (تحديثات كل 30 دقيقة) | 3600 | 744 | 1,000 |
| Standard (تحديثات كل 10 دقائق) | 600 | 4,464 | 10,000 |
WP-Cron ليس مجدولًا حقيقيًا: فهو يشغّل الأحداث المستحقة حين يزور أحدٌ الموقع، لذا قد يتأخر التحديث في موقع قليل الزيارات؛ وتستوعب مدة صلاحية الـ transient المضاعفة والنسخة المخزَّنة ذلك. وللحصول على توقيت دقيق، أضف define( 'DISABLE_WP_CRON', true ); إلى wp-config.php وشغّل الأحداث المستحقة من cron النظام باستخدام WP-CLI:
*/10 * * * * cd /var/www/html && wp cron event run --due-now > /dev/null 2>&1خطّط أيضًا للتخزين المؤقت للصفحات: فذاكرة التخزين المؤقت للصفحات الكاملة تخزّن مخرجات الرمز القصير مع الصفحة، فيرى الزوار السعر كما كان لحظة تخزين الصفحة. اجعل مدة التخزين المؤقت لصفحات الأسعار مساوية لفترة التحديث أو أقل منها.
متى تكون الودجة بلا شيفرة الخيار الأفضل
الرمز القصير هو الأداة المناسبة حين يجب أن يكون السعر جزءًا من HTML لديك أو حين تحتاج شيفرة PHP إلى الرقم، مثلًا لإعادة تسعير المنتجات. أما إن كنت تريد عرض الأسعار فقط، فودجة MetalAPI أبسط:
- لا مفتاح API ولا PHP. تبني الودجة في لوحة التحكم وتلصق شيفرة التضمين الخاصة بها في مكوّن HTML مخصص (Custom HTML). ولا تتطلب التغييرات اللاحقة على الرموز أو التخطيط أي تعديل على موقعك.
- لا استهلاك للحصة. لا تستهلك مشاهدات صفحات الودجة طلباتك الشهرية، وتتضمن كل خطة ودجات: 1 في Free، و3 في Lite، و10 في Standard.
- آمنة مع التخزين المؤقت للصفحات. تُحمَّل الأسعار داخل iframe، لذا لا تجمّدها أبدًا صفحة مخزَّنة مؤقتًا.
<div id="metalapi-widget-w_abc123"></div>
<script src="https://metalapi.com/js/widget.js" data-widget="w_abc123" async></script>إذا كانت استضافتك تحذف وسوم <script>، فاستخدم نسخة iframe من شيفرة التضمين. ويتناول مقال كيف تضيف ودجة لأسعار الذهب المباشرة أداة البناء ووضع الودجة في WordPress وحدود الخطط، وتعرض صفحة الودجات التخطيطات المتاحة.
الخطوات التالية
أنشئ حسابًا مجانيًا، وأضف مفتاحك إلى wp-config.php، وثبّت الإضافة مع ضبط MGP_INTERVAL على 86400: فالتحديث اليومي يستهلك 31 طلبًا من حصة خطة Free البالغة 100 طلب شهريًا. وحين تحتاج إلى أسعار أحدث، اضبط الفترة على فترة التحديث في خطتك الجديدة وقارن الخطط في صفحة الأسعار. ولواجهات Node.js الخلفية، يوضّح مقال واجهة API لأسعار الذهب في JavaScript الأنماط نفسها مع Express وNext.js.
الأسئلة الشائعة
أين ينبغي أن أخزّن مفتاح API في WordPress؟
في wp-config.php بوصفه ثابتًا، أو في متغير بيئة يُقرأ هناك. ولا تضعه أبدًا في ملفات السمة، التي كثيرًا ما ينتهي بها المطاف في Git، ولا في JavaScript، التي يستطيع كل زائر قراءتها. ولا ترسل طلبات PHP ترويسة Origin أو Referer، لذا يعمل حتى المفتاح المقيَّد بالنطاق من الخادم.
لماذا يعرض الرمز القصير سعر الذهب نفسه طوال عطلة نهاية الأسبوع؟
لا يُتداول الذهب الفوري من الجمعة 17:00 حتى الأحد 17:00 بتوقيت نيويورك، لذا تُرجع الواجهة آخر سعر حتى تُعاد فتح الأسواق. وفي خطة Free، لا تتغير الأسعار أيضًا إلا مرة واحدة يوميًا.
كم طلب API ستستهلك الإضافة؟
طلبًا واحدًا لكل تحديث، مهما كان عدد الزوار أو الصفحات أو الرموز القصيرة لديك، لأن استدعاءً واحدًا يُرجع كل العملات وتُحوَّل الوحدات محليًا: نحو 4,500 طلب شهريًا مع فترة 10 دقائق.
هل يمكنني استخدام سعر الذهب في أسعار منتجات WooCommerce؟
نعم. استدعِ mgp_prices() من PHP، مثلًا في مرشّح woocommerce_product_get_price، واضرب سعر الغرام في وزن المنتج ونقائه. وخزّن سعر الذهب المستخدم مع كل طلب شراء، حتى لا تتغير الفواتير لاحقًا.
هل أحتاج إلى cURL أو Guzzle في WordPress؟
لا. تستخدم wp_remote_get() واجهة HTTP في WordPress، التي تختار وسيلة نقل متاحة وتحترم إعدادات الخادم الوكيل. واحتفظ بـ cURL أو Guzzle لـ PHP العادية وأطر العمل مثل Laravel أو Symfony.
جرّبه مع بياناتك الخاصة
أنشئ حسابًا مجانيًا وأرسل طلبك الأول في أقل من دقيقتين. 100 طلب شهريًا، دون بطاقة ائتمان.
تابع القراءة
معنى XAU/USD: ماذا تعني الرموز XAU وXAG وXPT وXPD
شرح معنى XAU/USD: لماذا يملك الذهب رمز عملة في ISO 4217، وماذا تعني XAG وXPT وXPD، وكيف تقرأ اتجاه التسعير في الأسعار وفي بيانات واجهة API.
واجهة API مجانية لأسعار الذهب: ماذا تقدّم 100 طلب شهريًا
شرح صريح لواجهة API مجانية لأسعار الذهب: ما الذي تتضمنه خطة Free في MetalAPI، وكيف تكفي 100 طلب شهريًا بالتخزين المؤقت والتجميع، ومتى تنتقل إلى خطة مدفوعة.
واجهة API لأسعار الذهب في Python: الجلب والتخزين المؤقت والرسم
استخدم واجهة API لأسعار الذهب في Python: اجلب الأسعار اللحظية عبر requests، وعالج الأخطاء، وخزّن الاستجابات مؤقتًا، وارسم سلسلة زمنية بـ pandas وmatplotlib.