插件

在线商城

官方 shop 插件把产品目录变成可以下单的商城。插件随框架一起发布(plugins/shop),无需额外下载。

node node_modules/nuxtcms/scripts/plugin.mjs add shop
pnpm build:cf && pnpm deploy

shop 为付费插件:已授权的域名(以及插件中心所有者自己的站点)在 后台 → 插件 中自动激活;nuxt dev 下无需授权即可使用。

功能一览

模块功能
商品售价、划线价、SKU、库存(可不跟踪)、规格(每个规格可单独定价和库存)、图集、角标、单品税率、"价格面议"与仅展示模式
前台产品卡片显示价格、购买区(规格、数量)、图集、页头购物车按钮、侧滑购物车、悬浮购物车按钮、/cart、/checkout、/order/<订单号>、/order(查询订单)
结账免注册下单;快递配送(固定运费、满额包邮、可配送国家)或到店自提;优惠券(百分比、固定金额、免运费,可设时间、次数、门槛);价格含税或另计税;最低下单金额;购买条款勾选;Turnstile 与频率限制
支付Stripe Checkout、PayPal、Paytrail(芬兰,欧元)、微信支付与支付宝(中国大陆,人民币)、银行转账、货到付款 / 到店付款
订单待付款 → 已付款 → 处理中 → 已发货 → 已完成,已取消、已退款;下单即预留库存,取消/退款自动释放;销量统计;订单记录;物流公司和单号;内部备注;CSV 导出
邮件下单成功(附银行转账信息或自提地址)、付款成功、已发货(含物流单号)、已完成、已取消、已退款;新订单通知店主
自动化定时任务自动取消超时未付款的在线支付订单;事件 order.created、order.paid、order.status_changed 可推送到钉钉、飞书、企业微信等机器人
SEO产品 JSON-LD 中输出 schema.org Offer(价格、币种、库存状态)与 sku

运费模板

后台 商城 → 运费模板 可以按地区设置不同的运费;一个模板都没有时,沿用商城设置里的固定运费和满额包邮。

字段说明
适用国家 / 指定省份国家填 ISO 代码,* 表示全部;省份(州)留空表示整个国家,可写「上海, 江苏, 浙江」,「广东省」「广东」都能匹配
计费方式固定运费;按件数(首件 N 件多少钱,每续 M 件加多少);按重量(首重、续重按公斤填写,续重不足一档按一档算)
包邮条件满额包邮(按优惠后的金额)、满件包邮,可以同时设置

匹配顺序:先匹配指定了省份且省份对上的模板,其次是指定了国家的模板,最后是 *;同一级别按排序数字从小到大。收货地址匹配不到任何模板时,不能选快递配送下单。顾客还没填地址时,结算页按第一个全国模板预估运费。重量取商品编辑页「商城」卡片里的重量(克),未填写的商品按 0 计算;「免运费」优惠码对所有模板有效。

会员账户

在商城设置里打开 开启会员账户 后:

  • 页头出现账户图标,顾客可以注册、登录(/member/login)、找回密码(邮件链接 1 小时内有效,改密码后失效)。
  • 我的账户(/member):订单列表(点开即订单页)、个人资料、修改密码;收货地址(/member/addresses):增删改、设默认,最多 20 个。
  • 结账时自动带出姓名、邮箱、电话和默认地址,可以选择已保存的地址;填写新地址时可勾选「保存到地址簿」。
  • 关闭 允许免注册下单 后,必须登录才能结账;默认仍允许访客下单。
  • 后台 商城 → 会员:会员列表(订单数、已付款金额、最近下单)、停用 / 启用账户(停用后立即退出登录)。

会员与后台管理员是两套账户:会员使用单独的数据表(shop_customers、shop_addresses)和单独的 Cookie,无法进入后台。注册、登录和找回密码沿用「安全验证」里的登录验证设置,并有频率限制。会员下的订单关联到会员(shop_orders.customer_id,老站点升级时自动加列);免注册订单不会按邮箱自动归入会员。

积分

开启会员账户后,在商城设置里打开 开启积分:

