如何用 @spree/sdk 完成 Spree Store API 的首次调用:商品、购物车与结账?
【免费下载链接】spreeOpen Source eCommerce Platform for B2B, Marketplace, and Enterprise. REST API, TypeScript SDK, and production-ready Next.js storefront. Self-host it. Own your stack. No vendor lock-in. Zero platform fees.项目地址: https://gitcode.com/GitHub_Trending/sp/spree
这篇文章面向第一次接入 Spree Store API 的开发者:你需要在自己的前端项目里安装@spree/sdk,用一个 publishable key 初始化客户端,然后依次完成三件事——查询商品、创建购物车并添加商品、走完结账流程拿到订单。文中所有命令与代码来自 Spree 官方 SDK 文档(SDK Quickstart、Store API 认证参考),可以照抄执行。
前提条件:
- 一个可访问的 Spree 实例(可以是
http://localhost:3000的本地环境,也可以是已部署的地址); - 一个 Store API 的 publishable key(下文简称 API key,
pk_前缀); - 支持
npm/yarn/pnpm的 Node 环境。
准备本地实例与 publishable key
如果你还没有可运行的 Spree 实例,官方给出的最快方式是create-spree-app(要求 Node.js 20+ 和运行中的 Docker):
npx create-spree-app@latest my-storeCLI 会交互式询问选择Full-stack(后端 + Next.js 前台)或Backend only,并可选加载 sample data(商品、分类、图片)。完成后店铺运行在http://localhost:3000(端口 3000 被占用时会变化)。更多 CLI 选项见 create-spree-app 文档。
API key 的获取有两条路径(见 Store API 认证文档):
- 在 Spree Admin 面板的Settings > API Keys中创建;
- 或者通过 Spree CLI:
spree api-key create # Create a new API key spree api-key list # List existing API keyscreate-spree-app搭建的项目自带@spree/cli,因此可以直接在项目里运行上面的命令。注意区分用途:Store API 用pk_前缀的 publishable key,它面向客户侧(商品、购物车、结账、账户),文档明确说明它可安全用于客户端代码;后台管理(商品、订单、库存)走的是另一套 Admin SDK,不在本文范围内。
安装并初始化 @spree/sdk
在你自己的前端项目目录中安装 SDK:
npm install @spree/sdk # or yarn add @spree/sdk # or pnpm add @spree/sdk然后用createClient初始化客户端。baseUrl换成你的 Spree 实例地址,publishableKey换成你的pk_key:
import { createClient } from '@spree/sdk' const client = createClient({ baseUrl: 'http://localhost:3000', publishableKey: 'pk_xxx', })SDK 会把 publishable key 自动放进每个请求的X-Spree-Api-Keyheader,后续所有调用都不需要再手动传 key。如果你缺少 key 或 key 无效,API 会返回401 Unauthorized,错误体为:
{ "error": { "code": "invalid_token", "message": "Valid API key required" } }所以第一步的自检方式就是:初始化后直接调一个商品列表接口,看是否返回数据而不是 401。
第一次调用:查询商品
商品浏览是 Store API 的公开端点,只需要 publishable key,不需要用户登录:
// 商品列表(带分页与关联展开) const products = await client.products.list({ limit: 10, expand: ['variants', 'media'], }) // 按 slug 或 prefix ID 获取单个商品 const product = await client.products.get('spree-tote')两点说明:
'spree-tote'是 商品文档 中的示例 slug,请替换为你实例中真实存在的商品 slug(如果加载了 sample data,可在列表中拿到)。expand: ['variants', 'media']会把规格(variants)和媒体一起返回,后续加购物车需要用到 variant 的 ID。列表还支持扁平化过滤参数(如in_stock: true、search: 'blue shirt')和sort(price、-price、name等,-前缀表示降序),按需使用即可,首次调用不必加。
SDK 的响应是完整类型化的:products是PaginatedResponse<Product>,可以直接在 TypeScript 中访问字段。另外注意所有金额字段都是字符串(如"29.99"),显示用字段带货币格式(display_price),这是文档明确的约定,做计算时再parseFloat。
创建购物车并添加商品
游客(未登录用户)的购物车靠create返回的 token 管理。调用carts.create()后,把cart.token存下来,后续所有购物车操作都通过spreeToken选项传给 SDK,SDK 会自动以x-spree-tokenheader 发送:
// 创建游客购物车 const cart = await client.carts.create() const options = { spreeToken: cart.token } // 添加商品(variant_id 来自 products 接口展开的 variants,文档示例值) await client.carts.items.create(cart.id, { variant_id: 'var_abc123', quantity: 2, }, options) // 修改数量 / 删除行项目 await client.carts.items.update(cart.id, lineItemId, { quantity: 3 }, options) await client.carts.items.delete(cart.id, lineItemId, options)variant_id是文档示例值var_abc123,实际使用时取商品响应里variants数组中的真实 ID。购物车上还可以挂折扣码(client.carts.discountCodes.apply)、礼品卡(client.carts.giftCards.apply)、商店积分(client.carts.storeCredits.apply),首次跑通可以不涉及。
结账:地址、配送、支付与完成
Cart & Checkout 文档将结账流程拆为地址、配送、支付、完成四个环节,所有端点都以cartId为第一个参数。
1. 更新购物车(邮箱与收货地址)
await client.carts.update(cart.id, { email: 'customer@example.com', shipping_address: { first_name: 'John', last_name: 'Doe', address1: '123 Main St', city: 'New York', postal_code: '10001', phone: '+1 555 123 4567', country_iso: 'US', state_abbr: 'NY', }, }, options)billing_address_id是可选参数,可用已有地址 ID 代替完整账单地址。
2. 选择配送费率
fulfillments 直接包含在购物车响应中,没有单独的列表端点。从cart.fulfillments取到 fulfillment 和可选费率后:
const cart = await client.carts.get(cart.id, options) const fulfillments = cart.fulfillments await client.carts.fulfillments.update(cart.id, fulfillmentId, { selected_delivery_rate_id: 'rate_xxx', }, options)3. 创建支付
支付方式、支付记录、fulfillments 都在购物车响应里(cart.payment_methods)。每个 payment method 带session_required标志,这是支付路径的分叉点(见 Payments 文档):
session_required: false(Check、货到付款、银行转账等)→ 直接创建 payment:
const payment = await client.carts.payments.create(cart.id, { payment_method_id: 'pm_xxx', }, options)amount可选,默认取订单总额减去商店积分。payments.create()只对非 session 方式有效。
session_required: true(Stripe、Adyen、PayPal 等网关)→ 走 Payment Sessions:client.carts.paymentSessions.create创建会话,从返回的session.external_data取网关侧数据(如 Stripe 的client_secret),前端完成支付后再调用client.carts.paymentSessions.complete。这条链路涉及第三方网关配置,首次调用可先用非 session 方式跑通。
4. 完成结账
await client.carts.complete(cart.id, options)Quickstart 展示的最短路径就是在加完商品后直接调用carts.complete;如果你的实例要求先补齐地址、配送和支付,complete 会失败并返回错误,此时按上面顺序补齐即可。
验证结果
两个检查点:
结账前/结账后读取购物车,核对金额构成。cart 与 order 响应把应付金额拆成一组总额字段,每个字段都有原始字符串值和display_前缀的货币格式化双生子:item_total(商品)、delivery_total(配送)、discount_total(负数折扣)、fee_total(费用)、tax_total(税)、total(订单总价)、amount_due(扣除商店积分/礼品卡后实际待付)、covered_by_store_credit(布尔)。
const cart = await client.carts.get(cart.id, options) console.log(cart.total, cart.display_total, cart.amount_due)文档示例中display_total形如"$129.99",具体数值取决于你的商品与价格配置,不要把它当作固定预期值。
完成后取订单:
const order = await client.orders.get('R123456789', { expand: ['items', 'fulfillments'], }, { spreeToken: cart.token })'R123456789'是文档示例的订单 number,替换为 complete 后你的真实订单号。已登录客户还可以用 JWT 列出自己的订单(client.customer.orders.list({}, { token }))。
认证与报错判断
Store API 有三种认证方式,首次调用只需要前两种中的其一(来源:SDK 认证文档):
| 方式 | Header | 用途 |
|---|---|---|
| Publishable key | X-Spree-Api-Key: pk_xxx | 所有请求,必传,SDK 自动处理 |
| JWT | Authorization: Bearer <token> | 已登录客户(查订单、管理地址) |
| Order token | X-Spree-Token: <token> | 游客购物车与结账,SDK 通过spreeToken选项自动处理 |
如果需要登录客户流程,SDK 提供:
const { token, user } = await client.auth.login({ email: 'customer@example.com', password: 'password123', })JWT 默认 1 小时过期,过期后用client.auth.refresh({ token })刷新。游客登录后可以用client.carts.associate把游客购物车并入账户,这是可选项,不影响结账主路径。
错误统一抛SpreeError(见 Configuration 文档)。首次调用时最常见的是两类:
import { SpreeError } from '@spree/sdk' try { await client.products.get('non-existent') } catch (error) { if (error instanceof SpreeError) { console.log(error.code); // 'record_not_found' console.log(error.status); // 404 } }- 返回
401且 code 为invalid_token→ key 缺失或无效,回查publishableKey; - 抛
SpreeError且 code 为record_not_found、status 404 → 资源不存在,检查 slug、cartId或 variant ID 是否拼对; - 代理或服务器返回空 body/非 JSON 时,错误 code 为
http_error,保留 HTTP status 但不含响应体——遇到这种情况先确认请求打到的地址确实是你的 Spree 实例。
到这里,你就完成了@spree/sdk对 Store API 的首次完整调用:商品查询 → 购物车管理 → 结账完成 → 读取订单。后续如果需要按渠道隔离请求(channel配置)、本地化(locale/currency选项)或接入 Stripe 等 session 网关,可以分别参考 Configuration 与 Payments & Delivery 文档。
【免费下载链接】spreeOpen Source eCommerce Platform for B2B, Marketplace, and Enterprise. REST API, TypeScript SDK, and production-ready Next.js storefront. Self-host it. Own your stack. No vendor lock-in. Zero platform fees.项目地址: https://gitcode.com/GitHub_Trending/sp/spree
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考