Ver Fonte

创建订单

yangyb há 3 semanas atrás
pai
commit
fe4b365d9f

+ 1 - 19
mall-api/src/main/java/com/txz/mall/constants/Constants.java

@@ -400,15 +400,6 @@ public class Constants {
     public static final String PAY_TYPE_OFFLINE = "offline"; //线下支付
     public static final String PAY_TYPE_ALI_PAY = "alipay"; //支付宝
 
-    //支付客户端类型
-    public static final String PAY_TYPE_WE_CHAT_FROM_H5 = "weixinh5"; //H5唤起微信支付
-    public static final String PAY_TYPE_WE_CHAT_FROM_PUBLIC = "public"; //公众号
-    public static final String PAY_TYPE_WE_CHAT_FROM_PROGRAM = "routine"; //小程序
-
-    //后台微信登录类型
-    public static final String ADMIN_LOGIN_TYPE_WE_CHAT_FROM_PUBLIC = "admin_public"; //公众号
-
-
     //支付方式
     public static final String PAY_TYPE_STR_WE_CHAT = "微信支付"; //微信支付
     public static final String PAY_TYPE_STR_YUE = "余额支付"; //余额支付
@@ -436,7 +427,7 @@ public class Constants {
 
 
     // 订单缓存
-    public static final long ORDER_CASH_CONFIRM = (60 * 60);
+    public static final long ORDER_CASH_CONFIRM = (60);
     public static final String ORDER_CACHE_PER = "ORDER_CACHE:"; // redis缓存订单前缀
 
     //订单操作类型 -> 消息
@@ -461,15 +452,6 @@ public class Constants {
     //微信消息模板 tempKey
     public static final String WE_CHAT_TEMP_KEY_FIRST = "first";
     public static final String WE_CHAT_TEMP_KEY_END = "remark";
-    // 公众号模板消息
-    public static final String WE_CHAT_TEMP_KEY_COMBINATION_SUCCESS = "OPENTM407456411";// 拼团成功
-    public static final String WE_CHAT_TEMP_KEY_BARGAIN_SUCCESS = "OPENTM410292733";// 砍价成功
-    public static final String WE_CHAT_TEMP_KEY_EXPRESS = "OPENTM200565259";// 订单发货提醒
-    public static final String WE_CHAT_TEMP_KEY_DELIVERY = "OPENTM207707249";// 订单配送通知
-    public static final String WE_CHAT_TEMP_KEY_ORDER_PAY = "OPENTM207791277";// 订单支付成功通知
-    public static final String WE_CHAT_TEMP_KEY_ORDER_RECEIVING = "OPENTM413386489";// 订单收货通知
-    public static final String WE_CHAT_TEMP_KEY_ORDER_REFUND = "OPENTM207791277";// 退款进度通知
-    public static final String WE_CHAT_PUBLIC_TEMP_KEY_RECHARGE = "OPENTM200565260";// 充值成功
 
     // 小程序服务通知
     public static final String WE_CHAT_PROGRAM_TEMP_KEY_COMBINATION_SUCCESS = "5164";// 拼团成功

+ 6 - 14
mall-service/src/main/java/com/txz/mall/controller/OrderController.java

@@ -35,19 +35,12 @@ public class OrderController {
     private StoreOrderService storeOrderService;
 
     @PostMapping("/add")
-    @ApiOperation(value = "订单新增")
-    public Result add(@RequestBody StoreOrder storeOrder) {
-        if (storeOrder == null) {
+    @ApiOperation(value = "创建订单")
+    public Result add(@Validated @RequestBody CreateOrderRequest orderRequest) {
+        if (orderRequest == null) {
             return Result.fail(ResultCode.OBJECT_IS_NULL);
         }
-        try {
-            storeOrder.setCreateTime(new Date());
-//    		storeOrder.setCreateUserId(userId);
-            storeOrderService.save(storeOrder);
-        } catch (Exception e) {
-            log.error("新增对象操作异常e:{}", e);
-            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR);
-        }
+        storeOrderService.createOrder(orderRequest);
         return Result.success();
     }
 
@@ -157,9 +150,8 @@ public class OrderController {
 
     @ApiOperation(value = "预下单")
     @PostMapping(value = "/pre/order")
-    public Result<String> preOrder(@RequestBody @Validated PreOrderRequest request) {
-        String orderNO = storeOrderService.preOrder(request);
-        return Result.success(orderNO);
+    public Result preOrder(@RequestBody @Validated PreOrderRequest request) {
+        return Result.success(storeOrderService.preOrder(request));
     }
 
     @ApiOperation(value = "加载预下单")

+ 5 - 6
mall-service/src/main/java/com/txz/mall/core/RedisUtil.java

@@ -1,15 +1,14 @@
 package com.txz.mall.core;
 
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
-
-import javax.annotation.Resource;
-
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
  
  
 /**

+ 1 - 1
mall-service/src/main/java/com/txz/mall/model/StoreOrder.java

@@ -275,7 +275,7 @@ public class StoreOrder {
      */
     @ApiModelProperty(value = "拼团商品id 0一般商品")
     @Column(name = "combination_id")
-    private Integer combinationId;
+    private Long combinationId;
 
     /**
      * 拼团id 0没有拼团

+ 10 - 0
mall-service/src/main/java/com/txz/mall/service/ProductAttrValueService.java

@@ -38,4 +38,14 @@ public interface ProductAttrValueService extends Service<ProductAttrValue> {
      * @return StoreProductAttrValue
      */
     ProductAttrValue getByProductIdAndSkuAndType(Long productId, String suk, Integer type);
+
+    /**
+     * 添加/扣减库存
+     *
+     * @param id            秒杀商品id
+     * @param num           数量
+     * @param operationType 类型:add—添加,sub—扣减
+     * @param type          活动类型 0=商品,1=秒杀,2=砍价,3=拼团
+     */
+    void operationStock(Integer id, Integer num, String operationType, Integer type);
 }

+ 8 - 1
mall-service/src/main/java/com/txz/mall/service/StoreCombinationService.java

@@ -47,5 +47,12 @@ public interface StoreCombinationService extends Service<StoreCombination> {
      */
     StoreCombination getByIdException(Long id);
 
-
+    /**
+     * 添加/扣减库存
+     *
+     * @param id   秒杀商品id
+     * @param num  数量
+     * @param type 类型:add—添加,sub—扣减
+     */
+    void operationStock(Integer id, Integer num, String type);
 }

+ 8 - 0
mall-service/src/main/java/com/txz/mall/service/StoreOrderService.java

@@ -92,4 +92,12 @@ public interface StoreOrderService extends Service<StoreOrder> {
      * @return 预下单信息
      */
     PreOrderResponse loadPreOrder(String preOrderNo);
+
+    /**
+     * 创建订单
+     *
+     * @param orderRequest 创建订单请求参数
+     * @return MyRecord 订单编号
+     */
+    void createOrder(CreateOrderRequest orderRequest);
 }

+ 9 - 0
mall-service/src/main/java/com/txz/mall/service/StoreProductService.java

@@ -57,4 +57,13 @@ public interface StoreProductService extends Service<StoreProduct> {
      * @return 更新结果
      */
     void update(StoreProductAddRequest request);
+
+    /**
+     * 添加/扣减库存
+     *
+     * @param id   秒杀商品id
+     * @param num  数量
+     * @param type 类型:add—添加,sub—扣减
+     */
+    void operationStock(Integer id, Integer num, String type);
 }

+ 32 - 0
mall-service/src/main/java/com/txz/mall/service/impl/ProductAttrValueServiceImpl.java

@@ -1,6 +1,8 @@
 package com.txz.mall.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.txz.mall.core.AbstractService;
 import com.txz.mall.dao.ProductAttrValueMapper;
@@ -63,4 +65,34 @@ public class ProductAttrValueServiceImpl extends AbstractService<ProductAttrValu
         }
         return null;
     }
+
+    @Override
+    public void operationStock(Integer id, Integer num, String operationType, Integer type) {
+        UpdateWrapper<ProductAttrValue> updateWrapper = new UpdateWrapper<>();
+        if ("add".equals(operationType)) {
+            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
+            updateWrapper.setSql(StrUtil.format("sales = sales - {}", num));
+            if (type > 0) {
+                updateWrapper.setSql(StrUtil.format("quota = quota + {}", num));
+            }
+        }
+        if ("sub".equals(operationType)) {
+            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
+            updateWrapper.setSql(StrUtil.format("sales = sales + {}", num));
+            if (type > 0) {
+                updateWrapper.setSql(StrUtil.format("quota = quota - {}", num));
+                // 扣减时加乐观锁保证库存不为负
+                updateWrapper.last(StrUtil.format("and (quota - {} >= 0)", num));
+            } else {
+                // 扣减时加乐观锁保证库存不为负
+                updateWrapper.last(StrUtil.format("and (stock - {} >= 0)", num));
+            }
+        }
+        updateWrapper.eq("id", id);
+        updateWrapper.eq("type", type);
+//        boolean update = update(updateWrapper);
+//        if (!update) {
+//            throw new ServiceException("更新商品attrValue失败,attrValueId = " + id);
+//        }
+    }
 }

+ 23 - 2
mall-service/src/main/java/com/txz/mall/service/impl/StoreCombinationServiceImpl.java

@@ -2,7 +2,9 @@ package com.txz.mall.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.txz.mall.constants.Constants;
@@ -125,7 +127,6 @@ public class StoreCombinationServiceImpl extends AbstractService<StoreCombinatio
     }
 
 
-
     @Override
     public GoPinkResponse goPink(Long pinkId) {
         //判断拼团是否完成
@@ -303,5 +304,25 @@ public class StoreCombinationServiceImpl extends AbstractService<StoreCombinatio
         return combinationList.get(0);
     }
 
-
+    @Override
+    public void operationStock(Integer id, Integer num, String type) {
+        UpdateWrapper<StoreCombination> updateWrapper = new UpdateWrapper<>();
+        if ("add".equals(type)) {
+            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
+            updateWrapper.setSql(StrUtil.format("sales = sales - {}", num));
+            updateWrapper.setSql(StrUtil.format("quota = quota + {}", num));
+        }
+        if ("sub".equals(type)) {
+            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
+            updateWrapper.setSql(StrUtil.format("sales = sales + {}", num));
+            updateWrapper.setSql(StrUtil.format("quota = quota - {}", num));
+            // 扣减时加乐观锁保证库存不为负
+            updateWrapper.last(StrUtil.format(" and (quota - {} >= 0)", num));
+        }
+        updateWrapper.eq("id", id);
+//        boolean update = update(updateWrapper);
+//        if (!update) {
+//            throw new ServiceException("更新拼团商品库存失败,商品id = " + id);
+//        }
+    }
 }

+ 264 - 14
mall-service/src/main/java/com/txz/mall/service/impl/StoreOrderServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.excel.EasyExcel;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.txz.cif.dto.UserDTO;
@@ -19,6 +20,7 @@ import dto.*;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.time.DateUtils;
+import org.apache.commons.lang3.StringEscapeUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -440,7 +442,7 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
      * @param productNum           购买数量
      * @return MyRecord
      */
-    private Map<String, Object> commonValidateCombination(StoreCombination storeCombination, ProductAttrValue combinationAttrValue, Long userId, Integer productNum) {
+    private MyRecord commonValidateCombination(StoreCombination storeCombination, ProductAttrValue combinationAttrValue, Long userId, Integer productNum) {
         // 判断拼团时间段
         Date date = new Date();
         if (date.before(storeCombination.getStartTime())) {
@@ -491,9 +493,9 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
             }
         }
 
-        HashMap<String, Object> map = new LinkedHashMap<>();
-        map.put("productAttrValue", productAttrValue);
-        return map;
+        MyRecord record = new MyRecord();
+        record.set("productAttrValue", productAttrValue);
+        return record;
     }
 
 
@@ -604,16 +606,14 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
 //            }
 //        }
 //        // 积分部分
-//        BigDecimal payPrice = orderInfoVo.getProTotalFee().add(priceResponse.getFreightFee()).subtract(priceResponse.getCouponFee());
-//        priceResponse.setUseIntegral(request.getUseIntegral());
-//        priceResponse.setProTotalFee(orderInfoVo.getProTotalFee());
-//        if (!request.getUseIntegral() || user.getIntegral() <= 0) {// 不使用积分
-//            priceResponse.setDeductionPrice(BigDecimal.ZERO);
+        BigDecimal payPrice = orderInfoVo.getProTotalFee().add(priceResponse.getFreightFee()).subtract(priceResponse.getCouponFee());
+        priceResponse.setProTotalFee(orderInfoVo.getProTotalFee());
+        // 不使用积分
+        priceResponse.setDeductionPrice(BigDecimal.ZERO);
 //            priceResponse.setSurplusIntegral(user.getIntegral());
-//            priceResponse.setPayFee(payPrice);
-//            priceResponse.setUsedIntegral(0);
-//            return priceResponse;
-//        }
+        priceResponse.setPayFee(payPrice);
+        priceResponse.setUsedIntegral(0);
+        return priceResponse;
 //        // 使用积分
 //        // 查询积分使用比例
 //        String integralRatio = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_KEY_INTEGRAL_RATE);
@@ -636,7 +636,7 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
 //            priceResponse.setPayFee(payPrice);
 //            priceResponse.setDeductionPrice(deductionPrice);
 //        }
-        return priceResponse;
+//        return priceResponse;
     }
 
     @Override