设置说明
每消费 1 元获得积分订单 完成 后按商品实付金额发放(不含运费和另计的税),0 = 不发放
多少积分抵 1 元例如 100,即 100 积分抵 1 元
积分最多抵扣商品金额的 %例如 50,即最多抵扣一半
注册赠送积分新会员注册时发放

结账时会员可以勾选「使用积分抵扣」,按余额和上限自动计算;积分在下单时扣除。订单取消或退款时退回已用积分,并收回该订单发放的积分(余额不足时收回剩余部分)。会员在 我的账户 查看余额和明细;后台 商城 → 会员 点积分数字可以手动加减(不能扣成负数)。所有变动都记在 shop_points_ledger。

门店

在后台 商城 → 门店 添加门店(名称、地址、营业时间、电话、通知邮箱、服务区域、是否可自提)。没有门店时一切照旧:自提使用设置里的自提地址,订单不分配门店。

  • 到店自提:商城设置里开启「到店自提」后,结账时顾客从「可自提」的门店中选一家,必须选择;订单页和下单邮件显示该门店的地址、营业时间和电话。
  • 快递订单分配:按收货地址匹配门店的服务区域,规则和运费模板一样(地区匹配 > 国家匹配,同级按排序靠前)。服务国家留空的门店是兜底门店,接收其他门店都不覆盖的订单。
  • 通知:门店填了通知邮箱,分配给它的新订单会发一封邮件过去(和店主通知同样的内容)。
  • 后台:订单列表可以按门店筛选(也可以筛「未分配门店」),订单详情里可以改派门店,改派记在订单记录里。删除门店后,它的订单变为未分配。

门店库存

在 商城 → 门店库存 里,每个商品(有规格的按规格)一行、每家门店一列,填写各门店的库存:

  • 某个商品或规格只要填写了任意一家门店的库存,就改为 按门店计算:可售数量 = 启用门店的库存之和(自动写回商品,前台显示和下单数量限制照常生效)。在商品编辑里修改库存对它无效。
  • 下单从订单所属门店扣减,取消或退款时退回该门店;后台改派门店时,库存跟着订单从原门店转到新门店。
  • 到店自提只能选择备齐了这些商品的门店(结账页会标出缺货门店);快递订单优先分给服务区域内有货的门店,区域内都缺货时分给其他有货的门店。没有一家门店能备齐所有商品时无法下单,需要分开下单。
  • 停用的门店不计入可售数量。删除门店会一并删除它的库存。
  • 所有门店都留空,商品恢复按商品统一计算库存;没填写门店库存的商品一直按原方式计算。

商家入驻

开启会员账户后,在商城设置里打开 开启商家入驻,并设置平台默认佣金比例、订单完成后几天结算、商家最低提现金额。

  1. 申请:会员在 商家中心(/merchant,「我的账户」里有入口)填写店铺名称、联系人、电话等提交申请。
  2. 审核:后台 商城 → 商家入驻 通过或驳回(驳回原因商家可见,可修改后重新提交)。可以为每个商家单独设置佣金比例,留空用默认值。
  3. 分配商品:点商家的商品数,勾选它销售的商品。商品的标题、描述、图片仍由平台在后台维护,商家不接触网页内容和文件上传。
  4. 商家日常:在商家中心修改自己商品(含规格)的售价、划线价和库存(按门店计库存的商品由平台维护);查看包含自己商品的订单,只显示自己的商品行和收货信息(不显示买家邮箱),填写快递公司和单号标记发货(记入订单记录)。有新的已付款订单时给商家发邮件(店铺邮箱,留空用会员邮箱)。
  5. 结算:订单 付款 后为每个商家生成一条结算记录:应结算 = 该商家商品的销售额 − 平台佣金(四舍五入到分)。订单 完成 后过了结算天数计入商家余额。取消或退款时,未结算的取消、已结算的从余额扣回(可能为负,之后的结算先抵扣)。
  6. 提现:商家申请提现后金额立即从余额扣除;平台线下转账后在后台 提现记录 点「已打款」,或驳回并填写原因(金额退回)。同一时间只能有一笔处理中的提现。

