
本文详解如何在 PHP 后端正确解析 Shopify CDN 上的 currencies.js 文件,提取其中的 rates 对象,并规避因 JavaScript 变量声明和非标准格式导致的 JSON 解析失败问题。
本文详解如何在 php 后端正确解析 shopify cdn 上的 `currencies.js` 文件,提取其中的 `rates` 对象,并规避因 javascript 变量声明和非标准格式导致的 json 解析失败问题。
Shopify 的 https://cdn.shopify.com/s/javascripts/currencies.js 并非标准 JSON 接口,而是一个导出 JavaScript 全局对象(var Currency = { ... })的脚本文件。直接调用 json_decode() 必然返回 null,因为该内容本质是 JS 代码,不是合法 JSON 字符串。
要成功提取 rates 数据,核心思路是:将 JS 对象字面量字符串清洗为合法 JSON 格式,再进行解码。以下是经过验证的稳健处理流程(基于 Laravel 的 Http 客户端,但逻辑适用于任何 PHP HTTP 库):
$response = Http::get('https://cdn.shopify.com/s/javascripts/currencies.js');
if (!$response->successful()) {
throw new RuntimeException('Failed to fetch currencies.js: ' . $response->status());
}
$res = $response->body();
// 步骤 1:移除顶层变量声明
$res = trim(str_replace("var Currency=", "", $res));
// 步骤 2:移除末尾的函数定义与注释(关键!否则破坏结构)
$res = preg_replace('/,convert:.*?};/', '};', $res); // 更健壮地匹配函数块
$res = str_replace('//# sourceMappingURL=/s/javascripts/currencies.js.map', '', $res);
// 步骤 3:将 JS 对象键值对转换为双引号包裹的 JSON 格式
// 注意:仅处理顶层键(如 "USD", "EUR"),避免误伤数值或嵌套内容
$res = preg_replace('/([a-zA-Z_][a-zA-Z0-9_]*)\s*:/U', '"$1":', $res); // 安全转义键名
$res = str_replace('{', '{"', $res);
$res = str_replace(':', '":"', $res);
$res = str_replace(',', '","', $res);
$res = str_replace('}', '"}');
// 步骤 4:修复 rates 字段前缀(原为 `"rates":"{..."`,需改为 `"rates":{...`)
$res = str_replace('"rates":"{', '"rates":{', $res);
// 步骤 5:清理多余空白、换行与 HTML 实体干扰
$res = str_replace(["\n", "\r", "\t"], '', $res);
$res = str_replace('"', '"', $res);
$res = trim($res);
// 步骤 6:确保 JSON 结构闭合(防截断)
if (substr($res, -1) !== '}') {
$res = rtrim($res, '}') . '}';
}
// 最终解析
$enc = json_decode($res, true);
if (json_last_error() !== JSON_ERROR_NONE || !isset($enc['rates']) || !is_array($enc['rates'])) {
throw new RuntimeException('Failed to parse rates object from currencies.js');
}
// ✅ 成功获取汇率数组
$rates = $enc['rates'];
// 示例:安全获取并转换 VED 汇率(强制浮点数)
$vedRate = isset($rates['VED']) ? floatval($rates['VED']) : 0.0;
echo "VES rate: " . $vedRate; // 输出类似:VES rate: 36.25⚠️ 重要注意事项:
- 不要依赖硬编码字符串替换:Shopify 可能随时更新脚本结构(如新增字段、调整函数位置)。建议定期回归测试,并考虑添加 try/catch + 备用 fallback 机制。
- 避免正则过度匹配:示例中使用 preg_replace 处理 convert 函数更鲁棒,防止因换行或空格导致 str_replace 失效。
- 始终校验解析结果:json_decode() 后务必检查 json_last_error() 和 $enc['rates'] 是否存在且为数组。
- 生产环境建议缓存:该脚本更新频率低(通常数小时至数天),应配合 Redis 或文件缓存(TTL 30–60 分钟),减少外部请求与解析开销。
- 替代方案优先级:若业务允许,强烈推荐使用 Shopify Admin API 的 /admin/api/{version}/shop.json?fields=currencies 或第三方汇率服务(如 exchangerate-api.com),它们提供稳定、标准化、带认证的 JSON 接口。
通过以上清洗与解析策略,你可在服务端可靠获取 Shopify 所维护的多币种实时汇率,支撑价格转换、多币种展示等核心电商功能。










