首页 / 开发文档 / 在线商城

在线商城

卖东西:商品怎么建、库存怎么扣、订单走到哪一步、钱怎么收。

先搞清楚它和「应用商店」不是一回事

在线商城应用商店
卖给谁你站点的访客用这套系统的站长
卖什么你自己的实物 / 虚拟商品 / 服务插件、主题、增值服务
入口前台 /shop前台 /store(只在官方站)
后台商城 → 商品管理 / 订单与发货外观 → 商品与开发者

两者共用同一套收款配置(站点设置 → 在线收款),但订单、库存、收货地址各是各的。

开张五步

  1. 配好收款:站点设置 → 在线收款,填支付宝 / 微信。不配也能用,只是只能线下收款。
  2. 打开开关:站点设置 → 在线商城 → 勾「开启在线商城」。
  3. 加商品:两个入口都行 —— ① 商城 → 商品管理 → 填名字、挑栏目、填价格与库存(提交后自动跳到内容编辑器继续填详情); ② 内容管理里写好的文章,打开编辑页 → 「商城」标签 → 上架为商品, 在同一个标签里填价格与库存,跟着「保存内容」一起保存。用哪个入口取决于你是 "先想卖什么"还是"先写了什么"。
  4. 设运费:同一节里的「运费 / 满多少包邮」。
  5. 前台 /shop 就能看到商品了。买家要登录才能加购与下单。

商品 = 内容 + 交易信息

一件商品在库里是两行:一行是内容(图文详情、封面、SEO、评论、多语言、进 sitemap), 一行是交易信息(价格、库存、规格)。所以:

  • 商品详情页就是普通的内容详情页,地址也是 /detail/别名 —— 一个商品只有一个地址,不存在"商城页与文章页重复收录"的问题。
  • 要卖的是"内容的一部分"(压缩包、网盘地址、后半截正文)就配付费可见内容, 见下面那一节 —— 正文照样公开、照样被收录,只有那部分是付款后才给。
  • 内容列表里有「商品」标记,一眼能看出哪几篇同时也在卖。
  • 「从商城移除」只删交易信息,图文内容还在内容列表里,可以再挂回来。
为什么要分成两行,而不是在内容里加个"价格"字段? 因为下单要用一条 SQL 原子扣库存(UPDATE ... SET stock=stock-1 WHERE stock>=1), 列表要按价格排序与筛选。这些都必须落在数据库的正式列上;内容模型的扩展字段 存的是 JSON 文本,做不到(只能全表取出来在 PHP 里算,两个人同时下单就会超卖)。 同一件商品在内容侧还有一个「产品」模型,它里面的「价格」字段是展示用的文案, 写进正文区;收银台只认商城里的价格。两个都填不冲突,但改展示价不会影响收款。

库存是怎么算的

填什么含义
正数实际可卖数量
0售罄,前台显示「已售罄」且不能下单
-1不限量(虚拟商品、服务常用),不参与扣减

时间线:下单时预占 → 付款时计销量 → 关闭/超时则放回货架。

下单就占库存,不是付款才占。不这样的话,两个人同时下单会都以为"还有货", 付完款才发现发不出第二件。所以待付款的订单是占着货的 —— 超过 2 小时没付款会自动关闭并放回。

每一次库存变动都记在流水里。后台手工改库存也走同一条路 —— "库存怎么少了两件"这种问题,只能靠流水回答。

「每人限购」是跨订单算的

商品上的「每人限购」填 0 表示不限;填 N 就表示这个会员一共只能买 N 件。

  • 已经买过的件数会累计:分十次下单、每次一件,也绕不过去(这是"每人"两个字的意思, 只看单笔数量的话它就变成了"每单限购")。
  • 统计口径是「没被关闭、也没退款的订单」—— 待付款的单也算, 因为它下单时就把货占住了;取消或超时关闭之后名额还回去。
  • 能买的上限取「库存」与「限购剩余额度」里小的那个,商品页与购物车都会按它封顶, 并给一句人话说明("每人限购 2 件,你还能买 1 件")。

订单会经过哪几个状态

待付款 ──付款──→ 待发货 ──发货──→ 已发货 ──买家确认──→ 已完成
   │
   └──超时/取消──→ 已关闭(库存放回)

只有待付款的单能关闭,只有待发货的单能发货 —— 这两道闸门是为了 防止"没收到钱就发货"和"把已经发出去的单退掉库存"。

订单里的商品名与单价存的是下单当时的快照:以后改价改名,历史订单不会跟着变。 发货用的收货信息同理,买家之后改地址簿不影响已下的单。

钱怎么收

买家在订单页点「用支付宝支付」或「用微信支付」。付完之后:

  • 支付宝会跳回收银台,回来就是订单页;
  • 微信会显示一张二维码,扫完页面不会自动变 —— 点「我付好了」让系统去查一次。

线下转账、现金这些情况:后台订单页有「手工确认收款」。 它走的是和在线支付完全相同的入账路径(幂等、金额以本地订单为准), 重复点不会重复计销量。

