迷你商城後臺管理系統————stage2核心代碼實現

 

應用程序主函數接口

 

@SpringBootApplication(scanBasePackages = {"org.linlinjava.litemall.db", "org.linlinjava.litemall.core", "org.linlinjava.litemall.admin"})java

 

@MapperScan("org.linlinjava.litemall.db.dao")數據庫

 

@EnableTransactionManagement後端

 

@EnableSchedulingapi

 

public class Application {安全

 

 

 

    public static void main(String[] args) {微信

 

        SpringApplication.run(Application.class, args);app

 

    }異步

 

 

 

}ide

 

優惠卷管理

 

/**函數

 

 * 檢測優惠券過時狀況

 

 */

 

@Component

 

public class CouponJob {

 

    private final Log logger = LogFactory.getLog(CouponJob.class);

 

 

 

    @Autowired

 

    private LitemallCouponService couponService;

 

    @Autowired

 

    private LitemallCouponUserService couponUserService;

 

 

 

    /**

 

     * 每隔一個小時檢查

 

     * TODO

 

     * 注意,由於是相隔一個小時檢查,所以致使優惠券真正超時時間可能比設定時間延遲1個小時

 

     */

 

    @Scheduled(fixedDelay = 60 * 60 * 1000)

 

    public void checkCouponExpired() {

 

        logger.info("系統開啓任務檢查優惠券是否已通過期");

 

 

 

        List<LitemallCoupon> couponList = couponService.queryExpired();

 

        for(LitemallCoupon coupon : couponList){

 

            coupon.setStatus(CouponConstant.STATUS_EXPIRED);

 

            couponService.updateById(coupon);

 

        }

 

 

 

        List<LitemallCouponUser> couponUserList = couponUserService.queryExpired();

 

        for(LitemallCouponUser couponUser : couponUserList){

 

            couponUser.setStatus(CouponUserConstant.STATUS_EXPIRED);

 

            couponUserService.update(couponUser);

 

        }

 

    }

 

 

 

}

 

訂單管理

 

/**

 

 * 檢測訂單狀態

 

 */

 

@Component

 

public class OrderJob {

 

    private final Log logger = LogFactory.getLog(OrderJob.class);

 

 

 

    @Autowired

 

    private LitemallOrderGoodsService orderGoodsService;

 

    @Autowired

 

    private LitemallOrderService orderService;

 

    @Autowired

 

    private LitemallGoodsProductService productService;

 

 

 

    /**

 

     * 自動取消訂單

 

     * <p>

 

     * 定時檢查訂單未付款狀況,若是超時 LITEMALL_ORDER_UNPAID 分鐘則自動取消訂單

 

     * 定時時間是每次相隔半個小時。

 

     * <p>

 

     * TODO

 

     * 注意,由於是相隔半小時檢查,所以致使訂單真正超時時間是 [LITEMALL_ORDER_UNPAID, 30 + LITEMALL_ORDER_UNPAID]

 

     */

 

    @Scheduled(fixedDelay = 30 * 60 * 1000)

 

    @Transactional

 

    public void checkOrderUnpaid() {

 

        logger.info("系統開啓任務檢查訂單是否已經超期自動取消訂單");

 

 

 

        List<LitemallOrder> orderList = orderService.queryUnpaid(SystemConfig.getOrderUnpaid());

 

        for (LitemallOrder order : orderList) {

 

            // 設置訂單已取消狀態

 

            order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);

 

            order.setEndTime(LocalDateTime.now());

 

            if (orderService.updateWithOptimisticLocker(order) == 0) {

 

                throw new RuntimeException("更新數據已失效");

 

            }

 

 

 

            // 商品貨品數量增長

 

            Integer orderId = order.getId();

 

            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);

 

            for (LitemallOrderGoods orderGoods : orderGoodsList) {

 

                Integer productId = orderGoods.getProductId();

 

                Short number = orderGoods.getNumber();

 

                if (productService.addStock(productId, number) == 0) {

 

                    throw new RuntimeException("商品貨品庫存增長失敗");

 

                }

 

            }

 

            logger.info("訂單 ID=" + order.getId() + " 已經超期自動取消訂單");

 

        }

 

    }

 

 

 

    /**

 

     * 自動確認訂單

 

     * <p>

 

     * 定時檢查訂單未確認狀況,若是超時 LITEMALL_ORDER_UNCONFIRM 天則自動確認訂單

 

     * 定時時間是天天凌晨3點。

 

     * <p>

 

     * TODO

 

     * 注意,由於是相隔一天檢查,所以致使訂單真正超時時間是 [LITEMALL_ORDER_UNCONFIRM, 1 + LITEMALL_ORDER_UNCONFIRM]

 

     */

 

    @Scheduled(cron = "0 0 3 * * ?")

 

    public void checkOrderUnconfirm() {

 

        logger.info("系統開啓任務檢查訂單是否已經超期自動確認收貨");

 

 

 

        List<LitemallOrder> orderList = orderService.queryUnconfirm(SystemConfig.getOrderUnconfirm());

 

        for (LitemallOrder order : orderList) {

 

 

 

            // 設置訂單已取消狀態

 

            order.setOrderStatus(OrderUtil.STATUS_AUTO_CONFIRM);

 

            order.setConfirmTime(LocalDateTime.now());

 

            if (orderService.updateWithOptimisticLocker(order) == 0) {

 

                logger.info("訂單 ID=" + order.getId() + " 數據已經更新,放棄自動確認收貨");

 

            } else {

 

                logger.info("訂單 ID=" + order.getId() + " 已經超期自動確認收貨");

 

            }

 

        }

 

    }

 

 

 

    /**

 

     * 可評價訂單商品超期

 

     * <p>

 

     * 定時檢查訂單商品評價狀況,若是確認商品超時 LITEMALL_ORDER_COMMENT 天則取消可評價狀態

 

     * 定時時間是天天凌晨4點。

 

     * <p>

 

     * TODO

 

     * 注意,由於是相隔一天檢查,所以致使訂單真正超時時間是 [LITEMALL_ORDER_COMMENT, 1 + LITEMALL_ORDER_COMMENT]

 

     */

 

    @Scheduled(cron = "0 0 4 * * ?")

 

    public void checkOrderComment() {

 

        logger.info("系統開啓任務檢查訂單是否已經超期未評價");

 

 

 

        LocalDateTime now = LocalDateTime.now();

 

        List<LitemallOrder> orderList = orderService.queryComment(SystemConfig.getOrderComment());

 

        for (LitemallOrder order : orderList) {

 

            order.setComments((short) 0);

 

            orderService.updateWithOptimisticLocker(order);

 

 

 

            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());

 

            for (LitemallOrderGoods orderGoods : orderGoodsList) {

 

                orderGoods.setComment(-1);

 

                orderGoodsService.updateById(orderGoods);

 

            }

 

        }

 

    }

 

}

 

上架商品管理服務

 

@Service

 

public class AdminGoodsService {

 

    private final Log logger = LogFactory.getLog(AdminGoodsService.class);

 

 

 

    @Autowired

 

    private LitemallGoodsService goodsService;

 

    @Autowired

 

    private LitemallGoodsSpecificationService specificationService;

 

    @Autowired

 

    private LitemallGoodsAttributeService attributeService;

 

    @Autowired

 

    private LitemallGoodsProductService productService;

 

    @Autowired

 

    private LitemallCategoryService categoryService;

 

    @Autowired

 

    private LitemallBrandService brandService;

 

    @Autowired

 

    private LitemallCartService cartService;

 

    @Autowired

 

    private LitemallOrderGoodsService orderGoodsService;

 

 

 

    @Autowired

 

    private QCodeService qCodeService;

 

 

 

    public Object list(String goodsSn, String name,

 

                       Integer page, Integer limit, String sort, String order) {

 

        List<LitemallGoods> goodsList = goodsService.querySelective(goodsSn, name, page, limit, sort, order);

 

        return ResponseUtil.okList(goodsList);

 

    }

 

 

 

    private Object validate(GoodsAllinone goodsAllinone) {

 

        LitemallGoods goods = goodsAllinone.getGoods();

 

        String name = goods.getName();

 

        if (StringUtils.isEmpty(name)) {

 

            return ResponseUtil.badArgument();

 

        }

 

        String goodsSn = goods.getGoodsSn();

 

        if (StringUtils.isEmpty(goodsSn)) {

 

            return ResponseUtil.badArgument();

 

        }

 

        // 品牌商能夠不設置,若是設置則須要驗證品牌商存在

 

        Integer brandId = goods.getBrandId();

 

        if (brandId != null && brandId != 0) {

 

            if (brandService.findById(brandId) == null) {

 

                return ResponseUtil.badArgumentValue();

 

            }

 

        }

 

        // 分類能夠不設置,若是設置則須要驗證分類存在

 

        Integer categoryId = goods.getCategoryId();

 

        if (categoryId != null && categoryId != 0) {

 

            if (categoryService.findById(categoryId) == null) {

 

                return ResponseUtil.badArgumentValue();

 

            }

 

        }

 

 

 

        LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

 

        for (LitemallGoodsAttribute attribute : attributes) {

 

            String attr = attribute.getAttribute();

 

            if (StringUtils.isEmpty(attr)) {

 

                return ResponseUtil.badArgument();

 

            }

 

            String value = attribute.getValue();

 

            if (StringUtils.isEmpty(value)) {

 

                return ResponseUtil.badArgument();

 

            }

 

        }

 

 

 

        LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

 

        for (LitemallGoodsSpecification specification : specifications) {

 

            String spec = specification.getSpecification();

 

            if (StringUtils.isEmpty(spec)) {

 

                return ResponseUtil.badArgument();

 

            }

 

            String value = specification.getValue();

 

            if (StringUtils.isEmpty(value)) {

 

                return ResponseUtil.badArgument();

 

            }

 

        }

 

 

 

        LitemallGoodsProduct[] products = goodsAllinone.getProducts();

 

        for (LitemallGoodsProduct product : products) {

 

            Integer number = product.getNumber();

 

            if (number == null || number < 0) {

 

                return ResponseUtil.badArgument();

 

            }

 

 

 

            BigDecimal price = product.getPrice();

 

            if (price == null) {

 

                return ResponseUtil.badArgument();

 

            }

 

 

 

            String[] productSpecifications = product.getSpecifications();

 

            if (productSpecifications.length == 0) {

 

                return ResponseUtil.badArgument();

 

            }

 

        }

 

 

 

        return null;

 

    }

 

 

 

