Loading

商城项目业务逻辑

商城数据库概要设计

使用分库分表,给订单相关设置分表,订单号作为分表依据

商品库:商品sku表、sku属性表、sku图片表、商品spu表、spu属性表、spu图片表、商品品牌表、三级分类表等

一个sku关联多个spu表,

订单库:订单表、订单详情表、订单退款表、支付信息表、退货表、退款表、退货原因表

订单表相关表都用订单id相关联

会员库:会员表、会员等级表、会员收货地址、会员登陆记录表、会员收藏商品表、会员积分表、会员积分历史变化表

库存库:仓库表、商品库存表、采购信息表、库存工作单

管理员库:系统日志、角色表、菜单表、角色和菜单表、用户token表、系统验证码、系统日志表

优惠库:秒杀活动场次表、秒杀活动商品关联、会员价格表、优惠券信息、优惠券领取记录、优惠券与商品关联表、积分信息表

购物车:商品表,品牌表,分类表,库存表,用户表,库房表,购物车表,购物项表,优惠券表,商品推荐表。

登录模块

1.前后端对数据进行校验,请求进入后台

2.根据用户名或者手机号在数据中查询,并把数据加密的结果,和登录密码进行利用BCryptPasswordEncodermatches方法比对

3.比对成功返回

注册模块

1、前端判断用户输入参数格式

2、注册时需要输入手机短信验证码

3、首次注册把验证码存储在redis中,然后设置过期时间,1分钟

4、再发送验证的时候判断redis中,验证码是否过期,没过期不给予重发

5、登录的时候,获取存入Redis里的验证码,不为空验证通过删除验证码

6、输入账号密码点击注册,首先会判断redis中有没有该手机号的验证码

7、对比成功删除验证码,跳转到会员服务注册验证手机号用户名是否存在

8、不存在重复的就注册成功,然后跳转到用户登录页面

9、输入用户名密码,去数据库对比账户,密码用BCryptPasswordEncoder的matches方法

10、对比成功就把用户数据存在session中

会员服务拦截器会从请求中获取session,从中获取用户的信息,然后保存在ThreadLocal副本中,在其他方法中传递

OAuth2授权验证登录

用户登录请求授权,点击同意授权

  1. 会向认证中心申请的几个参数:client_id(客户端唯一id)、client_secret(客户端密钥)等等信息

  2. 带上这些参数向微博的认证中心获取授权码code

  3. 微博认证中心返回Authorization Code授权验证码

  4. 然后携带授权码发送请求给认证中心获取令牌Access Token

  5. 认证中心收到令牌会返回一段json数据,包含Access Token

    {    
      "access_token":"ACCESS_TOKEN",
      "token_type":"bearer",
      "expires_in":2592000,
      "refresh_token":"REFRESH_TOKEN",
      "scope":"read",
      "uid":100101
    }
    
  6. 携带这个json里面的令牌access_token去获取微博里面的用户信息

SSO单点登录

img

注销

3b139d2e-0b83-4a69-b4f2-316adb8997ce

购物车模块

未登录用户只能存20个数据,已登录用户只能存50个数据

未登录用户购物车只能存放在浏览器cookie中

已登录用户购物车存放在redis中

展示购物车是,如果用户登录了还要把cookie中的商品和已登录的商品进行合并

获取购物车

  1. 没登陆是临时用户,从浏览器的cookie获取购物车信息
  2. 已登录情况下就是当前用户购物车,从redis中获取
  3. 没登陆并且是临时用户,需要创建一个临时用户

获取购物车具体逻辑

1、方法请求之前,通过HandlerInterceptor拦截器获取用户登录或者未登录用户的信息

2、先从request请求里面获取session里面当前登录的用户,如果没有的话遍历获取浏览器cookie

3、查询cookie里面有没有user-key,没有的话配一个临时用户

4、临时用户user-key为随机生成的uuid,并标记为临时用户

5、把这些信息存放到ThreadLocal里面

6、获取购物车方法里面,取得当前拦截器的ThreadLocal,得到用户信息

7、如果用户信息不为空,说明已登录,

8、在所有方法执行完毕之后,如果当前用户不是临时用户把当前用户信息保存到浏览器

image-20211202210057317

添加购物车具体逻辑

  1. 根据当前用户的id获取redis中的购物车数据,拿当前需要添加的商品skuid和redis中的数据对比

  2. 如果有相同的数据,只需要增加购物车中的数量

  3. 如果redis中没有该商品,那么就新增进去

  4. 新增操作:远程调用商品服务根据skuid查询该商品的信息,还有该属性的信息库存数量等等

    封装成购物车的实体,重新放入原来的购物车中

订单确认页逻辑

订单确认页流程

去结算分别远程调用

  • 遍历重新获取购物车商品的价格
  • 获取用户的地址
  • 获取商品的库存信息

采用异步编排操作等待以上所有执行完

并生成唯一令牌保存在redis中过期时间30分钟,多次提交订单防重,重复提交的话每次都会生成新的token,之前的token会失效

成功生成确认订单的实体

