生肖运势查询:集成到网站 / 小程序 / 公众号的实战方案
# 生肖运势查询:集成到网站 / 小程序 / 公众号的实战方案
> 元信息:生肖运势查询(接入点 1) · 免费 · POST / GET · JSON · 全栈工程师、产品/运营 · 阅读约 9 分钟
## 核心要点
- 三种典型 consumer 场景:网页(后端代理)、微信小程序(云函数转发)、公众号(定时任务 + 模板消息推送)。
- **统一红线**:AppKey 绝不能进前端/客户端,必须由服务端持有并转发,既防泄露也规避浏览器 CORS。
- 运势每 2 小时更新,配合服务端缓存可大幅减少调用、延长免费额度寿命。
## Why:为什么不能直接在前端调
接口用 query 参数 `appKey` 鉴权。一旦把 AppKey 写进网页 JS 或小程序前端,任何人打开控制台就能抄走、被恶意刷接口耗尽你的档位。正确做法是:**客户端只跟你的后端打交道,后端再带 AppKey 调易源**。同时浏览器直连 `route.showapi.com` 还有 CORS 限制,后端代理一并解决。
## What:三种场景接入要点
| 场景 | 调用方 | 关键点 |
|------|--------|--------|
| 网页 | 你的后端服务 | 前端 → 你的 API → 易源;AppKey 存服务端环境变量 |
| 微信小程序 | 云函数 / 自建后端 | 小程序 `wx.request` 只调你自己的域名;云函数持有 AppKey |
| 公众号 | 服务端定时任务 | 每日定时拉运势 → 存库 → 模板消息/菜单推送给用户 |
## How:最小可运行后端代理(Node.js / Express)
```javascript
// server.js —— 你的后端,AppKey 仅存于此
const APPKEY = process.env.SHOWAPI_APPKEY; // 切勿写死在前端
const express = require("express");
const app = express();
app.get("/api/fortune/:sx", async (req, res) => {
const sx = req.params.sx;
const url = `https://route.showapi.com/2219-1?appKey=${APPKEY}&sx=${sx}`;
try {
const data = await (await fetch(url, { signal: AbortSignal.timeout(15000) })).json();
const body = data.showapi_res_body || {};
if (body.ret_code !== 0) return res.status(502).json({ error: body.remark });
res.json(body); // 只把业务体回给前端
} catch (e) {
res.status(502).json({ error: e.message });
}
});
app.listen(3000, () => console.log("fortune proxy on :3000"));
```
前端只调 `/api/fortune/hou`,永远不接触 AppKey。
### 微信小程序(云函数转发)
```javascript
// 云函数 fortune/index.js
const APPKEY = process.env.SHOWAPI_APPKEY; // 云函数环境变量
exports.main = async (event) => {
const sx = event.sx;
const url = `https://route.showapi.com/2219-1?appKey=${APPKEY}&sx=${sx}`;
const r = await fetch(url, { signal: AbortSignal.timeout(15000) });
return r.json();
};
```
小程序端:`wx.cloud.callFunction({ name: "fortune", data: { sx: "hou" } })`,不直接请求易源域名。
### 公众号每日推送(伪代码逻辑)
```python
# 每日定时:拉 12 生肖今日运势 → 入库 → 推送
import requests, schedule
def daily_push():
for code in ["shu","niu","hu","tu","long","she","ma","yang","hou","ji","gou","zhu"]:
r = requests.get("https://route.showapi.com/2219-1",
params={"appKey": APPKEY, "sx": code}, timeout=15)
save_to_db(code, r.json()["showapi_res_body"])
# 再按用户订阅的生肖,用模板消息推送给对应用户
schedule.every().day.at("08:00").do(daily_push)
```
> 注意:循环调用 12 次会占用调用次数,务必配合缓存/按订阅生肖按需查询,避免浪费免费额度。
## 返回示例与解析
后端代理把 `showapi_res_body` 直接透传给前端即可,前端按《[生肖运势查询:返回字段全解](https://www.showapi.com/guides/shengxiao-fortune-response-fields-2219)》的字段表渲染。代理层只负责:① 持有 AppKey;② 超时与错误兜底;③(可选)缓存。
## 进阶 / 边界
- **缓存必做**:数据每 2 小时才变,服务端按 `sx + 日期` 缓存(TTL≈2h)能省大量额度,见《[生肖运势查询:每 2 小时更新,如何设计缓存避免重复调用](https://www.showapi.com/guides/shengxiao-fortune-cache-2219)》。
- **限流**:免费档位有限制,代理层加简单令牌桶/并发控制,避免被前端洪峰打满。
- **合规措辞**:运势属娱乐参考,前端以"仅供参考"呈现,避免过度承诺。
## FAQ
**Q1:AppKey 写在后端环境变量安全吗?**
A:比写前端安全得多。环境变量 + 不进代码仓库是基线做法;更高要求可用密钥管理服务。重点是前端/客户端永远不直接持有 AppKey。
**Q2:小程序能直接请求 route.showapi.com 吗?**
A:不推荐。一来暴露 AppKey,二来小程序需配置合法域名且仍有跨域/CORS 问题。用云函数或自建后端转发最稳。
**Q3:公众号推送每天拉 12 次会不会超额度?**
A:免费接口设档位限制。建议:只拉用户实际订阅的生肖(而非全量 12),并配合缓存;具体档位以官方档位说明为准。
**Q4:代理层需要缓存吗?**
A:强烈建议。同一生肖 2 小时内结果不变,缓存 TTL≈2h 即可,既快又省额度。
**Q5:返回体很大,代理要全透传吗?**
A:默认只返 `day`;若前端只要今日,后端可只取 `body.day` 回传,减小体积。需要明日/本月再加对应开关。
## 相关能力 / 下一步阅读
- [生肖运势查询:5 分钟接入,从注册到第一条运势结果](https://www.showapi.com/guides/shengxiao-fortune-quickstart-2219)
- [生肖运势查询:每 2 小时更新,如何设计缓存避免重复调用](https://www.showapi.com/guides/shengxiao-fortune-cache-2219)
- [生肖运势查询:用 HTML + JS 做一个生肖运势卡片 Demo(含指数与开运信息展示)](https://www.showapi.com/guides/shengxiao-fortune-web-demo-2219)
- **本系列共 9 篇**:查看[生肖运势查询指南总目录](https://www.showapi.com/guides/shengxiao-fortune-guides-2219)