Resumen de Shangpin VII: Módulo de detalles del producto (solo para entrevistas)

1. Introducción comercial

     El negocio de pedidos es el núcleo de toda la plataforma de comercio electrónico y también es un negocio relativamente complicado. Es una estación de transferencia para convertir "cosas" en "dinero".

      Todo el módulo de pedidos consta de cuatro partes:

  1. página de pago

En la página de la lista del carrito de compras, hay un botón de pago. Cuando el usuario hace clic en este botón, saltará a la página de pago. La página de pago muestra los datos del producto (lista) seleccionados por el usuario en el carrito de compras, y también muestra todos los artículos del usuario Información del destinatario para que los usuarios elijan.

Para evitar que el usuario use la función de reversión del navegador después de enviar el pedido y enviar el pedido repetidamente sin actualizar, colocamos un número de serie (número de pedido) en la página de pago cuando se genera la página de pago.

Este número de serie es generado por UUID en segundo plano, y el número de serie se almacena en redis y en la página de liquidación.

  1. hacer un pedido

El usuario hace clic en el botón Enviar pedido en la página de pago para comenzar a realizar un pedido (se guarda la información del pedido),

  1. Para verificar el número de serie, compare el número de serie en la página de liquidación con el número de serie en redis. Si son iguales, puede realizar un pedido. Si son diferentes, no puede realizar un pedido.
  2. Verifique el inventario, llame a la interfaz de inventario y consulte el inventario. Si está agotado, le recordará que el inventario es insuficiente.
  3. Verifique el precio del producto para evitar que el precio del producto cambie cuando se realiza el pedido. Llame al servicio de productos para consultar el último precio del producto y compararlo con el precio anterior.
  4. Agregue datos a la tabla Pedidos y a la tabla Detalles del pedido.
  5. Elimine el número de serie en redis, de modo que solo se realice un pedido y el número de serie de redis desaparezca. Incluso si el usuario vuelve a la liquidación a través del navegador, la página de liquidación todavía tiene el número de serie, pero el número de serie en redis se ha ido, por lo que la comparación no funcionará.
  6. Después de guardar el pedido , use rabbitMQ para enviar un mensaje retrasado para cerrar el pedido vencido.
  1. Servicio de pago de atraque

Cuando el pedido se realiza con éxito, el usuario será redirigido a la página de pago, lo que le permitirá elegir el método de pago y realizar el pago.

Una vez que el pago se realiza correctamente, el servicio de pago utiliza RabbitMQ para notificar al servicio de pedidos que el estado del pedido debe modificarse de no pagado a pagado.

  1. Sistema de gestión de inventario de acoplamiento

Al realizar un pedido, verifique el inventario. Después de que el pago sea exitoso, el servicio de pedidos usa rabbitMQ para notificar al servicio de inventario para notificar el inventario para empacar. Cuando el inventario está bloqueado y el inventario se deduce del inventario, después de que la deducción es exitoso, el servicio de inventario usa rabbitMQ para notificar al servicio de pedidos Cambie el estado de Pagado a Pendiente de envío. Posteriormente, cuando se empaqueta y envía el inventario, se debe modificar el estado del pedido de pendiente de envío a enviado, y se mostrará la información de logística al usuario.

2. Página de liquidación

 Entrada: Haga clic en el botón Calcular en el carrito de compras

 analizar

   Los datos necesarios para la página de análisis:

  1. obtener información del usuario
  2. Lista de artículos seleccionados en el carrito
  3. recipiente de información

 

3. Haz un pedido

1. Estructura de datos

orderInfo: tabla de pedidos

orderDetail: detalles del pedido

identificación

Clave primaria. Generado automáticamente

consignatario

Nombre del destinatario. búsqueda de página

destinatario_tel

Número de teléfono del consignatario. búsqueda de página

dirección de entrega

Dirección de envío. búsqueda de página

cantidad total

Suma global. calcular

estado_pedido

Estado del pedido, utilizado para mostrar al usuario. Establezca el valor inicial.

ID de usuario

ID de usuario. Los interceptores esclavos se han puesto en atributos de solicitud.

forma de pago

Forma de pago (pago online, contrareembolso). búsqueda de página

ordenComentario

Estado del pedido. búsqueda de página

out_trade_no

Número de pago de terceros. Generado por reglas

crear_tiempo

Tiempo de creación. establecer la hora actual             

expire_time

Hora actual predeterminada + 1 día