提交订单逻辑

创建事务

  1. 去验令牌

    1. 创建订单的时候就会生成令牌token,然后存储在redis中,提交订单会再次核验是否redis有对应令牌,有的话删除令牌,没有的话不予再次提交订单。令牌的确认和删除需要保障原子性,利用redis的lua脚本进行操作
  2. 创建订单

    1. 生成订单号(时间戳)

    2. 获取选中购物车的所有项,创建订单项

    3. 获取收货人信息填充订单

    4. 计算订单金额

  3. 验价格

    1. 再次获取购物项,获取价格,之后提交订单以这个价格为准
  4. 构建订单项

    每个sku商品的信息

  5. 保存订单、以及订单项

  6. 锁定库存

    方法加上事务

    根据传入的订单项,拿商品的id去仓库表查询就近仓库,返回有库存的仓库

    然后遍历仓库查询是否有该商品的库存数量,仓库没有该商品就抛出异常

    有库存的去库存表更新,减去库存数量,并增加锁定库存数量,如果没有锁住抛出异常

    最后锁库存成功

    把消息发送给MQ,设置30分钟过期时间,延时队列,没有被消费就解锁库存

2.下单成功来支付选择页

3.下单失败回到订单页重新确认提交信息

库存解锁逻辑

1、下订单成功,订单过期没有支付被系统自动取消或者用户手动取消,都要解锁库存

2、下订单成功、库存锁定成功,但是业务调用失败导致订单回滚,之前锁定的库存就自动解锁,Seata分布式事务太慢,就要用一段时间后自动解决库存。

3、订单失败,因为锁库存失败有一个商品没有锁成功,导致整个锁库存服务都回滚,

取消、超时未支付关闭订单逻辑

订单创建后,默认放入延时队列,也就是订单的有效时间,超过这个时间没有支付或者用户主动取消都会导致订单信息进入order.release.order.queue队列,最后被释放

订单支付逻辑

传入支付信息(总价等等)

调用支付宝接口pay方法,到支付宝客户端

在客户端创建一个支付请求客户端生成请求

自动来到支付宝的收银台页面

支付之后跳转到支付成功页面

关闭订单逻辑

手动关闭和自动关闭

会发送一条消息到订单交换机,订单交换机分发到库存解锁队列、优惠券返还队列、释放订单队列

数据库保存每一条消息的详细信息,定期扫描数据库将失败的消息再发送一遍

秒杀商品上架

定时任务使用分布式锁防止定时任务重复执行,查询3天内需要上架的秒杀商品,查询完之后解锁

然后把扫描到的商品活动信息放入redis中

秒杀的起止时间作为key,场次和商品id作为value存入redis中

引入分布式锁的信号量,秒杀的数量作为信号量 一个秒杀减一个

利用商品随机码随机生成的token设置分布式信号量,秒杀的数量作为信号量 一个秒杀减一个

秒杀商品逻辑

image-20211024105228513

1、先判断是否登录,利用mvc视图监听

2、点击页面秒杀按钮,后台获取秒杀的商品Id信息,还有随机码、商品数量

3、根据商品ID去redis查询sku信息,从集合中获取到商品的json数据再转为实体

4、利用之前存储的随机校验码,和页面获取到的效验码对比,验证购买数量

5、然后根据商品的key值和当前用户id拼接作为新的key值存入redis ,并设置过期时间,可以防止同一个用户同一时间多次秒杀到同一个商品

6、根据随机码获取到信号量,扣去信号量

image-20211024180011240

7、整合成订单实体,快速向消息丢列发送订单消息,监听队列

8、队列调用创建订单的方法,并保存

9、同时发送数据至页面,页面识别到已生成订单号就转发至支付宝支付

10、支付成功之后,自动调用回调方法修改订单成已支付状态

秒杀完成

订单提交逻辑

  1. 去验令牌

    1. 创建订单的时候就会生成令牌token,然后存储在redis中,提交订单会再次核验是否redis有对应令牌,有的话删除令牌,没有的话不予再次提交订单。令牌的确认和删除需要保障原子性,利用redis的lua脚本进行操作
  2. 创建订单

    1. 生成订单号

    2. 获取选中购物车的所有项,创建订单项

    3. 获取收货人信息填充订单

    4. 计算订单金额

  3. 验价格

    1. 再次获取购物项,获取价格,之后提交订单以这个价格为准
  4. 构建订单项

    每个sku商品的信息

  5. 保存订单、以及订单项

  6. 锁定库存

    方法加上事务

    根据传入的订单项,拿商品的id去仓库表查询就近仓库,返回有库存的仓库

    然后遍历仓库查询是否有该商品的库存数量,仓库没有该商品就抛出异常

    有库存的去库存表更新,减去库存数量,并增加锁定库存数量,如果没有锁住抛出异常

    最后锁库存成功

2.下单成功来支付选择页

3.下单失败回到订单页重新确认提交信息

posted @ 2022-04-24 12:02  炒焖煎糖板栗  阅读(543)  评论(0编辑  收藏  举报