MetalAPI
XAU3.997,89−1,54%XAG53,936−1,51%XPT1.554,47−0,83%XPD1.047,03−0,44%XCU6,5080+2,29%WTI103,27+3,82%BRENT111,70−1,30%EUR1,120400−0,01%GBP1,337500−0,01%JPY0,0063761+0,14%CHF1,213445−0,25%TRY0,020125−0,12%BTC80.635,11−0,17%ETH2.353,78−0,09%
Todos os artigos
OuroPHPWordPressTutorial

API de preços do ouro em PHP: cURL, Guzzle e shortcode no WordPress

Use uma API de preços do ouro em PHP com cURL ou Guzzle, crie um shortcode [gold_price] no WordPress com transients e WP-Cron ou use um widget sem código.

Por MetalAPI Team··7 min de leitura

API de preços do ouro em PHP: o básico

Uma API de preços do ouro entrega ao seu código PHP o preço atual do ouro em JSON, para preços de produtos, uma linha de cotação em um tema ou um relatório diário. Este tutorial aborda PHP puro com cURL, o cliente HTTP Guzzle e o WordPress, onde um shortcode [gold_price] com cache, atualizado pelo WP-Cron, coloca o preço em qualquer post ou página. Ele usa a MetalAPI, uma API REST em JSON para metais preciosos, metais industriais, energia, moedas e cripto.

Você precisa de uma chave de API do painel da MetalAPI. As chaves começam com mk_live_, e o plano Free inclui 100 requisições por mês com atualização diária dos preços, sem cartão de crédito. Mantenha a chave fora do seu código: em uma variável de ambiente no PHP puro, ou no wp-config.php no WordPress.

Todo endpoint é uma requisição GET sob https://metalapi.com/api/v1. Envie a chave no cabeçalho X-API-Key (ou como Authorization: Bearer) em vez do parâmetro de consulta api_key, para que ela fique fora dos logs de acesso. Uma resposta de /latest com os valores de exemplo da documentação:

GET /api/v1/latest?base=USD&currencies=XAU,EUR
{
  "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 é o preço de uma onça troy de ouro em dólares; rates.XAU é o seu inverso, onças por dólar, então nunca o exiba como preço. rates.USDEUR é o preço de um euro em dólares, que o plugin para WordPress usa na conversão. timestamp é o horário dos dados de preço em segundos Unix.

Como obter o preço do ouro em PHP com cURL

A extensão cURL vem em quase toda instalação de PHP. Esta função envia a chave em um cabeçalho, define timeouts e transforma falhas de rede e erros da API em exceções:

gold.php
<?php
// PHP 8+ com a extensão curl. Execute: 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']));

Com os valores de exemplo, ele imprime Gold: 3997.89 USD per troy oz. O código da exceção é o código de erro da MetalAPI: tente de novo o 104 (o limite por minuto) após os segundos indicados em Retry-After e o 500 ou 503 com backoff, mas corrija a causa de códigos como 102 (chave inválida), 105 (cota mensal esgotada) ou 106 (endpoint fora do seu plano). O guia de tratamento de erros lista todos os códigos.

Usando Guzzle em vez de cURL

Em um projeto com Composer, o Guzzle faz o mesmo em menos linhas. Mantenha a barra final em base_uri e solicite caminhos relativos como latest, porque o Guzzle resolve /latest a partir da raiz do domínio. E desative http_errors, para que as respostas de erro retornem o corpo JSON da MetalAPI em vez de lançar uma exceção:

gold-guzzle.php
<?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']);

Timeouts e outras falhas de rede continuam lançando uma ConnectException, então capture-a onde uma falha não pode quebrar a página.

Preço do ouro no WordPress: um shortcode [gold_price] com cache

Dentro do WordPress, use wp_remote_get(), da HTTP API nativa. Duas regras de design mantêm o shortcode rápido e barato:

  • Não chame a API enquanto uma página é renderizada. O plugin mantém os preços em um transient que o WP-Cron atualiza em segundo plano. Os visitantes só disparam uma requisição quando o transient não existe, por exemplo logo após a ativação.
  • Solicite todas as moedas em uma só chamada. Com base USD e currencies=XAU,EUR,GBP, a resposta traz o preço em dólares do ouro e de cada moeda a partir do mesmo instantâneo, então o ouro em euros é USDXAU ÷ USDEUR, e os gramas resultam de 31,1034768 gramas por onça troy. Uma requisição por atualização cobre todas as moedas e unidades.

Transients podem sumir antes de expirar, por exemplo quando um cache de objetos persistente os descarta, então o plugin também guarda os últimos preços válidos em uma opção. Se uma atualização falha, ele registra o erro e serve essa cópia por cinco minutos. Primeiro, adicione a chave ao wp-config.php, acima da linha que diz para parar de editar:

wp-config.php
define( 'METALAPI_KEY', 'mk_live_your_key_here' );

Depois, salve o plugin como wp-content/plugins/metalapi-gold-price/metalapi-gold-price.php e ative-o em Plugins:

metalapi-gold-price.php
<?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;              // segundos. Standard: 600, Lite: 3600, Free: 86400
const MGP_CURRENCIES = [ 'EUR', 'GBP' ]; // além de USD, todas as moedas que os seus shortcodes usam
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 ); // espera e mantém os últimos preços válidos
        }
        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 ); // sobrevive a uma execução atrasada do cron
    update_option( 'mgp_prices_last', $prices, false );       // reserva caso o transient seja descartado
    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: atualiza em segundo plano uma vez por intervalo.
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' );
} );

