zekear/justo-mx-api

GitHub: zekear/justo-mx-api

面向 AI agent 的 Python CLI 工具,通过逆向工程 Jüsto 超市的内部 API 实现对话式自动下单购物。

Stars: 0 | Forks: 0

🛒🤖 justo-mx-api

赋予你的 AI agent 在 Jüsto(墨西哥的在线超市)购买杂货的能力。
这是一个命令行工具,旨在让助手(WhatsApp、Telegram 等)
搜索产品、组装购物车并生成真实订单 —— 全程通过对话和 API 完成。

Python Dependencias Para agentes License

## 🤖 它有什么用? 想象一下,通过 WhatsApp 对你的助手说:*"嘿,帮我在 Jüsto 订点香蕉、牛奶和 3 瓶可乐"*,然后它就 自己去做了:搜索产品、组装购物车、选择送货时间、向你展示总价,并且 —— 当你 同意后 —— **生成真实的订单**(货到付款)。 这个工具就是那只“手”:一个带有 **JSON 输出**和**单行命令**的简单 CLI, 专为让 AI agent(OpenClaw、自定义 bot 或其他任何工具)替你执行而设计。它解决了 最困难的部分 —— Jüsto 的 checkout API 并不简单(详见 [🔍 内部 API 原理](#-la-api-por-dentro))。 ### 专为 Agent 设计 - 🧾 所有命令均提供 **JSON 输出** → 方便 LLM 进行解析。 - 📏 **单行命令**(使用逗号分隔条目) → 在拒绝多行的 runtime 中不会中断。 - ⏳ **后台模式** (`order-bg` / `order-wait`) → 在远程节点上执行时,可避开较短的 RPC 超时限制。 - 🔒 **将“组装”与“购买”分离**:`order` 会将购物车保持为 `STAGED` 状态(不产生花费);只有 `confirm` 才会真正生成订单 → agent 可以在付款前**请求人工确认**。 - 🌎 **阿根廷到墨西哥的别名映射** (`palta`→`aguacate`, `choclo`→`elote`…) → 支持任何方言的列表。 👉 **可直接使用的 skill 示例:** [`examples/openclaw-skill.md`](examples/openclaw-skill.md) (一个内置了确认机制的 OpenClaw `SKILL.md`)。 ## 📦 安装 Python 3,**仅使用标准库** —— 无其他依赖。 ``` git clone https://github.com/zekear/justo-mx-api cd justo-mx-api chmod +x justo ln -s "$PWD/justo" ~/.local/bin/justo # opcional: ponelo en el PATH ``` ## ⚙️ 配置 通过环境变量提供凭据: ``` export JUSTO_EMAIL="vos@ejemplo.com" export JUSTO_PASSWORD="tu-password" export JUSTO_ZIP="11590" # tu código postal de entrega (default 11590) ``` …或者将 `JUSTO_CREDENTIALS` 指向一个 `.env` 风格的文件(参见 [`.env.example`](.env.example))。 **切勿将你的真实凭据上传到代码库中。** **送货地址**将从你账户的默认地址中获取(你可以在 Jüsto app 中进行管理)。**付款方式为货到付款** (`MANUAL`):不会扣除任何费用,也不会对任何信用卡进行 token化。 ## 🚀 用法 ``` # 搜索产品 + 价格 justo search "plátano" # 组装一个 REAL 购物车(出现在你的 Jüsto app 中),包含 slot + contra-entrega — 尚未购买 justo order "Plátano x6, Manzana Roja x10, Leche 1L x4, Pan Bimbo x2, Aguacate Hass x4" ``` `order` 返回一个 `STAGED` 摘要供你查看: ``` { "status": "STAGED", "checkout_token": "…", "total": 710.86, "currency": "MXN", "address": "Casa", "slot": "Recomendado — Mañana, 11:00AM - 01:00PM", "slot_options": [ {"n": 1, "label": "Recomendado — Mañana, 11:00AM - 01:00PM"}, {"n": 2, "label": "Entrega gratis — Miércoles, 07:00AM - 09:00AM"} ], "items": [ … ] } ``` ``` # 更改送货时间(使用 slot_options 的 n) justo set-slot 2 # 生成真实订单(contra entrega)— 之后可以从 Jüsto app 中取消 justo confirm # -> {"status":"ORDER_PLACED","order_number":"N0111…","total":710.86, …} ``` ### 数量与匹配 - 每个条目的数量后缀:`x4`、`×4` 或 `:4`。如果没有后缀,则默认为 1。 - 将条目放在**同一个参数中**并用逗号分隔。 - 匹配采用模糊匹配(匹配名称中的完整单词;否则返回第一个带有价格的结果)。当需要精确匹配特定商品时,请使用具体的词汇(品牌/尺寸)。 ### 后台模式(用于远程 agent) ``` job=$(justo order-bg "…lista larga…" | jq -r .job) justo order-wait "$job" # consultá hasta que esté el resumen STAGED ``` ## 🔍 内部 API 原理 Jüsto 的 checkout **并不是标准的 Saleor 流程**:它拥有自定义的 **cart-service** 和 **checkout-bff**。Saleor 公开的 `checkoutComplete` 对**墨西哥地区受限** (`Creation order for country MX not allowed`),因此直接针对 Saleor 组装的购物车永远无法完成结算。真实的流程是通过阅读网站上的 Next.js bundle 逆向工程出来的。 涉及两个 host,它们均位于 Cloudflare 之后: | Host | 角色 | |------|-----| | `api.justo.mx/graphql/` | Saleor GraphQL — **产品搜索** + 登录 (`tokenCreate`) | | `api.justo.cloud` | **cart-service** — 创建购物车、添加条目、合并 | | `client-api-gateway.justo.mx` | checkout 状态、送货时间、付款、**完成订单** | 所有经过身份验证的调用都会发送:`Authorization: JWT `,以及 `x-justo-country: MX`, `x-zip-code: `, `x-justo-platform: web-desktop`, `x-origin: cart_view`。 完整流程: 1. **登录** — Saleor `tokenCreate(email, password)` → JWT。`me.id` (base64 `User:`) → 数字格式的 `userId`。 2. **创建购物车** — `POST api.justo.cloud/cart-service/v3/cart` body `{userId, postalCode, items:[]}` → `{cartId}`。 3. **添加条目** — `POST api.justo.cloud/cart-service/v3/cart/{cartId}/items` body `{items:[{id:"", quantity}]}`。`productId` 是 Saleor 中该产品的数字 ID (将节点的 `id` 进行 base64 解码 → `Product:`)。**`id` 必须作为字符串发送。** 4. **合并** — `POST api.justo.cloud/cart-service/v2/cart/{cartId}/consolidate?userId={userId}` → `{context:{checkoutId (base64), checkoutToken (uuid), postalCode}}`. *(注意是 **v2** 并且在 `api.justo.cloud` —— v3 或 gateway 会返回 404/500。)* 5. **Checkout 状态** — `POST client-api-gateway.justo.mx/v2/checkout` body `{checkoutId, zipCode}` → UI 组件:地址(账户默认地址)、送货时间 (`slots-v2`,每一个都包含 `context:{shippingMethodId (base64), deliveryDate}`)、支付方式、总计。 6. **设置送货时间** — `POST client-api-gateway.justo.mx/v2/checkout/slots` body `{checkoutId, shippingMethodId, deliveryDate}`。 7. **设置支付方式** — `POST client-api-gateway.justo.mx/v2/checkout/paymentMethods` body `{checkoutId, gateway:"MANUAL"}` (货到付款)。**必须设置**:如果没有支付方式,完成订单的操作将被拒绝。 8. **完成** — `POST client-api-gateway.justo.mx/v1/checkout/complete` body `{cartId, checkoutId, zipcode, additionalData:{}}`. 响应**总是**显示一个“已完成”的弹窗 —— **真实的结果在 `tracking` 中**: 如果成功则为 `orderCompleted`(包含 `order_number` 和 `order_id`),如果失败则为 `orderRejected {reason}` (`reason: 10` = 缺少支付方式)。 ## 🤝 贡献 欢迎提交 Issues 和 PR。如果 Jüsto 的 API 发生变化,可以通过阅读 `https://justo.mx/_next/static/chunks/` 的 chunks 来重新验证 endpoint(`_buildManifest.js` 会映射 routes → chunks)。 ## 📄 许可证 [MIT](LICENSE)
标签:API集成, Homebrew安装, Python, 人工智能代理, 可观测性, 数字取证, 文档结构分析, 无后门, 电子商务, 自动化脚本, 逆向工具