说明:优惠券、积分抵扣和运费都由平台承担或收取,不影响商家结算;平台自己的商品(没有分配给商家)照常销售。暂停的商家不能登录商家中心,但它商品的订单照常产生结算。数据表为 shop_merchants、shop_merchant_earnings、shop_merchant_payouts,商品和订单明细上有 merchant_id。

两级分销

开启会员账户后,在商城设置里打开 开启两级分销:

设置说明
一级佣金比例 %推广员自己带来的订单,按商品实付金额计算(不含运费和另计的税)
二级佣金比例 %推广员的上级(邀请他的人)获得的比例,0 = 只有一级
推广员需后台审核打开后申请要在后台通过才生效
推广链接有效天数访客点击链接后这段时间内下单计入推广员,默认 30 天
订单完成后几天佣金到账默认 7 天,期间退款会取消佣金
最低提现金额低于这个金额不能申请提现

流程:

  1. 会员在 我的账户 → 推广中心 申请成为推广员,拿到推广码和链接。任何页面地址后加 ?ref=推广码 都有效。
  2. 访客通过链接进站,浏览器记住推广码。访客注册会员后与推广员 永久绑定;未注册或已有会员也按链接计入(链接过期后不再计入)。
  3. 订单 付款 后生成佣金(待到账):一级给推广员,二级给推广员的上级。订单 完成 后过了等待天数才到账,可以提现。到账由定时任务「商城:取消超时未付款订单」处理,打开推广中心或后台分销页时也会顺便结算。
  4. 订单取消或退款:未到账的佣金取消;已到账的佣金扣回,余额可能变成负数,之后的佣金会先抵扣。
  5. 推广员在推广中心填写收款方式(支付宝、微信、银行卡等)和账号申请提现,金额立即从余额扣除。商家在后台 商城 → 分销推广 → 提现记录 线下打款后点「已打款」(可填流水号);也可以驳回并填写原因,金额会退回余额。同一时间只能有一笔处理中的提现。

限制:最多两级;自己通过自己的链接购买不计佣金;停用的推广员不再获得新佣金(已有余额保留);推广员只能看到打码后的订单号,看不到买家信息。数据表为 shop_commissions 和 shop_withdrawals。

国内的分销活动请遵守相关法规,不要设置超过两级的返佣,也不要以拉人头本身作为收益来源。

发票与收据

商城设置 发票 / 收据 有四个选项:不提供、开票申请、自动收据、两者都提供。

  • 开票申请(适合中国大陆):顾客在结算页勾选「需要发票」,或付款后在订单页申请,填写个人 / 企业抬头和纳税人识别号(企业必填)。后台 商城 → 发票 处理:在税务系统开好后上传 PDF(最大 5 MB),顾客收到邮件并在订单页下载;也可以驳回并说明原因,顾客修改后重新提交。PDF 存在附件存储的 private/ 目录下,/api/media 不会提供这些文件,只能凭订单链接下载。
  • 自动收据(适合海外):订单付款后,订单页出现「查看收据」,打开即为可打印的收据 / 发票(卖方名称、地址、税号、购买方、明细、税额、积分和优惠),用浏览器「打印 → 另存为 PDF」即可保存。卖方信息在商城设置里填写,留空时使用站点名称和公司地址。

配置步骤

  1. 后台 → 插件 → 在线商城 → 配置(或 商城 → 商城设置):币种、税率、配送、自提、订单号前缀、通知邮箱以及要启用的支付方式。
  2. 打开任意产品,编辑器右侧的 商城 卡片里设置价格、库存、规格和图集,随产品一起保存。商城数据按产品 slug 关联,同一产品的各语言版本共用价格与库存。
  3. 在 后台 → 邮件配置 设置 SMTP,客户才能收到订单邮件。
  4. 确认定时任务 Worker(deploy/cron-worker)在运行,"取消超时未付款订单"任务才会执行。

支付方式