proceso_estado

Estado de progreso del pedido, control del programa, vista de gestión en segundo plano. establecer el valor inicial,

seguimiento_no

El número de logística, inicialmente vacío, se agregará después de la entrega

parent_order_id

Generado al dividir un pedido, el valor predeterminado está vacío

identificación

clave principal, generada automáticamente

Solicitar ID

Número de pedido, después de guardar la tabla principal, se le dará a la tabla esclava

sku_id

Pase de página de identificación del producto

sku_name

Nombre del producto, agregado en segundo plano

img_url

Ruta de la imagen, añadida en segundo plano

precio del pedido

El precio unitario del producto se obtiene de la página y se comprueba.

sku_num

El número de artículos, obtenidos de la página.

2. Analizar y realizar un pedido:

  1. Verificar antes de guardar el documento: verificar inventario, verificar precio.
  2. Guarde el documento: orderInfo orderDetail.
  3. Después de guardar, elimine los artículos del carrito de compras.
  4. Redirigir a la página de pago.

3. ¿Cómo resolver el problema de los usuarios que envían pedidos repetidamente mediante la actualización y reversión del navegador?

Al ingresar la página de liquidación, producimos un número de serie , luego guardamos una copia en el elemento oculto de la página de liquidación y guardamos una copia en Redis. Cada vez que el usuario envía un pedido, verificamos si el número de serie en reids coincide el enviado en la página. , si son iguales, se puede enviar, y el número de serie en el fondo se eliminará después de guardar el pedido. Luego, si el usuario envía la misma página por segunda vez, el número de serie no coincidirá y el pedido no se podrá guardar repetidamente.

3.1 Modificar la página de liquidación para aumentar la generación de número de serie

Clase de implementación

@Override 

  public String getTradeNo(String userId) { 

    // Definir clave

     String tradeNoKey = "usuario:" + userId + ":tradeCode" ; 

    // Definir un número de serie
 String tradeNo = UUID. randomUUID ().toString().replace( "-" , "" ); redisTemplate .opsForValue().set(tradeNoKey, tradeNo); return tradeNo; 
} @Override public boolean checkTradeCode(String userId, String tradeCodeNo) { // Definir clave String tradeNoKey = "usuario:" + ID de usuario + ":código de comercio" ;
    

    

    


  

  

  

    

    

    String redisTradeNo = (String) redisTemplate.opsForValue().get(tradeNoKey);

    return tradeCodeNo.equals(redisTradeNo);

}

  //删除流水号

  @Override

  public void deleteTradeNo(String userId) {

    // 定义key

    String tradeNoKey = "user:" + userId + ":tradeCode";

    // 删除数据

    redisTemplate.delete(tradeNoKey);

}

3.2 OrderController中的submitOrder方法中

/**
 *
提交订单
 * @param
orderInfo
 
* @param request
 
* @return
 
*/

@PostMapping("auth/submitOrder")
public Result submitOrder(@RequestBody OrderInfo orderInfo, HttpServletRequest request) {
   
// 获取到用户Id
   
String userId = AuthContextHolder.getUserId(request);
    orderInfo.setUserId(Long.parseLong(userId));
   
// 获取前台页面的流水号
   
String tradeNo = request.getParameter("tradeNo");
   
// 调用服务层的比较方法
    
boolean flag = orderService.checkTradeCode(userId, tradeNo);
   
if (!flag) {
       
// 比较失败!
       
return Result.fail().message("不能重复提交订单!");
    }
   
//  删除流水号
   
orderService.deleteTradeNo(userId);
   
// 验证库存:
   
List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
   
for (OrderDetail orderDetail : orderDetailList) {
       
// 验证库存:
       
boolean result = orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
       
if (!result) {
           
return Result.fail().message(orderDetail.getSkuName() + "库存不足!");
        }
       
// 验证价格:
       
BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
       
if (orderDetail.getOrderPrice().compareTo(skuPrice) != 0) {
           
// 重新查询价格!
           
cartFeignClient.loadCartCache(userId);
           
return Result.fail().message(orderDetail.getSkuName() + "价格有变动!");
        }
    }
   
// 验证通过,保存订单!
   
Long orderId = orderService.saveOrderInfo(orderInfo);
   
return Result.ok(orderId);
}

4、验库存

