刚开始做B2B平台时,很多人图省事,直接用ASP.NET Web Forms搭个单体应用,把所有功能都塞在一个项目里。这种做法在用户量少、业务简单时确实跑得挺欢,但一旦客户数量上来,订单处理、库存同步这些模块一多,系统就会变得臃肿不堪,改一个地方可能牵扯到整个项目,维护成本直线上升。说白了,这就是给自己挖坑。
我个人更推荐从一开始就用ASP.NET Core配合微服务架构来设计。
把用户管理、商品管理、订单处理、支付结算这些核心模块拆成独立的服务,每个服务都可以单独部署、扩展和维护。比如用户登录和商品搜索是两种完全不同性质的请求,拆分后,你可以给搜索服务配更高的并发资源,而用户服务则更注重数据安全性,互不干扰。
数据层方面,B2B平台通常会涉及海量商品信息和历史订单,单纯用关系型数据库可能扛不住。实际项目中,很多人选择用SQL Server存储核心交易数据,同时引入Redis做缓存,把热门商品、用户会话信息放进去,响应速度能提升好几倍。有次我帮一个客户优化,仅仅加了缓存层,首页加载时间就从3秒降到了0.5秒,用户反馈立竿见影。
B2B和B2C最大的不同,就是用户角色极其复杂。一个企业客户下面可能有采购员、财务、经理、老板等多种身份,每种身份看到的页面、能操作的功能都不一样。ASP.NET自带的Identity框架虽然能搞定基础的用户注册登录,但要支撑这种细粒度的权限控制,还得自己动手扩展。
常见的做法是建立“角色-权限-菜单”三级体系。比如采购员只能看到商品列表、下订单,财务只能查看发票和付款记录,而经理可以审批订单、修改价格。在ASP.NET中,我习惯用自定义的AuthorizeAttribute配合数据库中的权限表来实现。每次用户请求一个页面,程序先去查这个角色有没有对应权限,没有就直接跳转到无权限提示页,干净利落。
另外,还要考虑多站点管理。很多B2B平台会同时服务多个供应商,每个供应商有自己独立的商品库和定价策略。这时候就需要引入租户隔离的概念,每个租户的数据物理上或逻辑上分开。我见过一个项目,直接用数据库的schema来区分租户,每个供应商一个schema,既保证了数据隔离,又方便后期独立备份,效果很不错。
B2B的商品管理比普通电商复杂得多。首先,商品属性是动态的,不同行业的商品规格千差万别,比如钢材需要长度和厚度,化工品需要浓度和纯度。如果每个商品类型都建一张表,那数据库结构会变得极其混乱。更聪明的做法是用“属性-值”的键值对模型,把商品的核心信息存成结构化字段,而自定义属性存成JSON格式,ASP.NET Core对JSON处理很友好,解析起来不费劲。
定价策略更是B2B的核心痛点。同一个商品,给大客户的批发价,给小客户的零售价,甚至同一客户不同订单量下的阶梯价,都得灵活配置。我建议在商品表中维护一个基础价,然后单独建一张价格策略表,里面存储客户等级、订单数量区间和对应的折扣率。每次下单时,系统根据当前客户的等级和订单数量,动态计算出最终价格。这个逻辑如果写在代码里会很乱,用数据库的存储过程或者规则引擎来处理,会清晰很多。
库存同步也是个老大难问题。供应商那边的库存是实时变动的,如果平台上显示有货,实际却缺货,用户体验会非常糟糕。常见的方案是通过API定时拉取供应商库存,或者用消息队列实现实时同步。我偏向用后者,每次供应商库存变化,立即发送一条消息到平台,平台更新数据库。虽然实现起来稍微复杂点,但能最大程度避免超卖问题。
B2B的订单流程往往很长,从下单、审核、付款、发货到收货,中间还可能涉及多次修改和取消。用ASP.NET开发时,我习惯为每个订单设计一个状态机,比如“待审核、审核通过、待付款、已付款、发货中、已完成、已取消”。状态之间的跳转要严格限制,比如“已付款”的订单不能直接变成“已取消”,必须先走退款流程。这样能防止业务逻辑出现漏洞。
支付集成方面,B2B通常支持多种方式:银行转账、承兑汇票、在线支付等。在线支付部分,ASP.NET对接支付宝和微信支付都有成熟的SDK,难点在于处理回调。一定要在回调接口中做好幂等性处理,防止重复扣款。我遇到过踩坑的例子:网络抖动导致回调发了两次,代码没做判断,结果客户被扣了两笔钱,后续处理起来非常麻烦。
最后,别忘了日志和监控。B2B平台对数据准确性要求极高,任何订单异常都需要记录详细的操作日志,方便事后追溯。ASP.NET的ILogg昆明拓荒者运动设备有限公司er接口配合ELK或Seq之类的日志平台,可以快速定位问题。说白了,平时可能觉得日志没用,但出问题那天,它就是救命稻草。