关于 saleor-development
该技能面向使用 Saleor 的开发者,介绍基于 Django 和 GraphQL 的无头电商开发。内容包括查询 API、构建应用、处理 Webhook,以及扩展管理仪表板界面。
主要功能
- 01使用 GraphQL 查询商品与结账数据
- 02创建接收 Webhook 的 Saleor App
- 03验证 Webhook 签名
- 04向 Dashboard 注入自定义界面
- 05通过 Docker Compose 启动本地环境
适用场景
- 01为 Saleor 后端构建自定义店面
- 02响应订单或商品生命周期事件
- 03在 Dashboard 中添加商品操作面板
- 04本地开发和测试 Saleor 集成
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill saleor-development安装后在 Claude Code 中输入/saleor-development确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tile.jsonevals/dashboard-extension-with-app-bridge-comm/criteria.jsontask.mdevals/saleor-app-bootstrap-and-webhook-handlin/criteria.jsontask.mdevals/storefront-product-catalog-with-paginati/criteria.jsontask.md详细介绍
Saleor 开发
概述
Saleor 是一个基于 Django 和 Python 构建的无头、GraphQL 优先的电子商务平台。它提供完全类型化的 GraphQL API,供店面和第三方应用使用;提供基于 React 的仪表板来管理商店;还提供扩展系统,让你能够通过 Webhook 响应事件,或向仪表板注入 UI。本技能涵盖查询 Saleor API、构建 Saleor Apps(托管在 Saleor 之外的插件)以及使用 App Extensions 自定义仪表板。
何时使用本技能
- 为 Saleor 后端构建自定义店面(Next.js、Remix、移动应用)时
- 创建能够响应订单或商品生命周期 Webhook 的 Saleor App 时
- 通过 App Extensions 向 Saleor Dashboard 注入自定义 UI 面板时
- 探索或扩展 Saleor 商品目录、结账或客户 API 时
- 使用 Docker 设置本地 Saleor 开发环境时
前置条件与平台说明
本技能面向自定义/无头店面(Node.js、Python 或类似后端)。代码示例使用 TypeScript/Node.js,可适配任何技术栈。
Shopify:Shopify Hydrogen 是 Shopify 的无头框架。使用 Shopify 作为电商后端并搭配自定义前端,或将 Shopify 与其他同类最佳服务结合时,适用 MACH/可组合模式。 WooCommerce:WooCommerce 可通过其 REST API 和 WPGraphQL 作为无头后端。当将前端与 WordPress 解耦时,适用这些模式。 Magento:Magento 的 GraphQL API 和 PWA Studio 支持无头架构。在 MACH 技术栈中将 Magento 用作后端服务时,适用这些可组合模式。
你需要:
- Node.js 18+(或适配你的后端语言)
- PostgreSQL(或你偏好的关系型数据库)
- 用于缓存/队列的 Redis
- Stripe 账户和 API 密钥
- 电子邮件发送服务(SendGrid、AWS SES 或 Postmark)
- 用于容器编排的 Docker 和/或 Kubernetes
- CDN(Cloudflare、CloudFront 或 Fastly)
核心说明
-
使用 Docker Compose 在本地运行 Saleor
git clone https://github.com/saleor/saleor-platform.git cd saleor-platform docker compose up --detach # API: http://localhost:8000/graphql/ # Dashboard: http://localhost:9000创建首个超级用户并填充演示数据:
docker compose run --rm api python manage.py createsuperuser docker compose run --rm api python manage.py populatedb --createsuperuser -
查询店面 GraphQL API
使用 Saleor CLI 或任意 GraphQL 客户端(Apollo、urql、graphql-request)。
安装 CLI 以生成代码:
npm install -g @saleor/cli saleor configure示例 — 从默认渠道获取前 12 个商品:
query ProductList($channel: String!) { products(first: 12, channel: $channel) { edges { node { id name slug thumbnail { url alt } pricing { priceRange { start { gross { amount currency } } } } } } pageInfo { hasNextPage endCursor } } }import { createClient } from 'urql'; const client = createClient({ url: process.env.NEXT_PUBLIC_SALEOR_API_URL, fetchOptions: () => ({ headers: { 'Content-Type': 'application/json' }, }), }); const { data } = await client.query(PRODUCT_LIST_QUERY, { channel: 'default-channel' }).toPromise(); -
验证客户身份并开始结账
mutation CustomerLogin($email: String!, $password: String!) { tokenCreate(email: $email, password: $password) { token refreshToken errors { field message } user { id email } } }创建结账并添加商品行:
mutation CheckoutCreate($channel: String!, $lines: [CheckoutLineInput!]!) { checkoutCreate(input: { channel: $channel, lines: $lines }) { checkout { id token totalPrice { gross { amount currency } } } errors { field message } } }使用支付网关令牌完成结账(例如,来自 Stripe Elements 的令牌):
mutation CheckoutComplete($checkoutId: ID!, $paymentData: JSONString) { checkoutComplete(id: $checkoutId, paymentData: $paymentData) { order { id number status } errors { field message code } } } -
初始化 Saleor App
Saleor App 是一种 Node.js 服务,会向 Saleor 注册自身、接收 Webhook,并可选择通过 iframe 在仪表板中呈现 UI。
npx @saleor/app-sdk@latest create my-saleor-app cd my-saleor-app npm install npm run dev # Expose with: npx ngrok http 3000在仪表板的 Apps → Install custom app 下注册应用,并输入你的 ngrok URL。Saleor 会调用你的
/api/manifest端点:// pages/api/manifest.ts import { createManifestHandler } from "@saleor/app-sdk/handlers/next"; import { AppManifest } from "@saleor/app-sdk/types"; const manifest: AppManifest = { id: "my-saleor-app", name: "My Saleor App", version: "1.0.0", about: "Example app", permissions: ["MANAGE_ORDERS"], appUrl: process.env.APP_URL!, tokenTargetUrl: `${process.env.APP_URL}/api/register`, webhooks: [ { name: "Order Created", asyncEvents: ["ORDER_CREATED"], query: `subscription { event { ... on OrderCreated { order { id number } } } }`, targetUrl: `${process.env.APP_URL}/api/webhooks/order-created`, isActive: true, }, ], }; export default createManifestHandler({ manifestFactory: () => manifest }); -
安全处理 Saleor Webhook
Saleor 使用应用的密钥令牌,通过 HMAC-SHA256 签名对每个 Webhook 进行签名。
// pages/api/webhooks/order-created.ts import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next"; import { OrderCreatedDocument } from "@/generated/graphql"; const orderCreatedWebhook = new SaleorAsyncWebhook<OrderCreatedPayload>({ name: "Order Created", webhookPath: "api/webhooks/order-created", asyncEvent: "ORDER_CREATED", apl: saleorApp.apl, query: OrderCreatedDocument, }); export default orderCreatedWebhook.createHandler((req, res, ctx) => { const { order } = ctx.payload; console.log(`New order #${order.number} received`); // Trigger fulfillment, email, ERP sync, etc. return res.status(200).end(); }); export const config = { api: { bodyParser: false } }; // required for signature check -
添加仪表板扩展(自定义 UI 面板)
扩展会在 Saleor Dashboard 中呈现 iframe。在清单中声明扩展:
extensions: [ { label: "Sync to ERP", mount: "PRODUCT_DETAILS_MORE_ACTIONS", target: "POPUP", permissions: ["MANAGE_PRODUCTS"], url: `${process.env.APP_URL}/extension/product-sync`, }, ],扩展页面使用
@saleor/app-sdk与仪表板宿主进行通信:import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge"; export default function ProductSyncExtension() { const { appBridge } = useAppBridge(); const handleSync = async () => { appBridge?.dispatch(actions.Notification({ status: "success", title: "Sync started", text: "Product is being synced to ERP.", })); }; return <button onClick={handleSync}>Sync to ERP</button>; }
示例
使用 TypeScript 和 graphql-request 实现分页商品目录
import { GraphQLClient, gql } from 'graphql-request';
const client = new GraphQLClient(process.env.SALEOR_API_URL!, {
headers: { Authorization: `Bearer ${process.env.SALEOR_APP_TOKEN}` },
});
const PRODUCTS_QUERY = gql`
query Products($first: Int!, $after: String, $channel: String!) {
products(first: $first, after: $after, channel: $channel) {
edges { node { id name slug description } }
pageInfo { hasNextPage endCursor }
}
}
`;
async function fetchAllProducts(channel: string) {
const products = [];
let after: string | null = null;
do {
const data = await client.request(PRODUCTS_QUERY, { first: 100, after, channel });
products.push(...data.products.edges.map((e: any) => e.node));
after = data.products.pageInfo.hasNextPage ? data.products.pageInfo.endCursor : null;
} while (after);
return products;
}
通过 Admin API 更新订单状态
mutation FulfillOrder($orderId: ID!, $input: OrderFulfillInput!) {
orderFulfill(orderId: $orderId, input: $input) {
fulfillments {
id
status
trackingNumber
}
errors { field message code }
}
}
await client.request(FULFILL_ORDER_MUTATION, {
orderId: "T3JkZXI6MTIz",
input: {
lines: [{ orderLineId: "T3JkZXJMaW5lOjQ1", stocks: [{ warehouse: "V2FyZWhvdXNlOjE=", quantity: 1 }] }],
notifyCustomer: true,
allowStockToBeExceeded: false,
},
});
最佳实践
- 使用渠道进行多区域或 B2B/B2C 区分 — 每个商品列表、定价和结账流程都限定在特定渠道中;按地区/货币创建单独的渠道,而不是重复创建商品
- 根据架构生成 TypeScript 类型 — 运行
saleor app generate-types或使用graphql-codegen,以确保查询具有完整的类型定义 - 将应用令牌存储在 Saleor 的 APL(Auth Persistence Layer)中 — 默认的基于文件的 APL 适用于开发;生产环境请使用 Redis 或 Upstash APL
- 始终验证 Webhook 签名 — 使用
SaleorAsyncWebhook包装器,它会自动处理 HMAC 验证;绝不处理未经身份验证的负载 - 使用基于订阅的 Webhook 查询 — Saleor Webhook 使用 GraphQL 订阅来定义负载,让你可以精确控制包含哪些字段
- 在 CDN 层缓存商品目录响应 — 商品数据很少变化;在商品目录 API 路由上设置
Cache-Control: s-maxage=300 - 在生产环境中使用 Saleor Cloud — 自托管 Django + Celery + Redis + PostgreSQL 需要成熟的运维能力;Saleor Cloud 会处理这些工作
常见问题
| 问题 | 解决方案 |
|---|---|
| 未授权操作导致 GraphQL 错误 | 确保已在清单中授予应用正确的权限,并在控制面板的应用设置中授予权限 |
| Webhook 负载为空或缺少字段 | Webhook 负载由清单中的 GraphQL 订阅查询定义 — 将所需字段添加到 query 属性中 |
店面中的 tokenCreate 返回 null | 渠道必须启用店面 API 并指定所属国家/地区;请在控制面板中检查渠道配置 |
| 应用在本地运行正常,但部署后无法运行 | APP_URL 环境变量必须与 Saleor 可访问的公开 URL 一致;部署后请在控制面板中更新应用 URL |
| 控制面板扩展 iframe 为空白 | 扩展 URL 必须通过 HTTPS 提供服务,并且必须包含针对控制面板源的 Access-Control-Allow-Origin 标头 |
相关技能
- @shopify-hydrogen
- @composable-commerce
- @webhook-architecture
- @jamstack-storefront
- @commerce-api-gateway