@@ -863,4 +863,254 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
         preOrderResponse.setYuePayStatus(1);
         return preOrderResponse;
     }
+
+    @Override
+    public void createOrder(CreateOrderRequest request) {
+        UserDTO user = userDubboServiceClient.getUser(request.getUserId());
+        // 通过缓存获取预下单对象
+        String key = "user_order:" + request.getPreOrderNo();
+        boolean exists = redisUtil.hasKey(key);
+        if (!exists) {
+            throw new ServiceException("预下单订单不存在");
+        }
+        String orderVoString = redisUtil.get(key).toString();
+        OrderInfoVO orderInfoVo = JSONObject.parseObject(orderVoString, OrderInfoVO.class);
+
+        request.setPayType("yue");
+        request.setShippingType(1);
+
+//        if (request.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
+//            // 检测支付渠道
+//            if (StrUtil.isBlank(request.getPayChannel())) {
+//                throw new ServiceException("支付渠道不能为空!");
+//            }
+//        }
+
+        // 校验商品库存
+        List<MyRecord> skuRecordList = validateProductStock(orderInfoVo, user);
+
+        // 校验收货信息
+        String verifyCode = "";
+        String userAddressStr = "";
+//        if (request.getShippingType() == 1) {
+//            // 快递配送
+//            if (request.getAddressId() <= 0) {
+//                throw new ServiceException("请选择收货地址");
+//            }
+//            UserAddress userAddress = userAddressService.findById(request.getAddressId());
+//            if (ObjectUtil.isNull(userAddress) || userAddress.getIsDelete().equals(1)) {
+//                throw new ServiceException("收货地址有误");
+//            }
+//            request.setRealName(userAddress.getRealName());
+//            request.setPhone(userAddress.getPhone());
+//            userAddressStr = userAddress.getProvince() + userAddress.getCity() + userAddress.getDistrict() + userAddress.getDetail();
+//        }
+
+        // 计算订单各种价格
+        OrderComputedPriceRequest orderComputedPriceRequest = new OrderComputedPriceRequest();
+        orderComputedPriceRequest.setShippingType(request.getShippingType());
+        orderComputedPriceRequest.setAddressId(request.getAddressId());
+//        orderComputedPriceRequest.setCouponId(request.getCouponId());
+//        orderComputedPriceRequest.setUseIntegral(request.getUseIntegral());
+        ComputedOrderPriceResponse computedOrderPriceResponse = computedPrice(orderComputedPriceRequest, orderInfoVo, user);
+
+        // 生成订单号
+        String orderNo = OrderUtils.getOrderCode();
+
+        // 购买赠送的积分
+        List<StoreOrderInfo> storeOrderInfos = new ArrayList<>();
+        for (OrderInfoDetailVO detailVo : orderInfoVo.getOrderDetailList()) {
+            // 订单详情
+            StoreOrderInfo soInfo = new StoreOrderInfo();
+            soInfo.setProductId(detailVo.getProductId());
+            soInfo.setInfo(JSON.toJSON(detailVo).toString());
+            soInfo.setOrderNo(orderNo);
+            soInfo.setProductName(detailVo.getProductName());
+            soInfo.setAttrValueId(detailVo.getAttrValueId());
+            soInfo.setImage(detailVo.getImage());
+            soInfo.setSku(detailVo.getSku());
+            soInfo.setPrice(detailVo.getPrice());
+            soInfo.setPayNum(detailVo.getPayNum());
+            soInfo.setWeight(detailVo.getWeight());
+            soInfo.setVolume(detailVo.getVolume());
+            if (ObjectUtil.isNotNull(detailVo.getGiveIntegral()) && detailVo.getGiveIntegral() > 0) {
+                soInfo.setGiveIntegral(detailVo.getGiveIntegral());
+            } else {
+                soInfo.setGiveIntegral(0);
+            }
+            soInfo.setIsReply(0);
+            soInfo.setIsSub(detailVo.getIsSub());
+            soInfo.setProductType(detailVo.getProductType());
+            if (ObjectUtil.isNotNull(detailVo.getVipPrice())) {
+                soInfo.setVipPrice(detailVo.getVipPrice());
+            } else {
+                soInfo.setVipPrice(detailVo.getPrice());
+            }
+
+            storeOrderInfos.add(soInfo);
+        }
+
+        // 支付渠道 默认:余额支付
+        int isChannel = 3;
+        StoreOrder storeOrder = new StoreOrder();
+        storeOrder.setUid(user.getId());
+        storeOrder.setOrderId(orderNo);
+        storeOrder.setRealName(request.getRealName());
+        storeOrder.setUserPhone(request.getPhone());
+        storeOrder.setUserAddress(userAddressStr);
+        storeOrder.setTotalNum(orderInfoVo.getOrderProNum());
+        storeOrder.setCouponId(Optional.ofNullable(request.getCouponId()).orElse(0L));
+
+        // 订单总价
+        BigDecimal totalPrice = computedOrderPriceResponse.getProTotalFee().add(computedOrderPriceResponse.getFreightFee());
+
+        storeOrder.setTotalPrice(totalPrice);
+        storeOrder.setProTotalPrice(computedOrderPriceResponse.getProTotalFee());
+        storeOrder.setTotalPostage(computedOrderPriceResponse.getFreightFee());
+        storeOrder.setCouponPrice(computedOrderPriceResponse.getCouponFee());
+        storeOrder.setPayPrice(computedOrderPriceResponse.getPayFee());
+        storeOrder.setPayPostage(computedOrderPriceResponse.getFreightFee());
+        storeOrder.setDeductionPrice(computedOrderPriceResponse.getDeductionPrice());
+        storeOrder.setPayType(request.getPayType());
+//        storeOrder.setUseIntegral(computedOrderPriceResponse.getUsedIntegral());
+//        storeOrder.setGainIntegral(gainIntegral);
+        storeOrder.setMark(StringEscapeUtils.escapeHtml4(request.getMark()));
+        storeOrder.setCombinationId(orderInfoVo.getCombinationId());
+        storeOrder.setPinkId(orderInfoVo.getPinkId());
+        storeOrder.setBargainUserId(orderInfoVo.getBargainUserId());
+        storeOrder.setCreateTime(new Date());
+        storeOrder.setShippingType(request.getShippingType());
+        storeOrder.setIsChannel(isChannel);
+        storeOrder.setPaid(0);
+        storeOrder.setCost(BigDecimal.ZERO);
+        storeOrder.setType(0);
+
+//        StoreCouponUser storeCouponUser = new StoreCouponUser();
+//        // 优惠券修改
+//        if (storeOrder.getCouponId() > 0) {
+//            storeCouponUser = storeCouponUserService.getById(storeOrder.getCouponId());
+//            storeCouponUser.setStatus(1);
+//        }
+//        StoreCouponUser finalStoreCouponUser = storeCouponUser;
+
+        // 扣减库存
+        // 需要根据是否活动商品,扣减不同的库存
+        if (storeOrder.getCombinationId() > 0) {
+            // 拼团扣库存
+            MyRecord skuRecord = skuRecordList.get(0);
+            // 拼团商品扣库存
+            storeCombinationService.operationStock(skuRecord.getInt("activityId"), skuRecord.getInt("num"), "sub");
+            // 拼团商品规格扣库存
+            productAttrValueService.operationStock(skuRecord.getInt("activityAttrValueId"), skuRecord.getInt("num"), "sub", Constants.PRODUCT_TYPE_PINGTUAN);
+            // 普通商品口库存
+            storeProductService.operationStock(skuRecord.getInt("productId"), skuRecord.getInt("num"), "sub");
+            // 普通商品规格扣库存
+            productAttrValueService.operationStock(skuRecord.getInt("attrValueId"), skuRecord.getInt("num"), "sub", Constants.PRODUCT_TYPE_NORMAL);
+        } else { // 普通商品
+            for (MyRecord skuRecord : skuRecordList) {
+                // 普通商品口库存
+                storeProductService.operationStock(skuRecord.getInt("productId"), skuRecord.getInt("num"), "sub");
+                // 普通商品规格扣库存
+                productAttrValueService.operationStock(skuRecord.getInt("attrValueId"), skuRecord.getInt("num"), "sub", Constants.PRODUCT_TYPE_NORMAL);
+            }
+        }
+
+//        storeOrderService.create(storeOrder);
+        storeOrderInfos.forEach(info -> info.setOrderId(storeOrder.getId()));
+        // 优惠券修改
+//        if (storeOrder.getCouponId() > 0) {
+//            storeCouponUserService.updateById(finalStoreCouponUser);
+//        }
+//        // 保存购物车商品详情
+//        storeOrderInfoService.saveOrderInfos(storeOrderInfos);
+//        // 生成订单日志
+//        storeOrderStatusService.createLog(storeOrder.getId(), Constants.ORDER_STATUS_CACHE_CREATE_ORDER, "订单生成");
+//
+//        // 清除购物车数据
+//        if (CollUtil.isNotEmpty(orderInfoVo.getCartIdList())) {
+//            storeCartService.deleteCartByIds(orderInfoVo.getCartIdList());
+//        }
+//        return Boolean.TRUE;
+
+        // 删除缓存订单
+        if (redisUtil.hasKey(key)) {
+            redisUtil.del(key);
+        }
+
+        // 加入自动未支付自动取消队列
+//        redisUtil.lPush(Constants.ORDER_AUTO_CANCEL_KEY, storeOrder.getOrderId());
+//
+        MyRecord record = new MyRecord();
+        record.set("orderNo", storeOrder.getOrderId());
+//        return record;
+    }
+
+    /**
+     * 校验商品库存(生成订单)
+     *
+     * @param orderInfoVo 订单详情Vo
+     * @return List<MyRecord>
+     * skuRecord 扣减库存对象
+     * ——activityId             活动商品id
+     * ——activityAttrValueId    活动商品skuId
+     * ——productId              普通(主)商品id
+     * ——attrValueId            普通(主)商品skuId
+     * ——num                    购买数量
+     */
+    private List<MyRecord> validateProductStock(OrderInfoVO orderInfoVo, UserDTO user) {
+        List<MyRecord> recordList = CollUtil.newArrayList();
+        if (orderInfoVo.getCombinationId() > 0) {
+            // 拼团部分判断
+            Long combinationId = orderInfoVo.getCombinationId();
+            OrderInfoDetailVO detailVo = orderInfoVo.getOrderDetailList().get(0);
+            StoreCombination storeCombination = storeCombinationService.getByIdException(combinationId);
+            ProductAttrValue combinationAttrValue = productAttrValueService.getByIdAndProductIdAndType(detailVo.getAttrValueId(), combinationId, Constants.PRODUCT_TYPE_PINGTUAN);
+            if (ObjectUtil.isNull(combinationAttrValue)) {
+                throw new ServiceException("拼团商品规格不存在");
+            }
+            MyRecord combinationRecord = commonValidateCombination(storeCombination, combinationAttrValue, user.getId(), detailVo.getPayNum());
+            ProductAttrValue productAttrValue = combinationRecord.get("productAttrValue");
+
+            MyRecord record = new MyRecord();
+            record.set("activityId", combinationId);
+            record.set("activityAttrValueId", combinationAttrValue.getId());
+            record.set("productId", storeCombination.getProductId());
+            record.set("attrValueId", productAttrValue.getId());
+            record.set("num", detailVo.getPayNum());
+            recordList.add(record);
+            return recordList;
+        }
+        // 普通商品
+        List<OrderInfoDetailVO> orderDetailList = orderInfoVo.getOrderDetailList();
+        orderDetailList.forEach(e -> {
+            // 查询商品信息
+            StoreProduct storeProduct = storeProductService.findById(e.getProductId());
+            if (ObjectUtil.isNull(storeProduct)) {
+                throw new ServiceException("购买的商品信息不存在");
+            }
+            if (storeProduct.getIsDelete().equals(1)) {
+                throw new ServiceException("购买的商品已删除");
+            }
+            if (!storeProduct.getIsShow().equals(0)) {
+                throw new ServiceException("购买的商品已下架");
+            }
+            if (storeProduct.getStock().equals(0) || e.getPayNum() > storeProduct.getStock()) {
+                throw new ServiceException("购买的商品库存不足");
+            }
+            // 查询商品规格属性值信息
+            ProductAttrValue attrValue = productAttrValueService.getByIdAndProductIdAndType(e.getAttrValueId(), e.getProductId(), Constants.PRODUCT_TYPE_NORMAL);
+            if (ObjectUtil.isNull(attrValue)) {
+                throw new ServiceException("购买的商品规格信息不存在");
+            }
+            if (attrValue.getStock() < e.getPayNum()) {
+                throw new ServiceException("购买的商品库存不足");
+            }
+            MyRecord record = new MyRecord();
+            record.set("productId", e.getProductId());
+            record.set("num", e.getPayNum());
+            record.set("attrValueId", e.getAttrValueId());
+            recordList.add(record);
+        });
+        return recordList;
+    }
 }