Use-o em qualquer post, página ou bloco Shortcode como [gold_price] ou [gold_price currency="EUR" unit="gram"]. Com as cotações de exemplo, o segundo exibe 114,72 EUR / gram: 3.997,89 ÷ 1,1204 resulta em 3.568,27 euros por onça troy, e a divisão por 31,1034768 dá o preço por grama. Uma moeda que não está em MGP_CURRENCIES não imprime nada, então liste todas as moedas que os seus shortcodes usam.

Atualizando os preços do ouro com o WP-Cron

O hook de ativação agenda a atualização com o intervalo personalizado registrado via cron_schedules, e a desativação o remove. Defina MGP_INTERVAL como o intervalo de atualização do seu plano, ou mais longo quando a cota exigir:

PlanoMGP_INTERVALRequisições em um mês de 31 diasCota mensal
Free (atualização diária)8640031100
Lite (atualização a cada 30 minutos)36007441.000
Standard (atualização a cada 10 minutos)6004.46410.000

O WP-Cron não é um agendador de verdade: ele executa os eventos pendentes quando alguém visita o site, então, em um site com pouco tráfego, uma atualização pode atrasar; a vida útil dobrada do transient e a cópia armazenada absorvem isso. Para um horário exato, adicione define( 'DISABLE_WP_CRON', true ); ao wp-config.php e execute os eventos pendentes pelo cron do sistema com o WP-CLI:

crontab
*/10 * * * * cd /var/www/html && wp cron event run --due-now > /dev/null 2>&1

Leve em conta também o cache de páginas: um cache de página inteira armazena a saída do shortcode junto com a página, então os visitantes veem o preço do momento em que a página foi armazenada. Mantenha a vida útil do cache das páginas com preços igual ou inferior ao seu intervalo de atualização.

Quando um widget sem código é a melhor escolha

O shortcode é a ferramenta certa quando o preço precisa fazer parte do seu HTML ou quando o PHP precisa do número, por exemplo para reprecificar produtos. Se você só quer exibir preços, um widget da MetalAPI é mais simples:

  • Sem chave de API e sem PHP. Você cria o widget no painel e cola o código de incorporação dele em um bloco HTML personalizado (Custom HTML). Mudanças posteriores de símbolos ou de layout não exigem nenhuma edição no seu site.
  • Sem consumo de cota. As visualizações de página dos widgets não usam as suas requisições mensais, e todos os planos incluem widgets: 1 no Free, 3 no Lite e 10 no Standard.
  • Seguro com cache de páginas. Os preços são carregados dentro de um iframe, então uma página em cache nunca os congela.
Código de incorporação do widget
<div id="metalapi-widget-w_abc123"></div>
<script src="https://metalapi.com/js/widget.js" data-widget="w_abc123" async></script>

Se a sua hospedagem remove as tags <script>, use a versão em iframe do código de incorporação. Como adicionar um widget de cotação do ouro ao vivo aborda o construtor, o posicionamento no WordPress e os limites dos planos; a página de widgets mostra os layouts.

Próximos passos

Crie uma conta grátis, adicione a sua chave ao wp-config.php e instale o plugin com MGP_INTERVAL definido como 86400: uma atualização diária usa 31 das 100 requisições mensais do plano Free. Quando precisar de preços mais recentes, ajuste o intervalo ao intervalo de atualização do seu novo plano e compare os planos na página de preços. Para backends Node.js, API de preços do ouro em JavaScript mostra os mesmos padrões com Express e Next.js.

Perguntas frequentes

Onde devo armazenar a chave de API no WordPress?

No wp-config.php, como uma constante, ou em uma variável de ambiente lida ali. Nunca em arquivos do tema, que muitas vezes acabam no Git, nem em JavaScript, que qualquer visitante pode ler. Requisições feitas pelo PHP não enviam cabeçalho Origin nem Referer, então até uma chave restrita por domínio funciona a partir do servidor.

Por que o shortcode mostra o mesmo preço do ouro durante todo o fim de semana?

O ouro à vista não é negociado das 17h de sexta às 17h de domingo, horário de Nova York, então a API retorna o último preço até a reabertura dos mercados. No plano Free, além disso, os preços só mudam uma vez por dia.

Quantas requisições à API o plugin vai usar?

Uma por atualização, não importa quantos visitantes, páginas ou shortcodes você tenha, porque uma chamada retorna todas as moedas e as unidades são convertidas localmente: cerca de 4.500 por mês com um intervalo de 10 minutos.

Posso usar o preço do ouro nos preços de produtos do WooCommerce?

Sim. Chame mgp_prices() a partir do PHP, por exemplo em um filtro woocommerce_product_get_price, e multiplique o preço por grama pelo peso e pela pureza do produto. Armazene o preço do ouro usado em cada pedido, para que as faturas não mudem depois.

Preciso de cURL ou Guzzle no WordPress?

Não. wp_remote_get() usa a HTTP API do WordPress, que escolhe um transporte disponível e respeita as configurações de proxy. Deixe o cURL ou o Guzzle para PHP puro e para frameworks como Laravel ou Symfony.

Experimente com seus próprios dados

Crie uma conta grátis e faça sua primeira requisição em menos de dois minutos. 100 requisições por mês, sem cartão de crédito.

Continue lendo