支付方式需要填写说明
StripeSecret Key sk_…;可选 Webhook 密钥 whsec_…客户返回网站时通过 API 核实付款。更稳妥的做法是在 Stripe 后台添加 Webhook /api/shop/webhooks/stripe,事件选 checkout.session.completed 和 checkout.session.async_payment_succeeded。
PayPalClient ID + Secret,可切换沙箱使用 Orders v2,客户返回时扣款。
Paytrail商户号 + 密钥仅支持欧元。跳转参数与服务器回调 /api/shop/webhooks/paytrail 均做 HMAC 校验并核对金额。测试账号:商户号 375917,密钥 SAIPPUAKAUPPIAS。
微信支付商户号、AppID、APIv3 密钥、商户 API 证书序列号、商户 API 私钥(apiclient_key.pem);可选微信支付公钥及其 ID仅人民币,APIv3。电脑端在订单页显示二维码(Native 支付),付款后页面自动更新;手机浏览器在开启"H5 支付"后跳转微信付款(需在商户平台开通 H5 支付并配置域名),否则也显示二维码;微信内打开时显示二维码,长按识别即可。回调地址 /api/shop/webhooks/wechat(需 https):用 APIv3 密钥解密,填写公钥后同时校验签名。
支付宝AppID、应用私钥(RSA2,PKCS8 / PKCS1 均可)、支付宝公钥;沙箱开关仅人民币,公钥模式。电脑端跳转电脑网站支付(扫码或登录付款),手机端跳转手机网站支付并拉起支付宝 App。微信内不提供支付宝(微信会拦截)。异步通知 /api/shop/webhooks/alipay 做 RSA2 验签,客户返回时再调用 alipay.trade.query 核实。
银行转账转账说明订单保持"待付款",收到款项后在后台手动标记为已付款。
货到付款—同上,收款后手动标记为已付款。

所有在线支付在标记为已付款前,都会在服务器端核对订单金额与币种。微信支付和支付宝的付款有效期与"未付款订单自动取消"一致(time_expire);如果已取消的订单仍收到付款,会在订单记录里提示退款。浏览器从不提交价格,购物车由 /api/shop/quote 和 /api/shop/checkout 重新计价。

站点预设与环境变量

可以在站点的 nuxtcms.plugins.json 中预设插件设置(后台保存的值优先),支付密钥也可以放在环境变量里,不必存进数据库:

{ "plugins": [{ "id": "shop", "package": "nuxtcms/plugins/shop", "license": "NCMS-…",
  "settings": { "currency": "EUR", "taxRate": 14, "pickupEnabled": true, "orderPrefix": "LC" } }] }
变量对应设置
NUXT_SHOP_STRIPE_SECRET_KEY / NUXT_SHOP_STRIPE_WEBHOOK_SECRETStripe
NUXT_SHOP_PAYPAL_CLIENT_ID / NUXT_SHOP_PAYPAL_SECRETPayPal
NUXT_SHOP_PAYTRAIL_MERCHANT_ID / NUXT_SHOP_PAYTRAIL_SECRETPaytrail
NUXT_SHOP_WECHAT_MCH_ID / _APP_ID / _API_V3_KEY / _SERIAL_NO / _PRIVATE_KEY / _PUBLIC_KEY_ID / _PUBLIC_KEY微信支付
NUXT_SHOP_ALIPAY_APP_ID / NUXT_SHOP_ALIPAY_PRIVATE_KEY / NUXT_SHOP_ALIPAY_PUBLIC_KEY支付宝

自定义

所有界面都通过扩展点渲染,站点的布局不受影响。在站点的 app/app.config.ts 中调整:

export default defineAppConfig({
  nuxtcms: {
    slots: {
      'header:actions': { ShopCartButton: false }, // 站点页头已有自己的购物车图标
    },
  },
})

全局组件 ShopCartButton、ShopBuyBox、ShopCardPrice、ShopGallery 可以直接放进自定义布局(<ShopCartButton />)。站点也可以在同一路径覆盖插件页面,例如自己写一个 app/pages/checkout.vue。

数据表({前缀}shop_products、shop_orders、shop_order_items、shop_order_notes、shop_coupons)在首次使用时自动创建,支持 SQLite / D1、PostgreSQL 和 MySQL。