今日油价:公众号与小程序怎么加油价查询?省份选择与卡片展示

约 14 分钟 进阶今日油价小程序公众号云函数
# 今日油价:公众号与小程序怎么加油价查询?省份选择与卡片展示 接口/接入点:今日油价(apiCode=138)· 查询油价(138-46) · 免费 · 适用人群:公众号运营、小程序开发者 · 阅读时间:约 6 分钟 · 最后实测核对:2026-09-18 公众号菜单点进去选省份看油价,是小程序里最容易做起来的一个功能。链路只有三段:前端选省、云函数代理、卡片渲染。省份列表直接从接口返回生成,省掉自己维护枚举表的功夫。 ## 核心要点 - 后端一次不传 `prov` 的调用就能取回 31 个省级行政区的名称与价格,2026-09-18 实测返回 31 条、`showapi_fee_num=1`。 - AppKey 放云函数环境变量,小程序前端只调云函数,不接触密钥。 - 省份名按精确匹配处理,下拉列表里的值与接口返回的 `prov` 保持一致即可。 ## 为什么适合放在公众号与小程序里 车主类公众号、养车小程序天然有查油价的需求:用户主动查、顺手就能分享,比推一篇图文更容易形成使用习惯。今日油价(apiCode=138)覆盖 31 个省级行政区,返回结构化 JSON,注册后即可调用,做起步功能的成本很低。 ## 云函数:代理与取数 小程序云函数持有 AppKey,一次全量调用填充缓存,之后按省从缓存里取。 ```javascript // 云函数入口(Node.js) const cloud = require("wx-server-sdk"); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); const API = "https://route.showapi.com/138-46"; let snapshot = { prices: null, ct: null, expireAt: 0 }; async function refreshSnapshot(ttlMs = 3600_000) { if (snapshot.prices && Date.now() < snapshot.expireAt) return snapshot.prices; const resp = await fetch(API, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" }, // 不传 prov 取全量;AppKey 从云函数环境变量注入 body: new URLSearchParams({ appKey: process.env.OIL_APPKEY }), signal: AbortSignal.timeout(5000), }); const data = await resp.json(); if (data.showapi_res_code !== 0) throw new Error(data.showapi_res_error); const body = data.showapi_res_body; if (body.ret_code !== 0) throw new Error(body.remark); snapshot = { prices: Object.fromEntries(body.list.map((x) => [x.prov, x])), ct: body.list[0].ct, expireAt: Date.now() + ttlMs, }; return snapshot.prices; } const pick = (raw) => (raw && Number(raw) > 0 ? Number(Number(raw).toFixed(2)) : null); exports.main = async (event) => { const action = event.action || "price"; if (action === "provinces") { const prices = await refreshSnapshot(); return { provinces: Object.keys(prices).sort() }; } const prov = event.prov || "北京"; const prices = await refreshSnapshot(); const item = prices[prov]; if (!item) return { ok: false, msg: "请选择标准省名" }; return { ok: true, prov: item.prov, gas: { p89: pick(item.p89), p92: pick(item.p92), p95: pick(item.p95), p98: pick(item.p98) }, diesel: pick(item.p0), ct: item.ct, }; }; ``` Python 侧的后端实现(自建服务器时用): ```python import time import requests from flask import Flask, jsonify, request app = Flask(__name__) API = "https://route.showapi.com/138-46" _cache = {"prices": None, "expire_at": 0} def snapshot(ttl=3600): if _cache["prices"] and time.time() < _cache["expire_at"]: return _cache["prices"] resp = requests.post(API, data={"appKey": "YOUR_APPKEY"}, timeout=5).json() body = resp["showapi_res_body"] if body.get("ret_code") != 0: raise RuntimeError(body.get("remark")) _cache["prices"] = {x["prov"]: x for x in body["list"]} _cache["expire_at"] = time.time() + ttl return _cache["prices"] @app.route("/api/oil/price") def price(): item = snapshot().get(request.args.get("prov", "北京")) if not item: return jsonify({"ok": False, "msg": "请选择标准省名"}), 404 return jsonify({"ok": True, "prov": item["prov"], "p92": item["p92"], "p95": item["p95"], "diesel": item["p0"], "ct": item["ct"]}) ``` cURL(本地验证云函数或后端接口): ```bash curl -X POST "https://route.showapi.com/138-46?appKey=YOUR_APPKEY" \ -H "content-type: application/x-www-form-urlencoded" -d "prov=%E5%B9%BF%E8%A5%BF" ``` ## 小程序端:picker 与卡片 ```javascript Page({ data: { provinces: [], idx: 0, price: null }, async onLoad() { // 省份选项来自云函数,不用在前端写死 const res = await wx.cloud.callFunction({ name: "oilPrice", data: { action: "provinces" } }); this.setData({ provinces: res.result.provinces }); this.load("北京"); }, async load(prov) { const res = await wx.cloud.callFunction({ name: "oilPrice", data: { prov } }); this.setData({ price: res.result }); }, onProv(e) { const prov = this.data.provinces[e.detail.value]; this.setData({ idx: e.detail.value }); this.load(prov); }, }); ``` ```html <picker mode="selector" range="{{provinces}}" value="{{idx}}" bindchange="onProv"> <view>当前省份:{{provinces[idx]}}</view> </picker> <view class="oil-card" wx:if="{{price.ok}}"> <view>{{price.prov}} 今日油价</view> <view>92号:{{price.gas.p92 === null ? '—' : price.gas.p92}} 元/升</view> <view>95号:{{price.gas.p95 === null ? '—' : price.gas.p95}} 元/升</view> <view>0号柴油:{{price.diesel === null ? '—' : price.diesel}} 元/升</view> <view class="ts">数据时间 {{price.ct}}</view> </view> ``` 公众号侧的做法更简单:在自定义菜单里挂一个 H5 页面地址,页面调你的后端接口,省份选择用一个 `<select>` 即可。菜单跳转用的链接需要走你自己的域名,AppKey 依然留在后端。 ## 适用条件与注意事项 - 省份名用接口返回的 `prov` 值,不要出现带「省」「市」后缀的写法。2026-09-18 实测 `prov=北京市` 返回 `ret_code=-1`。 - `p89` 有 7 个省份返回 `"0.00"`(2026-09-18 实测),在后端统一转成 `null`,前端显示「—」。 - 云函数冷启动后缓存会重建,属正常现象;回源次数按实例数计,量级仍然很低。 - AppKey 放云函数环境变量,不进代码仓库。 - 小程序需要在小程序后台配置合法域名,H5 页面需要在公众号后台配置业务域名。 ## FAQ **Q1:AppKey 能直接写在小程序里吗?** 不能。放云函数环境变量,或放在你自己的后端服务上,由服务端代理请求今日油价。 **Q2:省份下拉的 31 个选项要自己写吗?** 不用。2026-09-18 实测不传 `prov` 的调用会返回 31 个省级行政区的 `prov` 值,直接作为选项即可。 **Q3:免费档位够公众号用吗?** 注册默认是 L0(100 次/天,1 QPS)。后端按全量快照缓存后,回源次数按小时计,通常够用。需要更高额度时可按积分规则升级档位,见 https://www.showapi.com/free-api **Q4:想让用户看到涨跌,怎么加?** 另外调用查询行情(138-49),它返回 8 个标号的涨跌对象与调价日,`prov` 必填。用法见《今日油价涨跌幅怎么查?查询行情接入点的调价日与涨跌率用法》。 **Q5:卡片时间显示哪个字段?** `ct`,并说明它是数据生成时间。 ## 相关能力 / 下一步阅读 - [在车主服务 APP 里接入今日油价的完整流程](https://www.showapi.com/guides/oilprice-app-integration-138) - [今日油价调用量规划:缓存粒度与 TTL 的确定方式](https://www.showapi.com/guides/oilprice-cache-138) - [今日油价返回字段对照:p89/p92/p0 与 ct 的含义与空值处理](https://www.showapi.com/guides/oilprice-fields-138) - **本系列共 13 篇**:查看[今日油价指南总目录](https://www.showapi.com/guides/oilprice-guides-138)
加载中...