淘宝客网站域名国药控股cms系统
- 作者: 五速梦信息网
- 时间: 2026年03月21日 08:21
当前位置: 首页 > news >正文
淘宝客网站域名,国药控股cms系统,网站建设报价表格式,wordpress 安装启动最近再写支付模块就到处借鉴 旨在回顾一下。 1.确认订单功能 使用场景是#xff1a;用户在选择好购物车后#xff0c;或者是直接选择商品后#xff08;选择商品封装为购物车#xff09; 这样做是根据尚硅谷来学习的 目前需要这些属性#xff0c;原因是在确认订单页面后…最近再写支付模块就到处借鉴 旨在回顾一下。 1.确认订单功能 使用场景是用户在选择好购物车后或者是直接选择商品后选择商品封装为购物车 这样做是根据尚硅谷来学习的 目前需要这些属性原因是在确认订单页面后 展现一个最优惠的状态 1.1实体类 /*** 用户id/ApiModelProperty(用户id)private Integer userId;/** 购物车列表/ApiModelProperty(购物车中已选中商品)private ListCartInfo cartItemsList;ApiModelProperty(最优惠的优惠券id)private Integer userCouponsId;/** 总金额/ApiModelProperty(总金额)private Double totalAmount;/** 优惠金额/ApiModelProperty(优惠金额)private Double discount;/** 实付金额*/ApiModelProperty(实付金额)private Double actuallyPay;1.2确认订单实现类 期间做了一些修改 之前是设置的有购物车状态 这些步骤都是在后端处理 后来又采用了前端传递购物车属性 美其名曰叫 减少io次数 缓解数据库压力 通过传入的userId 查找 订单列表 购物车列表 期间有个redis操作 是根据时间 来生成 后续在生成订单时会用到 public OrderConfirmVo confirmOrder(CartConfirmDto cartConfirmDto) {//获取用户id参数 以方便后续使用//获取用户地址列表Integer userId cartConfirmDto.getUserId();ListAddresses addressesList addressesDao.getByUserId(userId);//获取购物车中已经选中的商品ListCartInfo cartItemsList cartConfirmDto.getCartItemsList(); // ListCartItems cartItemsList cartItemsDao.querySelectedCartItems(userId);if (cartItemsList.isEmpty()){throw new PorkException(您购物车中未选中商品,500);}for (CartInfo cartInfo : cartItemsList) {Integer productId cartInfo.getProductId();Products products productsDao.queryById(productId);cartInfo.setMainPhoto(products.getMainPhoto());cartInfo.setName(products.getName());Integer flavorId cartInfo.getFlavorId();String flavorDescription flavorsService.queryNameById(flavorId);cartInfo.setFlavorDescription(flavorDescription);}//生成订单唯一标示String orderNo System.currentTimeMillis();redisTemplate.opsForValue().set(RedisConst.ORDER_REPEATorderNo,orderNo,24, TimeUnit.HOURS);//1.获取最优惠优惠券//2.先获取订单价格//3.找到实付金额 // Double totalPrice cartItemsDao.getActuallyPay(userId); // UserCoupons userCoupon userCouponsDao.queryOptimalUserCoupon(totalPrice, userId); // Double discount userCoupon.getCoupons().getDiscount(); // Double actuallyPay totalPrice - discount;Double totalPrice cartConfirmDto.getTotalAmount();Integer userCouponId cartConfirmDto.getUserCouponsId();Double discount cartConfirmDto.getDiscount();Double actuallyPay cartConfirmDto.getActuallyPay();UserCoupons userCoupon userCouponsDao.queryById(userCouponId);//查询可用优惠券ListUserCoupons userCoupons userCouponsDao.queryAvailableUserCoupons(totalPrice, userId);//进行封装OrderConfirmVo orderConfirmVo new OrderConfirmVo(userId,totalPrice,userCoupon,discount,actuallyPay,orderNo,userCoupons,addressesList,cartItemsList);return orderConfirmVo;} 1.3返回类 /ApiModelProperty(用户id)private Integer userId;/** 总金额/ApiModelProperty(总金额)private Double totalAmount;ApiModelProperty(最优惠的优惠券)private UserCoupons userCoupons;/** 优惠金额/ApiModelProperty(优惠金额)private Double discount;/** 实付金额/ApiModelProperty(实付金额)private Double actuallyPay;/** 订单号/ApiModelProperty(订单号)private String orderNo;/** 用户所有优惠券/ApiModelProperty(用户优惠券)private ListUserCoupons userCouponsList;/** 用户地址/ApiModelProperty(用户地址列表)private ListAddresses addressesList;/** 购物车列表*/ApiModelProperty(购物车列表)private ListCartInfo cartItemsList;2.生成订单 2.1请求实体类 生成订单后里面的属性 ApiModelProperty(value 使用预生产订单号防重)private String orderNo;ApiModelProperty(value 用户id)private Integer userId;ApiModelProperty(value 下单时所使用的地址信息)private Integer addressesId;ApiModelProperty(value 下单选中的优惠券id)private Integer userCouponId;ApiModelProperty(value 订单备注)private String comment;ApiModelProperty(value 所选中商品)private ListCartInfo cartItemsList;ApiModelProperty(value 最后订单总价)private Double totalPrice;ApiModelProperty(value 优惠金额)private Double discount;ApiModelProperty(订单实付金额)private Double ActuallyPay; 2.2生成订单方法实体类 使用lua脚本来保证原子性 如果redis中有相同orderNo 则说明正常提交订单 然后把redis删除 期间也有锁单 2.2.1检查锁 Overridepublic Boolean checkAndLock(ListProductStockVo productStockVoList, String orderNo) {//1.判断productStockVoList是否为空if (CollectionUtils.isEmpty(productStockVoList)){throw new PorkException(ResultCodeEnum.DATA_ERROR);}//2.遍历productStockVoList得到每个商品验证库存并锁定库存,具备原子性productStockVoList.stream().forEach(productStockVo - {this.checkLock(productStockVo);});//3.只要有一个商品锁定失败所有锁定成功的商品都解锁 用于检查流中是否至少有一个元素满足指定的条件boolean flag productStockVoList.stream().anyMatch(productStockVo - !productStockVo.getIsLock());if (flag){//所有锁定成功的商品都解锁productStockVoList.stream().filter(ProductStockVo::getIsLock).forEach(productStockVo - {flavorsDao.unlockStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());});return false;} //4 如果所有商品都锁定成功了redis缓存相关数据为了方便后面解锁和减库存redisTemplate.opsForValue().set(RedisConst.SROCK_INFOorderNo,productStockVoList,33, TimeUnit.MINUTES);return true;} 2.2.2获得公平锁 private void checkLock(ProductStockVo productStockVo) {//获取锁 公平锁谁等待时间长给谁发锁RLock rLock this.redissonClient.getFairLock(RedisConst.SKUKEY_PREFIXproductStockVo.getFlavorId());rLock.lock();try {//验证库存Flavors flavors flavorsDao.checkStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());//判断没有满足条件商品设置isLock值为false返回if (flavors null){productStockVo.setIsLock(false);return;}//又满足条件商品锁定库存 update rows 影响行数Integer rows flavorsDao.lockStock(productStockVo.getFlavorId(),productStockVo.getSkuNum());if (rows 1) {productStockVo.setIsLock(true);}}finally {//解锁rLock.unlock();}} 2.2.3提交订单 public OrderGenerateInfo submitOrder(OrderSubmitVo orderSubmitVo) {//第一步拿出userId确定给那个用户设置订单Integer userId orderSubmitVo.getUserId();//第二步 订单不能重复提交重复提交验证//通过redis lua 脚本实现 //lua脚本保证原子性//1.获取传递过来的orderNoString orderNo orderSubmitVo.getOrderNo();if (orderNo.isEmpty()){throw new PorkException(ResultCodeEnum.ILLEGAL_REQUEST);}//2.拿着orderNo到redis中查询 此lua脚本解析 如果redis中存在的值 这一个值 那么 这个值 不过没有存在 就返回0 然后结束String script if(redis.call(get, KEYS[1]) ARGV[1]) then return redis.call(del, KEYS[1]) else return 0 end;//3.如果redis有相同orderNo表示正常提交订单 把redis的orderNo删除Boolean flag (Boolean) redisTemplate.execute(new DefaultRedisScript(script, Boolean.class),Arrays.asList(RedisConst.ORDER_REPEAT orderNo),orderNo);//4.如果redis没有相同orderNo表示重复提交了不能再往后进行if (!flag){throw new PorkException(ResultCodeEnum.REPEAT_SUBMIT);}//第三步 验证库存 并且 锁定库存订单在30分钟内锁定库存 没有真正减库存//获取当前购物车商品ListCartInfo cartItemsList orderSubmitVo.getCartItemsList();//新建一个锁单Vo 然后把商品信息封装到 Vo里面if (!CollectionUtils.isEmpty(cartItemsList)){ListProductStockVo productStockVoList cartItemsList.stream().map(item -{ProductStockVo productStockVo new ProductStockVo();productStockVo.setFlavorId(item.getFlavorId());productStockVo.setSkuNum(item.getQuantity());return productStockVo;}).collect(Collectors.toList());//验证库存保证具备原子性 解决超卖问题Boolean isLockSuccess flavorsService.checkAndLock(productStockVoList, orderNo);if (!isLockSuccess){throw new PorkException(ResultCodeEnum.ORDER_STOCK_FALL);}}//第四步 下单过程OrderGenerateInfo orderGenerateInfo this.saveOrder(orderSubmitVo);//对已生成订单的购物车进行删除ListInteger cartIdList cartItemsList.stream().map(CartInfo::getId).collect(Collectors.toList());cartItemsDao.deleteBatchIds(cartIdList);//1.向两张表中添加数据 order_info order_item//返回订单id return orderGenerateInfo;} 2.2.4保存订单 Transactional(rollbackFor {Exception.class})public OrderGenerateInfo saveOrder(OrderSubmitVo orderSubmitVo) {Integer userId orderSubmitVo.getUserId();ListCartInfo cartItemsList orderSubmitVo.getCartItemsList();if (CollectionUtils.isEmpty(cartItemsList)){throw new PorkException(ResultCodeEnum.DATA_ERROR);}ListString goodInfoList new ArrayListString();String goodInfo ;for (CartInfo cartInfo : cartItemsList) {Integer flavorId cartInfo.getFlavorId();Integer productId cartInfo.getProductId();Integer quantity cartInfo.getQuantity();String productName productsService.queryNameById(productId);String flavorName flavorsService.queryNameById(flavorId);goodInfo productName:flavorName*quantity;goodInfoList.add(goodInfo);}//查数据 顾客收货地址Integer addressesId orderSubmitVo.getAddressesId();Addresses addresses addressesDao.queryById(addressesId);if (addresses null){throw new PorkException(ResultCodeEnum.DATA_ERROR);}String recipientName addresses.getRecipientName();String recipientPhone addresses.getRecipientPhone();String province addresses.getProvince();String city addresses.getCity();String district addresses.getDistrict();String detail addresses.getDetail();String orderAddress province city district detail;//计算金额Double totalPrice orderSubmitVo.getTotalPrice();Double discount orderSubmitVo.getDiscount();Double actuallyPay orderSubmitVo.getActuallyPay();//原金额 // Double totalAmount cartItemsDao.getActuallyPay(userId); // Double discount 0.00; // Double actuallyPay totalAmount; // Integer couponId 0;Integer userCouponId orderSubmitVo.getUserCouponId(); // UserCoupons userCoupons userCouponsDao.queryById(userCouponId);//把优惠券设置为已使用userCouponsDao.update(userCouponId); // if (userCoupons!null){ // couponId userCoupons.getCouponId(); // }//优惠券金额 // if (userCouponId ! null){ // UserCoupons userCoupons userCouponsDao.queryById(userCouponId); // couponId userCoupons.getCouponId(); // discount couponsDao.queryById(couponId).getDiscount(); // } // //实付金额 // actuallyPay totalPrice - discount;//封装订单项ListOrderItems orderItemsList new ArrayList();for (CartInfo cartItems : cartItemsList) {OrderItems orderItem new OrderItems();orderItem.setProductId(cartItems.getProductId());orderItem.setFlavorId(cartItems.getFlavorId());orderItem.setQuantity(cartItems.getQuantity());orderItem.setPrice(cartItems.getPrice());orderItem.setStatus(0);orderItemsList.add(orderItem);}Orders order new Orders();order.setUserId(userId);order.setTotalAmount(totalPrice);order.setStatus(0);order.setConsignee(recipientName);order.setPhone(recipientPhone);order.setAddress(orderAddress);order.setDiscount(discount);order.setOrderNo(orderSubmitVo.getOrderNo());order.setComment(orderSubmitVo.getComment());order.setActuallyPay(actuallyPay);order.setCouponId(userCouponId);order.setGoodInfo(String.join(, , goodInfoList));//添加数据到订单基本表ordersDao.insert(order);//添加订单里面的订单项orderItemsList.forEach(orderItems - {orderItems.setOrderId(order.getId());orderItemsDao.insert(orderItems);});//如果当前订单使用优惠券更新优惠券状态if (order.getCouponId()! null){userCouponsDao.update(userCouponId);}//在redis中记录用户购物数量//hash类型 key(userId) - field(skuId)-value(skuNum)String orderSkuKey RedisConst.ORDER_SKU_MAP orderSubmitVo.getUserId();BoundHashOperationsString, String, Integer hashOperations redisTemplate.boundHashOps(orderSkuKey);cartItemsList.forEach(cartInfo - {if(hashOperations.hasKey(cartInfo.getFlavorId().toString())) {Integer orderSkuNum hashOperations.get(cartInfo.getFlavorId().toString()) cartInfo.getQuantity();hashOperations.put(cartInfo.getFlavorId().toString(), orderSkuNum);}});redisTemplate.expire(orderSkuKey, DateUtil.getCurrentExpireTimes(), TimeUnit.SECONDS);//设置订单过期时间 30分钟后取消订单long orderTimeOut 1;String keyRedis String.valueOf(StrUtil.format({}:{},RedisConst.REDIS_ORDER_KEY_IS_PAY_0,order.getId()));//设置过期时间redisTemplate.opsForValue().set(keyRedis,order.getOrderNo(),orderTimeOut,TimeUnit.MINUTES);//订单idOrderGenerateInfo orderGenerateInfo new OrderGenerateInfo(order.getId(),orderTimeOut);return orderGenerateInfo;}3.讲讲Redis过期键监听器 redis过期键监听器 实现对键的监听 如果该键过期了则进行注册过的操作 3.1配置监听器 像只注册了订单服务的话 你就只能使用订单服务 若使用其他服务的话 也要进行集成 Configuration AllArgsConstructor public class RedisListenerConfig {private final RedisTemplateString, String redisTemplate;private final RedissonConfig redisConfigProperties;private final OrdersService ordersService;// private final OrderItemsService orderItemsService;BeanRedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {RedisMessageListenerContainer container new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.addMessageListener(new RedisKeyExpirationListener(redisTemplate, redisConfigProperties, ordersService), new PatternTopic(StrUtil.format(keyevent{}:expired, redisConfigProperties.getDatabase())));return container;} } 3.2配置redis 开启监听器 3.3写监听器 Component public class RedisKeyExpirationListener implements MessageListener {private RedisTemplateString, String redisTemplate;private RedissonConfig redisConfigProperties;private OrdersService ordersService;// private OrderItemsService orderItemsService;public RedisKeyExpirationListener(RedisTemplateString, String redisTemplate,RedissonConfig redisConfigProperties,OrdersService orderInfoService){this.redisTemplate redisTemplate;this.redisConfigProperties redisConfigProperties;this.ordersService orderInfoService; // this.orderItemsService orderItemsService;}Overridepublic void onMessage(Message message, byte[] bytes) {RedisSerializer? serializer redisTemplate.getValueSerializer();String channel String.valueOf(serializer.deserialize(message.getChannel()));String body String.valueOf(serializer.deserialize(message.getBody()));//key过期监听if(StrUtil.format(keyevent{}:expired, redisConfigProperties.getDatabase()).equals(channel)){//订单自动取消if(body.contains(RedisConst.REDIS_ORDER_KEY_IS_PAY_0)) {body body.replace(RedisConst.REDIS_ORDER_KEY_IS_PAY_0, );String[] str body.split(:);String wxOrderId str[1];System.out.println(wxOrderId);Orders orders ordersService.queryById(Integer.valueOf(wxOrderId));if(orders ! null orders.getStatus() 0){//只有待支付的订单能取消//TODO 订单取消 库存增加 减优惠券 // orderItemsService.toCancel(orders.getId());ordersService.cancelOrder(orders.getId());System.out.println(订单idorders.getId()已删除);}}
- 上一篇: 淘宝客网站设计saas系统是什么意思
- 下一篇: 淘宝客网站源码html做生意网站
相关文章
-
淘宝客网站设计saas系统是什么意思
淘宝客网站设计saas系统是什么意思
- 技术栈
- 2026年03月21日
-
淘宝客网站如何备案深圳房管局官网
淘宝客网站如何备案深圳房管局官网
- 技术栈
- 2026年03月21日
-
淘宝客网站如何备案河北唐山 网站建设
淘宝客网站如何备案河北唐山 网站建设
- 技术栈
- 2026年03月21日
-
淘宝客网站源码html做生意网站
淘宝客网站源码html做生意网站
- 技术栈
- 2026年03月21日
-
淘宝客网站怎么做推广计划石家庄兼职建站
淘宝客网站怎么做推广计划石家庄兼职建站
- 技术栈
- 2026年03月21日
-
淘宝客怎么自建网站做推广阿里万网站建设
淘宝客怎么自建网站做推广阿里万网站建设
- 技术栈
- 2026年03月21日