    /**

 

     * 編輯商品

 

     * <p>

 

     * TODO

 

     * 目前商品修改的邏輯是

 

     * 1. 更新litemall_goods

 

     * 2. 邏輯刪除litemall_goods_specificationlitemall_goods_attributelitemall_goods_product

 

     * 3. 添加litemall_goods_specificationlitemall_goods_attributelitemall_goods_product

 

     * <p>

 

     * 這裏商品三個表的數據採用刪除再添加的策略是由於

 

     * 商品編輯頁面,支持管理員添加刪除商品規格、添加刪除商品屬性,所以這裏僅僅更新是不可能的,

 

     * 只能刪除三個表舊的數據,而後添加新的數據。

 

     * 可是這裏又會引入新的問題,就是存在訂單商品貨品ID指向了失效的商品貨品表。

 

     * 所以這裏會拒絕管理員編輯商品,若是訂單或購物車中存在商品。

 

     * 因此這裏可能須要從新設計。

 

     */

 

    @Transactional

 

    public Object update(GoodsAllinone goodsAllinone) {

 

        Object error = validate(goodsAllinone);

 

        if (error != null) {

 

            return error;

 

        }

 

 

 

        LitemallGoods goods = goodsAllinone.getGoods();

 

        LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

 

        LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

 

        LitemallGoodsProduct[] products = goodsAllinone.getProducts();

 

 

 

        Integer id = goods.getId();

 

 

 

        //將生成的分享圖片地址寫入數據庫

 

        String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

 

        goods.setShareUrl(url);

 

 

 

        // 商品基本信息表litemall_goods

 

        if (goodsService.updateById(goods) == 0) {

 

            throw new RuntimeException("更新數據失敗");

 

        }

 

 

 

        Integer gid = goods.getId();

 

        specificationService.deleteByGid(gid);

 

        attributeService.deleteByGid(gid);

 

        productService.deleteByGid(gid);

 

 

 

        // 商品規格表litemall_goods_specification

 

        for (LitemallGoodsSpecification specification : specifications) {

 

            specification.setGoodsId(goods.getId());

 

            specificationService.add(specification);

 

        }

 

 

 

        // 商品參數表litemall_goods_attribute

 

        for (LitemallGoodsAttribute attribute : attributes) {

 

            attribute.setGoodsId(goods.getId());

 

            attributeService.add(attribute);

 

        }

 

 

 

        // 商品貨品表litemall_product

 

        for (LitemallGoodsProduct product : products) {

 

            product.setGoodsId(goods.getId());

 

            productService.add(product);

 

        }

 

 

 

        return ResponseUtil.ok();

 

    }

 

 

 

    @Transactional

 

    public Object delete(LitemallGoods goods) {

 

        Integer id = goods.getId();

 

        if (id == null) {

 

            return ResponseUtil.badArgument();

 

        }

 

 

 

        Integer gid = goods.getId();

 

        goodsService.deleteById(gid);

 

        specificationService.deleteByGid(gid);

 

        attributeService.deleteByGid(gid);

 

        productService.deleteByGid(gid);

 

        return ResponseUtil.ok();

 

    }

 

 

 

    @Transactional

 

    public Object create(GoodsAllinone goodsAllinone) {

 

        Object error = validate(goodsAllinone);

 

        if (error != null) {

 

            return error;

 

        }

 

 

 

        LitemallGoods goods = goodsAllinone.getGoods();

 

        LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

 

        LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

 

        LitemallGoodsProduct[] products = goodsAllinone.getProducts();

 

 

 

        String name = goods.getName();

 

        if (goodsService.checkExistByName(name)) {

 

            return ResponseUtil.fail(GOODS_NAME_EXIST, "商品名已經存在");

 

        }

 

 

 

        // 商品基本信息表litemall_goods

 

        goodsService.add(goods);

 

 

 

        //將生成的分享圖片地址寫入數據庫

 

        String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

 

        if (!StringUtils.isEmpty(url)) {

 

            goods.setShareUrl(url);

 

            if (goodsService.updateById(goods) == 0) {

 

                throw new RuntimeException("更新數據失敗");

 

            }

 

        }

 

 

 

        // 商品規格表litemall_goods_specification

 

        for (LitemallGoodsSpecification specification : specifications) {

 

            specification.setGoodsId(goods.getId());

 

            specificationService.add(specification);

 

        }

 

 

 

        // 商品參數表litemall_goods_attribute

 

        for (LitemallGoodsAttribute attribute : attributes) {

 

            attribute.setGoodsId(goods.getId());

 

            attributeService.add(attribute);

 

        }

 

 

 

        // 商品貨品表litemall_product

 

        for (LitemallGoodsProduct product : products) {

 

            product.setGoodsId(goods.getId());

 

            productService.add(product);

 

        }

 

        return ResponseUtil.ok();

 

    }

 

 

 

    public Object list2() {

 

        // http://element-cn.eleme.io/#/zh-CN/component/cascader

 

        // 管理員設置所屬分類

 

        List<LitemallCategory> l1CatList = categoryService.queryL1();

 

        List<CatVo> categoryList = new ArrayList<>(l1CatList.size());

 

 

 

        for (LitemallCategory l1 : l1CatList) {

 

            CatVo l1CatVo = new CatVo();

 

            l1CatVo.setValue(l1.getId());

 

            l1CatVo.setLabel(l1.getName());

 

 

 

            List<LitemallCategory> l2CatList = categoryService.queryByPid(l1.getId());

 

            List<CatVo> children = new ArrayList<>(l2CatList.size());

 

            for (LitemallCategory l2 : l2CatList) {

 

                CatVo l2CatVo = new CatVo();

 

                l2CatVo.setValue(l2.getId());

 

                l2CatVo.setLabel(l2.getName());

 

                children.add(l2CatVo);

 

            }

 

            l1CatVo.setChildren(children);

 

 

 

            categoryList.add(l1CatVo);

 

        }

 

 

 

        // http://element-cn.eleme.io/#/zh-CN/component/select

 

        // 管理員設置所屬品牌商

 

        List<LitemallBrand> list = brandService.all();

 

        List<Map<String, Object>> brandList = new ArrayList<>(l1CatList.size());

 

        for (LitemallBrand brand : list) {

 

            Map<String, Object> b = new HashMap<>(2);

 

            b.put("value", brand.getId());

 

            b.put("label", brand.getName());

 

            brandList.add(b);

 

        }

 

 

 

        Map<String, Object> data = new HashMap<>();

 

        data.put("categoryList", categoryList);

 

        data.put("brandList", brandList);

 

        return ResponseUtil.ok(data);

 

    }

 

 

 

    public Object detail(Integer id) {

 

        LitemallGoods goods = goodsService.findById(id);

 

        List<LitemallGoodsProduct> products = productService.queryByGid(id);

 

        List<LitemallGoodsSpecification> specifications = specificationService.queryByGid(id);

 

        List<LitemallGoodsAttribute> attributes = attributeService.queryByGid(id);

 

 

 

        Integer categoryId = goods.getCategoryId();

 

        LitemallCategory category = categoryService.findById(categoryId);

 

        Integer[] categoryIds = new Integer[]{};

 

        if (category != null) {

 

            Integer parentCategoryId = category.getPid();

 

            categoryIds = new Integer[]{parentCategoryId, categoryId};

 

        }

 

 

 

        Map<String, Object> data = new HashMap<>();

 

        data.put("goods", goods);

 

        data.put("specifications", specifications);

 

        data.put("products", products);

 

        data.put("attributes", attributes);

 

        data.put("categoryIds", categoryIds);

 

 

 

        return ResponseUtil.ok(data);

 

    }

 

 

 

}

 

訂單管理服務

 

@Service

 

 

 

public class AdminOrderService {

 

    private final Log logger = LogFactory.getLog(AdminOrderService.class);

 

 

 

    @Autowired

 

    private LitemallOrderGoodsService orderGoodsService;

 

    @Autowired

 

    private LitemallOrderService orderService;

 

    @Autowired

 

    private LitemallGoodsProductService productService;

 

    @Autowired

 

    private LitemallUserService userService;

 

    @Autowired

 

    private LitemallCommentService commentService;

 

    @Autowired

 

    private WxPayService wxPayService;

 

    @Autowired

 

    private NotifyService notifyService;

 

    @Autowired

 

    private LogHelper logHelper;

 

 

 

    public Object list(Integer userId, String orderSn, List<Short> orderStatusArray,

 

                       Integer page, Integer limit, String sort, String order) {

 

        List<LitemallOrder> orderList = orderService.querySelective(userId, orderSn, orderStatusArray, page, limit, sort, order);

 

        return ResponseUtil.okList(orderList);

 

    }

 

 

 

    public Object detail(Integer id) {

 

        LitemallOrder order = orderService.findById(id);

 

        List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(id);

 

        UserVo user = userService.findUserVoById(order.getUserId());

 

        Map<String, Object> data = new HashMap<>();

 

        data.put("order", order);

 

        data.put("orderGoods", orderGoods);

 

        data.put("user", user);

 

 

 

        return ResponseUtil.ok(data);

 

    }

 

 

 

    /**

 

     * 訂單退款

 

     * <p>

 

     * 1. 檢測當前訂單是否可以退款;

 

     * 2. 微信退款操做;

 

     * 3. 設置訂單退款確認狀態;

 

     * 4. 訂單商品庫存回庫。

 

     * <p>

 

     * TODO

 

     * 雖然接入了微信退款API,可是從安全角度考慮,建議開發者刪除這裏微信退款代碼,採用如下兩步走步驟:

 

     * 1. 管理員登陸微信官方支付平臺點擊退款操做進行退款

 

     * 2. 管理員登陸litemall管理後臺點擊退款操做進行訂單狀態修改和商品庫存回庫

 

     *

 

     * @param body 訂單信息,{ orderIdxxx }

 

     * @return 訂單退款操做結果

 

     */

 