回调丢了怎么办:订单页的「我付好了(查一下)」会主动向网关查一次。 这是防火墙、超时、用户提前关页面之后的兜底。

钱到了、单却已经关了怎么办

这种情况是真会发生的:买家扫码付了款却没回到网站,两小时后我们把订单超时关闭、 库存放回货架,而他的付款在关单之后才到账。系统对它的处理是记账,但不自动处置:

  • 订单状态不会改回「待发货」—— 那张单的库存已经放回去了,改回去等于凭空多卖一次;
  • 不会自动退款 —— 退款是真实资金动作,要不要发货、退多少,得人判断;
  • 后台「商城订单」会把它标成 异常收款:顶部有计数、列表里可以按「异常收款」这一档筛出来, 单子上会写明「这一单已关闭,但收到了付款」,旁边有「标记已处置」。

你要做的:去支付渠道后台退款,或者联系买家补发货;处置完在后台把那面旗摘掉、写一句说明。

关单时程序还会尽力通知网关把这笔交易也关掉(支付宝、微信都有关单接口), 为的是缩小上面那个时间窗。但那一步是尽力而为(网关没配、网络不通、接口报错都不影响本地作废), 所以这条人工兜底仍然必须有。

付费可见内容(买完才给的那部分)

很多卖内容的场景不是"买一件商品",而是正文公开、某一部分要付款后才给: 压缩包下载、网盘地址与提取码、后半截正文。这样前台的文章照常被搜索引擎收录, 掏钱的人拿到的才是"货"。

怎么配:内容编辑页 →「商城」标签 → 上架为商品 → 填价格 → 下面的「付费可见内容」里填两块(都在同一个表单里,跟着「保存内容」一起保存):

  • 付费后可见的正文:一段 HTML,只有买过的人看得到。
  • 付费后可见的附件/网盘:每行一条,格式 名称 | 地址 | 提取码 | 说明 (后两段可省)。地址留空就只是一条"包含什么"的说明 —— 它会给所有人看, 用来告诉还没买的人"买了能拿到什么"。
为什么未购买者也能看到清单,却看不到链接。 "买了能得到什么"是成交的前提,藏起来只会让人不敢买; 而地址与提取码才是要卖的东西,服务端对没买的人连数据都不返回 —— 不是"前端藏起来",所以查看网页源码也拿不到。

站内附件 vs 外部网盘

放什么怎么填能不能防转发
压缩包等站内文件用「选择文件并上传」按钮,自动写成 paid/<内容id>/文件名 能:文件存在 storage/paid/(wwwroot 之外), 只能经 /shop/dl-… 取,那个地址每次都会重新校验购买记录, 所以把链接转给别人也拿不到
百度网盘等外链直接贴 https://…,提取码填第三段 不能:对方看到链接就能转发。这是外链的性质,不是这里没做

什么时候算"买过":会员名下有这张商品的已付款订单(待发货/已发货/已完成)。 待付款不算(没给钱不给货),关闭或退款的单也不算。

改内容不会让老买家重新付钱,但他下次看到的就是你改后的新内容 —— 替换附件时请想清楚:已经卖出去的那批人也会看到新文件。
另外:一个内容只有一份付费可见内容(不是每个买家一份、也不能给某个人单独发一份)。 需要"按人发不同东西"的场合,目前只能靠站外沟通。

收货地址簿

买家在 /shop/addr 管理自己的收货地址:新增、修改、删除、设默认都在这一页。 结算页的「收货信息」旁边有「管理收货地址」入口。

为什么地址管理不放在结算页里:结算页那行的地址是下单表单里的单选按钮, 在它里面再放一个「删除」表单就成了 form 套 form —— 浏览器会丢掉内层表单, 症状是"点删除没反应"。分开一页最稳,而且地址管理本来也不该只有结算的时候才进得来。

删地址不影响已经下过的订单:订单上存的是下单当时的地址快照。 删掉的如果是默认地址,程序会自动把另一个提成默认 —— 否则下次结算页没有预选项,"默认地址"这个功能就等于没有。

运费只做了最简单的一条规则

一段固定运费 + 满多少包邮;全是虚拟商品的订单不收运费。

按重量、按地区、按件数的阶梯计价没有做 —— 那需要一张规则表和一个匹配引擎, 边界极多(首重续重、偏远地区、按件叠加),做一半的计价规则比没有更难解释。 需要复杂计价的站点可以在此基础上自己接。

关掉商城会怎样

前台 /shop 返回 404,访客看不到商品也下不了单。 商品、订单、收货地址一条都不会删;已经付了款的订单照常在后台处理。 再打开开关就恢复原样。

收货地址与手机号是个人信息。只有买家本人和后台看得到; 后台订单列表里手机号是打码的,进到具体订单才显示完整的(那时候是要照着发货)。
没找到答案? 可以在 联系我们 留言说明使用场景,我们会补充进文档。
Powered by NaichaCMS