chore[litemall-admin-api, litemall-wx-api]: 取消编程式事务管理,采用@Transactional注解事务管理
This commit is contained in:
@@ -5,15 +5,14 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.linlinjava.litemall.db.domain.LitemallGoodsProduct;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrder;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
|
||||
import org.linlinjava.litemall.db.service.*;
|
||||
import org.linlinjava.litemall.db.service.LitemallGoodsProductService;
|
||||
import org.linlinjava.litemall.db.service.LitemallOrderGoodsService;
|
||||
import org.linlinjava.litemall.db.service.LitemallOrderService;
|
||||
import org.linlinjava.litemall.db.util.OrderUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
@@ -25,9 +24,6 @@ import java.util.List;
|
||||
public class OrderJob {
|
||||
private final Log logger = LogFactory.getLog(OrderJob.class);
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager txManager;
|
||||
|
||||
@Autowired
|
||||
private LitemallOrderGoodsService orderGoodsService;
|
||||
@Autowired
|
||||
@@ -46,6 +42,7 @@ public class OrderJob {
|
||||
* 这里可以进一步地配合用户订单查询时订单未付款检查,如果订单超时半小时则取消。
|
||||
*/
|
||||
@Scheduled(fixedDelay = 30 * 60 * 1000)
|
||||
@Transactional
|
||||
public void checkOrderUnpaid() {
|
||||
logger.info("系统开启任务检查订单是否已经超期自动取消订单");
|
||||
|
||||
@@ -58,35 +55,24 @@ public class OrderJob {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 开启事务管理
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
TransactionStatus status = txManager.getTransaction(def);
|
||||
try {
|
||||
// 设置订单已取消状态
|
||||
order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);
|
||||
order.setEndTime(LocalDateTime.now());
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
throw new Exception("更新数据已失效");
|
||||
}
|
||||
|
||||
// 商品货品数量增加
|
||||
Integer orderId = order.getId();
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
|
||||
for (LitemallOrderGoods orderGoods : orderGoodsList) {
|
||||
Integer productId = orderGoods.getProductId();
|
||||
LitemallGoodsProduct product = productService.findById(productId);
|
||||
Short number = orderGoods.getNumber();
|
||||
if (productService.addStock(productId, number) == 0) {
|
||||
throw new Exception("商品货品库存增加失败");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
txManager.rollback(status);
|
||||
logger.info("订单 ID=" + order.getId() + " 数据更新失败,放弃自动确认收货");
|
||||
return;
|
||||
// 设置订单已取消状态
|
||||
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();
|
||||
LitemallGoodsProduct product = productService.findById(productId);
|
||||
Short number = orderGoods.getNumber();
|
||||
if (productService.addStock(productId, number) == 0) {
|
||||
throw new RuntimeException("商品货品库存增加失败");
|
||||
}
|
||||
}
|
||||
txManager.commit(status);
|
||||
logger.info("订单 ID=" + order.getId() + " 已经超期自动取消订单");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
package org.linlinjava.litemall.admin.service;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.linlinjava.litemall.admin.dao.GoodsAllinone;
|
||||
import org.linlinjava.litemall.admin.util.CatVo;
|
||||
import org.linlinjava.litemall.core.qcode.QCodeService;
|
||||
import org.linlinjava.litemall.core.util.ResponseUtil;
|
||||
import org.linlinjava.litemall.db.domain.*;
|
||||
import org.linlinjava.litemall.db.service.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.linlinjava.litemall.admin.util.AdminResponseCode.GOODS_NAME_EXIST;
|
||||
import static org.linlinjava.litemall.admin.util.AdminResponseCode.GOODS_UPDATE_NOT_ALLOWED;
|
||||
|
||||
@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);
|
||||
int total = goodsService.countSelective(goodsSn, name, page, limit, sort, order);
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("total", total);
|
||||
data.put("items", goodsList);
|
||||
|
||||
return ResponseUtil.ok(data);
|
||||
}
|
||||
|
||||
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_specification、litemall_goods_attribute、litemall_goods_product
|
||||
* 3. 添加litemall_goods_specification、litemall_goods_attribute、litemall_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();
|
||||
// 检查是否存在购物车商品或者订单商品
|
||||
// 如果存在则拒绝修改商品。
|
||||
if (orderGoodsService.checkExist(id)) {
|
||||
return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在订单中,不能修改");
|
||||
}
|
||||
if (cartService.checkExist(id)) {
|
||||
return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在购物车中,不能修改");
|
||||
}
|
||||
|
||||
//将生成的分享图片地址写入数据库
|
||||
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);
|
||||
}
|
||||
qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package org.linlinjava.litemall.admin.service;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.linlinjava.litemall.core.notify.NotifyService;
|
||||
import org.linlinjava.litemall.core.notify.NotifyType;
|
||||
import org.linlinjava.litemall.core.util.JacksonUtil;
|
||||
import org.linlinjava.litemall.core.util.ResponseUtil;
|
||||
import org.linlinjava.litemall.db.domain.LitemallComment;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrder;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
|
||||
import org.linlinjava.litemall.db.domain.UserVo;
|
||||
import org.linlinjava.litemall.db.service.*;
|
||||
import org.linlinjava.litemall.db.util.OrderUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.linlinjava.litemall.admin.util.AdminResponseCode.*;
|
||||
|
||||
@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;
|
||||
|
||||
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);
|
||||
int total = orderService.countSelective(userId, orderSn, orderStatusArray, page, limit, sort, order);
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("total", total);
|
||||
data.put("items", orderList);
|
||||
|
||||
return ResponseUtil.ok(data);
|
||||
}
|
||||
|
||||
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 订单信息,{ orderId:xxx }
|
||||
* @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)});
|
||||
|
||||
return ResponseUtil.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发货
|
||||
* 1. 检测当前订单是否能够发货
|
||||
* 2. 设置订单发货状态
|
||||
*
|
||||
* @param body 订单信息,{ orderId:xxx, 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});
|
||||
|
||||
return ResponseUtil.ok();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 回复订单商品
|
||||
*
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,31 +5,15 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc;
|
||||
import org.linlinjava.litemall.admin.dao.GoodsAllinone;
|
||||
import org.linlinjava.litemall.admin.util.CatVo;
|
||||
import org.linlinjava.litemall.core.qcode.QCodeService;
|
||||
import org.linlinjava.litemall.core.util.ResponseUtil;
|
||||
import org.linlinjava.litemall.admin.service.AdminGoodsService;
|
||||
import org.linlinjava.litemall.core.validator.Order;
|
||||
import org.linlinjava.litemall.core.validator.Sort;
|
||||
import org.linlinjava.litemall.db.domain.*;
|
||||
import org.linlinjava.litemall.db.service.*;
|
||||
import org.linlinjava.litemall.db.domain.LitemallGoods;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.linlinjava.litemall.admin.util.AdminResponseCode.GOODS_NAME_EXIST;
|
||||
import static org.linlinjava.litemall.admin.util.AdminResponseCode.GOODS_UPDATE_NOT_ALLOWED;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/admin/goods")
|
||||
@@ -38,366 +22,88 @@ public class AdminGoodsController {
|
||||
private final Log logger = LogFactory.getLog(AdminGoodsController.class);
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager txManager;
|
||||
|
||||
@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;
|
||||
private AdminGoodsService adminGoodsService;
|
||||
|
||||
/**
|
||||
* 查询商品
|
||||
*
|
||||
* @param goodsSn
|
||||
* @param name
|
||||
* @param page
|
||||
* @param limit
|
||||
* @param sort
|
||||
* @param order
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("admin:goods:list")
|
||||
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="查询")
|
||||
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "查询")
|
||||
@GetMapping("/list")
|
||||
public Object list(String goodsSn, String name,
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer limit,
|
||||
@Sort @RequestParam(defaultValue = "add_time") String sort,
|
||||
@Order @RequestParam(defaultValue = "desc") String order) {
|
||||
List<LitemallGoods> goodsList = goodsService.querySelective(goodsSn, name, page, limit, sort, order);
|
||||
int total = goodsService.countSelective(goodsSn, name, page, limit, sort, order);
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("total", total);
|
||||
data.put("items", goodsList);
|
||||
|
||||
return ResponseUtil.ok(data);
|
||||
}
|
||||
|
||||
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;
|
||||
return adminGoodsService.list(goodsSn, name, page, limit, sort, order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑商品
|
||||
* <p>
|
||||
* TODO
|
||||
* 目前商品修改的逻辑是
|
||||
* 1. 更新litemall_goods表
|
||||
* 2. 逻辑删除litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
|
||||
* 3. 添加litemall_goods_specification、litemall_goods_attribute、litemall_goods_product
|
||||
*
|
||||
* 这里商品三个表的数据采用删除再添加的策略是因为
|
||||
* 商品编辑页面,支持管理员添加删除商品规格、添加删除商品属性,因此这里仅仅更新是不可能的,
|
||||
* 只能删除三个表旧的数据,然后添加新的数据。
|
||||
* 但是这里又会引入新的问题,就是存在订单商品货品ID指向了失效的商品货品表。
|
||||
* 因此这里会拒绝管理员编辑商品,如果订单或购物车中存在商品。
|
||||
* 所以这里可能需要重新设计。
|
||||
* @param goodsAllinone
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("admin:goods:update")
|
||||
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="编辑")
|
||||
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "编辑")
|
||||
@PostMapping("/update")
|
||||
public Object update(@RequestBody 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();
|
||||
// 检查是否存在购物车商品或者订单商品
|
||||
// 如果存在则拒绝修改商品。
|
||||
if(orderGoodsService.checkExist(id)){
|
||||
return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在订单中,不能修改");
|
||||
}
|
||||
if(cartService.checkExist(id)){
|
||||
return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在购物车中,不能修改");
|
||||
}
|
||||
|
||||
// 开启事务管理
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
TransactionStatus status = txManager.getTransaction(def);
|
||||
try {
|
||||
|
||||
//将生成的分享图片地址写入数据库
|
||||
String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
|
||||
goods.setShareUrl(url);
|
||||
|
||||
// 商品基本信息表litemall_goods
|
||||
if (goodsService.updateById(goods) == 0) {
|
||||
throw new Exception("更新数据失败");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
txManager.rollback(status);
|
||||
logger.error("系统内部错误", ex);
|
||||
return ResponseUtil.fail();
|
||||
}
|
||||
txManager.commit(status);
|
||||
|
||||
qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
|
||||
|
||||
return ResponseUtil.ok();
|
||||
return adminGoodsService.update(goodsAllinone);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除商品
|
||||
*
|
||||
* @param goods
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("admin:goods:delete")
|
||||
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="删除")
|
||||
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "删除")
|
||||
@PostMapping("/delete")
|
||||
public Object delete(@RequestBody LitemallGoods goods) {
|
||||
Integer id = goods.getId();
|
||||
if (id == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
// 开启事务管理
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
TransactionStatus status = txManager.getTransaction(def);
|
||||
try {
|
||||
|
||||
Integer gid = goods.getId();
|
||||
goodsService.deleteById(gid);
|
||||
specificationService.deleteByGid(gid);
|
||||
attributeService.deleteByGid(gid);
|
||||
productService.deleteByGid(gid);
|
||||
} catch (Exception ex) {
|
||||
txManager.rollback(status);
|
||||
logger.error("系统内部错误", ex);
|
||||
return ResponseUtil.fail();
|
||||
}
|
||||
txManager.commit(status);
|
||||
return ResponseUtil.ok();
|
||||
return adminGoodsService.delete(goods);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加商品
|
||||
*
|
||||
* @param goodsAllinone
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("admin:goods:create")
|
||||
@RequiresPermissionsDesc(menu={"商品管理" , "商品上架"}, button="上架")
|
||||
@RequiresPermissionsDesc(menu = {"商品管理", "商品上架"}, button = "上架")
|
||||
@PostMapping("/create")
|
||||
public Object create(@RequestBody 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, "商品名已经存在");
|
||||
}
|
||||
|
||||
// 开启事务管理
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
TransactionStatus status = txManager.getTransaction(def);
|
||||
try {
|
||||
|
||||
// 商品基本信息表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 Exception("更新数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 商品规格表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);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
txManager.rollback(status);
|
||||
logger.error("系统内部错误", ex);
|
||||
return ResponseUtil.fail();
|
||||
}
|
||||
txManager.commit(status);
|
||||
|
||||
return ResponseUtil.ok();
|
||||
return adminGoodsService.create(goodsAllinone);
|
||||
}
|
||||
|
||||
@RequiresPermissions("admin:goods:list")
|
||||
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="查询")
|
||||
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "查询")
|
||||
@GetMapping("/catAndBrand")
|
||||
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);
|
||||
return adminGoodsService.list2();
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品详情
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("admin:goods:read")
|
||||
@RequiresPermissionsDesc(menu={"商品管理" , "商品列表"}, button="编辑")
|
||||
@RequiresPermissionsDesc(menu = {"商品管理", "商品列表"}, button = "编辑")
|
||||
@GetMapping("/detail")
|
||||
public Object detail(@NotNull 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);
|
||||
return adminGoodsService.detail(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,42 +1,18 @@
|
||||
package org.linlinjava.litemall.admin.web;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc;
|
||||
import org.linlinjava.litemall.core.notify.NotifyService;
|
||||
import org.linlinjava.litemall.core.notify.NotifyType;
|
||||
import org.linlinjava.litemall.core.util.JacksonUtil;
|
||||
import org.linlinjava.litemall.core.util.ResponseUtil;
|
||||
import org.linlinjava.litemall.admin.service.AdminOrderService;
|
||||
import org.linlinjava.litemall.core.validator.Order;
|
||||
import org.linlinjava.litemall.core.validator.Sort;
|
||||
import org.linlinjava.litemall.db.domain.LitemallComment;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrder;
|
||||
import org.linlinjava.litemall.db.domain.LitemallOrderGoods;
|
||||
import org.linlinjava.litemall.db.domain.UserVo;
|
||||
import org.linlinjava.litemall.db.service.*;
|
||||
import org.linlinjava.litemall.db.util.OrderUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.linlinjava.litemall.admin.util.AdminResponseCode.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/admin/order")
|
||||
@@ -45,25 +21,22 @@ public class AdminOrderController {
|
||||
private final Log logger = LogFactory.getLog(AdminOrderController.class);
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager txManager;
|
||||
|
||||
@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;
|
||||
private AdminOrderService adminOrderService;
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
*
|
||||
* @param userId
|
||||
* @param orderSn
|
||||
* @param orderStatusArray
|
||||
* @param page
|
||||
* @param limit
|
||||
* @param sort
|
||||
* @param order
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("admin:order:list")
|
||||
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="查询")
|
||||
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "查询")
|
||||
@GetMapping("/list")
|
||||
public Object list(Integer userId, String orderSn,
|
||||
@RequestParam(required = false) List<Short> orderStatusArray,
|
||||
@@ -71,218 +44,60 @@ public class AdminOrderController {
|
||||
@RequestParam(defaultValue = "10") Integer limit,
|
||||
@Sort @RequestParam(defaultValue = "add_time") String sort,
|
||||
@Order @RequestParam(defaultValue = "desc") String order) {
|
||||
List<LitemallOrder> orderList = orderService.querySelective(userId, orderSn, orderStatusArray, page, limit, sort, order);
|
||||
int total = orderService.countSelective(userId, orderSn, orderStatusArray, page, limit, sort, order);
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("total", total);
|
||||
data.put("items", orderList);
|
||||
|
||||
return ResponseUtil.ok(data);
|
||||
return adminOrderService.list(userId, orderSn, orderStatusArray, page, limit, sort, order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单详情
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("admin:order:read")
|
||||
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="详情")
|
||||
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "详情")
|
||||
@GetMapping("/detail")
|
||||
public Object detail(@NotNull 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);
|
||||
return adminOrderService.detail(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够退款;
|
||||
* 2. 微信退款操作;
|
||||
* 3. 设置订单退款确认状态;
|
||||
* 4. 订单商品库存回库。
|
||||
* <p>
|
||||
* TODO
|
||||
* 虽然接入了微信退款API,但是从安全角度考虑,建议开发者删除这里微信退款代码,采用以下两步走步骤:
|
||||
* 1. 管理员登录微信官方支付平台点击退款操作进行退款
|
||||
* 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库
|
||||
*
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @return 订单退款操作结果
|
||||
*/
|
||||
@RequiresPermissions("admin:order:refund")
|
||||
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="订单退款")
|
||||
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "订单退款")
|
||||
@PostMapping("refund")
|
||||
public Object refund(@RequestBody 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, "订单退款失败");
|
||||
}
|
||||
|
||||
// 开启事务管理
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
TransactionStatus status = txManager.getTransaction(def);
|
||||
try {
|
||||
// 设置订单取消状态
|
||||
order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
throw new Exception("更新数据已失效");
|
||||
}
|
||||
|
||||
// 商品货品数量增加
|
||||
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 Exception("商品货品库存增加失败");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
txManager.rollback(status);
|
||||
logger.error("系统内部错误", ex);
|
||||
return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
|
||||
}
|
||||
txManager.commit(status);
|
||||
|
||||
//TODO 发送邮件和短信通知,这里采用异步发送
|
||||
// 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功,请耐心等待到账。”
|
||||
// 注意订单号只发后6位
|
||||
notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});
|
||||
|
||||
return ResponseUtil.ok();
|
||||
return adminOrderService.refund(body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发货
|
||||
* 1. 检测当前订单是否能够发货
|
||||
* 2. 设置订单发货状态
|
||||
*
|
||||
* @param body 订单信息,{ orderId:xxx, shipSn: xxx, shipChannel: xxx }
|
||||
* @param body 订单信息,{ orderId:xxx, shipSn: xxx, shipChannel: xxx }
|
||||
* @return 订单操作结果
|
||||
* 成功则 { errno: 0, errmsg: '成功' }
|
||||
* 失败则 { errno: XXX, errmsg: XXX }
|
||||
*/
|
||||
@RequiresPermissions("admin:order:ship")
|
||||
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="订单发货")
|
||||
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "订单发货")
|
||||
@PostMapping("ship")
|
||||
public Object ship(@RequestBody 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});
|
||||
|
||||
return ResponseUtil.ok();
|
||||
return adminOrderService.ship(body);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 回复订单商品
|
||||
*
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @return 订单操作结果
|
||||
* 成功则 { errno: 0, errmsg: '成功' }
|
||||
* 失败则 { errno: XXX, errmsg: XXX }
|
||||
*/
|
||||
@RequiresPermissions("admin:order:reply")
|
||||
@RequiresPermissionsDesc(menu={"商城管理" , "订单管理"}, button="订单商品回复")
|
||||
@RequiresPermissionsDesc(menu = {"商城管理", "订单管理"}, button = "订单商品回复")
|
||||
@PostMapping("reply")
|
||||
public Object reply(@RequestBody 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();
|
||||
return adminOrderService.reply(body);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,928 @@
|
||||
package org.linlinjava.litemall.wx.service;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
||||
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
|
||||
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.linlinjava.litemall.core.express.ExpressService;
|
||||
import org.linlinjava.litemall.core.express.dao.ExpressInfo;
|
||||
import org.linlinjava.litemall.core.notify.NotifyService;
|
||||
import org.linlinjava.litemall.core.notify.NotifyType;
|
||||
import org.linlinjava.litemall.core.qcode.QCodeService;
|
||||
import org.linlinjava.litemall.core.system.SystemConfig;
|
||||
import org.linlinjava.litemall.core.util.DateTimeUtil;
|
||||
import org.linlinjava.litemall.core.util.JacksonUtil;
|
||||
import org.linlinjava.litemall.core.util.ResponseUtil;
|
||||
import org.linlinjava.litemall.db.domain.*;
|
||||
import org.linlinjava.litemall.db.service.*;
|
||||
import org.linlinjava.litemall.db.util.CouponUserConstant;
|
||||
import org.linlinjava.litemall.db.util.OrderHandleOption;
|
||||
import org.linlinjava.litemall.db.util.OrderUtil;
|
||||
import org.linlinjava.litemall.wx.annotation.LoginUser;
|
||||
import org.linlinjava.litemall.wx.util.IpUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.linlinjava.litemall.wx.util.WxResponseCode.*;
|
||||
|
||||
/**
|
||||
* 订单服务
|
||||
*
|
||||
* <p>
|
||||
* 订单状态:
|
||||
* 101 订单生成,未支付;102,下单后未支付用户取消;103,下单后未支付超时系统自动取消
|
||||
* 201 支付完成,商家未发货;202,订单生产,已付款未发货,但是退款取消;
|
||||
* 301 商家发货,用户未确认;
|
||||
* 401 用户确认收货; 402 用户没有确认收货超过一定时间,系统自动确认收货;
|
||||
*
|
||||
* <p>
|
||||
* 用户操作:
|
||||
* 当101用户未付款时,此时用户可以进行的操作是取消订单,或者付款操作
|
||||
* 当201支付完成而商家未发货时,此时用户可以取消订单并申请退款
|
||||
* 当301商家已发货时,此时用户可以有确认收货的操作
|
||||
* 当401用户确认收货以后,此时用户可以进行的操作是删除订单,评价商品,或者再次购买
|
||||
* 当402系统自动确认收货以后,此时用户可以删除订单,评价商品,或者再次购买
|
||||
*
|
||||
* <p>
|
||||
* 注意:目前不支持订单退货和售后服务
|
||||
*/
|
||||
@Service
|
||||
public class WxOrderService {
|
||||
private final Log logger = LogFactory.getLog(WxOrderService.class);
|
||||
|
||||
@Autowired
|
||||
private LitemallUserService userService;
|
||||
@Autowired
|
||||
private LitemallOrderService orderService;
|
||||
@Autowired
|
||||
private LitemallOrderGoodsService orderGoodsService;
|
||||
@Autowired
|
||||
private LitemallAddressService addressService;
|
||||
@Autowired
|
||||
private LitemallCartService cartService;
|
||||
@Autowired
|
||||
private LitemallRegionService regionService;
|
||||
@Autowired
|
||||
private LitemallGoodsProductService productService;
|
||||
@Autowired
|
||||
private WxPayService wxPayService;
|
||||
@Autowired
|
||||
private NotifyService notifyService;
|
||||
@Autowired
|
||||
private LitemallUserFormIdService formIdService;
|
||||
@Autowired
|
||||
private LitemallGrouponRulesService grouponRulesService;
|
||||
@Autowired
|
||||
private LitemallGrouponService grouponService;
|
||||
@Autowired
|
||||
private QCodeService qCodeService;
|
||||
@Autowired
|
||||
private ExpressService expressService;
|
||||
@Autowired
|
||||
private LitemallCommentService commentService;
|
||||
@Autowired
|
||||
private LitemallCouponService couponService;
|
||||
@Autowired
|
||||
private LitemallCouponUserService couponUserService;
|
||||
@Autowired
|
||||
private CouponVerifyService couponVerifyService;
|
||||
|
||||
private String detailedAddress(LitemallAddress litemallAddress) {
|
||||
Integer provinceId = litemallAddress.getProvinceId();
|
||||
Integer cityId = litemallAddress.getCityId();
|
||||
Integer areaId = litemallAddress.getAreaId();
|
||||
String provinceName = regionService.findById(provinceId).getName();
|
||||
String cityName = regionService.findById(cityId).getName();
|
||||
String areaName = regionService.findById(areaId).getName();
|
||||
String fullRegion = provinceName + " " + cityName + " " + areaName;
|
||||
return fullRegion + " " + litemallAddress.getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param showType 订单信息:
|
||||
* 0,全部订单;
|
||||
* 1,待付款;
|
||||
* 2,待发货;
|
||||
* 3,待收货;
|
||||
* 4,待评价。
|
||||
* @param page 分页页数
|
||||
* @param size 分页大小
|
||||
* @return 订单列表
|
||||
*/
|
||||
public Object list(Integer userId, Integer showType, Integer page, Integer size) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
List<Short> orderStatus = OrderUtil.orderStatus(showType);
|
||||
List<LitemallOrder> orderList = orderService.queryByOrderStatus(userId, orderStatus);
|
||||
int count = orderService.countByOrderStatus(userId, orderStatus);
|
||||
|
||||
List<Map<String, Object>> orderVoList = new ArrayList<>(orderList.size());
|
||||
for (LitemallOrder order : orderList) {
|
||||
Map<String, Object> orderVo = new HashMap<>();
|
||||
orderVo.put("id", order.getId());
|
||||
orderVo.put("orderSn", order.getOrderSn());
|
||||
orderVo.put("actualPrice", order.getActualPrice());
|
||||
orderVo.put("orderStatusText", OrderUtil.orderStatusText(order));
|
||||
orderVo.put("handleOption", OrderUtil.build(order));
|
||||
|
||||
LitemallGroupon groupon = grouponService.queryByOrderId(order.getId());
|
||||
if (groupon != null) {
|
||||
orderVo.put("isGroupin", true);
|
||||
} else {
|
||||
orderVo.put("isGroupin", false);
|
||||
}
|
||||
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
|
||||
List<Map<String, Object>> orderGoodsVoList = new ArrayList<>(orderGoodsList.size());
|
||||
for (LitemallOrderGoods orderGoods : orderGoodsList) {
|
||||
Map<String, Object> orderGoodsVo = new HashMap<>();
|
||||
orderGoodsVo.put("id", orderGoods.getId());
|
||||
orderGoodsVo.put("goodsName", orderGoods.getGoodsName());
|
||||
orderGoodsVo.put("number", orderGoods.getNumber());
|
||||
orderGoodsVo.put("picUrl", orderGoods.getPicUrl());
|
||||
orderGoodsVoList.add(orderGoodsVo);
|
||||
}
|
||||
orderVo.put("goodsList", orderGoodsVoList);
|
||||
|
||||
orderVoList.add(orderVo);
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("count", count);
|
||||
result.put("data", orderVoList);
|
||||
|
||||
return ResponseUtil.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单详情
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param orderId 订单ID
|
||||
* @return 订单详情
|
||||
*/
|
||||
public Object detail(Integer userId, Integer orderId) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
// 订单信息
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (null == order) {
|
||||
return ResponseUtil.fail(ORDER_UNKNOWN, "订单不存在");
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.fail(ORDER_INVALID, "不是当前用户的订单");
|
||||
}
|
||||
Map<String, Object> orderVo = new HashMap<String, Object>();
|
||||
orderVo.put("id", order.getId());
|
||||
orderVo.put("orderSn", order.getOrderSn());
|
||||
orderVo.put("addTime", order.getAddTime());
|
||||
orderVo.put("consignee", order.getConsignee());
|
||||
orderVo.put("mobile", order.getMobile());
|
||||
orderVo.put("address", order.getAddress());
|
||||
orderVo.put("goodsPrice", order.getGoodsPrice());
|
||||
orderVo.put("freightPrice", order.getFreightPrice());
|
||||
orderVo.put("actualPrice", order.getActualPrice());
|
||||
orderVo.put("orderStatusText", OrderUtil.orderStatusText(order));
|
||||
orderVo.put("handleOption", OrderUtil.build(order));
|
||||
orderVo.put("expCode", order.getShipChannel());
|
||||
orderVo.put("expNo", order.getShipSn());
|
||||
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("orderInfo", orderVo);
|
||||
result.put("orderGoods", orderGoodsList);
|
||||
|
||||
// 订单状态为已发货且物流信息不为空
|
||||
//"YTO", "800669400640887922"
|
||||
if (order.getOrderStatus().equals(OrderUtil.STATUS_SHIP)) {
|
||||
ExpressInfo ei = expressService.getExpressInfo(order.getShipChannel(), order.getShipSn());
|
||||
result.put("expressInfo", ei);
|
||||
}
|
||||
|
||||
return ResponseUtil.ok(result);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交订单
|
||||
* <p>
|
||||
* 1. 创建订单表项和订单商品表项;
|
||||
* 2. 购物车清空;
|
||||
* 3. 优惠券设置已用;
|
||||
* 4. 商品货品库存减少;
|
||||
* 5. 如果是团购商品,则创建团购活动表项。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ cartId:xxx, addressId: xxx, couponId: xxx, message: xxx, grouponRulesId: xxx, grouponLinkId: xxx}
|
||||
* @return 提交订单操作结果
|
||||
*/
|
||||
@Transactional
|
||||
public Object submit(Integer userId, String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
if (body == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
Integer cartId = JacksonUtil.parseInteger(body, "cartId");
|
||||
Integer addressId = JacksonUtil.parseInteger(body, "addressId");
|
||||
Integer couponId = JacksonUtil.parseInteger(body, "couponId");
|
||||
String message = JacksonUtil.parseString(body, "message");
|
||||
Integer grouponRulesId = JacksonUtil.parseInteger(body, "grouponRulesId");
|
||||
Integer grouponLinkId = JacksonUtil.parseInteger(body, "grouponLinkId");
|
||||
|
||||
//如果是团购项目,验证活动是否有效
|
||||
if (grouponRulesId != null && grouponRulesId > 0) {
|
||||
LitemallGrouponRules rules = grouponRulesService.queryById(grouponRulesId);
|
||||
//找不到记录
|
||||
if (rules == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
//团购活动已经过期
|
||||
if (grouponRulesService.isExpired(rules)) {
|
||||
return ResponseUtil.fail(GROUPON_EXPIRED, "团购活动已过期!");
|
||||
}
|
||||
}
|
||||
|
||||
if (cartId == null || addressId == null || couponId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
// 收货地址
|
||||
LitemallAddress checkedAddress = addressService.findById(addressId);
|
||||
if (checkedAddress == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
// 团购优惠
|
||||
BigDecimal grouponPrice = new BigDecimal(0.00);
|
||||
LitemallGrouponRules grouponRules = grouponRulesService.queryById(grouponRulesId);
|
||||
if (grouponRules != null) {
|
||||
grouponPrice = grouponRules.getDiscount();
|
||||
}
|
||||
|
||||
// 货品价格
|
||||
List<LitemallCart> checkedGoodsList = null;
|
||||
if (cartId.equals(0)) {
|
||||
checkedGoodsList = cartService.queryByUidAndChecked(userId);
|
||||
} else {
|
||||
LitemallCart cart = cartService.findById(cartId);
|
||||
checkedGoodsList = new ArrayList<>(1);
|
||||
checkedGoodsList.add(cart);
|
||||
}
|
||||
if (checkedGoodsList.size() == 0) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
BigDecimal checkedGoodsPrice = new BigDecimal(0.00);
|
||||
for (LitemallCart checkGoods : checkedGoodsList) {
|
||||
// 只有当团购规格商品ID符合才进行团购优惠
|
||||
if (grouponRules != null && grouponRules.getGoodsId().equals(checkGoods.getGoodsId())) {
|
||||
checkedGoodsPrice = checkedGoodsPrice.add(checkGoods.getPrice().subtract(grouponPrice).multiply(new BigDecimal(checkGoods.getNumber())));
|
||||
} else {
|
||||
checkedGoodsPrice = checkedGoodsPrice.add(checkGoods.getPrice().multiply(new BigDecimal(checkGoods.getNumber())));
|
||||
}
|
||||
}
|
||||
|
||||
// 获取可用的优惠券信息
|
||||
// 使用优惠券减免的金额
|
||||
BigDecimal couponPrice = new BigDecimal(0.00);
|
||||
// 如果couponId=0则没有优惠券,couponId=-1则不使用优惠券
|
||||
if(couponId != 0 && couponId != -1){
|
||||
LitemallCoupon coupon = couponVerifyService.checkCoupon(userId, couponId, checkedGoodsPrice);
|
||||
if(coupon == null){
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
couponPrice = coupon.getDiscount();
|
||||
}
|
||||
|
||||
|
||||
// 根据订单商品总价计算运费,满足条件(例如88元)则免运费,否则需要支付运费(例如8元);
|
||||
BigDecimal freightPrice = new BigDecimal(0.00);
|
||||
if (checkedGoodsPrice.compareTo(SystemConfig.getFreightLimit()) < 0) {
|
||||
freightPrice = SystemConfig.getFreight();
|
||||
}
|
||||
|
||||
// 可以使用的其他钱,例如用户积分
|
||||
BigDecimal integralPrice = new BigDecimal(0.00);
|
||||
|
||||
// 订单费用
|
||||
BigDecimal orderTotalPrice = checkedGoodsPrice.add(freightPrice).subtract(couponPrice);
|
||||
// 最终支付费用
|
||||
BigDecimal actualPrice = orderTotalPrice.subtract(integralPrice);
|
||||
|
||||
Integer orderId = null;
|
||||
LitemallOrder order = null;
|
||||
// 订单
|
||||
order = new LitemallOrder();
|
||||
order.setUserId(userId);
|
||||
order.setOrderSn(orderService.generateOrderSn(userId));
|
||||
order.setOrderStatus(OrderUtil.STATUS_CREATE);
|
||||
order.setConsignee(checkedAddress.getName());
|
||||
order.setMobile(checkedAddress.getMobile());
|
||||
order.setMessage(message);
|
||||
String detailedAddress = detailedAddress(checkedAddress);
|
||||
order.setAddress(detailedAddress);
|
||||
order.setGoodsPrice(checkedGoodsPrice);
|
||||
order.setFreightPrice(freightPrice);
|
||||
order.setCouponPrice(couponPrice);
|
||||
order.setIntegralPrice(integralPrice);
|
||||
order.setOrderPrice(orderTotalPrice);
|
||||
order.setActualPrice(actualPrice);
|
||||
|
||||
// 有团购活动
|
||||
if (grouponRules != null) {
|
||||
order.setGrouponPrice(grouponPrice); // 团购价格
|
||||
} else {
|
||||
order.setGrouponPrice(new BigDecimal(0.00)); // 团购价格
|
||||
}
|
||||
|
||||
// 添加订单表项
|
||||
orderService.add(order);
|
||||
orderId = order.getId();
|
||||
|
||||
// 添加订单商品表项
|
||||
for (LitemallCart cartGoods : checkedGoodsList) {
|
||||
// 订单商品
|
||||
LitemallOrderGoods orderGoods = new LitemallOrderGoods();
|
||||
orderGoods.setOrderId(order.getId());
|
||||
orderGoods.setGoodsId(cartGoods.getGoodsId());
|
||||
orderGoods.setGoodsSn(cartGoods.getGoodsSn());
|
||||
orderGoods.setProductId(cartGoods.getProductId());
|
||||
orderGoods.setGoodsName(cartGoods.getGoodsName());
|
||||
orderGoods.setPicUrl(cartGoods.getPicUrl());
|
||||
orderGoods.setPrice(cartGoods.getPrice());
|
||||
orderGoods.setNumber(cartGoods.getNumber());
|
||||
orderGoods.setSpecifications(cartGoods.getSpecifications());
|
||||
orderGoods.setAddTime(LocalDateTime.now());
|
||||
|
||||
orderGoodsService.add(orderGoods);
|
||||
}
|
||||
|
||||
// 删除购物车里面的商品信息
|
||||
cartService.clearGoods(userId);
|
||||
|
||||
// 商品货品数量减少
|
||||
for (LitemallCart checkGoods : checkedGoodsList) {
|
||||
Integer productId = checkGoods.getProductId();
|
||||
LitemallGoodsProduct product = productService.findById(productId);
|
||||
|
||||
Integer remainNumber = product.getNumber() - checkGoods.getNumber();
|
||||
if (remainNumber < 0) {
|
||||
throw new RuntimeException("下单的商品货品数量大于库存量");
|
||||
}
|
||||
if (productService.reduceStock(productId, checkGoods.getNumber()) == 0) {
|
||||
throw new RuntimeException("商品货品库存减少失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果使用了优惠券,设置优惠券使用状态
|
||||
if(couponId != 0 && couponId != -1){
|
||||
LitemallCouponUser couponUser = couponUserService.queryOne(userId, couponId);
|
||||
couponUser.setStatus(CouponUserConstant.STATUS_USED);
|
||||
couponUser.setUsedTime(LocalDateTime.now());
|
||||
couponUser.setOrderId(orderId);
|
||||
couponUserService.update(couponUser);
|
||||
}
|
||||
|
||||
//如果是团购项目,添加团购信息
|
||||
if (grouponRulesId != null && grouponRulesId > 0) {
|
||||
LitemallGroupon groupon = new LitemallGroupon();
|
||||
groupon.setOrderId(orderId);
|
||||
groupon.setPayed(false);
|
||||
groupon.setUserId(userId);
|
||||
groupon.setRulesId(grouponRulesId);
|
||||
|
||||
//参与者
|
||||
if (grouponLinkId != null && grouponLinkId > 0) {
|
||||
//参与的团购记录
|
||||
LitemallGroupon baseGroupon = grouponService.queryById(grouponLinkId);
|
||||
groupon.setCreatorUserId(baseGroupon.getCreatorUserId());
|
||||
groupon.setGrouponId(grouponLinkId);
|
||||
groupon.setShareUrl(baseGroupon.getShareUrl());
|
||||
} else {
|
||||
groupon.setCreatorUserId(userId);
|
||||
groupon.setGrouponId(0);
|
||||
}
|
||||
|
||||
grouponService.createGroupon(groupon);
|
||||
}
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("orderId", orderId);
|
||||
return ResponseUtil.ok(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够取消;
|
||||
* 2. 设置订单取消状态;
|
||||
* 3. 商品货品库存恢复;
|
||||
* 4. TODO 优惠券;
|
||||
* 5. TODO 团购活动。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @return 取消订单操作结果
|
||||
*/
|
||||
@Transactional
|
||||
public Object cancel(Integer userId, String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
LocalDateTime preUpdateTime = order.getUpdateTime();
|
||||
|
||||
// 检测是否能够取消
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isCancel()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能取消");
|
||||
}
|
||||
|
||||
// 设置订单已取消状态
|
||||
order.setOrderStatus(OrderUtil.STATUS_CANCEL);
|
||||
order.setEndTime(LocalDateTime.now());
|
||||
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("商品货品库存增加失败");
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseUtil.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 付款订单的预支付会话标识
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够付款
|
||||
* 2. 微信商户平台返回支付订单ID
|
||||
* 3. 设置订单付款状态
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @return 支付订单ID
|
||||
*/
|
||||
@Transactional
|
||||
public Object prepay(Integer userId, String body, HttpServletRequest request) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
// 检测是否能够取消
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isPay()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能支付");
|
||||
}
|
||||
|
||||
LitemallUser user = userService.findById(userId);
|
||||
String openid = user.getWeixinOpenid();
|
||||
if (openid == null) {
|
||||
return ResponseUtil.fail(AUTH_OPENID_UNACCESS, "订单不能支付");
|
||||
}
|
||||
WxPayMpOrderResult result = null;
|
||||
try {
|
||||
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
|
||||
orderRequest.setOutTradeNo(order.getOrderSn());
|
||||
orderRequest.setOpenid(openid);
|
||||
orderRequest.setBody("订单:" + order.getOrderSn());
|
||||
// 元转成分
|
||||
int fee = 0;
|
||||
BigDecimal actualPrice = order.getActualPrice();
|
||||
fee = actualPrice.multiply(new BigDecimal(100)).intValue();
|
||||
orderRequest.setTotalFee(fee);
|
||||
orderRequest.setSpbillCreateIp(IpUtil.getIpAddr(request));
|
||||
|
||||
result = wxPayService.createOrder(orderRequest);
|
||||
|
||||
//缓存prepayID用于后续模版通知
|
||||
String prepayId = result.getPackageValue();
|
||||
prepayId = prepayId.replace("prepay_id=", "");
|
||||
LitemallUserFormid userFormid = new LitemallUserFormid();
|
||||
userFormid.setOpenid(user.getWeixinOpenid());
|
||||
userFormid.setFormid(prepayId);
|
||||
userFormid.setIsprepay(true);
|
||||
userFormid.setUseamount(3);
|
||||
userFormid.setExpireTime(LocalDateTime.now().plusDays(7));
|
||||
formIdService.addUserFormid(userFormid);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ResponseUtil.fail(ORDER_PAY_FAIL, "订单不能支付");
|
||||
}
|
||||
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
return ResponseUtil.updatedDateExpired();
|
||||
}
|
||||
return ResponseUtil.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信付款成功或失败回调接口
|
||||
* <p>
|
||||
* 1. 检测当前订单是否是付款状态;
|
||||
* 2. 设置订单付款成功状态相关信息;
|
||||
* 3. 响应微信商户平台.
|
||||
*
|
||||
* @param request 请求内容
|
||||
* @param response 响应内容
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Transactional
|
||||
public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
|
||||
String xmlResult = null;
|
||||
try {
|
||||
xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return WxPayNotifyResponse.fail(e.getMessage());
|
||||
}
|
||||
|
||||
WxPayOrderNotifyResult result = null;
|
||||
try {
|
||||
result = wxPayService.parseOrderNotifyResult(xmlResult);
|
||||
} catch (WxPayException e) {
|
||||
e.printStackTrace();
|
||||
return WxPayNotifyResponse.fail(e.getMessage());
|
||||
}
|
||||
|
||||
logger.info("处理腾讯支付平台的订单支付");
|
||||
logger.info(result);
|
||||
|
||||
String orderSn = result.getOutTradeNo();
|
||||
String payId = result.getTransactionId();
|
||||
|
||||
// 分转化成元
|
||||
String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
|
||||
LitemallOrder order = orderService.findBySn(orderSn);
|
||||
if (order == null) {
|
||||
return WxPayNotifyResponse.fail("订单不存在 sn=" + orderSn);
|
||||
}
|
||||
|
||||
// 检查这个订单是否已经处理过
|
||||
if (OrderUtil.isPayStatus(order) && order.getPayId() != null) {
|
||||
return WxPayNotifyResponse.success("订单已经处理成功!");
|
||||
}
|
||||
|
||||
// 检查支付订单金额
|
||||
if (!totalFee.equals(order.getActualPrice().toString())) {
|
||||
return WxPayNotifyResponse.fail(order.getOrderSn() + " : 支付金额不符合 totalFee=" + totalFee);
|
||||
}
|
||||
|
||||
order.setPayId(payId);
|
||||
order.setPayTime(LocalDateTime.now());
|
||||
order.setOrderStatus(OrderUtil.STATUS_PAY);
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
// 这里可能存在这样一个问题,用户支付和系统自动取消订单发生在同时
|
||||
// 如果数据库首先因为系统自动取消订单而更新了订单状态;
|
||||
// 此时用户支付完成回调这里也要更新数据库,而由于乐观锁机制这里的更新会失败
|
||||
// 因此,这里会重新读取数据库检查状态是否是订单自动取消,如果是则更新成支付状态。
|
||||
order = orderService.findBySn(orderSn);
|
||||
int updated = 0;
|
||||
if (OrderUtil.isAutoCancelStatus(order)) {
|
||||
order.setPayId(payId);
|
||||
order.setPayTime(LocalDateTime.now());
|
||||
order.setOrderStatus(OrderUtil.STATUS_PAY);
|
||||
updated = orderService.updateWithOptimisticLocker(order);
|
||||
}
|
||||
|
||||
// 如果updated是0,那么数据库更新失败
|
||||
if (updated == 0) {
|
||||
return WxPayNotifyResponse.fail("更新数据已失效");
|
||||
}
|
||||
}
|
||||
|
||||
// 支付成功,有团购信息,更新团购信息
|
||||
LitemallGroupon groupon = grouponService.queryByOrderId(order.getId());
|
||||
if (groupon != null) {
|
||||
LitemallGrouponRules grouponRules = grouponRulesService.queryById(groupon.getRulesId());
|
||||
|
||||
//仅当发起者才创建分享图片
|
||||
if (groupon.getGrouponId() == 0) {
|
||||
String url = qCodeService.createGrouponShareImage(grouponRules.getGoodsName(), grouponRules.getPicUrl(), groupon);
|
||||
groupon.setShareUrl(url);
|
||||
}
|
||||
groupon.setPayed(true);
|
||||
if (grouponService.updateById(groupon) == 0) {
|
||||
return WxPayNotifyResponse.fail("更新数据已失效");
|
||||
}
|
||||
}
|
||||
|
||||
//TODO 发送邮件和短信通知,这里采用异步发送
|
||||
// 订单支付成功以后,会发送短信给用户,以及发送邮件给管理员
|
||||
notifyService.notifyMail("新订单通知", order.toString());
|
||||
// 这里微信的短信平台对参数长度有限制,所以将订单号只截取后6位
|
||||
notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[]{orderSn.substring(8, 14)});
|
||||
|
||||
// 请依据自己的模版消息配置更改参数
|
||||
String[] parms = new String[]{
|
||||
order.getOrderSn(),
|
||||
order.getOrderPrice().toString(),
|
||||
DateTimeUtil.getDateTimeDisplayString(order.getAddTime()),
|
||||
order.getConsignee(),
|
||||
order.getMobile(),
|
||||
order.getAddress()
|
||||
};
|
||||
|
||||
notifyService.notifyWxTemplate(result.getOpenid(), NotifyType.PAY_SUCCEED, parms, "pages/index/index?orderId=" + order.getId());
|
||||
|
||||
return WxPayNotifyResponse.success("处理成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单申请退款
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够退款;
|
||||
* 2. 设置订单申请退款状态。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @return 订单退款操作结果
|
||||
*/
|
||||
public Object refund(Integer userId, String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isRefund()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能取消");
|
||||
}
|
||||
|
||||
// 设置订单申请退款状态
|
||||
order.setOrderStatus(OrderUtil.STATUS_REFUND);
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
return ResponseUtil.updatedDateExpired();
|
||||
}
|
||||
|
||||
//TODO 发送邮件和短信通知,这里采用异步发送
|
||||
// 有用户申请退款,邮件通知运营人员
|
||||
notifyService.notifyMail("退款申请", order.toString());
|
||||
|
||||
return ResponseUtil.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认收货
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够确认收货;
|
||||
* 2. 设置订单确认收货状态。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @return 订单操作结果
|
||||
*/
|
||||
public Object confirm(Integer userId, String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isConfirm()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能确认收货");
|
||||
}
|
||||
|
||||
Short comments = orderGoodsService.getComments(orderId);
|
||||
order.setComments(comments);
|
||||
|
||||
order.setOrderStatus(OrderUtil.STATUS_CONFIRM);
|
||||
order.setConfirmTime(LocalDateTime.now());
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
return ResponseUtil.updatedDateExpired();
|
||||
}
|
||||
return ResponseUtil.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除订单
|
||||
* <p>
|
||||
* 1. 检测当前订单是否可以删除;
|
||||
* 2. 删除订单。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @return 订单操作结果
|
||||
*/
|
||||
public Object delete(Integer userId, String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isDelete()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能删除");
|
||||
}
|
||||
|
||||
// 订单order_status没有字段用于标识删除
|
||||
// 而是存在专门的delete字段表示是否删除
|
||||
orderService.deleteById(orderId);
|
||||
|
||||
return ResponseUtil.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 待评价订单商品信息
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param orderId 订单ID
|
||||
* @param goodsId 商品ID
|
||||
* @return 待评价订单商品信息
|
||||
*/
|
||||
public Object goods(Integer userId, Integer orderId, Integer goodsId) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.findByOidAndGid(orderId, goodsId);
|
||||
int size = orderGoodsList.size();
|
||||
|
||||
Assert.state(size < 2, "存在多个符合条件的订单商品");
|
||||
|
||||
if (size == 0) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
LitemallOrderGoods orderGoods = orderGoodsList.get(0);
|
||||
return ResponseUtil.ok(orderGoods);
|
||||
}
|
||||
|
||||
/**
|
||||
* 评价订单商品
|
||||
* <p>
|
||||
* 确认商品收货或者系统自动确认商品收货后7天内可以评价,过期不能评价。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
* @return 订单操作结果
|
||||
*/
|
||||
public Object comment(Integer userId, String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
Integer orderGoodsId = JacksonUtil.parseInteger(body, "orderGoodsId");
|
||||
if (orderGoodsId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
LitemallOrderGoods orderGoods = orderGoodsService.findById(orderGoodsId);
|
||||
if (orderGoods == null) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
Integer orderId = orderGoods.getOrderId();
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
Short orderStatus = order.getOrderStatus();
|
||||
if (!OrderUtil.isConfirmStatus(order) && !OrderUtil.isAutoConfirmStatus(order)) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "当前商品不能评价");
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.fail(ORDER_INVALID, "当前商品不属于用户");
|
||||
}
|
||||
Integer commentId = orderGoods.getComment();
|
||||
if (commentId == -1) {
|
||||
return ResponseUtil.fail(ORDER_COMMENT_EXPIRED, "当前商品评价时间已经过期");
|
||||
}
|
||||
if (commentId != 0) {
|
||||
return ResponseUtil.fail(ORDER_COMMENTED, "订单商品已评价");
|
||||
}
|
||||
|
||||
String content = JacksonUtil.parseString(body, "content");
|
||||
Integer star = JacksonUtil.parseInteger(body, "star");
|
||||
if (star == null || star < 0 || star > 5) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
Boolean hasPicture = JacksonUtil.parseBoolean(body, "hasPicture");
|
||||
List<String> picUrls = JacksonUtil.parseStringList(body, "picUrls");
|
||||
if (hasPicture == null || !hasPicture) {
|
||||
picUrls = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
// 1. 创建评价
|
||||
LitemallComment comment = new LitemallComment();
|
||||
comment.setUserId(userId);
|
||||
comment.setType((byte) 0);
|
||||
comment.setValueId(orderGoods.getGoodsId());
|
||||
comment.setStar(star.shortValue());
|
||||
comment.setContent(content);
|
||||
comment.setHasPicture(hasPicture);
|
||||
comment.setPicUrls(picUrls.toArray(new String[]{}));
|
||||
commentService.save(comment);
|
||||
|
||||
// 2. 更新订单商品的评价列表
|
||||
orderGoods.setComment(comment.getId());
|
||||
orderGoodsService.updateById(orderGoods);
|
||||
|
||||
// 3. 更新订单中未评价的订单商品可评价数量
|
||||
Short commentCount = order.getComments();
|
||||
if (commentCount > 0) {
|
||||
commentCount--;
|
||||
}
|
||||
order.setComments(commentCount);
|
||||
orderService.updateWithOptimisticLocker(order);
|
||||
|
||||
return ResponseUtil.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +1,17 @@
|
||||
package org.linlinjava.litemall.wx.web;
|
||||
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
||||
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
|
||||
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.linlinjava.litemall.core.express.ExpressService;
|
||||
import org.linlinjava.litemall.core.express.dao.ExpressInfo;
|
||||
import org.linlinjava.litemall.core.notify.NotifyService;
|
||||
import org.linlinjava.litemall.core.notify.NotifyType;
|
||||
import org.linlinjava.litemall.core.qcode.QCodeService;
|
||||
import org.linlinjava.litemall.core.system.SystemConfig;
|
||||
import org.linlinjava.litemall.core.util.DateTimeUtil;
|
||||
import org.linlinjava.litemall.core.util.JacksonUtil;
|
||||
import org.linlinjava.litemall.core.util.ResponseUtil;
|
||||
import org.linlinjava.litemall.db.domain.*;
|
||||
import org.linlinjava.litemall.db.service.*;
|
||||
import org.linlinjava.litemall.db.util.CouponUserConstant;
|
||||
import org.linlinjava.litemall.db.util.OrderHandleOption;
|
||||
import org.linlinjava.litemall.db.util.OrderUtil;
|
||||
import org.linlinjava.litemall.wx.annotation.LoginUser;
|
||||
import org.linlinjava.litemall.wx.util.IpUtil;
|
||||
import org.linlinjava.litemall.wx.service.WxOrderService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.linlinjava.litemall.wx.util.WxResponseCode.*;
|
||||
|
||||
/**
|
||||
* 订单服务
|
||||
*
|
||||
* <p>
|
||||
* 订单状态:
|
||||
* 101 订单生成,未支付;102,下单后未支付用户取消;103,下单后未支付超时系统自动取消
|
||||
* 201 支付完成,商家未发货;202,订单生产,已付款未发货,但是退款取消;
|
||||
* 301 商家发货,用户未确认;
|
||||
* 401 用户确认收货; 402 用户没有确认收货超过一定时间,系统自动确认收货;
|
||||
*
|
||||
* <p>
|
||||
* 用户操作:
|
||||
* 当101用户未付款时,此时用户可以进行的操作是取消订单,或者付款操作
|
||||
* 当201支付完成而商家未发货时,此时用户可以取消订单并申请退款
|
||||
* 当301商家已发货时,此时用户可以有确认收货的操作
|
||||
* 当401用户确认收货以后,此时用户可以进行的操作是删除订单,评价商品,或者再次购买
|
||||
* 当402系统自动确认收货以后,此时用户可以删除订单,评价商品,或者再次购买
|
||||
*
|
||||
* <p>
|
||||
* 注意:目前不支持订单退货和售后服务
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/wx/order")
|
||||
@Validated
|
||||
@@ -76,65 +19,13 @@ public class WxOrderController {
|
||||
private final Log logger = LogFactory.getLog(WxOrderController.class);
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager txManager;
|
||||
@Autowired
|
||||
private LitemallUserService userService;
|
||||
@Autowired
|
||||
private LitemallOrderService orderService;
|
||||
@Autowired
|
||||
private LitemallOrderGoodsService orderGoodsService;
|
||||
@Autowired
|
||||
private LitemallAddressService addressService;
|
||||
@Autowired
|
||||
private LitemallCartService cartService;
|
||||
@Autowired
|
||||
private LitemallRegionService regionService;
|
||||
@Autowired
|
||||
private LitemallGoodsProductService productService;
|
||||
@Autowired
|
||||
private WxPayService wxPayService;
|
||||
@Autowired
|
||||
private NotifyService notifyService;
|
||||
@Autowired
|
||||
private LitemallUserFormIdService formIdService;
|
||||
@Autowired
|
||||
private LitemallGrouponRulesService grouponRulesService;
|
||||
@Autowired
|
||||
private LitemallGrouponService grouponService;
|
||||
@Autowired
|
||||
private QCodeService qCodeService;
|
||||
@Autowired
|
||||
private ExpressService expressService;
|
||||
@Autowired
|
||||
private LitemallCommentService commentService;
|
||||
@Autowired
|
||||
private LitemallCouponService couponService;
|
||||
@Autowired
|
||||
private LitemallCouponUserService couponUserService;
|
||||
@Autowired
|
||||
private CouponVerifyService couponVerifyService;
|
||||
|
||||
private String detailedAddress(LitemallAddress litemallAddress) {
|
||||
Integer provinceId = litemallAddress.getProvinceId();
|
||||
Integer cityId = litemallAddress.getCityId();
|
||||
Integer areaId = litemallAddress.getAreaId();
|
||||
String provinceName = regionService.findById(provinceId).getName();
|
||||
String cityName = regionService.findById(cityId).getName();
|
||||
String areaName = regionService.findById(areaId).getName();
|
||||
String fullRegion = provinceName + " " + cityName + " " + areaName;
|
||||
return fullRegion + " " + litemallAddress.getAddress();
|
||||
}
|
||||
private WxOrderService wxOrderService;
|
||||
|
||||
/**
|
||||
* 订单列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param showType 订单信息:
|
||||
* 0,全部订单;
|
||||
* 1,待付款;
|
||||
* 2,待发货;
|
||||
* 3,待收货;
|
||||
* 4,待评价。
|
||||
* @param showType 订单信息
|
||||
* @param page 分页页数
|
||||
* @param size 分页大小
|
||||
* @return 订单列表
|
||||
@@ -144,50 +35,7 @@ public class WxOrderController {
|
||||
@RequestParam(defaultValue = "0") Integer showType,
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer size) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
List<Short> orderStatus = OrderUtil.orderStatus(showType);
|
||||
List<LitemallOrder> orderList = orderService.queryByOrderStatus(userId, orderStatus);
|
||||
int count = orderService.countByOrderStatus(userId, orderStatus);
|
||||
|
||||
List<Map<String, Object>> orderVoList = new ArrayList<>(orderList.size());
|
||||
for (LitemallOrder order : orderList) {
|
||||
Map<String, Object> orderVo = new HashMap<>();
|
||||
orderVo.put("id", order.getId());
|
||||
orderVo.put("orderSn", order.getOrderSn());
|
||||
orderVo.put("actualPrice", order.getActualPrice());
|
||||
orderVo.put("orderStatusText", OrderUtil.orderStatusText(order));
|
||||
orderVo.put("handleOption", OrderUtil.build(order));
|
||||
|
||||
LitemallGroupon groupon = grouponService.queryByOrderId(order.getId());
|
||||
if (groupon != null) {
|
||||
orderVo.put("isGroupin", true);
|
||||
} else {
|
||||
orderVo.put("isGroupin", false);
|
||||
}
|
||||
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
|
||||
List<Map<String, Object>> orderGoodsVoList = new ArrayList<>(orderGoodsList.size());
|
||||
for (LitemallOrderGoods orderGoods : orderGoodsList) {
|
||||
Map<String, Object> orderGoodsVo = new HashMap<>();
|
||||
orderGoodsVo.put("id", orderGoods.getId());
|
||||
orderGoodsVo.put("goodsName", orderGoods.getGoodsName());
|
||||
orderGoodsVo.put("number", orderGoods.getNumber());
|
||||
orderGoodsVo.put("picUrl", orderGoods.getPicUrl());
|
||||
orderGoodsVoList.add(orderGoodsVo);
|
||||
}
|
||||
orderVo.put("goodsList", orderGoodsVoList);
|
||||
|
||||
orderVoList.add(orderVo);
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("count", count);
|
||||
result.put("data", orderVoList);
|
||||
|
||||
return ResponseUtil.ok(result);
|
||||
return wxOrderService.list(userId, showType, page, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,58 +47,11 @@ public class WxOrderController {
|
||||
*/
|
||||
@GetMapping("detail")
|
||||
public Object detail(@LoginUser Integer userId, @NotNull Integer orderId) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
// 订单信息
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (null == order) {
|
||||
return ResponseUtil.fail(ORDER_UNKNOWN, "订单不存在");
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.fail(ORDER_INVALID, "不是当前用户的订单");
|
||||
}
|
||||
Map<String, Object> orderVo = new HashMap<String, Object>();
|
||||
orderVo.put("id", order.getId());
|
||||
orderVo.put("orderSn", order.getOrderSn());
|
||||
orderVo.put("addTime", order.getAddTime());
|
||||
orderVo.put("consignee", order.getConsignee());
|
||||
orderVo.put("mobile", order.getMobile());
|
||||
orderVo.put("address", order.getAddress());
|
||||
orderVo.put("goodsPrice", order.getGoodsPrice());
|
||||
orderVo.put("freightPrice", order.getFreightPrice());
|
||||
orderVo.put("actualPrice", order.getActualPrice());
|
||||
orderVo.put("orderStatusText", OrderUtil.orderStatusText(order));
|
||||
orderVo.put("handleOption", OrderUtil.build(order));
|
||||
orderVo.put("expCode", order.getShipChannel());
|
||||
orderVo.put("expNo", order.getShipSn());
|
||||
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("orderInfo", orderVo);
|
||||
result.put("orderGoods", orderGoodsList);
|
||||
|
||||
// 订单状态为已发货且物流信息不为空
|
||||
//"YTO", "800669400640887922"
|
||||
if (order.getOrderStatus().equals(OrderUtil.STATUS_SHIP)) {
|
||||
ExpressInfo ei = expressService.getExpressInfo(order.getShipChannel(), order.getShipSn());
|
||||
result.put("expressInfo", ei);
|
||||
}
|
||||
|
||||
return ResponseUtil.ok(result);
|
||||
|
||||
return wxOrderService.detail(userId, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交订单
|
||||
* <p>
|
||||
* 1. 创建订单表项和订单商品表项;
|
||||
* 2. 购物车清空;
|
||||
* 3. 优惠券设置已用;
|
||||
* 4. 商品货品库存减少;
|
||||
* 5. 如果是团购商品,则创建团购活动表项。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ cartId:xxx, addressId: xxx, couponId: xxx, message: xxx, grouponRulesId: xxx, grouponLinkId: xxx}
|
||||
@@ -258,219 +59,11 @@ public class WxOrderController {
|
||||
*/
|
||||
@PostMapping("submit")
|
||||
public Object submit(@LoginUser Integer userId, @RequestBody String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
if (body == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
Integer cartId = JacksonUtil.parseInteger(body, "cartId");
|
||||
Integer addressId = JacksonUtil.parseInteger(body, "addressId");
|
||||
Integer couponId = JacksonUtil.parseInteger(body, "couponId");
|
||||
String message = JacksonUtil.parseString(body, "message");
|
||||
Integer grouponRulesId = JacksonUtil.parseInteger(body, "grouponRulesId");
|
||||
Integer grouponLinkId = JacksonUtil.parseInteger(body, "grouponLinkId");
|
||||
|
||||
//如果是团购项目,验证活动是否有效
|
||||
if (grouponRulesId != null && grouponRulesId > 0) {
|
||||
LitemallGrouponRules rules = grouponRulesService.queryById(grouponRulesId);
|
||||
//找不到记录
|
||||
if (rules == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
//团购活动已经过期
|
||||
if (grouponRulesService.isExpired(rules)) {
|
||||
return ResponseUtil.fail(GROUPON_EXPIRED, "团购活动已过期!");
|
||||
}
|
||||
}
|
||||
|
||||
if (cartId == null || addressId == null || couponId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
// 收货地址
|
||||
LitemallAddress checkedAddress = addressService.findById(addressId);
|
||||
if (checkedAddress == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
// 团购优惠
|
||||
BigDecimal grouponPrice = new BigDecimal(0.00);
|
||||
LitemallGrouponRules grouponRules = grouponRulesService.queryById(grouponRulesId);
|
||||
if (grouponRules != null) {
|
||||
grouponPrice = grouponRules.getDiscount();
|
||||
}
|
||||
|
||||
// 货品价格
|
||||
List<LitemallCart> checkedGoodsList = null;
|
||||
if (cartId.equals(0)) {
|
||||
checkedGoodsList = cartService.queryByUidAndChecked(userId);
|
||||
} else {
|
||||
LitemallCart cart = cartService.findById(cartId);
|
||||
checkedGoodsList = new ArrayList<>(1);
|
||||
checkedGoodsList.add(cart);
|
||||
}
|
||||
if (checkedGoodsList.size() == 0) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
BigDecimal checkedGoodsPrice = new BigDecimal(0.00);
|
||||
for (LitemallCart checkGoods : checkedGoodsList) {
|
||||
// 只有当团购规格商品ID符合才进行团购优惠
|
||||
if (grouponRules != null && grouponRules.getGoodsId().equals(checkGoods.getGoodsId())) {
|
||||
checkedGoodsPrice = checkedGoodsPrice.add(checkGoods.getPrice().subtract(grouponPrice).multiply(new BigDecimal(checkGoods.getNumber())));
|
||||
} else {
|
||||
checkedGoodsPrice = checkedGoodsPrice.add(checkGoods.getPrice().multiply(new BigDecimal(checkGoods.getNumber())));
|
||||
}
|
||||
}
|
||||
|
||||
// 获取可用的优惠券信息
|
||||
// 使用优惠券减免的金额
|
||||
BigDecimal couponPrice = new BigDecimal(0.00);
|
||||
// 如果couponId=0则没有优惠券,couponId=-1则不使用优惠券
|
||||
if(couponId != 0 && couponId != -1){
|
||||
LitemallCoupon coupon = couponVerifyService.checkCoupon(userId, couponId, checkedGoodsPrice);
|
||||
if(coupon == null){
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
couponPrice = coupon.getDiscount();
|
||||
}
|
||||
|
||||
|
||||
// 根据订单商品总价计算运费,满足条件(例如88元)则免运费,否则需要支付运费(例如8元);
|
||||
BigDecimal freightPrice = new BigDecimal(0.00);
|
||||
if (checkedGoodsPrice.compareTo(SystemConfig.getFreightLimit()) < 0) {
|
||||
freightPrice = SystemConfig.getFreight();
|
||||
}
|
||||
|
||||
// 可以使用的其他钱,例如用户积分
|
||||
BigDecimal integralPrice = new BigDecimal(0.00);
|
||||
|
||||
// 订单费用
|
||||
BigDecimal orderTotalPrice = checkedGoodsPrice.add(freightPrice).subtract(couponPrice);
|
||||
// 最终支付费用
|
||||
BigDecimal actualPrice = orderTotalPrice.subtract(integralPrice);
|
||||
|
||||
// 开启事务管理
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
TransactionStatus status = txManager.getTransaction(def);
|
||||
Integer orderId = null;
|
||||
LitemallOrder order = null;
|
||||
try {
|
||||
// 订单
|
||||
order = new LitemallOrder();
|
||||
order.setUserId(userId);
|
||||
order.setOrderSn(orderService.generateOrderSn(userId));
|
||||
order.setOrderStatus(OrderUtil.STATUS_CREATE);
|
||||
order.setConsignee(checkedAddress.getName());
|
||||
order.setMobile(checkedAddress.getMobile());
|
||||
order.setMessage(message);
|
||||
String detailedAddress = detailedAddress(checkedAddress);
|
||||
order.setAddress(detailedAddress);
|
||||
order.setGoodsPrice(checkedGoodsPrice);
|
||||
order.setFreightPrice(freightPrice);
|
||||
order.setCouponPrice(couponPrice);
|
||||
order.setIntegralPrice(integralPrice);
|
||||
order.setOrderPrice(orderTotalPrice);
|
||||
order.setActualPrice(actualPrice);
|
||||
|
||||
// 有团购活动
|
||||
if (grouponRules != null) {
|
||||
order.setGrouponPrice(grouponPrice); // 团购价格
|
||||
} else {
|
||||
order.setGrouponPrice(new BigDecimal(0.00)); // 团购价格
|
||||
}
|
||||
|
||||
// 添加订单表项
|
||||
orderService.add(order);
|
||||
orderId = order.getId();
|
||||
|
||||
// 添加订单商品表项
|
||||
for (LitemallCart cartGoods : checkedGoodsList) {
|
||||
// 订单商品
|
||||
LitemallOrderGoods orderGoods = new LitemallOrderGoods();
|
||||
orderGoods.setOrderId(order.getId());
|
||||
orderGoods.setGoodsId(cartGoods.getGoodsId());
|
||||
orderGoods.setGoodsSn(cartGoods.getGoodsSn());
|
||||
orderGoods.setProductId(cartGoods.getProductId());
|
||||
orderGoods.setGoodsName(cartGoods.getGoodsName());
|
||||
orderGoods.setPicUrl(cartGoods.getPicUrl());
|
||||
orderGoods.setPrice(cartGoods.getPrice());
|
||||
orderGoods.setNumber(cartGoods.getNumber());
|
||||
orderGoods.setSpecifications(cartGoods.getSpecifications());
|
||||
orderGoods.setAddTime(LocalDateTime.now());
|
||||
|
||||
orderGoodsService.add(orderGoods);
|
||||
}
|
||||
|
||||
// 删除购物车里面的商品信息
|
||||
cartService.clearGoods(userId);
|
||||
|
||||
// 商品货品数量减少
|
||||
for (LitemallCart checkGoods : checkedGoodsList) {
|
||||
Integer productId = checkGoods.getProductId();
|
||||
LitemallGoodsProduct product = productService.findById(productId);
|
||||
|
||||
Integer remainNumber = product.getNumber() - checkGoods.getNumber();
|
||||
if (remainNumber < 0) {
|
||||
throw new RuntimeException("下单的商品货品数量大于库存量");
|
||||
}
|
||||
if (productService.reduceStock(productId, checkGoods.getNumber()) == 0) {
|
||||
throw new Exception("商品货品库存减少失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果使用了优惠券,设置优惠券使用状态
|
||||
if(couponId != 0 && couponId != -1){
|
||||
LitemallCouponUser couponUser = couponUserService.queryOne(userId, couponId);
|
||||
couponUser.setStatus(CouponUserConstant.STATUS_USED);
|
||||
couponUser.setUsedTime(LocalDateTime.now());
|
||||
couponUser.setOrderId(orderId);
|
||||
couponUserService.update(couponUser);
|
||||
}
|
||||
|
||||
//如果是团购项目,添加团购信息
|
||||
if (grouponRulesId != null && grouponRulesId > 0) {
|
||||
LitemallGroupon groupon = new LitemallGroupon();
|
||||
groupon.setOrderId(orderId);
|
||||
groupon.setPayed(false);
|
||||
groupon.setUserId(userId);
|
||||
groupon.setRulesId(grouponRulesId);
|
||||
|
||||
//参与者
|
||||
if (grouponLinkId != null && grouponLinkId > 0) {
|
||||
//参与的团购记录
|
||||
LitemallGroupon baseGroupon = grouponService.queryById(grouponLinkId);
|
||||
groupon.setCreatorUserId(baseGroupon.getCreatorUserId());
|
||||
groupon.setGrouponId(grouponLinkId);
|
||||
groupon.setShareUrl(baseGroupon.getShareUrl());
|
||||
} else {
|
||||
groupon.setCreatorUserId(userId);
|
||||
groupon.setGrouponId(0);
|
||||
}
|
||||
|
||||
grouponService.createGroupon(groupon);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
txManager.rollback(status);
|
||||
logger.error("系统内部错误", ex);
|
||||
return ResponseUtil.fail(ORDER_CHECKOUT_FAIL, "下单失败");
|
||||
}
|
||||
txManager.commit(status);
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("orderId", orderId);
|
||||
return ResponseUtil.ok(data);
|
||||
return wxOrderService.submit(userId, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够取消;
|
||||
* 2. 设置订单取消状态;
|
||||
* 3. 商品货品库存恢复;
|
||||
* 4. TODO 优惠券;
|
||||
* 5. TODO 团购活动。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
@@ -478,67 +71,11 @@ public class WxOrderController {
|
||||
*/
|
||||
@PostMapping("cancel")
|
||||
public Object cancel(@LoginUser Integer userId, @RequestBody String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
LocalDateTime preUpdateTime = order.getUpdateTime();
|
||||
|
||||
// 检测是否能够取消
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isCancel()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能取消");
|
||||
}
|
||||
|
||||
// 开启事务管理
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
TransactionStatus status = txManager.getTransaction(def);
|
||||
try {
|
||||
// 设置订单已取消状态
|
||||
order.setOrderStatus(OrderUtil.STATUS_CANCEL);
|
||||
order.setEndTime(LocalDateTime.now());
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
throw new Exception("更新数据已失效");
|
||||
}
|
||||
|
||||
// 商品货品数量增加
|
||||
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 Exception("商品货品库存增加失败");
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
txManager.rollback(status);
|
||||
logger.error("系统内部错误", ex);
|
||||
return ResponseUtil.fail(ORDER_CANCEL_FAIL, "订单取消失败");
|
||||
}
|
||||
txManager.commit(status);
|
||||
|
||||
return ResponseUtil.ok();
|
||||
return wxOrderService.cancel(userId, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 付款订单的预支付会话标识
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够付款
|
||||
* 2. 微信商户平台返回支付订单ID
|
||||
* 3. 设置订单付款状态
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
@@ -546,77 +83,13 @@ public class WxOrderController {
|
||||
*/
|
||||
@PostMapping("prepay")
|
||||
public Object prepay(@LoginUser Integer userId, @RequestBody String body, HttpServletRequest request) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
// 检测是否能够取消
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isPay()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能支付");
|
||||
}
|
||||
|
||||
LitemallUser user = userService.findById(userId);
|
||||
String openid = user.getWeixinOpenid();
|
||||
if (openid == null) {
|
||||
return ResponseUtil.fail(AUTH_OPENID_UNACCESS, "订单不能支付");
|
||||
}
|
||||
WxPayMpOrderResult result = null;
|
||||
try {
|
||||
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
|
||||
orderRequest.setOutTradeNo(order.getOrderSn());
|
||||
orderRequest.setOpenid(openid);
|
||||
orderRequest.setBody("订单:" + order.getOrderSn());
|
||||
// 元转成分
|
||||
Integer fee = 0;
|
||||
BigDecimal actualPrice = order.getActualPrice();
|
||||
fee = actualPrice.multiply(new BigDecimal(100)).intValue();
|
||||
orderRequest.setTotalFee(fee);
|
||||
orderRequest.setSpbillCreateIp(IpUtil.getIpAddr(request));
|
||||
|
||||
result = wxPayService.createOrder(orderRequest);
|
||||
|
||||
//缓存prepayID用于后续模版通知
|
||||
String prepayId = result.getPackageValue();
|
||||
prepayId = prepayId.replace("prepay_id=", "");
|
||||
LitemallUserFormid userFormid = new LitemallUserFormid();
|
||||
userFormid.setOpenid(user.getWeixinOpenid());
|
||||
userFormid.setFormid(prepayId);
|
||||
userFormid.setIsprepay(true);
|
||||
userFormid.setUseamount(3);
|
||||
userFormid.setExpireTime(LocalDateTime.now().plusDays(7));
|
||||
formIdService.addUserFormid(userFormid);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ResponseUtil.fail(ORDER_PAY_FAIL, "订单不能支付");
|
||||
}
|
||||
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
return ResponseUtil.updatedDateExpired();
|
||||
}
|
||||
return ResponseUtil.ok(result);
|
||||
return wxOrderService.prepay(userId, body, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信付款成功或失败回调接口
|
||||
* <p>
|
||||
* 1. 检测当前订单是否是付款状态;
|
||||
* 2. 设置订单付款成功状态相关信息;
|
||||
* 3. 响应微信商户平台.
|
||||
* <p>
|
||||
* TODO
|
||||
* 注意,这里pay-notify是示例地址,建议开发者应该设立一个隐蔽的回调地址
|
||||
*
|
||||
* @param request 请求内容
|
||||
@@ -625,110 +98,11 @@ public class WxOrderController {
|
||||
*/
|
||||
@PostMapping("pay-notify")
|
||||
public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
|
||||
String xmlResult = null;
|
||||
try {
|
||||
xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return WxPayNotifyResponse.fail(e.getMessage());
|
||||
}
|
||||
|
||||
WxPayOrderNotifyResult result = null;
|
||||
try {
|
||||
result = wxPayService.parseOrderNotifyResult(xmlResult);
|
||||
} catch (WxPayException e) {
|
||||
e.printStackTrace();
|
||||
return WxPayNotifyResponse.fail(e.getMessage());
|
||||
}
|
||||
|
||||
logger.info("处理腾讯支付平台的订单支付");
|
||||
logger.info(result);
|
||||
|
||||
String orderSn = result.getOutTradeNo();
|
||||
String payId = result.getTransactionId();
|
||||
|
||||
// 分转化成元
|
||||
String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
|
||||
LitemallOrder order = orderService.findBySn(orderSn);
|
||||
if (order == null) {
|
||||
return WxPayNotifyResponse.fail("订单不存在 sn=" + orderSn);
|
||||
}
|
||||
|
||||
// 检查这个订单是否已经处理过
|
||||
if (OrderUtil.isPayStatus(order) && order.getPayId() != null) {
|
||||
return WxPayNotifyResponse.success("订单已经处理成功!");
|
||||
}
|
||||
|
||||
// 检查支付订单金额
|
||||
if (!totalFee.equals(order.getActualPrice().toString())) {
|
||||
return WxPayNotifyResponse.fail(order.getOrderSn() + " : 支付金额不符合 totalFee=" + totalFee);
|
||||
}
|
||||
|
||||
order.setPayId(payId);
|
||||
order.setPayTime(LocalDateTime.now());
|
||||
order.setOrderStatus(OrderUtil.STATUS_PAY);
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
// 这里可能存在这样一个问题,用户支付和系统自动取消订单发生在同时
|
||||
// 如果数据库首先因为系统自动取消订单而更新了订单状态;
|
||||
// 此时用户支付完成回调这里也要更新数据库,而由于乐观锁机制这里的更新会失败
|
||||
// 因此,这里会重新读取数据库检查状态是否是订单自动取消,如果是则更新成支付状态。
|
||||
order = orderService.findBySn(orderSn);
|
||||
int updated = 0;
|
||||
if (OrderUtil.isAutoCancelStatus(order)) {
|
||||
order.setPayId(payId);
|
||||
order.setPayTime(LocalDateTime.now());
|
||||
order.setOrderStatus(OrderUtil.STATUS_PAY);
|
||||
updated = orderService.updateWithOptimisticLocker(order);
|
||||
}
|
||||
|
||||
// 如果updated是0,那么数据库更新失败
|
||||
if (updated == 0) {
|
||||
return WxPayNotifyResponse.fail("更新数据已失效");
|
||||
}
|
||||
}
|
||||
|
||||
// 支付成功,有团购信息,更新团购信息
|
||||
LitemallGroupon groupon = grouponService.queryByOrderId(order.getId());
|
||||
if (groupon != null) {
|
||||
LitemallGrouponRules grouponRules = grouponRulesService.queryById(groupon.getRulesId());
|
||||
|
||||
//仅当发起者才创建分享图片
|
||||
if (groupon.getGrouponId() == 0) {
|
||||
String url = qCodeService.createGrouponShareImage(grouponRules.getGoodsName(), grouponRules.getPicUrl(), groupon);
|
||||
groupon.setShareUrl(url);
|
||||
}
|
||||
groupon.setPayed(true);
|
||||
if (grouponService.updateById(groupon) == 0) {
|
||||
return WxPayNotifyResponse.fail("更新数据已失效");
|
||||
}
|
||||
}
|
||||
|
||||
//TODO 发送邮件和短信通知,这里采用异步发送
|
||||
// 订单支付成功以后,会发送短信给用户,以及发送邮件给管理员
|
||||
notifyService.notifyMail("新订单通知", order.toString());
|
||||
// 这里微信的短信平台对参数长度有限制,所以将订单号只截取后6位
|
||||
notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[]{orderSn.substring(8, 14)});
|
||||
|
||||
// 请依据自己的模版消息配置更改参数
|
||||
String[] parms = new String[]{
|
||||
order.getOrderSn(),
|
||||
order.getOrderPrice().toString(),
|
||||
DateTimeUtil.getDateTimeDisplayString(order.getAddTime()),
|
||||
order.getConsignee(),
|
||||
order.getMobile(),
|
||||
order.getAddress()
|
||||
};
|
||||
|
||||
notifyService.notifyWxTemplate(result.getOpenid(), NotifyType.PAY_SUCCEED, parms, "pages/index/index?orderId=" + order.getId());
|
||||
|
||||
return WxPayNotifyResponse.success("处理成功!");
|
||||
return wxOrderService.payNotify(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单申请退款
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够退款;
|
||||
* 2. 设置订单申请退款状态。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
@@ -736,45 +110,11 @@ public class WxOrderController {
|
||||
*/
|
||||
@PostMapping("refund")
|
||||
public Object refund(@LoginUser Integer userId, @RequestBody String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isRefund()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能取消");
|
||||
}
|
||||
|
||||
// 设置订单申请退款状态
|
||||
order.setOrderStatus(OrderUtil.STATUS_REFUND);
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
return ResponseUtil.updatedDateExpired();
|
||||
}
|
||||
|
||||
//TODO 发送邮件和短信通知,这里采用异步发送
|
||||
// 有用户申请退款,邮件通知运营人员
|
||||
notifyService.notifyMail("退款申请", order.toString());
|
||||
|
||||
return ResponseUtil.ok();
|
||||
return wxOrderService.refund(userId, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认收货
|
||||
* <p>
|
||||
* 1. 检测当前订单是否能够确认收货;
|
||||
* 2. 设置订单确认收货状态。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
@@ -782,43 +122,11 @@ public class WxOrderController {
|
||||
*/
|
||||
@PostMapping("confirm")
|
||||
public Object confirm(@LoginUser Integer userId, @RequestBody String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isConfirm()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能确认收货");
|
||||
}
|
||||
|
||||
Short comments = orderGoodsService.getComments(orderId);
|
||||
order.setComments(comments);
|
||||
|
||||
order.setOrderStatus(OrderUtil.STATUS_CONFIRM);
|
||||
order.setConfirmTime(LocalDateTime.now());
|
||||
if (orderService.updateWithOptimisticLocker(order) == 0) {
|
||||
return ResponseUtil.updatedDateExpired();
|
||||
}
|
||||
return ResponseUtil.ok();
|
||||
return wxOrderService.confirm(userId, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除订单
|
||||
* <p>
|
||||
* 1. 检测当前订单是否可以删除;
|
||||
* 2. 删除订单。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
@@ -826,32 +134,7 @@ public class WxOrderController {
|
||||
*/
|
||||
@PostMapping("delete")
|
||||
public Object delete(@LoginUser Integer userId, @RequestBody String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
|
||||
if (orderId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
OrderHandleOption handleOption = OrderUtil.build(order);
|
||||
if (!handleOption.isDelete()) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "订单不能删除");
|
||||
}
|
||||
|
||||
// 订单order_status没有字段用于标识删除
|
||||
// 而是存在专门的delete字段表示是否删除
|
||||
orderService.deleteById(orderId);
|
||||
|
||||
return ResponseUtil.ok();
|
||||
return wxOrderService.delete(userId, body);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -866,27 +149,11 @@ public class WxOrderController {
|
||||
public Object goods(@LoginUser Integer userId,
|
||||
@NotNull Integer orderId,
|
||||
@NotNull Integer goodsId) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.findByOidAndGid(orderId, goodsId);
|
||||
int size = orderGoodsList.size();
|
||||
|
||||
Assert.state(size < 2, "存在多个符合条件的订单商品");
|
||||
|
||||
if (size == 0) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
|
||||
LitemallOrderGoods orderGoods = orderGoodsList.get(0);
|
||||
return ResponseUtil.ok(orderGoods);
|
||||
return wxOrderService.goods(userId, orderId, goodsId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 评价订单商品
|
||||
* <p>
|
||||
* 确认商品收货或者系统自动确认商品收货后7天内可以评价,过期不能评价。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param body 订单信息,{ orderId:xxx }
|
||||
@@ -894,73 +161,7 @@ public class WxOrderController {
|
||||
*/
|
||||
@PostMapping("comment")
|
||||
public Object comment(@LoginUser Integer userId, @RequestBody String body) {
|
||||
if (userId == null) {
|
||||
return ResponseUtil.unlogin();
|
||||
}
|
||||
|
||||
Integer orderGoodsId = JacksonUtil.parseInteger(body, "orderGoodsId");
|
||||
if (orderGoodsId == null) {
|
||||
return ResponseUtil.badArgument();
|
||||
}
|
||||
LitemallOrderGoods orderGoods = orderGoodsService.findById(orderGoodsId);
|
||||
if (orderGoods == null) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
Integer orderId = orderGoods.getOrderId();
|
||||
LitemallOrder order = orderService.findById(orderId);
|
||||
if (order == null) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
Short orderStatus = order.getOrderStatus();
|
||||
if (!OrderUtil.isConfirmStatus(order) && !OrderUtil.isAutoConfirmStatus(order)) {
|
||||
return ResponseUtil.fail(ORDER_INVALID_OPERATION, "当前商品不能评价");
|
||||
}
|
||||
if (!order.getUserId().equals(userId)) {
|
||||
return ResponseUtil.fail(ORDER_INVALID, "当前商品不属于用户");
|
||||
}
|
||||
Integer commentId = orderGoods.getComment();
|
||||
if (commentId == -1) {
|
||||
return ResponseUtil.fail(ORDER_COMMENT_EXPIRED, "当前商品评价时间已经过期");
|
||||
}
|
||||
if (commentId != 0) {
|
||||
return ResponseUtil.fail(ORDER_COMMENTED, "订单商品已评价");
|
||||
}
|
||||
|
||||
String content = JacksonUtil.parseString(body, "content");
|
||||
Integer star = JacksonUtil.parseInteger(body, "star");
|
||||
if (star == null || star < 0 || star > 5) {
|
||||
return ResponseUtil.badArgumentValue();
|
||||
}
|
||||
Boolean hasPicture = JacksonUtil.parseBoolean(body, "hasPicture");
|
||||
List<String> picUrls = JacksonUtil.parseStringList(body, "picUrls");
|
||||
if (hasPicture == null || !hasPicture) {
|
||||
picUrls = new ArrayList<>(0);
|
||||
}
|
||||
|
||||
// 1. 创建评价
|
||||
LitemallComment comment = new LitemallComment();
|
||||
comment.setUserId(userId);
|
||||
comment.setType((byte) 0);
|
||||
comment.setValueId(orderGoods.getGoodsId());
|
||||
comment.setStar(star.shortValue());
|
||||
comment.setContent(content);
|
||||
comment.setHasPicture(hasPicture);
|
||||
comment.setPicUrls(picUrls.toArray(new String[]{}));
|
||||
commentService.save(comment);
|
||||
|
||||
// 2. 更新订单商品的评价列表
|
||||
orderGoods.setComment(comment.getId());
|
||||
orderGoodsService.updateById(orderGoods);
|
||||
|
||||
// 3. 更新订单中未评价的订单商品可评价数量
|
||||
Short commentCount = order.getComments();
|
||||
if (commentCount > 0) {
|
||||
commentCount--;
|
||||
}
|
||||
order.setComments(commentCount);
|
||||
orderService.updateWithOptimisticLocker(order);
|
||||
|
||||
return ResponseUtil.ok();
|
||||
return wxOrderService.comment(userId, body);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user