    @Transactional

 

    public Object refund(String body) {

 

        Integer orderId = JacksonUtil.parseInteger(body, "orderId");

 

        String refundMoney = JacksonUtil.parseString(body, "refundMoney");

 

        if (orderId == null) {

 

            return ResponseUtil.badArgument();

 

        }

 

        if (StringUtils.isEmpty(refundMoney)) {

 

            return ResponseUtil.badArgument();

 

        }

 

 

 

        LitemallOrder order = orderService.findById(orderId);

 

        if (order == null) {

 

            return ResponseUtil.badArgument();

 

        }

 

 

 

        if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {

 

            return ResponseUtil.badArgumentValue();

 

        }

 

 

 

        // 若是訂單不是退款狀態,則不能退款

 

        if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {

 

            return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "訂單不能確認收貨");

 

        }

 

 

 

        // 微信退款

 

        WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();

 

        wxPayRefundRequest.setOutTradeNo(order.getOrderSn());

 

        wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());

 

        // 元轉成分

 

        Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();

 

        wxPayRefundRequest.setTotalFee(totalFee);

 

        wxPayRefundRequest.setRefundFee(totalFee);

 

 

 

        WxPayRefundResult wxPayRefundResult = null;

 

        try {

 

            wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);

 

        } catch (WxPayException e) {

 

            e.printStackTrace();

 

            return ResponseUtil.fail(ORDER_REFUND_FAILED, "訂單退款失敗");

 

        }

 

        if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {

 

            logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());

 

            return ResponseUtil.fail(ORDER_REFUND_FAILED, "訂單退款失敗");

 

        }

 

        if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {

 

            logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());

 

            return ResponseUtil.fail(ORDER_REFUND_FAILED, "訂單退款失敗");

 

        }

 

 

 

        // 設置訂單取消狀態

 

        order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);

 

        if (orderService.updateWithOptimisticLocker(order) == 0) {

 

            throw new RuntimeException("更新數據已失效");

 

        }

 

 

 

        // 商品貨品數量增長

 

        List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);

 

        for (LitemallOrderGoods orderGoods : orderGoodsList) {

 

            Integer productId = orderGoods.getProductId();

 

            Short number = orderGoods.getNumber();

 

            if (productService.addStock(productId, number) == 0) {

 

                throw new RuntimeException("商品貨品庫存增長失敗");

 

            }

 

        }

 

 

 

        //TODO 發送郵件和短信通知,這裏採用異步發送

 

        // 退款成功通知用戶, 例如您申請的訂單退款 [ 單號:{1} ] 已成功,請耐心等待到帳。

 

        // 注意訂單號只發後6

 

        notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});

 

 

 

        logHelper.logOrderSucceed("退款", "訂單編號 " + orderId);

 

        return ResponseUtil.ok();

 

    }

 

 

 

    /**

 

     * 發貨

 

     * 1. 檢測當前訂單是否可以發貨

 

     * 2. 設置訂單發貨狀態

 

     *

 

     * @param body 訂單信息,{ orderIdxxx, shipSn: xxx, shipChannel: xxx }

 

     * @return 訂單操做結果

 

     * 成功則 { errno: 0, errmsg: '成功' }

 

     * 失敗則 { errno: XXX, errmsg: XXX }

 

     */

 

    public Object ship(String body) {

 

        Integer orderId = JacksonUtil.parseInteger(body, "orderId");

 

        String shipSn = JacksonUtil.parseString(body, "shipSn");

 

        String shipChannel = JacksonUtil.parseString(body, "shipChannel");

 

        if (orderId == null || shipSn == null || shipChannel == null) {

 

            return ResponseUtil.badArgument();

 

        }

 

 

 

        LitemallOrder order = orderService.findById(orderId);

 

        if (order == null) {

 

            return ResponseUtil.badArgument();

 

        }

 

 

 

        // 若是訂單不是已付款狀態,則不能發貨

 

        if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {

 

            return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "訂單不能確認收貨");

 

        }

 

 

 

        order.setOrderStatus(OrderUtil.STATUS_SHIP);

 

        order.setShipSn(shipSn);

 

        order.setShipChannel(shipChannel);

 

        order.setShipTime(LocalDateTime.now());

 

        if (orderService.updateWithOptimisticLocker(order) == 0) {

 

            return ResponseUtil.updatedDateExpired();

 

        }

 

 

 

        //TODO 發送郵件和短信通知,這裏採用異步發送

 

        // 發貨會發送通知短信給用戶:          *

 

        // "您的訂單已經發貨,快遞公司 {1},快遞單 {2} ,請注意查收"

 

        notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[]{shipChannel, shipSn});

 

 

 

        logHelper.logOrderSucceed("發貨", "訂單編號 " + orderId);

 

        return ResponseUtil.ok();

 

    }

 

 

 

 

 

    /**

 

     * 回覆訂單商品

 

     *

 

     * @param body 訂單信息,{ orderIdxxx }

 

     * @return 訂單操做結果

 

     * 成功則 { errno: 0, errmsg: '成功' }

 

     * 失敗則 { errno: XXX, errmsg: XXX }

 

     */

 

    public Object reply(String body) {

 

        Integer commentId = JacksonUtil.parseInteger(body, "commentId");

 

        if (commentId == null || commentId == 0) {

 

            return ResponseUtil.badArgument();

 

        }

 

        // 目前只支持回覆一次

 

        if (commentService.findById(commentId) != null) {

 

            return ResponseUtil.fail(ORDER_REPLY_EXIST, "訂單商品已回覆!");

 

        }

 

        String content = JacksonUtil.parseString(body, "content");

 

        if (StringUtils.isEmpty(content)) {

 

            return ResponseUtil.badArgument();

 

        }

 

        // 建立評價回覆

 

        LitemallComment comment = new LitemallComment();

 

        comment.setType((byte) 2);

 

        comment.setValueId(commentId);

 

        comment.setContent(content);

 

        comment.setUserId(0);                 // 評價回覆沒有用

 

        comment.setStar((short) 0);           // 評價回覆沒有用

 

        comment.setHasPicture(false);        // 評價回覆沒有用

 

        comment.setPicUrls(new String[]{});  // 評價回覆沒有用

 

        commentService.save(comment);

 

 

 

        return ResponseUtil.ok();

 

    }

 

 

 

}

 

操做日誌管理服務

 

/**

 

 * 這裏的日誌類型設計成四種(固然開發者須要能夠本身擴展)

 

 * 通常日誌:用戶以爲須要查看的通常操做日誌,建議是默認的日誌級別

 

 * 安全日誌:用戶安全相關的操做日誌,例如登陸、刪除管理員

 

 * 訂單日誌:用戶交易相關的操做日誌,例如訂單發貨、退款

 

 * 其餘日誌:若是以上三種不合適,能夠選擇其餘日誌,建議是優先級最低的日誌級別

 

 *

 

 * 固然可能不少操做是不須要記錄到數據庫的,例如編輯商品、編輯廣告品之類。

 

 */

 

@Component

 

public class LogHelper {

 

    public final static Integer LOG_TYPE_GENERAL = 0;

 

    public final static Integer LOG_TYPE_AUTH = 1;

 

    public final static Integer LOG_TYPE_ORDER = 2;

 

    public final static Integer LOG_TYPE_OTHER = 3;

 

 

 

    @Autowired

 

    private LitemallLogService logService;

 

 

 

    public void logGeneralSucceed(String action){

 

        logAdmin(LOG_TYPE_GENERAL, action, true, "", "");

 

    }

 

 

 

    public void logGeneralSucceed(String action, String result){

 

        logAdmin(LOG_TYPE_GENERAL, action, true, result, "");

 

    }

 

 

 

    public void logGeneralFail(String action, String error){

 

        logAdmin(LOG_TYPE_GENERAL, action, false, error, "");

 

    }

 

 

 

    public void logAuthSucceed(String action){

 

        logAdmin(LOG_TYPE_AUTH, action, true, "", "");

 

    }

 

 

 

    public void logAuthSucceed(String action, String result){

 

        logAdmin(LOG_TYPE_AUTH, action, true, result, "");

 

    }

 

 

 

    public void logAuthFail(String action, String error){

 

        logAdmin(LOG_TYPE_AUTH, action, false, error, "");

 

    }

 

 

 

    public void logOrderSucceed(String action){

 

        logAdmin(LOG_TYPE_ORDER, action, true, "", "");

 

    }

 

 

 

    public void logOrderSucceed(String action, String result){

 

        logAdmin(LOG_TYPE_ORDER, action, true, result, "");

 

    }

 

 

 

    public void logOrderFail(String action, String error){

 

        logAdmin(LOG_TYPE_ORDER, action, false, error, "");

 

    }

 

 

 

    public void logOtherSucceed(String action){

 

        logAdmin(LOG_TYPE_OTHER, action, true, "", "");

 

    }

 

 

 

    public void logOtherSucceed(String action, String result){

 

        logAdmin(LOG_TYPE_OTHER, action, true, result, "");

 

    }

 

 

 

 

 

    public void logOtherFail(String action, String error){

 

        logAdmin(LOG_TYPE_OTHER, action, false, error, "");

 

    }

 

 

 

    public void logAdmin (Integer type, String action, Boolean succeed, String result, String comment){

 

        LitemallLog log = new LitemallLog();

 

 

 

        Subject currentUser = SecurityUtils.getSubject();

 

        if(currentUser != null) {

 

            LitemallAdmin admin = (LitemallAdmin) currentUser.getPrincipal();

 

            if(admin != null) {

 

                log.setAdmin(admin.getUsername());

 

            }

 

            else{

 

                log.setAdmin("匿名用戶");

 

            }

 

        }

 

        else{

 

            log.setAdmin("匿名用戶");

 

        }

 

 

 

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

 

        if(request != null) {

 

            log.setIp(IpUtil.getIpAddr(request));

 

        }

 

 

 

        log.setType(type);

 

        log.setAction(action);

 

        log.setStatus(succeed);

 

        log.setResult(result);

 

        log.setComment(comment);

 

        logService.add(log);

 

    }

 

 

 

}

 