通过restful接口查询商品是否有库存

    一般电商系统的商品库存,都不由电商系统本身来管理,由另外一套仓库管理系统,或者进销存系统来管理,电商系统通过第三方接口调用该系统。

    由于库管系统可能是异构的系统,所以不在微服务体系之内。只支持restful风格的webservice调用和消息队列的调用。

详见《库存管理系统手册》

根据手册中的接口文档,编写调用代码。

查询库存接口

四、业务流程和话术

1、订单业务流程图

    

 

2、业务话术(自己总结)

     当用户点击结算的时候,这块我们用网关全局过滤器先判断用户是否登录,如果用户没有登录,则跳转到登陆页面,让用户去登录,登录成功之后,跳转到订单结算页面(这块在跳转到登录页面的时候,把之前的请求地址保存下来,作为参数进行跳转,在登录成功之后,查看是否有请求参数,如果有就跳转到对应的url,如果值为null,跳转到首页);如果用户登录了,则跳转到订单结算页面;

当跳转到订单结算页面的时候,首先对收货人地址进行管理,其次选择支付方式,一期的时候只提供了支付宝支付(微信、支付宝),确认订单信息,然后提交数据到后台,生成对应的订单表、订单详情表和订单物流表(当订单生成的时候,我们要调用对应的库存系统针对订单的商品数量进行验库存,还要进行验价格)。当订单创建成功之后,自动跳转到成功页面(将订单数据和到期时间传递过去)。

这块我们设置的订单的有效时间为24小时(这个时间可以自己定,只要合理就行),因为我们利用延时队列实现定时消息发送,消费者到时间后监听到消息,进行订单校验,如果订单是未支付状态,把订单状态修改为关闭订单。

3、常见面试问题:

  1. 订单表结构(存了什么信息)?

谁负责订单的开发,谁创建订单表。

订单表:

     人+流程+金额+时间

 收货人信息(收货人电话、地址、名称)、用户的id、总金额、订单状态、订单交易编号(全局唯一不重复,采用字符串+时间戳+随机数)、物流单编号、创建时间、失效时间。

订单明细表:

  商品有关的数据

Sku的id,数量、购买的价格、默认图片

  1. 订单业务流程是什么样的?(订单你是怎么做的?)

看上面的文字描述,把文字描述 变成你的话 面试的时候 说出来了。

  1. 订单有效期是多久,怎么取消订单?

有效期 只要合理就行   30分钟、45分、2小时  24小时

 10秒钟,365一天  这种的就是不合理了。

咱们使用的是 rabbitMQ的延时消息。下订单时候 发送 了一个消息,这个消息时间不到不能被消费,只有时间到了,消费者才能去消费这个消息,进行订单的关闭,关闭之前需要判断 订单是否支付,只有没支付的订单才能关闭。

  1. 怎么防止订单重复提交?
  1. 用户通过浏览器回退功能,回退到结算页,并且没有刷新页面的情况下,再次提交订单。 解决是通过 生成结算的时候  生成流水号,这个流水号存redis一份,在结算页也存了一份,当提交订单的时候,结算页中的流水号会传给提交订单接口,拿到页面传过的流水号和redis的流水号比较,相同,可以提交订单,不同不能提交订单。当订单提交完成后,删除redis的流水号,redis流水号没了,再回退提交,比较流水号就会不通过。
  2. 用户通过浏览器回退功能,回退到结算页,刷新页面了,重新请求了一次结算页,结算页会重新查询购物车中选中的商品数据。当用户下单成功后,可以去删除购物车中所有选中的商品。
  1. 订单超卖问题怎么解决的?

这个商品在库存中就一个了,有多个人同时下单,这种问题 你们怎么解决的?

咱们做的:

   这个问题没解决,都可以下单成功。

  为了多卖货,减少库存积压,增加流动资金

用户都可以下单成功 也都可以付钱成功,没货了,再去进。

拼多多:2天内发货。

下单的时候  就去做库存扣减,防止超卖:

  1. 防止并发的情况 库存扣减变成负数。

加锁了

 使用分布式锁。

数据库层面的锁。

悲观锁:

 Select 库存量 from 库存表 where skuid=? for update;

Update 更新 去减库存。

事务的提交或者回滚的时候 锁释放。

乐观锁

表中加一个version字段

Select 库存量,version from 库存表 where skuid =?

  Update 库存表 set (库存量-1,version+1) where skuid =? And version=之前查出的值。

  1. 订单状态都有什么

Supongo que te gusta

Origin blog.csdn.net/leader_song/article/details/132113093
Recomendado
Clasificación