+ 23 - 0
mall-service/src/main/java/com/txz/mall/service/impl/StoreProductServiceImpl.java

@@ -9,6 +9,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
 import com.alibaba.fastjson.parser.Feature;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.txz.mall.constants.Constants;
 import com.txz.mall.core.AbstractService;
@@ -324,6 +325,28 @@ public class StoreProductServiceImpl extends AbstractService<StoreProduct> imple
         assignAttributes(request, 1);
     }
 
+    @Override
+    public void operationStock(Integer id, Integer num, String type) {
+        UpdateWrapper<StoreProduct> updateWrapper = new UpdateWrapper<>();
+        if ("add".equals(type)) {
+            updateWrapper.setSql(StrUtil.format("stock = stock + {}", num));
+            updateWrapper.setSql(StrUtil.format("sales = sales - {}", num));
+            updateWrapper.setSql(StrUtil.format("quota = quota + {}", num));
+        }
+        if ("sub".equals(type)) {
+            updateWrapper.setSql(StrUtil.format("stock = stock - {}", num));
+            updateWrapper.setSql(StrUtil.format("sales = sales + {}", num));
+            updateWrapper.setSql(StrUtil.format("quota = quota - {}", num));
+            // 扣减时加乐观锁保证库存不为负
+            updateWrapper.last(StrUtil.format(" and (quota - {} >= 0)", num));
+        }
+        updateWrapper.eq("id", id);
+//        boolean update = update(updateWrapper);
+//        if (!update) {
+//            throw new ServiceException("更新商品库存失败!商品id = " + id);
+//        }
+    }
+
     // 生成货号的方法
     private String generateItemNumber(String cateIdStr) {
         // 1. 获取类目ID的字符串形式

+ 52 - 0
mall-service/src/main/java/com/txz/mall/util/PayConstants.java

@@ -0,0 +1,52 @@
+package com.txz.mall.util;
+
+/**
+ * 支付相关常量类
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+public class PayConstants {
+
+    //支付方式
+    public static final String PAY_TYPE_WE_CHAT = "weixin"; //微信支付
+    public static final String PAY_TYPE_YUE = "yue"; //余额支付
+    public static final String PAY_TYPE_OFFLINE = "offline"; //线下支付
+    public static final String PAY_TYPE_ALI_PAY = "alipay"; //支付宝
+    public static final String PAY_TYPE_ZERO_PAY = "zeroPay"; // 零元付
+
+    //支付渠道
+    public static final String PAY_CHANNEL_WE_CHAT_H5 = "weixinh5"; //H5唤起微信支付
+    public static final String PAY_CHANNEL_WE_CHAT_PUBLIC = "public"; //公众号
+    public static final String PAY_CHANNEL_WE_CHAT_PROGRAM = "routine"; //小程序
+    public static final String PAY_CHANNEL_WE_CHAT_APP_IOS = "weixinAppIos"; //微信App支付ios
+    public static final String PAY_CHANNEL_WE_CHAT_APP_ANDROID = "weixinAppAndroid"; //微信App支付android
+
+    public static final String PAY_CHANNEL_ALI_PAY = "alipay"; //支付宝支付
+    public static final String PAY_CHANNEL_ALI_APP_PAY = "appAliPay"; //支付宝App支付
+
+    public static final String WX_PAY_TRADE_TYPE_JS = "JSAPI";
+    public static final String WX_PAY_TRADE_TYPE_H5 = "MWEB";
+
+    //微信支付接口请求地址
+    public static final String WX_PAY_API_URL = "https://api.mch.weixin.qq.com/";
+    // 微信统一预下单
+    public static final String WX_PAY_API_URI = "pay/unifiedorder";
+    // 微信查询订单
+    public static final String WX_PAY_ORDER_QUERY_API_URI = "pay/orderquery";
+    // 微信支付回调地址
+    public static final String WX_PAY_NOTIFY_API_URI = "/api/admin/payment/callback/wechat";
+    // 微信退款回调地址
+    public static final String WX_PAY_REFUND_NOTIFY_API_URI = "/api/admin/payment/callback/wechat/refund";
+
+    public static final String WX_PAY_SIGN_TYPE_MD5 = "MD5";
+    public static final String WX_PAY_SIGN_TYPE_SHA256 = "HMAC-SHA256";
+
+    public static final String FIELD_SIGN = "sign";
+}

+ 74 - 0
mall-service/src/main/java/dto/CreateOrderRequest.java

@@ -0,0 +1,74 @@
+package dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ * 创建订单请求对象
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "CreateOrderRequest对象", description = "创建订单请求对象")
+public class CreateOrderRequest implements Serializable {
+
+    private static final long serialVersionUID = -6133994384185333872L;
+
+    @ApiModelProperty(value = "预下单订单号")
+    @NotBlank(message = "预下单订单号不能为空")
+    private String preOrderNo;
+
+    @ApiModelProperty(value = "快递类型: 1-快递配送,2-到店自提")
+//    @NotNull(message = "快递类型不能为空")
+//    @Range(min = 1, max = 2, message = "未知的快递类型")
+    private Integer shippingType;
+
+    @ApiModelProperty(value = "收货地址id")
+    private Long addressId;
+
+    @ApiModelProperty(value = "优惠券编号")
+    private Long couponId;
+
+    @ApiModelProperty(value = "支付类型:weixin-微信支付,yue-余额支付,alipay-支付宝支付")
+//    @NotBlank(message = "支付类型不能为空")
+    private String payType;
+
+    @ApiModelProperty(value = "支付渠道:weixinh5-微信H5支付,public-公众号支付,routine-小程序支付,weixinAppIos-微信appios支付,weixinAppAndroid-微信app安卓支付,alipay-支付宝支付,appAliPay-App支付宝支付")
+//    @NotBlank(message = "支付渠道不能为空")
+    private String payChannel;
+
+    @ApiModelProperty(value = "是否使用积分")
+//    @NotNull(message = "是否使用积分不能为空")
+    private Boolean useIntegral;
+
+    @ApiModelProperty(value = "订单备注")
+    private String mark;
+
+    // 以下为到店自提参数
+
+    @ApiModelProperty(value = "自提点id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "真实名称")
+    private String realName;
+
+    @ApiModelProperty(value = "手机号码")
+    private String phone;
+
+    private Long userId;
+}

+ 3 - 4
mall-service/src/main/java/dto/OrderComputedPriceRequest.java

@@ -5,7 +5,6 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
-import org.hibernate.validator.constraints.Range;
 
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
@@ -21,14 +20,14 @@ public class OrderComputedPriceRequest {
     private String preOrderNo;
 
     @ApiModelProperty(value = "地址id")
-    private Integer addressId;
+    private Long addressId;
 
 //    @ApiModelProperty(value = "优惠券id")
 //    private Integer couponId;
 
     @ApiModelProperty(value = "快递类型: 1-快递配送,2-到店自提")
-    @NotNull(message = "快递类型不能为空")
-    @Range(min = 1, max = 2, message = "未知的快递类型")
+//    @NotNull(message = "快递类型不能为空")
+//    @Range(min = 1, max = 2, message = "未知的快递类型")
     private Integer shippingType;
 
 //    @ApiModelProperty(value = "是否使用积分")

+ 1 - 1
mall-service/src/main/java/dto/PreOrderDetailRequest.java

@@ -49,7 +49,7 @@ public class PreOrderDetailRequest {
     private Long combinationId = 0L;
 
     @ApiModelProperty(value = "拼团团长id")
-    private Integer pinkId = 0;
+    private Long pinkId = 0L;
 
 //    @ApiModelProperty(value = "秒杀商品id")
 //    private Integer seckillId = 0;

+ 469 - 0
mall-service/src/main/java/vo/MyRecord.java

@@ -0,0 +1,469 @@
+package vo;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.*;
+
+/**
+ * 公共对象
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+public class MyRecord implements Serializable {
+
+    private static final long serialVersionUID = 905784513600884082L;
+
+    private static final Logger logger = LoggerFactory.getLogger(MyRecord.class);
+
+    private Map<String, Object> columns;
+
+    /**
+     * @param o
+     * @return
+     * @desc 获取属性名数组
+     */
+    private static String[] getFiledName(Object o) {
+        Field[] fields = o.getClass().getDeclaredFields();
+        String[] fieldNames = new String[fields.length];
+        for (int i = 0; i < fields.length; i++) {
+            fieldNames[i] = fields[i].getName();
+        }
+        return fieldNames;
+    }
+
+    /**
+     * @param fieldName
+     * @param o
+     * @return
+     * @desc 根据属性名获取属性值
+     */
+    private static Object getFieldValueByName(String fieldName, Object o) {
+        try {
+            String firstLetter = fieldName.substring(0, 1).toUpperCase();
+            String getter = "get" + firstLetter + fieldName.substring(1);
+            Method method = o.getClass().getMethod(getter, new Class[]{});
+            Object value = method.invoke(o, new Object[]{});
+            return value;
+        } catch (Exception e) {
+            e.printStackTrace();
+            logger.error("获取属性值失败!" + e, e);
+        }
+        return null;
+    }
+
+    /**
+     * @param fieldName
+     * @param o
+     * @return
+     * @desc 获取属性的数据类型
+     */
+    private static Object getFiledType(String fieldName, Object o) {
+        Field[] fields = o.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            if (Objects.equals(fieldName, field.getName())) {
+                return field.getType();
+            }
+        }
+        return null;
+    }
+
+    void setColumnsMap(Map<String, Object> columns) {
+        this.columns = columns;
+    }
+
+    /**
+     * Return columns map.
+     */
+    public Map<String, Object> getColumns() {
+        if (null == columns) {
+            columns = new HashMap<String, Object>();
+        }
+        return columns;
+    }
+
+    /**
+     * Set columns value with map.
+     *
+     * @param columns the columns map
+     */
+    public MyRecord setColums(Map<String, Object> columns) {
+        this.getColumns().putAll(columns);
+        return this;
+    }
+
+    /**
+     * Set columns value with MyRecord.
+     *
+     * @param record the MyRecord object
+     */
+    public MyRecord setColums(MyRecord record) {
+        this.getColumns().putAll(record.getColumns());
+        return this;
+    }
+
+    /**
+     * Set columns value with JSONObject.
+     *
+     * @param jsonObject the MyRecord object
+     */
+    public MyRecord setColums(JSONObject jsonObject) {
+        Map<String, Object> columns = this.getColumns();
+        jsonObject.forEach(columns::put);
+        return this;
+    }
+
+    /**
+     * Set columns value with Model object.
+     *
+     * @param t
+     * @param <T>
+     * @return
+     */
+    public <T> MyRecord setColums(T t) {
+        Map<String, Object> columns = this.getColumns();
+
+        String[] fieldNames = getFiledName(t);
+
+        for (int i = 0; i < fieldNames.length; i++) {
+            String name = fieldNames[i];
+            if (!StringUtils.isEmpty(name) && "serialVersionUID".equals(name)) {
+                continue;
+            }
+            Object value = getFieldValueByName(name, t);
+            if (null != value) {
+//                if (getFiledType(name, t).equals(Date.class)) {
+//                    value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date)value);
+//                }
+                columns.put(name, value);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Remove attribute of this myRecord.
+     *
+     * @param column the column name of the myRecord
+     */
+    public MyRecord remove(String column) {
+        getColumns().remove(column);
+        return this;
+    }
+
+    /**
+     * Remove columns of this myRecord.
+     *
+     * @param columns the column names of the myRecord
+     */
+    public MyRecord remove(String... columns) {
+        if (columns != null)
+            for (String c : columns)
+                this.getColumns().remove(c);
+        return this;
+    }
+
+    /**
+     * Remove columns if it is null.
+     */
+    public MyRecord removeNullValueColumns() {
+        for (Iterator<Map.Entry<String, Object>> it = getColumns().entrySet().iterator(); it.hasNext(); ) {
+            Map.Entry<String, Object> e = it.next();
+            if (e.getValue() == null) {
+                it.remove();
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Keep columns of this record and remove other columns.
+     *
+     * @param columns the column names of the record
+     */
+    public MyRecord keep(String... columns) {
+        if (columns != null && columns.length > 0) {
+            Map<String, Object> newColumns = new HashMap<String, Object>(columns.length);    // getConfig().containerFactory.getColumnsMap();
+            for (String c : columns)
+                if (this.getColumns().containsKey(c))    // prevent put null value to the newColumns
+                    newColumns.put(c, this.getColumns().get(c));
+
+            this.getColumns().clear();
+            this.getColumns().putAll(newColumns);
+        } else
+            this.getColumns().clear();
+        return this;
+    }
+
+    /**
+     * Keep column of this record and remove other columns.
+     *
+     * @param column the column names of the record
+     */
+    public MyRecord keep(String column) {
+        if (getColumns().containsKey(column)) {    // prevent put null value to the newColumns
+            Object keepIt = getColumns().get(column);
+            getColumns().clear();
+            getColumns().put(column, keepIt);
+        } else
+            getColumns().clear();
+        return this;
+    }
+
+    /**
+     * Remove all columns of this record.
+     */
+    public MyRecord clear() {
+        getColumns().clear();
+        return this;
+    }
+
+    /**
+     * Set column to record.
+     *
+     * @param column the column name
+     * @param value  the value of the column
+     */
+    public MyRecord set(String column, Object value) {
+        getColumns().put(column, value);
+        return this;
+    }
+
+    /**
+     * Set column to record.
+     *
+     * @param column    the column name
+     * @param valueList the value of the column
+     */
+    public MyRecord set(String column, List<MyRecord> valueList) {
+        List<HashMap<String, Object>> value = new ArrayList<>();
+        valueList.forEach(o -> {
+            HashMap<String, Object> va = new HashMap<>(o.getColumns());
+            value.add(va);
+        });
+        getColumns().put(column, value);
+        return this;
+    }
+
+    /**
+     * Get column of any mysql type
+     */
+    public <T> T get(String column) {
+        return (T) getColumns().get(column);
+    }
+
+    /**
+     * Get column of any mysql type. Returns defaultValue if null.
+     */
+    public <T> T get(String column, Object defaultValue) {
+        Object result = getColumns().get(column);
+        return (T) (result != null ? result : defaultValue);
+    }
+
+    public Object getObject(String column) {
+        return getColumns().get(column);
+    }
+
+    public Object getObject(String column, Object defaultValue) {
+        Object result = getColumns().get(column);
+        return result != null ? result : defaultValue;
+    }
+
+    /**
+     * Get column of mysql type: varchar, char, enum, set, text, tinytext, mediumtext, longtext
+     */
+    public String getStr(String column) {
+        // return (String)getColumns().get(column);
+        Object s = getColumns().get(column);
+        return s != null ? s.toString() : null;
+    }
+
+    /**
+     * Get column of mysql type: int, integer, tinyint(n) n > 1, smallint, mediumint
+     */
+    public Integer getInt(String column) {
+        Number n = getNumber(column);
+        return n != null ? n.intValue() : null;
+    }
+
+    /**
+     * Get column of mysql type: bigint
+     */
+    public Long getLong(String column) {
+        Number n = getNumber(column);
+        return n != null ? n.longValue() : null;
+    }
+
+    /**
+     * Get column of mysql type: unsigned bigint
+     */
+    public java.math.BigInteger getBigInteger(String column) {
+        return (java.math.BigInteger) getColumns().get(column);
+    }
+
+    /**
+     * Get column of mysql type: date, year
+     */
+    public Date getDate(String column) {
+        return (Date) getColumns().get(column);
+    }
+
+    /**
+     * Get column of mysql type: time
+     */
+    public java.sql.Time getTime(String column) {
+        return (java.sql.Time) getColumns().get(column);
+    }
+
+    /**
+     * Get column of mysql type: timestamp, datetime
+     */
+    public java.sql.Timestamp getTimestamp(String column) {
+        return (java.sql.Timestamp) getColumns().get(column);
+    }
+
+    /**
+     * Get column of mysql type: real, double
+     */
+    public Double getDouble(String column) {
+        Number n = getNumber(column);
+        return n != null ? n.doubleValue() : null;
+    }
+
+    /**
+     * Get column of mysql type: float
+     */
+    public Float getFloat(String column) {
+        Number n = getNumber(column);
+        return n != null ? n.floatValue() : null;
+    }
+
+    public Short getShort(String column) {
+        Number n = getNumber(column);
+        return n != null ? n.shortValue() : null;
+    }
+
+    public Byte getByte(String column) {
+        Number n = getNumber(column);
+        return n != null ? n.byteValue() : null;
+    }
+
+    /**
+     * Get column of mysql type: bit, tinyint(1)
+     */
+    public Boolean getBoolean(String column) {
+        return (Boolean) getColumns().get(column);
+    }
+
+    /**
+     * Get column of mysql type: decimal, numeric
+     */
+    public BigDecimal getBigDecimal(String column) {
+        Object n = getColumns().get(column);
+        if (n instanceof BigDecimal) {
+            return (BigDecimal) n;
+        } else if (n != null) {
+            return new BigDecimal(n.toString());
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get column of mysql type: binary, varbinary, tinyblob, blob, mediumblob, longblob
+     * I have not finished the test.
+     */
+    public byte[] getBytes(String column) {
+        return (byte[]) getColumns().get(column);
+    }
+
+    /**
+     * Get column of any type that extends from Number
+     */
+    public Number getNumber(String column) {
+        if (getColumns().get(column) instanceof String) {
+            try {
+                return NumberFormat.getInstance().parse(getColumns().get(column).toString());
+            } catch (ParseException e) {
+                System.out.println("类型转换错误e = " + e.getMessage());
+                e.printStackTrace();
+            }
+        }
+        return (Number) getColumns().get(column);
+    }
+
+    public String toString() {
+        if (columns == null) {
+            return "{}";
+        }
+        StringBuilder sb = new StringBuilder();
+        sb.append('{');
+        boolean first = true;
+        for (Map.Entry<String, Object> e : getColumns().entrySet()) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(", ");
+            }
+            Object value = e.getValue();
+            if (value != null) {
+                value = value.toString();
+            }
+            sb.append(e.getKey()).append(':').append(value);
+        }
+        sb.append('}');
+        return sb.toString();
+    }
+
+    public boolean equals(Object o) {
+        if (!(o instanceof MyRecord))
+            return false;
+        if (o == this)
+            return true;
+        return getColumns().equals(((MyRecord) o).getColumns());
+    }
+
+    public int hashCode() {
+        return getColumns().hashCode();
+    }
+
+    /**
+     * Return column names of this record.
+     */
+    public String[] getColumnNames() {
+        Set<String> attrNameSet = getColumns().keySet();
+        return attrNameSet.toArray(new String[attrNameSet.size()]);
+    }
+
+    /**
+     * Return column values of this record.
+     */
+    public Object[] getColumnValues() {
+        Collection<Object> attrValueCollection = getColumns().values();
+        return attrValueCollection.toArray(new Object[attrValueCollection.size()]);
+    }
+
+    /**
+     * Return json string of this record.
+     */
+    public String toJson() {
+        return JSON.toJSONString(getColumns());
+    }
+
+}

+ 6 - 6
mall-service/src/main/java/vo/OrderInfoVO.java

@@ -78,11 +78,11 @@ public class OrderInfoVO {
     @ApiModelProperty(value = "订单详情数组")
     private List<OrderInfoDetailVO> orderDetailList;
 
-    @ApiModelProperty(value = "秒杀商品Id")
-    private Integer seckillId = 0;
-
-    @ApiModelProperty(value = "砍价商品Id")
-    private Integer bargainId = 0;
+//    @ApiModelProperty(value = "秒杀商品Id")
+//    private Integer seckillId = 0;
+//
+//    @ApiModelProperty(value = "砍价商品Id")
+//    private Integer bargainId = 0;
 
     @ApiModelProperty(value = "用户砍价活动id")
     private Integer bargainUserId;
@@ -91,7 +91,7 @@ public class OrderInfoVO {
     private Long combinationId = 0L;
 
     @ApiModelProperty(value = "拼团团长Id")
-    private Integer pinkId = 0;
+    private Long pinkId = 0L;
 
     @ApiModelProperty(value = "购物车编号列表")
     private List<Long> cartIdList;