顧客(會員)身份認證

 

public class AdminAuthorizingRealm extends AuthorizingRealm {

 

 

 

    private static final Logger log = LoggerFactory.getLogger(AdminAuthorizingRealm.class);

 

    @Autowired

 

    private LitemallAdminService adminService;

 

    @Autowired

 

    private LitemallRoleService roleService;

 

    @Autowired

 

    private LitemallPermissionService permissionService;

 

 

 

    @Override

 

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

 

        if (principals == null) {

 

            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");

 

        }

 

 

 

        LitemallAdmin admin = (LitemallAdmin) getAvailablePrincipal(principals);

 

        Integer[] roleIds = admin.getRoleIds();

 

        Set<String> roles = roleService.queryByIds(roleIds);

 

        Set<String> permissions = permissionService.queryByRoleIds(roleIds);

 

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

 

        info.setRoles(roles);

 

        info.setStringPermissions(permissions);

 

        return info;

 

    }

 

 

 

    @Override

 

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

 

 

 

        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

 

        String username = upToken.getUsername();

 

        String password=new String(upToken.getPassword());

 

 

 

        if (StringUtils.isEmpty(username)) {

 

            throw new AccountException("用戶名不能爲空");

 

        }

 

        if (StringUtils.isEmpty(password)) {

 

            throw new AccountException("密碼不能爲空");

 

        }

 

 

 

        List<LitemallAdmin> adminList = adminService.findAdmin(username);

 

        Assert.state(adminList.size() < 2, "同一個用戶名存在兩個帳戶");

 

        if (adminList.size() == 0) {

 

            throw new UnknownAccountException("找不到用戶("+username+")的賬號信息");

 

        }

 

        LitemallAdmin admin = adminList.get(0);

 

 

 

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

 

        if (!encoder.matches(password, admin.getPassword())) {

 

            throw new UnknownAccountException("找不到用戶("+username+")的賬號信息");

 

        }

 

 

 

        return new SimpleAuthenticationInfo(admin,password,getName());

 

    }

 

 

 

}

 

廣告管理控制器

 

 

 

Ps:其餘控制器與此相似,不在一一冗贅

 

 

 

@RestController

 

@RequestMapping("/admin/ad")

 

@Validated

 

public class AdminAdController {

 

    private final Log logger = LogFactory.getLog(AdminAdController.class);

 

 

 

    @Autowired

 

    private LitemallAdService adService;

 

 

 

    @RequiresPermissions("admin:ad:list")

 

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="查詢")

 

    @GetMapping("/list")

 

    public Object list(String name, String content,

 

                       @RequestParam(defaultValue = "1") Integer page,

 

                       @RequestParam(defaultValue = "10") Integer limit,

 

                       @Sort @RequestParam(defaultValue = "add_time") String sort,

 

                       @Order @RequestParam(defaultValue = "desc") String order) {

 

        List<LitemallAd> adList = adService.querySelective(name, content, page, limit, sort, order);

 

        return ResponseUtil.okList(adList);

 

    }

 

 

 

    private Object validate(LitemallAd ad) {

 

        String name = ad.getName();

 

        if (StringUtils.isEmpty(name)) {

 

            return ResponseUtil.badArgument();

 

        }

 

        String content = ad.getContent();

 

        if (StringUtils.isEmpty(content)) {

 

            return ResponseUtil.badArgument();

 

        }

 

        return null;

 

    }

 

 

 

    @RequiresPermissions("admin:ad:create")

 

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="添加")

 

    @PostMapping("/create")

 

    public Object create(@RequestBody LitemallAd ad) {

 

        Object error = validate(ad);

 

        if (error != null) {

 

            return error;

 

        }

 

        adService.add(ad);

 

        return ResponseUtil.ok(ad);

 

    }

 

 

 

    @RequiresPermissions("admin:ad:read")

 

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="詳情")

 

    @GetMapping("/read")

 

    public Object read(@NotNull Integer id) {

 

        LitemallAd ad = adService.findById(id);

 

        return ResponseUtil.ok(ad);

 

    }

 

 

 

    @RequiresPermissions("admin:ad:update")

 

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="編輯")

 

    @PostMapping("/update")

 

    public Object update(@RequestBody LitemallAd ad) {

 

        Object error = validate(ad);

 

        if (error != null) {

 

            return error;

 

        }

 

        if (adService.updateById(ad) == 0) {

 

            return ResponseUtil.updatedDataFailed();

 

        }

 

 

 

        return ResponseUtil.ok(ad);

 

    }

 

 

 

    @RequiresPermissions("admin:ad:delete")

 

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="刪除")

 

    @PostMapping("/delete")

 

    public Object delete(@RequestBody LitemallAd ad) {

 

        Integer id = ad.getId();

 

        if (id == null) {

 

            return ResponseUtil.badArgument();

 

        }

 

        adService.deleteById(id);

 

        return ResponseUtil.ok();

 

    }

 

 

 

}

 

數據庫操做部分

 

Ps:其餘操做和對商品品牌數據庫表操做相似,再次不在冗贅。

 

商品品牌數據庫表操做

 

@Service

 

publicclassLitemallBrandService {

 

    @Resource

 

    privateLitemallBrandMapperbrandMapper;

 

    privateColumn[] columns = newColumn[]{Column.id, Column.name, Column.desc, Column.picUrl, Column.floorPrice};

 

 

 

    publicList<LitemallBrand> query(Integerpage, Integerlimit, Stringsort, Stringorder) {

 

        LitemallBrandExampleexample = newLitemallBrandExample();

 

        example.or().andDeletedEqualTo(false);

 

        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {

 

            example.setOrderByClause(sort + " " + order);

 

        }

 

        PageHelper.startPage(page, limit);

 

        returnbrandMapper.selectByExampleSelective(example, columns);

 

    }

 

 

 

    publicList<LitemallBrand> query(Integerpage, Integerlimit) {

 

        returnquery(page, limit, null, null);

 

    }

 

 

 

    publicLitemallBrandfindById(Integerid) {

 

        returnbrandMapper.selectByPrimaryKey(id);

 

    }

 

 

 

    publicList<LitemallBrand> querySelective(Stringid, Stringname, Integerpage, Integersize, Stringsort, Stringorder) {

 

        LitemallBrandExampleexample = newLitemallBrandExample();

 

        LitemallBrandExample.Criteriacriteria = example.createCriteria();

 

 

 

        if (!StringUtils.isEmpty(id)) {

 

            criteria.andIdEqualTo(Integer.valueOf(id));

 

        }

 

        if (!StringUtils.isEmpty(name)) {

 

            criteria.andNameLike("%" + name + "%");

 

        }

 

        criteria.andDeletedEqualTo(false);

 

 

 

        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {

 

            example.setOrderByClause(sort + " " + order);

 

        }

 

 

 

        PageHelper.startPage(page, size);

 

        returnbrandMapper.selectByExample(example);

 

    }

 

 

 

    publicintupdateById(LitemallBrandbrand) {

 

        brand.setUpdateTime(LocalDateTime.now());

 

        returnbrandMapper.updateByPrimaryKeySelective(brand);

 

    }

 

 

 

    publicvoiddeleteById(Integerid) {

 

        brandMapper.logicalDeleteByPrimaryKey(id);

 

    }

 

 

 

    publicvoidadd(LitemallBrandbrand) {

 

        brand.setAddTime(LocalDateTime.now());

 

        brand.setUpdateTime(LocalDateTime.now());

 

        brandMapper.insertSelective(brand);

 

    }

 

 

 

    publicList<LitemallBrand> all() {

 

        LitemallBrandExampleexample = newLitemallBrandExample();

 

        example.or().andDeletedEqualTo(false);

 

        returnbrandMapper.selectByExample(example);

 

    }

 

}

 

核心操做部分

 

Ps:其餘核心操做同存儲(商品信息、圖片對象等)操做、物流查詢服務相似,不在冗贅。

 

存儲操做

 

/**

 

 * 對象存儲接口

 

 */

 

publicinterfaceStorage {

 

 

 

    /**

 

     * 存儲一個文件對象

 

     *

 

     * @paraminputStream   文件輸入流

 

     * @paramcontentLength文件長度

 

     * @paramcontentType   文件類型

 

     * @paramkeyName       文件名

 

     */

 

    voidstore(InputStreaminputStream, longcontentLength, StringcontentType, StringkeyName);

 

 

 

    Stream<Path> loadAll();

 

 

 

    Pathload(StringkeyName);

 

 

 

    ResourceloadAsResource(StringkeyName);

 

 

 

    voiddelete(StringkeyName);

 

 

 

    StringgenerateUrl(StringkeyName);

 

}

 

物流查詢服務

 

/**

 

 * 物流查詢服務

 

 *

 

 * 快遞鳥即時查詢API http://www.kdniao.com/api-track

 

 */

 

public class ExpressService {

 

    //請求url

 

    private String ReqURL = "http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";

 

 

 

    private ExpressProperties properties;

 

 

 

    public ExpressProperties getProperties() {

 

        return properties;

 

    }

 

 

 

    public void setProperties(ExpressProperties properties) {

 

        this.properties = properties;

 

    }

 

 

 

    /**

 

     * 獲取物流供應商名

 

     *

 

     * @param vendorCode

 

     * @return

 

     */

 

    public String getVendorName(String vendorCode) {

 

        for (Map<String, String> item : properties.getVendors()) {

 

            if (item.get("code").equals(vendorCode))

 

                return item.get("name");

 

        }

 

        return null;

 

    }

 

 

 

    /**

 

     * 獲取物流信息

 

     *

 

     * @param expCode

 

     * @param expNo

 

     * @return

 

     */

 

