H5下单接口

pull/1/head
chuzhichao 2 years ago
parent d84285761b
commit 582778b116

@ -0,0 +1,104 @@
package com.ruoyi.common.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by yangyincong on 15/8/16.
* ID workId (1~4)
*/
public class IDGenerator {
private final static Logger logger = LoggerFactory.getLogger(IDGenerator.class);
private final static long twepoch = 1361753741828L;
private final static long workerIdBits = 4L;
private final static long maxWorkerId = -1L ^ -1L << workerIdBits;
private final static long sequenceBits = 10L;
private long workerId;
private long sequence = 0L;
private final static long workerIdShift = sequenceBits;
private final static long timestampLeftShift = sequenceBits + workerIdBits;
private final static long sequenceMask = -1L ^ -1L << sequenceBits;
private long lastTimestamp = -1L;
private IDGenerator(final long workerId) {
super();
this.workerId = workerId;
}
public static long generateMinId(int wid, long time) {
return (time - twepoch << timestampLeftShift) | (wid << workerIdShift);
}
public synchronized long nextId() {
long timestamp = this.timeGen();
if (this.lastTimestamp == timestamp) {
this.sequence = (this.sequence + 1) & sequenceMask;
if (this.sequence == 0) {
timestamp = this.tilNextMillis(this.lastTimestamp);
}
} else {
this.sequence = 0;
}
if (timestamp < this.lastTimestamp) {
try {
throw new Exception(
String.format(
"Clock moved backwards. Refusing to generate id for %d milliseconds",
this.lastTimestamp - timestamp));
} catch (Exception e) {
e.printStackTrace();
}
}
this.lastTimestamp = timestamp;
long nextId = ((timestamp - twepoch << timestampLeftShift))
| (this.workerId << workerIdShift) | (this.sequence);
return nextId;
}
public static long generateMaxId(long wid, long time) {
return (time - twepoch << timestampLeftShift) | (wid << workerIdShift) | sequenceMask;
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
private static IDGenerator generator;
public static synchronized void init(Long workerId) throws Exception {
workerId = workerId % maxWorkerId;
logger.info("程序中init的workid为{}", workerId);
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format(
"worker Id can't be greater than %d or less than 0",
IDGenerator.maxWorkerId));
}
generator = new IDGenerator(workerId);
}
public static Long generateId() {
if (null == generator) {
synchronized (IDGenerator.class) {
if (null == generator) {
try {
init(2L);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return generator.nextId();
}
}

@ -6,7 +6,12 @@ import com.cyl.h5.pojo.vo.form.OrderSubmitForm;
import com.cyl.h5.pojo.vo.query.OrderH5Query; import com.cyl.h5.pojo.vo.query.OrderH5Query;
import com.cyl.oms.pojo.vo.OrderVO; import com.cyl.oms.pojo.vo.OrderVO;
import com.cyl.oms.service.OrderService; import com.cyl.oms.service.OrderService;
import com.cyl.ums.domain.Member;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisService;
import com.ruoyi.framework.config.LocalDataUtil;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@ -20,12 +25,32 @@ import java.util.List;
@RestController @RestController
@RequestMapping("/h5/order") @RequestMapping("/h5/order")
@Slf4j
public class H5OrderController { public class H5OrderController {
@Autowired @Autowired
private OrderService orderService; private OrderService orderService;
@Autowired
private RedisService redisService;
@PostMapping("/add") @PostMapping("/add")
public ResponseEntity<OrderVO> submit(@RequestBody OrderSubmitForm form) { public ResponseEntity<Long> submit(@RequestBody OrderSubmitForm form) {
return ResponseEntity.ok(orderService.submit(form)); Member member = (Member) LocalDataUtil.getVar(Constants.MEMBER_INFO);
Long memberId = member.getId();
String redisKey = "h5_order_add" + memberId;
String redisValue = memberId + "_" + System.currentTimeMillis();
try{
redisService.lock(redisKey, redisValue, 60);
return ResponseEntity.ok(orderService.submit(form));
}catch (Exception e){
log.info("创建订单方法异常", e);
return null;
}finally {
try {
redisService.unLock(redisKey, redisValue);
} catch (Exception e) {
e.printStackTrace();
}
}
} }
@PostMapping("orders") @PostMapping("orders")
public ResponseEntity<Page<OrderVO>> queryOrderPage(@RequestBody OrderH5Query query, Pageable pageReq) { public ResponseEntity<Page<OrderVO>> queryOrderPage(@RequestBody OrderH5Query query, Pageable pageReq) {

@ -1,5 +1,6 @@
package com.cyl.h5.pojo.vo.form; package com.cyl.h5.pojo.vo.form;
import com.cyl.h5.pojo.dto.OrderProductListDTO;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
@ -11,8 +12,12 @@ public class OrderSubmitForm {
@NotNull @NotNull
private Long addressId; private Long addressId;
private String note; private String note;
/** 支付方式 0未支付 1支付宝 2微信 默认微信 */
private Integer payType = 2;
/** 订单来源购物车则为cart */
private String from;
@NotEmpty @NotEmpty
private List<SkuParam> skus; private List<OrderProductListDTO> skuList;
@Data @Data
public static class SkuParam { public static class SkuParam {
private Long skuId; private Long skuId;

@ -2,6 +2,9 @@ package com.cyl.oms.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
@ -20,6 +23,7 @@ public class Order extends BaseAudit {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ApiModelProperty("订单id") @ApiModelProperty("订单id")
@TableId(type = IdType.ASSIGN_ID)
private Long id; private Long id;
@ApiModelProperty("MEMBER_ID") @ApiModelProperty("MEMBER_ID")

@ -1,6 +1,9 @@
package com.cyl.oms.domain; package com.cyl.oms.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
@ -19,6 +22,7 @@ public class OrderItem extends BaseAudit {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ApiModelProperty("ID") @ApiModelProperty("ID")
@TableId(type = IdType.ASSIGN_ID)
private Long id; private Long id;
@ApiModelProperty("订单id") @ApiModelProperty("订单id")

@ -0,0 +1,4 @@
package com.cyl.oms.pojo.dto;
public class SaveOrderItemDTO {
}

@ -1,11 +1,16 @@
package com.cyl.oms.service; package com.cyl.oms.service;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyl.h5.pojo.dto.OrderProductListDTO;
import com.cyl.ums.domain.Member;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.ruoyi.common.utils.IDGenerator;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -13,6 +18,7 @@ import org.springframework.stereotype.Service;
import com.cyl.oms.mapper.OrderItemMapper; import com.cyl.oms.mapper.OrderItemMapper;
import com.cyl.oms.domain.OrderItem; import com.cyl.oms.domain.OrderItem;
import com.cyl.oms.pojo.query.OrderItemQuery; import com.cyl.oms.pojo.query.OrderItemQuery;
import org.springframework.transaction.annotation.Transactional;
/** /**
* Service * Service
@ -21,7 +27,7 @@ import com.cyl.oms.pojo.query.OrderItemQuery;
* @author zcc * @author zcc
*/ */
@Service @Service
public class OrderItemService { public class OrderItemService extends ServiceImpl<OrderItemMapper, OrderItem> {
@Autowired @Autowired
private OrderItemMapper orderItemMapper; private OrderItemMapper orderItemMapper;
@ -136,4 +142,32 @@ public class OrderItemService {
public int deleteById(Long id) { public int deleteById(Long id) {
return orderItemMapper.deleteById(id); return orderItemMapper.deleteById(id);
} }
@Transactional
public void saveOrderItem(Member member, LocalDateTime optTime,
Long orderId, List<OrderProductListDTO> list){
List<OrderItem> addOrderItemList = new ArrayList<>();
list.forEach(item -> {
OrderItem orderItem = new OrderItem();
orderItem.setId(IDGenerator.generateId());
orderItem.setOrderId(orderId);
orderItem.setProductId(item.getProduct().getId());
orderItem.setOutProductId(item.getProduct().getOutProductId());
orderItem.setSkuId(item.getSku().getId());
orderItem.setOutSkuId(item.getSku().getOutSkuId());
orderItem.setPic(item.getSku().getPic());
orderItem.setProductName(item.getProduct().getName());
orderItem.setSalePrice(item.getSku().getPrice());
orderItem.setQuantity(item.getQuantity());
orderItem.setProductCategoryId(item.getProduct().getCategoryId());
orderItem.setSpData(item.getSku().getSpData());
orderItem.setCreateBy(member.getId());
orderItem.setCreateTime(optTime);
addOrderItemList.add(orderItem);
});
boolean flag = saveBatch(addOrderItemList);
if (!flag){
throw new RuntimeException("新增订单item失败");
}
}
} }

@ -12,7 +12,9 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyl.h5.pojo.dto.OrderCreateDTO; import com.cyl.h5.pojo.dto.OrderCreateDTO;
import com.cyl.h5.pojo.dto.OrderProductListDTO; import com.cyl.h5.pojo.dto.OrderProductListDTO;
import com.cyl.h5.pojo.vo.OrderCalcVO; import com.cyl.h5.pojo.vo.OrderCalcVO;
@ -21,7 +23,9 @@ import com.cyl.h5.pojo.vo.form.OrderSubmitForm;
import com.cyl.h5.pojo.vo.query.OrderH5Query; import com.cyl.h5.pojo.vo.query.OrderH5Query;
import com.cyl.oms.convert.OrderConvert; import com.cyl.oms.convert.OrderConvert;
import com.cyl.oms.domain.OrderItem; import com.cyl.oms.domain.OrderItem;
import com.cyl.oms.domain.OrderOperateHistory;
import com.cyl.oms.mapper.OrderItemMapper; import com.cyl.oms.mapper.OrderItemMapper;
import com.cyl.oms.mapper.OrderOperateHistoryMapper;
import com.cyl.oms.pojo.vo.OrderVO; import com.cyl.oms.pojo.vo.OrderVO;
import com.cyl.pms.convert.SkuConvert; import com.cyl.pms.convert.SkuConvert;
import com.cyl.pms.domain.Product; import com.cyl.pms.domain.Product;
@ -31,12 +35,15 @@ import com.cyl.pms.mapper.SkuMapper;
import com.cyl.pms.pojo.vo.SkuVO; import com.cyl.pms.pojo.vo.SkuVO;
import com.cyl.ums.domain.Member; import com.cyl.ums.domain.Member;
import com.cyl.ums.domain.MemberAddress; import com.cyl.ums.domain.MemberAddress;
import com.cyl.ums.domain.MemberCart;
import com.cyl.ums.mapper.MemberAddressMapper; import com.cyl.ums.mapper.MemberAddressMapper;
import com.cyl.ums.mapper.MemberCartMapper;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.IDGenerator;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.config.LocalDataUtil; import com.ruoyi.framework.config.LocalDataUtil;
import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.mapper.SysUserMapper;
@ -49,7 +56,10 @@ import org.springframework.stereotype.Service;
import com.cyl.oms.mapper.OrderMapper; import com.cyl.oms.mapper.OrderMapper;
import com.cyl.oms.domain.Order; import com.cyl.oms.domain.Order;
import com.cyl.oms.pojo.query.OrderQuery; import com.cyl.oms.pojo.query.OrderQuery;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
/** /**
@ -74,6 +84,12 @@ public class OrderService {
private ProductMapper productMapper; private ProductMapper productMapper;
@Autowired @Autowired
private SkuConvert skuConvert; private SkuConvert skuConvert;
@Autowired
private OrderItemService orderItemService;
@Autowired
private OrderOperateHistoryMapper orderOperateHistoryMapper;
@Autowired
private MemberCartMapper memberCartMapper;
/** /**
* *
@ -243,73 +259,109 @@ public class OrderService {
return orderMapper.deleteById(id); return orderMapper.deleteById(id);
} }
public OrderVO submit(OrderSubmitForm form) { @Transactional
MemberAddress addr = memberAddressMapper.selectById(form.getAddressId()); public Long submit(OrderSubmitForm form) {
if (addr == null) { Member member = (Member) LocalDataUtil.getVar(Constants.MEMBER_INFO);
throw new BaseException("参数错误"); //只支持快递
Long addressId = form.getAddressId();
if (addressId == null){
throw new RuntimeException("收获地址不能为空");
}
MemberAddress memberAddress = memberAddressMapper.selectById(addressId);
if (memberAddress == null){
throw new RuntimeException("收货地址不能为空");
}
//sku不能为空
List<OrderProductListDTO> skuList = form.getSkuList();
if (CollectionUtil.isEmpty(skuList)){
throw new RuntimeException("商品SKU信息不能为空");
} }
List<Long> skuIds = form.getSkus().stream().map(OrderSubmitForm.SkuParam::getSkuId).distinct().collect(Collectors.toList()); //将sku信息转换为 keyskuId value购买数量
List<Sku> skus = skuMapper.selectBatchIds(skuIds); Map<Long, Integer> skuQuantityMap = skuList.stream().collect(Collectors.toMap(OrderProductListDTO::getSkuId, OrderProductListDTO::getQuantity));
if (skuIds.size() != skus.size()) { //查询所有sku信息
throw new BaseException("参数错误"); Map<Long, Sku> querySkuMap = skuMapper
.selectBatchIds(skuList.stream().map(OrderProductListDTO::getSkuId).collect(Collectors.toList()))
.stream().collect(Collectors.toMap(Sku::getId, it -> it));
//计算商品总额、订单总额(订单总金额=商品总金额,因为暂时没有运费等概念)
BigDecimal productTotalAmount = BigDecimal.ZERO;
BigDecimal orderTotalAmount = BigDecimal.ZERO;
for (OrderProductListDTO dto : skuList){
if (!querySkuMap.containsKey(dto.getSkuId())){
throw new RuntimeException("商品SKU不存在");
}
Sku sku = querySkuMap.get(dto.getSkuId());
Product product = productMapper.selectById(sku.getProductId());
if (product == null){
throw new RuntimeException("商品不存在");
}
if (Constants.PublishStatus.UNDERCARRIAGE.equals(product.getPublishStatus())){
throw new RuntimeException("商品" + product.getName() + "已下架");
}
productTotalAmount = productTotalAmount.add(sku.getPrice().multiply(BigDecimal.valueOf(skuQuantityMap.get(sku.getId()))));
orderTotalAmount = orderTotalAmount.add(sku.getPrice().multiply(BigDecimal.valueOf(skuQuantityMap.get(sku.getId()))));
dto.setSku(sku);
dto.setProduct(product);
} }
Map<Long, Sku> id2sku = skus.stream().collect(Collectors.toMap(Sku::getId, it -> it)); LocalDateTime optTime = LocalDateTime.now();
Map<Long, Product> id2Product = productMapper.selectBatchIds(
skus.stream().map(Sku::getProductId).distinct().collect(Collectors.toList())
).stream().collect(Collectors.toMap(Product::getId, it -> it));
// 1. 生成订单商品快照 //生成一个统一的订单号
Long orderId = IDGenerator.generateId();
//创建订单
Order order = new Order(); Order order = new Order();
order.setTotalAmount(BigDecimal.ZERO); order.setId(orderId);
List<OrderItem> items = new ArrayList<>(); order.setMemberId(member.getId());
form.getSkus().forEach(it -> { order.setMemberUsername(member.getNickname());
Sku s = id2sku.get(it.getSkuId()); order.setPayType(Constants.PayType.WECHAT);
Product p = id2Product.get(s.getProductId()); order.setTotalAmount(orderTotalAmount);
order.setPurchasePrice(BigDecimal.ZERO);
OrderItem item = new OrderItem(); order.setFreightAmount(BigDecimal.ZERO);
item.setProductId(s.getProductId()); order.setPayAmount(orderTotalAmount);
item.setOutProductId(p.getOutProductId()); //暂时为接入支付,直接设置为待发货
item.setSkuId(it.getSkuId()); order.setStatus(Constants.OrderStatus.SEND);
item.setOutSkuId(s.getOutSkuId());
item.setProductSnapshotId(p.getId());
item.setSkuSnapshotId(s.getId());
item.setPic(StrUtil.isNotEmpty(s.getPic()) ? s.getPic() : p.getPic());
item.setProductName(p.getName());
item.setSalePrice(s.getPrice());
item.setQuantity(it.getQuantity());
item.setProductCategoryId(p.getCategoryId());
item.setSpData(s.getSpData());
items.add(item);
order.setTotalAmount(order.getTotalAmount().add(s.getPrice().multiply(BigDecimal.valueOf(it.getQuantity()))));
});
LoginUser user = SecurityUtils.getLoginUser();
// 2. 生成订单
order.setMemberId(user.getUserId());
order.setMemberUsername(user.getUsername());
order.setStatus(0);
order.setAftersaleStatus(1); order.setAftersaleStatus(1);
order.setAutoConfirmDay(7); order.setReceiverName(memberAddress.getName());
order.setReceiverName(addr.getName()); order.setReceiverPhone(memberAddress.getPhone());
order.setReceiverPhone(addr.getPhone()); order.setReceiverPostCode(memberAddress.getPostCode());
order.setReceiverProvince(addr.getProvince()); order.setReceiverProvince(memberAddress.getProvince());
order.setReceiverDistrict(addr.getDistrict()); order.setReceiverCity(memberAddress.getCity());
order.setReceiverDetailAddress(addr.getDetailAddress()); order.setReceiverDistrict(memberAddress.getDistrict());
order.setReceiverDetailAddress(memberAddress.getDetailAddress());
order.setNote(form.getNote()); order.setNote(form.getNote());
order.setConfirmStatus(0); order.setConfirmStatus(0);
order.setDeleteStatus(0); order.setDeleteStatus(0);
orderMapper.insert(order); order.setPaymentTime(optTime);
items.forEach(it -> it.setOrderId(order.getId())); order.setCreateTime(optTime);
items.forEach(orderItemMapper::insert); order.setCreateBy(member.getId());
int rows = orderMapper.insert(order);
// 3. 判断是否付费,生成支付订单 if (rows < 1){
if (BigDecimal.ZERO.compareTo(order.getTotalAmount()) > 0) { throw new RuntimeException("订单新增失败");
// todo 生成支付订单 }
// 保存orderItem
orderItemService.saveOrderItem(member, optTime, orderId, skuList);
// 保存订单操作记录
OrderOperateHistory orderOperateHistory = new OrderOperateHistory();
orderOperateHistory.setOrderId(orderId);
orderOperateHistory.setOperateMan(member.getId() + "");
orderOperateHistory.setOrderStatus(Constants.OrderStatus.SEND);
orderOperateHistory.setCreateTime(optTime);
orderOperateHistory.setCreateBy(member.getId());
rows = orderOperateHistoryMapper.insert(orderOperateHistory);
if (rows < 1){
throw new RuntimeException("保存订单操作记录失败");
}
//若来源为购物车,删除购物车
if (Constants.OrderFrom.CART.equals(form.getFrom())){
List<Long> skuIdList = skuList.stream().map(OrderProductListDTO::getSkuId).collect(Collectors.toList());
LambdaUpdateWrapper<MemberCart> wrapper = Wrappers.lambdaUpdate();
wrapper.eq(MemberCart::getMemberId, member.getId());
wrapper.in(MemberCart::getSkuId, skuIdList);
rows = memberCartMapper.delete(wrapper);
if (rows < 1){
throw new RuntimeException("删除购物车失败");
}
} }
OrderVO vo = orderConvert.do2vo(order); //当前返回成功消息接入支付后可返回payId
vo.setItems(items); return orderId;
return vo;
} }
public Page<OrderVO> queryOrderPage(OrderH5Query query, Pageable pageReq) { public Page<OrderVO> queryOrderPage(OrderH5Query query, Pageable pageReq) {
@ -405,4 +457,5 @@ public class OrderService {
res.setProductTotalAmount(productTotalAmount); res.setProductTotalAmount(productTotalAmount);
return res; return res;
} }
} }

Loading…
Cancel
Save