Để lấy giá vàng trực tiếp trong Node.js, dùng fetch gốc gửi GET đến api.goldprice.dev/v1/spot/XAU-USD-SPOT kèm khóa API trong header X-API-Key, không cần thư viện HTTP. Lưu phản hồi trong Map 60 giây và tính giá bằng decimal.js. Gói Free có 5.000 lượt gọi/tháng, không cần thẻ tín dụng. Đã kiểm thử tháng Bảy 2026 trên Node 22 LTS.
Lấy khóa API goldprice.dev
Đăng ký miễn phí tại goldprice.dev/onboarding. Sau khi xác nhận email, bạn sẽ thấy khóa bắt đầu bằng ga_live_ trên bảng điều khiển. Đặt khóa làm biến môi trường:
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_hereGói Free có 5.000 lượt gọi/tháng và giá vàng giao ngay bằng 31 loại tiền. Không cần thẻ tín dụng.
Cài decimal.js
Node 18+ có sẵn fetch, không cần thư viện HTTP. Bạn chỉ cần thêm decimal.js để tính giá chính xác, tránh sai số của kiểu Number trong JavaScript. Cài bằng lệnh sau:
npm install decimal.jsViết mã gọi goldprice
Lưu thành goldprice.mjs. Hàm spot() lưu đệm từng mã trong Map 60 giây, thử lại tối đa 3 lần khi gặp 429 với thời gian chờ tăng theo cấp số nhân, rồi trả giá dạng Decimal. Giá mua/bán chỉ có ở gói trả phí, khi thiếu sẽ là null.
// node: goldprice.mjs// curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOTimport Decimal from "decimal.js";const API_BASE = "https://api.goldprice.dev";const API_KEY = process.env.GOLDPRICE_API_KEY;if (!API_KEY) { throw new Error("GOLDPRICE_API_KEY not set");}const TTL_MS = 60_000;const cache = new Map();/** Fetch live spot price. Cached 60s per symbol, retries 3x on 429. */export async function spot(symbol = "XAU-USD-SPOT") { const cached = cache.get(symbol); if (cached && cached.expiresAt > Date.now()) { return cached.data; } let lastErr; for (let attempt = 0; attempt < 3; attempt++) { const res = await fetch(`${API_BASE}/v1/spot/${symbol}`, { headers: { "X-API-Key": API_KEY }, signal: AbortSignal.timeout(5000), }); if (res.status === 429) { lastErr = new Error("goldprice: 429 rate limited"); const backoffMs = 2 ** attempt * 1000; // 1s, 2s, 4s await new Promise((resolve) => setTimeout(resolve, backoffMs)); continue; } if (!res.ok) { throw new Error(`goldprice: unexpected status ${res.status}`); } const raw = await res.json(); const data = { symbol: raw.symbol, quoteCurrency: raw.quote_currency, price: new Decimal(raw.price), bid: raw.bid == null ? null : new Decimal(raw.bid), ask: raw.ask == null ? null : new Decimal(raw.ask), isStale: raw.is_stale, computedAt: raw.computed_at, }; cache.set(symbol, { data, expiresAt: Date.now() + TTL_MS }); return data; } throw lastErr;}Chạy mã
Nhập mô-đun và gọi spot(). Lần đầu gọi API; các lần trong 60 giây trả Decimal từ bộ nhớ đệm, không gửi yêu cầu mạng. Khởi động lại tiến trình sẽ xóa bộ nhớ đệm. Dùng Redis nếu cần chia sẻ giữa các tiến trình.
import { spot } from "./goldprice.mjs";const r = await spot("XAU-USD-SPOT");console.log(`${r.symbol}-${r.quoteCurrency}: ${r.price} (computed ${r.computedAt})`);// XAU-USD: 4012.75 (computed 2026-10-23T07:00:18.221118+00:00)Đổi tiền tệ hoặc kim loại
Mã có dạng METAL-CURRENCY-SPOT. Truyền mã dùng bất kỳ loại tiền nào trong 31 loại được hỗ trợ vào spot(). Mỗi mã có bộ nhớ đệm riêng trong Map. Bảng theo dõi 5 mã mỗi 60 giây gọi API 5 lần/phút nếu chưa có bộ nhớ đệm, 0 lần nếu đã có.
// USD spot, defaultawait spot("XAU-USD-SPOT");await spot("XAU-INR-SPOT");await spot("XAU-EUR-SPOT");// Silver in USDawait spot("XAG-USD-SPOT");Kết quả mong đợi
{ "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"}Stdout in một dòng: mã, tiền định giá, giá dạng Decimal của decimal.js và dấu thời gian computedAt theo ISO 8601. Mã xử lý tiếp theo dùng đối tượng thường do spot() trả về.
Lỗi thường gặp
| Mã | Biểu hiện | Cách sửa |
|---|---|---|
| 401 | goldprice: unexpected status 401 ngay lần gọi đầu | Thiếu khóa API hoặc khóa không hợp lệ. Kiểm tra biến bằng echo $GOLDPRICE_API_KEY. Nếu trống, lấy khóa từ bảng điều khiển và đặt lại biến. Mô-đun báo lỗi ngay khi được nhập nếu biến môi trường trống, giúp phát hiện trước khi gửi yêu cầu. |
| 429 | Cả ba lần thử lại đều nhận 429, sau đó spot() bị từ chối | Bạn đã chạm giới hạn mỗi phút. Bộ nhớ đệm 60 giây giúp tránh lỗi khi truy vấn đều đặn. Nếu nhiều mã khác nhau được gọi cùng lúc, hãy giãn các lượt gọi. Với lưu lượng lớn liên tục, xem gói trả phí tại /pricing. |
| N/A | Giá có vẻ đúng nhưng lệch nhẹ sau nhiều phép tính | Number của JavaScript là số thực IEEE-754: 0.1 + 0.2 === 0.30000000000000004. Giá vàng có 2 chữ số thập phân; cộng hàng nghìn giá trị bằng Number gây sai số ở mức điểm cơ bản. Giữ giá dạng Decimal của decimal.js khi tính toán, chỉ gọi .toString() hoặc .toNumber() lúc hiển thị hoặc tuần tự hóa. |
Làm thêm
- Giữ bộ nhớ đệm giữa các tiến trình: thay
Mapbằng Redis để các worker dùng chung giá đã lưu - Thêm hàm
bars()gọi/v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=...và dùng chuỗi dữ liệu để kiểm thử chiến lược - Kết nối client với route Express hoặc Fastify để phục vụ nội bộ cho dịch vụ không dùng Node
- Gộp các yêu cầu đồng thời cho cùng mã chưa có bộ nhớ đệm thành một lượt fetch
- Thêm chỉ số Prometheus cho tỷ lệ dùng bộ nhớ đệm, độ trễ p50/p95 và số lần thử lại do 429