    public ExpressInfo getExpressInfo(String expCode, String expNo) {

 

        try {

 

            String result = getOrderTracesByJson(expCode, expNo);

 

            ObjectMapper objMap = new ObjectMapper();

 

            ExpressInfo ei = objMap.readValue(result, ExpressInfo.class);

 

            ei.setShipperName(getVendorName(expCode));

 

            return ei;

 

        } catch (Exception e) {

 

            e.printStackTrace();

 

        }

 

 

 

        return null;

 

    }

 

 

 

    /**

 

     * Json方式 查詢訂單物流軌跡

 

     *

 

     * @throws Exception

 

     */

 

    private String getOrderTracesByJson(String expCode, String expNo) throws Exception {

 

        if (!properties.isEnable()) {

 

            return null;

 

        }

 

 

 

        String requestData = "{'OrderCode':'','ShipperCode':'" + expCode + "','LogisticCode':'" + expNo + "'}";

 

 

 

        Map<String, String> params = new HashMap<String, String>();

 

        params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));

 

        params.put("EBusinessID", properties.getAppId());

 

        params.put("RequestType", "1002");

 

        String dataSign = encrypt(requestData, properties.getAppKey(), "UTF-8");

 

        params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));

 

        params.put("DataType", "2");

 

 

 

        String result = HttpUtil.sendPost(ReqURL, params);

 

 

 

        //根據公司業務處理返回的信息......

 

 

 

        return result;

 

    }

 

 

 

    /**

 

     * MD5加密

 

     *

 

     * @param str     內容

 

     * @param charset 編碼方式

 

     * @throws Exception

 

     */

 

    private String MD5(String str, String charset) throws Exception {

 

        MessageDigest md = MessageDigest.getInstance("MD5");

 

        md.update(str.getBytes(charset));

 

        byte[] result = md.digest();

 

        StringBuffer sb = new StringBuffer(32);

 

        for (int i = 0; i < result.length; i++) {

 

            int val = result[i] & 0xff;

 

            if (val <= 0xf) {

 

                sb.append("0");

 

            }

 

            sb.append(Integer.toHexString(val));

 

        }

 

        return sb.toString().toLowerCase();

 

    }

 

 

 

    /**

 

     * Sign簽名生成

 

     *

 

     * @param content  內容

 

     * @param keyValue Appkey

 

     * @param charset  編碼方式

 

     * @return DataSign簽名

 

     */

 

    private String encrypt(String content, String keyValue, String charset) {

 

        if (keyValue != null) {

 

            content = content + keyValue;

 

        }

 

        byte[] src = new byte[0];

 

        try {

 

            src = MD5(content, charset).getBytes(charset);

 

            return Base64Utils.encodeToString(src);

 

        } catch (Exception e) {

 

            e.printStackTrace();

 

        }

 

 

 

        return null;

 

    } 

 

}

 

 

迷你商城後端管理

     應用程序主函數接口

@SpringBootApplication(scanBasePackages = {"org.linlinjava.litemall.db", "org.linlinjava.litemall.core", "org.linlinjava.litemall.admin"})

@MapperScan("org.linlinjava.litemall.db.dao")

@EnableTransactionManagement

@EnableScheduling

public class Application {

 

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);

    }

 

}

     優惠卷管理

/**

 * 檢測優惠券過時狀況

 */

@Component

public class CouponJob {

    private final Log logger = LogFactory.getLog(CouponJob.class);

 

    @Autowired

    private LitemallCouponService couponService;

    @Autowired

    private LitemallCouponUserService couponUserService;

 

    /**

     * 每隔一個小時檢查

     * TODO

     * 注意,由於是相隔一個小時檢查,所以致使優惠券真正超時時間可能比設定時間延遲1個小時

     */

    @Scheduled(fixedDelay = 60 * 60 * 1000)

    public void checkCouponExpired() {

        logger.info("系統開啓任務檢查優惠券是否已通過期");

 

        List<LitemallCoupon> couponList = couponService.queryExpired();

        for(LitemallCoupon coupon : couponList){

            coupon.setStatus(CouponConstant.STATUS_EXPIRED);

            couponService.updateById(coupon);

        }

 

        List<LitemallCouponUser> couponUserList = couponUserService.queryExpired();

        for(LitemallCouponUser couponUser : couponUserList){

            couponUser.setStatus(CouponUserConstant.STATUS_EXPIRED);

            couponUserService.update(couponUser);

        }

    }

 

}

訂單管理

/**

 * 檢測訂單狀態

 */

@Component

public class OrderJob {

    private final Log logger = LogFactory.getLog(OrderJob.class);

 

    @Autowired

    private LitemallOrderGoodsService orderGoodsService;

    @Autowired

    private LitemallOrderService orderService;

    @Autowired

    private LitemallGoodsProductService productService;

 

    /**

     * 自動取消訂單

     * <p>

     * 定時檢查訂單未付款狀況,若是超時 LITEMALL_ORDER_UNPAID 分鐘則自動取消訂單

     * 定時時間是每次相隔半個小時。

     * <p>

     * TODO

     * 注意,由於是相隔半小時檢查,所以致使訂單真正超時時間是 [LITEMALL_ORDER_UNPAID, 30 + LITEMALL_ORDER_UNPAID]

     */

    @Scheduled(fixedDelay = 30 * 60 * 1000)

    @Transactional

    public void checkOrderUnpaid() {

        logger.info("系統開啓任務檢查訂單是否已經超期自動取消訂單");

 

        List<LitemallOrder> orderList = orderService.queryUnpaid(SystemConfig.getOrderUnpaid());

        for (LitemallOrder order : orderList) {

            // 設置訂單已取消狀態

            order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);

            order.setEndTime(LocalDateTime.now());

            if (orderService.updateWithOptimisticLocker(order) == 0) {

                throw new RuntimeException("更新數據已失效");

            }

 

            // 商品貨品數量增長

            Integer orderId = order.getId();

            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);

            for (LitemallOrderGoods orderGoods : orderGoodsList) {

                Integer productId = orderGoods.getProductId();

                Short number = orderGoods.getNumber();

                if (productService.addStock(productId, number) == 0) {

                    throw new RuntimeException("商品貨品庫存增長失敗");

                }

            }

            logger.info("訂單 ID=" + order.getId() + " 已經超期自動取消訂單");

        }

    }

 

    /**

     * 自動確認訂單

     * <p>

     * 定時檢查訂單未確認狀況,若是超時 LITEMALL_ORDER_UNCONFIRM 天則自動確認訂單

     * 定時時間是天天凌晨3點。

     * <p>

     * TODO

     * 注意,由於是相隔一天檢查,所以致使訂單真正超時時間是 [LITEMALL_ORDER_UNCONFIRM, 1 + LITEMALL_ORDER_UNCONFIRM]

     */

    @Scheduled(cron = "0 0 3 * * ?")

    public void checkOrderUnconfirm() {

        logger.info("系統開啓任務檢查訂單是否已經超期自動確認收貨");

 

        List<LitemallOrder> orderList = orderService.queryUnconfirm(SystemConfig.getOrderUnconfirm());

        for (LitemallOrder order : orderList) {

 

            // 設置訂單已取消狀態

            order.setOrderStatus(OrderUtil.STATUS_AUTO_CONFIRM);

            order.setConfirmTime(LocalDateTime.now());

            if (orderService.updateWithOptimisticLocker(order) == 0) {

                logger.info("訂單 ID=" + order.getId() + " 數據已經更新,放棄自動確認收貨");

            } else {

                logger.info("訂單 ID=" + order.getId() + " 已經超期自動確認收貨");

            }

        }

    }

 

    /**

     * 可評價訂單商品超期

     * <p>

     * 定時檢查訂單商品評價狀況,若是確認商品超時 LITEMALL_ORDER_COMMENT 天則取消可評價狀態

     * 定時時間是天天凌晨4點。

     * <p>

     * TODO

     * 注意,由於是相隔一天檢查,所以致使訂單真正超時時間是 [LITEMALL_ORDER_COMMENT, 1 + LITEMALL_ORDER_COMMENT]

     */

    @Scheduled(cron = "0 0 4 * * ?")

    public void checkOrderComment() {

        logger.info("系統開啓任務檢查訂單是否已經超期未評價");

 

        LocalDateTime now = LocalDateTime.now();

        List<LitemallOrder> orderList = orderService.queryComment(SystemConfig.getOrderComment());

        for (LitemallOrder order : orderList) {

            order.setComments((short) 0);

            orderService.updateWithOptimisticLocker(order);

 

            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());

            for (LitemallOrderGoods orderGoods : orderGoodsList) {

                orderGoods.setComment(-1);

                orderGoodsService.updateById(orderGoods);

            }

        }

    }

}

上架商品管理服務

@Service

public class AdminGoodsService {

    private final Log logger = LogFactory.getLog(AdminGoodsService.class);

 

    @Autowired

    private LitemallGoodsService goodsService;

    @Autowired

    private LitemallGoodsSpecificationService specificationService;

    @Autowired

    private LitemallGoodsAttributeService attributeService;

    @Autowired

    private LitemallGoodsProductService productService;

    @Autowired

    private LitemallCategoryService categoryService;

    @Autowired

    private LitemallBrandService brandService;

    @Autowired

    private LitemallCartService cartService;

    @Autowired

    private LitemallOrderGoodsService orderGoodsService;

 

    @Autowired

    private QCodeService qCodeService;

 

    public Object list(String goodsSn, String name,

                       Integer page, Integer limit, String sort, String order) {

        List<LitemallGoods> goodsList = goodsService.querySelective(goodsSn, name, page, limit, sort, order);

        return ResponseUtil.okList(goodsList);

    }

 

    private Object validate(GoodsAllinone goodsAllinone) {

        LitemallGoods goods = goodsAllinone.getGoods();

        String name = goods.getName();

        if (StringUtils.isEmpty(name)) {

            return ResponseUtil.badArgument();

        }

        String goodsSn = goods.getGoodsSn();

        if (StringUtils.isEmpty(goodsSn)) {

            return ResponseUtil.badArgument();

        }

        // 品牌商能夠不設置,若是設置則須要驗證品牌商存在

        Integer brandId = goods.getBrandId();

        if (brandId != null && brandId != 0) {

            if (brandService.findById(brandId) == null) {

                return ResponseUtil.badArgumentValue();

            }

        }

        // 分類能夠不設置,若是設置則須要驗證分類存在

        Integer categoryId = goods.getCategoryId();

        if (categoryId != null && categoryId != 0) {

            if (categoryService.findById(categoryId) == null) {

                return ResponseUtil.badArgumentValue();

            }

        }

 

        LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

        for (LitemallGoodsAttribute attribute : attributes) {

            String attr = attribute.getAttribute();

            if (StringUtils.isEmpty(attr)) {

                return ResponseUtil.badArgument();

            }

            String value = attribute.getValue();

            if (StringUtils.isEmpty(value)) {

                return ResponseUtil.badArgument();

            }

        }

 

        LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

        for (LitemallGoodsSpecification specification : specifications) {

            String spec = specification.getSpecification();

            if (StringUtils.isEmpty(spec)) {

                return ResponseUtil.badArgument();

            }

            String value = specification.getValue();

            if (StringUtils.isEmpty(value)) {

                return ResponseUtil.badArgument();

            }

        }

 

        LitemallGoodsProduct[] products = goodsAllinone.getProducts();

        for (LitemallGoodsProduct product : products) {

            Integer number = product.getNumber();

            if (number == null || number < 0) {

                return ResponseUtil.badArgument();

            }

 

            BigDecimal price = product.getPrice();

            if (price == null) {

                return ResponseUtil.badArgument();

            }

 

            String[] productSpecifications = product.getSpecifications();

            if (productSpecifications.length == 0) {

                return ResponseUtil.badArgument();

            }

        }

 

        return null;

    }

 

    /**

     * 編輯商品

     * <p>

     * TODO

     * 目前商品修改的邏輯是

     * 1. 更新litemall_goods

     * 2. 邏輯刪除litemall_goods_specificationlitemall_goods_attributelitemall_goods_product

     * 3. 添加litemall_goods_specificationlitemall_goods_attributelitemall_goods_product

     * <p>

     * 這裏商品三個表的數據採用刪除再添加的策略是由於

     * 商品編輯頁面,支持管理員添加刪除商品規格、添加刪除商品屬性,所以這裏僅僅更新是不可能的,

     * 只能刪除三個表舊的數據,而後添加新的數據。

     * 可是這裏又會引入新的問題,就是存在訂單商品貨品ID指向了失效的商品貨品表。

     * 所以這裏會拒絕管理員編輯商品,若是訂單或購物車中存在商品。

     * 因此這裏可能須要從新設計。

     */

    @Transactional

    public Object update(GoodsAllinone goodsAllinone) {

        Object error = validate(goodsAllinone);

        if (error != null) {

            return error;

        }

 

        LitemallGoods goods = goodsAllinone.getGoods();

        LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

        LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

        LitemallGoodsProduct[] products = goodsAllinone.getProducts();

 

        Integer id = goods.getId();

 

        //將生成的分享圖片地址寫入數據庫

        String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

        goods.setShareUrl(url);

 

        // 商品基本信息表litemall_goods

        if (goodsService.updateById(goods) == 0) {

            throw new RuntimeException("更新數據失敗");

        }

 

        Integer gid = goods.getId();

        specificationService.deleteByGid(gid);

        attributeService.deleteByGid(gid);

        productService.deleteByGid(gid);

 

        // 商品規格表litemall_goods_specification

        for (LitemallGoodsSpecification specification : specifications) {

            specification.setGoodsId(goods.getId());

            specificationService.add(specification);

        }

 

        // 商品參數表litemall_goods_attribute

        for (LitemallGoodsAttribute attribute : attributes) {

            attribute.setGoodsId(goods.getId());

            attributeService.add(attribute);

        }

 

        // 商品貨品表litemall_product

        for (LitemallGoodsProduct product : products) {

            product.setGoodsId(goods.getId());

            productService.add(product);

        }

 

        return ResponseUtil.ok();

    }

 

    @Transactional

    public Object delete(LitemallGoods goods) {

        Integer id = goods.getId();

        if (id == null) {

            return ResponseUtil.badArgument();

        }

 

        Integer gid = goods.getId();

        goodsService.deleteById(gid);

        specificationService.deleteByGid(gid);

        attributeService.deleteByGid(gid);

        productService.deleteByGid(gid);

        return ResponseUtil.ok();

    }

 

    @Transactional

    public Object create(GoodsAllinone goodsAllinone) {

        Object error = validate(goodsAllinone);

        if (error != null) {

            return error;

        }

 

        LitemallGoods goods = goodsAllinone.getGoods();

        LitemallGoodsAttribute[] attributes = goodsAllinone.getAttributes();

        LitemallGoodsSpecification[] specifications = goodsAllinone.getSpecifications();

        LitemallGoodsProduct[] products = goodsAllinone.getProducts();

 

        String name = goods.getName();

        if (goodsService.checkExistByName(name)) {

            return ResponseUtil.fail(GOODS_NAME_EXIST, "商品名已經存在");

        }

 

        // 商品基本信息表litemall_goods

        goodsService.add(goods);

 

        //將生成的分享圖片地址寫入數據庫

        String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

        if (!StringUtils.isEmpty(url)) {

            goods.setShareUrl(url);

            if (goodsService.updateById(goods) == 0) {

                throw new RuntimeException("更新數據失敗");

            }

        }

 

        // 商品規格表litemall_goods_specification

        for (LitemallGoodsSpecification specification : specifications) {

            specification.setGoodsId(goods.getId());

            specificationService.add(specification);

        }

 

        // 商品參數表litemall_goods_attribute

        for (LitemallGoodsAttribute attribute : attributes) {

            attribute.setGoodsId(goods.getId());

            attributeService.add(attribute);

        }

 

        // 商品貨品表litemall_product

        for (LitemallGoodsProduct product : products) {

            product.setGoodsId(goods.getId());

            productService.add(product);

        }

        return ResponseUtil.ok();

    }

 

    public Object list2() {

        // http://element-cn.eleme.io/#/zh-CN/component/cascader

        // 管理員設置所屬分類

        List<LitemallCategory> l1CatList = categoryService.queryL1();

        List<CatVo> categoryList = new ArrayList<>(l1CatList.size());

 

        for (LitemallCategory l1 : l1CatList) {

            CatVo l1CatVo = new CatVo();

            l1CatVo.setValue(l1.getId());

            l1CatVo.setLabel(l1.getName());

 

            List<LitemallCategory> l2CatList = categoryService.queryByPid(l1.getId());

            List<CatVo> children = new ArrayList<>(l2CatList.size());

            for (LitemallCategory l2 : l2CatList) {

                CatVo l2CatVo = new CatVo();

                l2CatVo.setValue(l2.getId());

                l2CatVo.setLabel(l2.getName());

                children.add(l2CatVo);

            }

            l1CatVo.setChildren(children);

 

            categoryList.add(l1CatVo);

        }

 

        // http://element-cn.eleme.io/#/zh-CN/component/select

        // 管理員設置所屬品牌商

        List<LitemallBrand> list = brandService.all();

        List<Map<String, Object>> brandList = new ArrayList<>(l1CatList.size());

        for (LitemallBrand brand : list) {

            Map<String, Object> b = new HashMap<>(2);

            b.put("value", brand.getId());

            b.put("label", brand.getName());

            brandList.add(b);

        }

 

        Map<String, Object> data = new HashMap<>();

        data.put("categoryList", categoryList);

        data.put("brandList", brandList);

        return ResponseUtil.ok(data);

    }

 

    public Object detail(Integer id) {

        LitemallGoods goods = goodsService.findById(id);

        List<LitemallGoodsProduct> products = productService.queryByGid(id);

        List<LitemallGoodsSpecification> specifications = specificationService.queryByGid(id);

        List<LitemallGoodsAttribute> attributes = attributeService.queryByGid(id);

 

        Integer categoryId = goods.getCategoryId();

        LitemallCategory category = categoryService.findById(categoryId);

        Integer[] categoryIds = new Integer[]{};

        if (category != null) {

            Integer parentCategoryId = category.getPid();

            categoryIds = new Integer[]{parentCategoryId, categoryId};

        }

 

        Map<String, Object> data = new HashMap<>();

        data.put("goods", goods);

        data.put("specifications", specifications);

        data.put("products", products);

        data.put("attributes", attributes);

        data.put("categoryIds", categoryIds);

 

        return ResponseUtil.ok(data);

    }

 

}

訂單管理服務

@Service

 

public class AdminOrderService {

    private final Log logger = LogFactory.getLog(AdminOrderService.class);

 

    @Autowired

    private LitemallOrderGoodsService orderGoodsService;

    @Autowired

    private LitemallOrderService orderService;

    @Autowired

    private LitemallGoodsProductService productService;

    @Autowired

    private LitemallUserService userService;

    @Autowired

    private LitemallCommentService commentService;

    @Autowired

    private WxPayService wxPayService;

    @Autowired

    private NotifyService notifyService;

    @Autowired

    private LogHelper logHelper;

 

    public Object list(Integer userId, String orderSn, List<Short> orderStatusArray,

                       Integer page, Integer limit, String sort, String order) {

        List<LitemallOrder> orderList = orderService.querySelective(userId, orderSn, orderStatusArray, page, limit, sort, order);

        return ResponseUtil.okList(orderList);

    }

 

    public Object detail(Integer id) {

        LitemallOrder order = orderService.findById(id);

        List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(id);

        UserVo user = userService.findUserVoById(order.getUserId());

        Map<String, Object> data = new HashMap<>();

        data.put("order", order);

        data.put("orderGoods", orderGoods);

        data.put("user", user);

 

        return ResponseUtil.ok(data);

    }

 

    /**

     * 訂單退款

     * <p>

     * 1. 檢測當前訂單是否可以退款;

     * 2. 微信退款操做;

     * 3. 設置訂單退款確認狀態;

     * 4. 訂單商品庫存回庫。

     * <p>

     * TODO

     * 雖然接入了微信退款API,可是從安全角度考慮,建議開發者刪除這裏微信退款代碼,採用如下兩步走步驟:

     * 1. 管理員登陸微信官方支付平臺點擊退款操做進行退款

     * 2. 管理員登陸litemall管理後臺點擊退款操做進行訂單狀態修改和商品庫存回庫

     *

     * @param body 訂單信息,{ orderIdxxx }

     * @return 訂單退款操做結果

     */

    @Transactional

    public Object refund(String body) {

        Integer orderId = JacksonUtil.parseInteger(body, "orderId");

        String refundMoney = JacksonUtil.parseString(body, "refundMoney");

        if (orderId == null) {

            return ResponseUtil.badArgument();

        }

        if (StringUtils.isEmpty(refundMoney)) {

            return ResponseUtil.badArgument();

        }

 

        LitemallOrder order = orderService.findById(orderId);

        if (order == null) {

            return ResponseUtil.badArgument();

        }

 

        if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {

            return ResponseUtil.badArgumentValue();

        }

 

        // 若是訂單不是退款狀態,則不能退款

        if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {

            return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "訂單不能確認收貨");

        }

 

        // 微信退款

        WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();

        wxPayRefundRequest.setOutTradeNo(order.getOrderSn());

        wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());

        // 元轉成分

        Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();

        wxPayRefundRequest.setTotalFee(totalFee);

        wxPayRefundRequest.setRefundFee(totalFee);

 

        WxPayRefundResult wxPayRefundResult = null;

        try {

            wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);

        } catch (WxPayException e) {

            e.printStackTrace();

            return ResponseUtil.fail(ORDER_REFUND_FAILED, "訂單退款失敗");

        }

        if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {

            logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());

            return ResponseUtil.fail(ORDER_REFUND_FAILED, "訂單退款失敗");

        }

        if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {

            logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());

            return ResponseUtil.fail(ORDER_REFUND_FAILED, "訂單退款失敗");

        }

 

        // 設置訂單取消狀態

        order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);

        if (orderService.updateWithOptimisticLocker(order) == 0) {

            throw new RuntimeException("更新數據已失效");

        }

 

        // 商品貨品數量增長

        List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);

        for (LitemallOrderGoods orderGoods : orderGoodsList) {

            Integer productId = orderGoods.getProductId();

            Short number = orderGoods.getNumber();

            if (productService.addStock(productId, number) == 0) {

                throw new RuntimeException("商品貨品庫存增長失敗");

            }

        }

 

        //TODO 發送郵件和短信通知,這裏採用異步發送

        // 退款成功通知用戶, 例如您申請的訂單退款 [ 單號:{1} ] 已成功,請耐心等待到帳。

        // 注意訂單號只發後6

        notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});

 

        logHelper.logOrderSucceed("退款", "訂單編號 " + orderId);

        return ResponseUtil.ok();

    }

 

    /**

     * 發貨

     * 1. 檢測當前訂單是否可以發貨

     * 2. 設置訂單發貨狀態

     *

     * @param body 訂單信息,{ orderIdxxx, shipSn: xxx, shipChannel: xxx }

     * @return 訂單操做結果

     * 成功則 { errno: 0, errmsg: '成功' }

     * 失敗則 { errno: XXX, errmsg: XXX }

     */

    public Object ship(String body) {

        Integer orderId = JacksonUtil.parseInteger(body, "orderId");

        String shipSn = JacksonUtil.parseString(body, "shipSn");

        String shipChannel = JacksonUtil.parseString(body, "shipChannel");

        if (orderId == null || shipSn == null || shipChannel == null) {

            return ResponseUtil.badArgument();

        }

 

        LitemallOrder order = orderService.findById(orderId);

        if (order == null) {

            return ResponseUtil.badArgument();

        }

 

        // 若是訂單不是已付款狀態,則不能發貨

        if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {

            return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "訂單不能確認收貨");

        }

 

        order.setOrderStatus(OrderUtil.STATUS_SHIP);

        order.setShipSn(shipSn);

        order.setShipChannel(shipChannel);

        order.setShipTime(LocalDateTime.now());

        if (orderService.updateWithOptimisticLocker(order) == 0) {

            return ResponseUtil.updatedDateExpired();

        }

 

        //TODO 發送郵件和短信通知,這裏採用異步發送

        // 發貨會發送通知短信給用戶:          *

        // "您的訂單已經發貨,快遞公司 {1},快遞單 {2} ,請注意查收"

        notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[]{shipChannel, shipSn});

 

        logHelper.logOrderSucceed("發貨", "訂單編號 " + orderId);

        return ResponseUtil.ok();

    }

 

 

    /**

     * 回覆訂單商品

     *

     * @param body 訂單信息,{ orderIdxxx }

     * @return 訂單操做結果

     * 成功則 { errno: 0, errmsg: '成功' }

     * 失敗則 { errno: XXX, errmsg: XXX }

     */

    public Object reply(String body) {

        Integer commentId = JacksonUtil.parseInteger(body, "commentId");

        if (commentId == null || commentId == 0) {

            return ResponseUtil.badArgument();

        }

        // 目前只支持回覆一次

        if (commentService.findById(commentId) != null) {

            return ResponseUtil.fail(ORDER_REPLY_EXIST, "訂單商品已回覆!");

        }

        String content = JacksonUtil.parseString(body, "content");

        if (StringUtils.isEmpty(content)) {

            return ResponseUtil.badArgument();

        }

        // 建立評價回覆

        LitemallComment comment = new LitemallComment();

        comment.setType((byte) 2);

        comment.setValueId(commentId);

        comment.setContent(content);

        comment.setUserId(0);                 // 評價回覆沒有用

        comment.setStar((short) 0);           // 評價回覆沒有用

        comment.setHasPicture(false);        // 評價回覆沒有用

        comment.setPicUrls(new String[]{});  // 評價回覆沒有用

        commentService.save(comment);

 

        return ResponseUtil.ok();

    }

 

}

操做日誌管理服務

/**

 * 這裏的日誌類型設計成四種(固然開發者須要能夠本身擴展)

 * 通常日誌:用戶以爲須要查看的通常操做日誌,建議是默認的日誌級別

 * 安全日誌:用戶安全相關的操做日誌,例如登陸、刪除管理員

 * 訂單日誌:用戶交易相關的操做日誌,例如訂單發貨、退款

 * 其餘日誌:若是以上三種不合適,能夠選擇其餘日誌,建議是優先級最低的日誌級別

 *

 * 固然可能不少操做是不須要記錄到數據庫的,例如編輯商品、編輯廣告品之類。

 */

@Component

public class LogHelper {

    public final static Integer LOG_TYPE_GENERAL = 0;

    public final static Integer LOG_TYPE_AUTH = 1;

    public final static Integer LOG_TYPE_ORDER = 2;

    public final static Integer LOG_TYPE_OTHER = 3;

 

    @Autowired

    private LitemallLogService logService;

 

    public void logGeneralSucceed(String action){

        logAdmin(LOG_TYPE_GENERAL, action, true, "", "");

    }

 

    public void logGeneralSucceed(String action, String result){

        logAdmin(LOG_TYPE_GENERAL, action, true, result, "");

    }

 

    public void logGeneralFail(String action, String error){

        logAdmin(LOG_TYPE_GENERAL, action, false, error, "");

    }

 

    public void logAuthSucceed(String action){

        logAdmin(LOG_TYPE_AUTH, action, true, "", "");

    }

 

    public void logAuthSucceed(String action, String result){

        logAdmin(LOG_TYPE_AUTH, action, true, result, "");

    }

 

    public void logAuthFail(String action, String error){

        logAdmin(LOG_TYPE_AUTH, action, false, error, "");

    }

 

    public void logOrderSucceed(String action){

        logAdmin(LOG_TYPE_ORDER, action, true, "", "");

    }

 

    public void logOrderSucceed(String action, String result){

        logAdmin(LOG_TYPE_ORDER, action, true, result, "");

    }

 

    public void logOrderFail(String action, String error){

        logAdmin(LOG_TYPE_ORDER, action, false, error, "");

    }

 

    public void logOtherSucceed(String action){

        logAdmin(LOG_TYPE_OTHER, action, true, "", "");

    }

 

    public void logOtherSucceed(String action, String result){

        logAdmin(LOG_TYPE_OTHER, action, true, result, "");

    }

 

 

    public void logOtherFail(String action, String error){

        logAdmin(LOG_TYPE_OTHER, action, false, error, "");

    }

 

    public void logAdmin (Integer type, String action, Boolean succeed, String result, String comment){

        LitemallLog log = new LitemallLog();

 

        Subject currentUser = SecurityUtils.getSubject();

        if(currentUser != null) {

            LitemallAdmin admin = (LitemallAdmin) currentUser.getPrincipal();

            if(admin != null) {

                log.setAdmin(admin.getUsername());

            }

            else{

                log.setAdmin("匿名用戶");

            }

        }

        else{

            log.setAdmin("匿名用戶");

        }

 

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        if(request != null) {

            log.setIp(IpUtil.getIpAddr(request));

        }

 

        log.setType(type);

        log.setAction(action);

        log.setStatus(succeed);

        log.setResult(result);

        log.setComment(comment);

        logService.add(log);

    }

 

}

     顧客(會員)身份認證

public class AdminAuthorizingRealm extends AuthorizingRealm {

 

    private static final Logger log = LoggerFactory.getLogger(AdminAuthorizingRealm.class);

    @Autowired

    private LitemallAdminService adminService;

    @Autowired

    private LitemallRoleService roleService;

    @Autowired

    private LitemallPermissionService permissionService;

 

    @Override

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        if (principals == null) {

            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");

        }

 

        LitemallAdmin admin = (LitemallAdmin) getAvailablePrincipal(principals);

        Integer[] roleIds = admin.getRoleIds();

        Set<String> roles = roleService.queryByIds(roleIds);

        Set<String> permissions = permissionService.queryByRoleIds(roleIds);

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        info.setRoles(roles);

        info.setStringPermissions(permissions);

        return info;

    }

 

    @Override

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

 

        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        String username = upToken.getUsername();

        String password=new String(upToken.getPassword());

 

        if (StringUtils.isEmpty(username)) {

            throw new AccountException("用戶名不能爲空");

        }

        if (StringUtils.isEmpty(password)) {

            throw new AccountException("密碼不能爲空");

        }

 

        List<LitemallAdmin> adminList = adminService.findAdmin(username);

        Assert.state(adminList.size() < 2, "同一個用戶名存在兩個帳戶");

        if (adminList.size() == 0) {

            throw new UnknownAccountException("找不到用戶("+username+")的賬號信息");

        }

        LitemallAdmin admin = adminList.get(0);

 

        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

        if (!encoder.matches(password, admin.getPassword())) {

            throw new UnknownAccountException("找不到用戶("+username+")的賬號信息");

        }

 

        return new SimpleAuthenticationInfo(admin,password,getName());

    }

 

}

廣告管理控制器

 

Ps:其餘控制器與此相似,不在一一冗贅

 

@RestController

@RequestMapping("/admin/ad")

@Validated

public class AdminAdController {

    private final Log logger = LogFactory.getLog(AdminAdController.class);

 

    @Autowired

    private LitemallAdService adService;

 

    @RequiresPermissions("admin:ad:list")

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="查詢")

    @GetMapping("/list")

    public Object list(String name, String content,

                       @RequestParam(defaultValue = "1") Integer page,

                       @RequestParam(defaultValue = "10") Integer limit,

                       @Sort @RequestParam(defaultValue = "add_time") String sort,

                       @Order @RequestParam(defaultValue = "desc") String order) {

        List<LitemallAd> adList = adService.querySelective(name, content, page, limit, sort, order);

        return ResponseUtil.okList(adList);

    }

 

    private Object validate(LitemallAd ad) {

        String name = ad.getName();

        if (StringUtils.isEmpty(name)) {

            return ResponseUtil.badArgument();

        }

        String content = ad.getContent();

        if (StringUtils.isEmpty(content)) {

            return ResponseUtil.badArgument();

        }

        return null;

    }

 

    @RequiresPermissions("admin:ad:create")

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="添加")

    @PostMapping("/create")

    public Object create(@RequestBody LitemallAd ad) {

        Object error = validate(ad);

        if (error != null) {

            return error;

        }

        adService.add(ad);

        return ResponseUtil.ok(ad);

    }

 

    @RequiresPermissions("admin:ad:read")

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="詳情")

    @GetMapping("/read")

    public Object read(@NotNull Integer id) {

        LitemallAd ad = adService.findById(id);

        return ResponseUtil.ok(ad);

    }

 

    @RequiresPermissions("admin:ad:update")

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="編輯")

    @PostMapping("/update")

    public Object update(@RequestBody LitemallAd ad) {

        Object error = validate(ad);

        if (error != null) {

            return error;

        }

        if (adService.updateById(ad) == 0) {

            return ResponseUtil.updatedDataFailed();

        }

 

        return ResponseUtil.ok(ad);

    }

 

    @RequiresPermissions("admin:ad:delete")

    @RequiresPermissionsDesc(menu={"推廣管理" , "廣告管理"}, button="刪除")

    @PostMapping("/delete")

    public Object delete(@RequestBody LitemallAd ad) {

        Integer id = ad.getId();

        if (id == null) {

            return ResponseUtil.badArgument();

        }

        adService.deleteById(id);

        return ResponseUtil.ok();

    }

 

}

     數據庫操做部分

Ps:其餘操做和對商品品牌數據庫表操做相似,再次不在冗贅。

商品品牌數據庫表操做

@Service

publicclassLitemallBrandService {

    @Resource

    privateLitemallBrandMapperbrandMapper;

    privateColumn[] columns = newColumn[]{Column.id, Column.name, Column.desc, Column.picUrl, Column.floorPrice};

 

    publicList<LitemallBrand> query(Integerpage, Integerlimit, Stringsort, Stringorder) {

        LitemallBrandExampleexample = newLitemallBrandExample();

        example.or().andDeletedEqualTo(false);

        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {

            example.setOrderByClause(sort + " " + order);

        }

        PageHelper.startPage(page, limit);

        returnbrandMapper.selectByExampleSelective(example, columns);

    }

 

    publicList<LitemallBrand> query(Integerpage, Integerlimit) {

        returnquery(page, limit, null, null);

    }

 

    publicLitemallBrandfindById(Integerid) {

        returnbrandMapper.selectByPrimaryKey(id);

    }

 

    publicList<LitemallBrand> querySelective(Stringid, Stringname, Integerpage, Integersize, Stringsort, Stringorder) {

        LitemallBrandExampleexample = newLitemallBrandExample();

        LitemallBrandExample.Criteriacriteria = example.createCriteria();

 

        if (!StringUtils.isEmpty(id)) {

            criteria.andIdEqualTo(Integer.valueOf(id));

        }

        if (!StringUtils.isEmpty(name)) {

            criteria.andNameLike("%" + name + "%");

        }

        criteria.andDeletedEqualTo(false);

 

        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {

            example.setOrderByClause(sort + " " + order);

        }

 

        PageHelper.startPage(page, size);

        returnbrandMapper.selectByExample(example);

    }

 

    publicintupdateById(LitemallBrandbrand) {

        brand.setUpdateTime(LocalDateTime.now());

        returnbrandMapper.updateByPrimaryKeySelective(brand);

    }

 

    publicvoiddeleteById(Integerid) {

        brandMapper.logicalDeleteByPrimaryKey(id);

    }

 

    publicvoidadd(LitemallBrandbrand) {

        brand.setAddTime(LocalDateTime.now());

        brand.setUpdateTime(LocalDateTime.now());

        brandMapper.insertSelective(brand);

    }

 

    publicList<LitemallBrand> all() {

        LitemallBrandExampleexample = newLitemallBrandExample();

        example.or().andDeletedEqualTo(false);

        returnbrandMapper.selectByExample(example);

    }

}

     核心操做部分

Ps:其餘核心操做同存儲(商品信息、圖片對象等)操做、物流查詢服務相似,不在冗贅。

存儲操做

/**

 * 對象存儲接口

 */

publicinterfaceStorage {

 

    /**

     * 存儲一個文件對象

     *

     * @paraminputStream   文件輸入流

     * @paramcontentLength文件長度

     * @paramcontentType   文件類型

     * @paramkeyName       文件名

     */

    voidstore(InputStreaminputStream, longcontentLength, StringcontentType, StringkeyName);

 

    Stream<Path> loadAll();

 

    Pathload(StringkeyName);

 

    ResourceloadAsResource(StringkeyName);

 

    voiddelete(StringkeyName);

 

    StringgenerateUrl(StringkeyName);

}

物流查詢服務

/**

 * 物流查詢服務

 *

 * 快遞鳥即時查詢API http://www.kdniao.com/api-track

 */

public class ExpressService {

    //請求url

    private String ReqURL = "http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";

 

    private ExpressProperties properties;

 

    public ExpressProperties getProperties() {

        return properties;

    }

 

    public void setProperties(ExpressProperties properties) {

        this.properties = properties;

    }

 

    /**

     * 獲取物流供應商名

     *

     * @param vendorCode

     * @return

     */

    public String getVendorName(String vendorCode) {

        for (Map<String, String> item : properties.getVendors()) {

            if (item.get("code").equals(vendorCode))

                return item.get("name");

        }

        return null;

    }

 

    /**

     * 獲取物流信息

     *

     * @param expCode

     * @param expNo

     * @return

     */

    public ExpressInfo getExpressInfo(String expCode, String expNo) {

        try {

            String result = getOrderTracesByJson(expCode, expNo);

            ObjectMapper objMap = new ObjectMapper();

            ExpressInfo ei = objMap.readValue(result, ExpressInfo.class);

            ei.setShipperName(getVendorName(expCode));

            return ei;

        } catch (Exception e) {

            e.printStackTrace();

        }

 

        return null;

    }

 

    /**

     * Json方式 查詢訂單物流軌跡

     *

     * @throws Exception

     */

    private String getOrderTracesByJson(String expCode, String expNo) throws Exception {

        if (!properties.isEnable()) {

            return null;

        }

 

        String requestData = "{'OrderCode':'','ShipperCode':'" + expCode + "','LogisticCode':'" + expNo + "'}";

 

        Map<String, String> params = new HashMap<String, String>();

        params.put("RequestData", URLEncoder.encode(requestData, "UTF-8"));

        params.put("EBusinessID", properties.getAppId());

        params.put("RequestType", "1002");

        String dataSign = encrypt(requestData, properties.getAppKey(), "UTF-8");

        params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));

        params.put("DataType", "2");

 

        String result = HttpUtil.sendPost(ReqURL, params);

 

        //根據公司業務處理返回的信息......

 

        return result;

    }

 

    /**

     * MD5加密

     *

     * @param str     內容

     * @param charset 編碼方式

     * @throws Exception

     */

    private String MD5(String str, String charset) throws Exception {

        MessageDigest md = MessageDigest.getInstance("MD5");

        md.update(str.getBytes(charset));

        byte[] result = md.digest();

        StringBuffer sb = new StringBuffer(32);

        for (int i = 0; i < result.length; i++) {

            int val = result[i] & 0xff;

            if (val <= 0xf) {

                sb.append("0");

            }

            sb.append(Integer.toHexString(val));

        }

        return sb.toString().toLowerCase();

    }

 

    /**

     * Sign簽名生成

     *

     * @param content  內容

     * @param keyValue Appkey

     * @param charset  編碼方式

     * @return DataSign簽名

     */

    private String encrypt(String content, String keyValue, String charset) {

        if (keyValue != null) {

            content = content + keyValue;

        }

        byte[] src = new byte[0];

        try {

            src = MD5(content, charset).getBytes(charset);

            return Base64Utils.encodeToString(src);

        } catch (Exception e) {

            e.printStackTrace();

        }

 

        return null;

    }

 

 

}

相關文章
相關標籤/搜索