mirror of
https://gitee.com/youlaitech/youlai-mall.git
synced 2024-12-22 20:54:26 +08:00
refactor: Seata实验室案例调整为Seata官网购买商品示例
This commit is contained in:
parent
fdfcd93b4b
commit
43ee28ac8a
@ -2,8 +2,8 @@ package com.youlai.laboratory.seata.controller;
|
|||||||
|
|
||||||
import com.youlai.common.result.Result;
|
import com.youlai.common.result.Result;
|
||||||
import com.youlai.laboratory.seata.pojo.form.SeataForm;
|
import com.youlai.laboratory.seata.pojo.form.SeataForm;
|
||||||
import com.youlai.laboratory.seata.pojo.vo.SeataDataVO;
|
import com.youlai.laboratory.seata.pojo.vo.SeataVO;
|
||||||
import com.youlai.laboratory.seata.service.ISeataService;
|
import com.youlai.laboratory.seata.service.SeataService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -22,26 +22,12 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class SeataController {
|
public class SeataController {
|
||||||
|
|
||||||
private final ISeataService seataService;
|
private final SeataService seataService;
|
||||||
|
|
||||||
@ApiOperation("订单支付")
|
|
||||||
@PostMapping("/order/_pay")
|
|
||||||
public Result payOrder(@RequestBody SeataForm seataForm) {
|
|
||||||
|
|
||||||
boolean openTx = seataForm.isOpenTx();
|
|
||||||
boolean result;
|
|
||||||
if (openTx) {
|
|
||||||
result = seataService.payOrderWithGlobalTx(seataForm);
|
|
||||||
} else {
|
|
||||||
result = seataService.payOrder(seataForm);
|
|
||||||
}
|
|
||||||
return Result.success(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("获取模拟数据")
|
@ApiOperation("获取模拟数据")
|
||||||
@GetMapping("/data")
|
@GetMapping("/data")
|
||||||
public Result getData() {
|
public Result getData() {
|
||||||
SeataDataVO result = seataService.getData();
|
SeataVO result = seataService.getData();
|
||||||
return Result.success(result);
|
return Result.success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,4 +38,19 @@ public class SeataController {
|
|||||||
return Result.success(result);
|
return Result.success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation("购买商品")
|
||||||
|
@PostMapping("/purchaseGoods")
|
||||||
|
public Result purchaseGoods(@RequestBody SeataForm seataForm) {
|
||||||
|
boolean openTx = seataForm.isOpenTx();
|
||||||
|
|
||||||
|
String orderSn = null;
|
||||||
|
if (openTx) {
|
||||||
|
// 开启全局事务
|
||||||
|
orderSn = seataService.purchaseGoodsWithGlobalTx(seataForm);
|
||||||
|
} else {
|
||||||
|
orderSn = seataService.purchaseGoods(seataForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.success(orderSn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,28 @@ package com.youlai.laboratory.seata.pojo.form;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
* @author haoxr
|
* @author haoxr
|
||||||
* @date 2022/4/21 23:16
|
* @date 2022/4/21 23:16
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class SeataForm {
|
public class SeataForm {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员ID
|
||||||
|
*/
|
||||||
|
private Long memberId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品ID
|
||||||
|
*/
|
||||||
|
private Long skuId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单金额
|
||||||
|
*/
|
||||||
|
private Long amount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否开启事务
|
* 是否开启事务
|
||||||
@ -16,9 +32,9 @@ public class SeataForm {
|
|||||||
private boolean openTx;
|
private boolean openTx;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单异常
|
* 是否开启异常
|
||||||
*/
|
*/
|
||||||
private boolean orderEx;
|
private boolean openEx;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import lombok.Data;
|
|||||||
*/
|
*/
|
||||||
@ApiModel("Seata模拟数据视图对象")
|
@ApiModel("Seata模拟数据视图对象")
|
||||||
@Data
|
@Data
|
||||||
public class SeataDataVO {
|
public class SeataVO {
|
||||||
|
|
||||||
@ApiModelProperty("商品库存信息")
|
@ApiModelProperty("商品库存信息")
|
||||||
private StockInfo stockInfo;
|
private StockInfo stockInfo;
|
@ -1,35 +1,20 @@
|
|||||||
package com.youlai.laboratory.seata.service;
|
package com.youlai.laboratory.seata.service;
|
||||||
|
|
||||||
import com.youlai.laboratory.seata.pojo.form.SeataForm;
|
import com.youlai.laboratory.seata.pojo.form.SeataForm;
|
||||||
import com.youlai.laboratory.seata.pojo.vo.SeataDataVO;
|
import com.youlai.laboratory.seata.pojo.vo.SeataVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author haoxr
|
* @author haoxr
|
||||||
* @date 2022/4/16 20:49
|
* @date 2022/4/16 20:49
|
||||||
*/
|
*/
|
||||||
public interface ISeataService {
|
public interface SeataService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 模拟订单支付
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean payOrder(SeataForm seataForm);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模拟订单支付(分布式事务)
|
|
||||||
*
|
|
||||||
* @param seataForm
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean payOrderWithGlobalTx(SeataForm seataForm);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取模拟数据
|
* 获取模拟数据
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
SeataDataVO getData();
|
SeataVO getData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置模拟数据
|
* 重置模拟数据
|
||||||
@ -37,4 +22,18 @@ public interface ISeataService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean resetData();
|
boolean resetData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买商品
|
||||||
|
*
|
||||||
|
* @return 订单号
|
||||||
|
*/
|
||||||
|
String purchaseGoods(SeataForm seataForm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买商品(全局事务)
|
||||||
|
*
|
||||||
|
* @return 订单号
|
||||||
|
*/
|
||||||
|
String purchaseGoodsWithGlobalTx(SeataForm seataForm);
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
package com.youlai.laboratory.seata.service.impl;
|
package com.youlai.laboratory.seata.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.youlai.common.result.Result;
|
||||||
import com.youlai.laboratory.seata.pojo.form.SeataForm;
|
import com.youlai.laboratory.seata.pojo.form.SeataForm;
|
||||||
import com.youlai.laboratory.seata.pojo.vo.SeataDataVO;
|
import com.youlai.laboratory.seata.pojo.vo.SeataVO;
|
||||||
import com.youlai.laboratory.seata.service.ISeataService;
|
import com.youlai.laboratory.seata.service.SeataService;
|
||||||
import com.youlai.mall.oms.api.OrderFeignClient;
|
import com.youlai.mall.oms.api.OrderFeignClient;
|
||||||
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
||||||
|
import com.youlai.mall.oms.dto.SeataOrderDTO;
|
||||||
import com.youlai.mall.pms.api.SkuFeignClient;
|
import com.youlai.mall.pms.api.SkuFeignClient;
|
||||||
import com.youlai.mall.pms.pojo.dto.SkuInfoDTO;
|
import com.youlai.mall.pms.pojo.dto.SkuInfoDTO;
|
||||||
import com.youlai.mall.ums.api.MemberFeignClient;
|
import com.youlai.mall.ums.api.MemberFeignClient;
|
||||||
@ -24,7 +26,7 @@ import org.springframework.stereotype.Service;
|
|||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class SeataServiceImpl implements ISeataService {
|
public class SeataServiceImpl implements SeataService {
|
||||||
|
|
||||||
private final SkuFeignClient skuFeignClient;
|
private final SkuFeignClient skuFeignClient;
|
||||||
private final OrderFeignClient orderFeignClient;
|
private final OrderFeignClient orderFeignClient;
|
||||||
@ -66,12 +68,14 @@ public class SeataServiceImpl implements ISeataService {
|
|||||||
log.info("========扣减商品库存(Seata)========");
|
log.info("========扣减商品库存(Seata)========");
|
||||||
skuFeignClient.deductStock(skuId, 1); // 扣减库存
|
skuFeignClient.deductStock(skuId, 1); // 扣减库存
|
||||||
|
|
||||||
log.info("========扣减账户余额(Seata)========");
|
log.info("========修改订单状态(Seata)========");
|
||||||
memberFeignClient.deductBalance(memberId, 1000 * 100l); // 扣款1000
|
orderFeignClient.createOrder(orderId, 201, seataForm.isOrderEx()); // 已支付
|
||||||
|
|
||||||
log.info("========修改订单状态(Seata)========");
|
log.info("========修改订单状态(Seata)========");
|
||||||
orderFeignClient.updateOrderStatus(orderId, 201, seataForm.isOrderEx()); // 已支付
|
orderFeignClient.updateOrderStatus(orderId, 201, seataForm.isOrderEx()); // 已支付
|
||||||
|
|
||||||
|
log.info("========扣减账户余额(Seata)========");
|
||||||
|
memberFeignClient.deductBalance(memberId, 1000 * 100l); // 扣款1000
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,26 +85,26 @@ public class SeataServiceImpl implements ISeataService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public SeataDataVO getData() {
|
public SeataVO getData() {
|
||||||
SeataDataVO seataDataVO = new SeataDataVO();
|
SeataVO seataVO = new SeataVO();
|
||||||
|
|
||||||
SkuInfoDTO skuInfoDTO = skuFeignClient.getSkuInfo(skuId).getData();
|
SkuInfoDTO skuInfoDTO = skuFeignClient.getSkuInfo(skuId).getData();
|
||||||
SeataDataVO.StockInfo stockInfo = new SeataDataVO.StockInfo();
|
SeataVO.StockInfo stockInfo = new SeataVO.StockInfo();
|
||||||
BeanUtil.copyProperties(skuInfoDTO, stockInfo);
|
BeanUtil.copyProperties(skuInfoDTO, stockInfo);
|
||||||
stockInfo.setName(skuInfoDTO.getSkuName());
|
stockInfo.setName(skuInfoDTO.getSkuName());
|
||||||
seataDataVO.setStockInfo(stockInfo);
|
seataVO.setStockInfo(stockInfo);
|
||||||
|
|
||||||
MemberInfoDTO memberInfoDTO = memberFeignClient.getMemberInfo(memberId).getData();
|
MemberInfoDTO memberInfoDTO = memberFeignClient.getMemberInfo(memberId).getData();
|
||||||
SeataDataVO.AccountInfo accountInfo = new SeataDataVO.AccountInfo();
|
SeataVO.AccountInfo accountInfo = new SeataVO.AccountInfo();
|
||||||
BeanUtil.copyProperties(memberInfoDTO, accountInfo);
|
BeanUtil.copyProperties(memberInfoDTO, accountInfo);
|
||||||
seataDataVO.setAccountInfo(accountInfo);
|
seataVO.setAccountInfo(accountInfo);
|
||||||
|
|
||||||
OrderInfoDTO orderInfoDTO = orderFeignClient.getOrderInfo(orderId).getData();
|
OrderInfoDTO orderInfoDTO = orderFeignClient.getOrderInfo(orderId).getData();
|
||||||
SeataDataVO.OrderInfo orderInfo = new SeataDataVO.OrderInfo();
|
SeataVO.OrderInfo orderInfo = new SeataVO.OrderInfo();
|
||||||
BeanUtil.copyProperties(orderInfoDTO, orderInfo);
|
BeanUtil.copyProperties(orderInfoDTO, orderInfo);
|
||||||
seataDataVO.setOrderInfo(orderInfo);
|
seataVO.setOrderInfo(orderInfo);
|
||||||
|
|
||||||
return seataDataVO;
|
return seataVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,4 +120,52 @@ public class SeataServiceImpl implements ISeataService {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买商品
|
||||||
|
*
|
||||||
|
* @return 订单号
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String purchaseGoods(SeataForm seataForm) {
|
||||||
|
log.info("========扣减商品库存(全局事务)========");
|
||||||
|
skuFeignClient.deductStock(seataForm.getSkuId(), 1); // 扣减库存
|
||||||
|
|
||||||
|
log.info("========创建订单(全局事务)========");
|
||||||
|
SeataOrderDTO seataOrderDTO = new SeataOrderDTO(
|
||||||
|
seataForm.getMemberId(),
|
||||||
|
seataForm.getSkuId(),
|
||||||
|
seataForm.getAmount()
|
||||||
|
);
|
||||||
|
boolean openEx = seataForm.isOpenEx(); // 是否开启异常
|
||||||
|
Result<String> result = orderFeignClient.createOrder(seataOrderDTO, openEx);
|
||||||
|
String orderSn = result.getData();
|
||||||
|
|
||||||
|
return orderSn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买商品(全局事务)
|
||||||
|
*
|
||||||
|
* @return 订单号
|
||||||
|
*/
|
||||||
|
@GlobalTransactional
|
||||||
|
@Override
|
||||||
|
public String purchaseGoodsWithGlobalTx(SeataForm seataForm) {
|
||||||
|
|
||||||
|
log.info("========扣减商品库存(全局事务)========");
|
||||||
|
skuFeignClient.deductStock(seataForm.getSkuId(), 1); // 扣减库存
|
||||||
|
|
||||||
|
log.info("========创建订单(全局事务)========");
|
||||||
|
SeataOrderDTO seataOrderDTO = new SeataOrderDTO(
|
||||||
|
seataForm.getMemberId(),
|
||||||
|
seataForm.getSkuId(),
|
||||||
|
seataForm.getAmount()
|
||||||
|
);
|
||||||
|
boolean openEx = seataForm.isOpenEx(); // 是否开启异常
|
||||||
|
Result<String> result = orderFeignClient.createOrder(seataOrderDTO, openEx);
|
||||||
|
String orderSn = result.getData();
|
||||||
|
|
||||||
|
return orderSn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ package com.youlai.mall.oms.api;
|
|||||||
|
|
||||||
import com.youlai.common.result.Result;
|
import com.youlai.common.result.Result;
|
||||||
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
||||||
|
import com.youlai.mall.oms.dto.SeataOrderDTO;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单Feign客户端
|
* 订单Feign客户端
|
||||||
@ -38,4 +36,13 @@ public interface OrderFeignClient {
|
|||||||
@GetMapping("/api/v1/orders/{orderId}/info")
|
@GetMapping("/api/v1/orders/{orderId}/info")
|
||||||
Result<OrderInfoDTO> getOrderInfo(@PathVariable Long orderId);
|
Result<OrderInfoDTO> getOrderInfo(@PathVariable Long orderId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 「实验室」创建订单
|
||||||
|
*
|
||||||
|
* @param orderDTO
|
||||||
|
* @param openEx 是否出现异常
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@PostMapping("/api/v1/orders")
|
||||||
|
Result<String> createOrder(SeataOrderDTO orderDTO, boolean openEx);
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ package com.youlai.mall.oms.dto;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单信息传输层对象
|
* 订单传输层对象
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:xianrui0365@163.com">haoxr</a>
|
* @author haoxr
|
||||||
* @date 2022/4/17 21:12
|
* @date 2022/4/17
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class OrderInfoDTO {
|
public class OrderInfoDTO {
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.youlai.mall.oms.dto;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class SeataOrderDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员ID
|
||||||
|
*/
|
||||||
|
private Long memberId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品ID
|
||||||
|
*/
|
||||||
|
private Long skuId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单金额
|
||||||
|
*/
|
||||||
|
private Long amount;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -11,17 +11,17 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum OrderTypeEnum {
|
public enum OrderSourceTypeEnum {
|
||||||
|
|
||||||
WEB(0), // PC订单
|
PC(0), // PC订单
|
||||||
APP(1), // APP订单
|
APP(1), // APP订单
|
||||||
;
|
;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private Integer code;
|
private Integer code;
|
||||||
|
|
||||||
public static OrderTypeEnum getValue(Integer code){
|
public static OrderSourceTypeEnum getValue(Integer code){
|
||||||
for (OrderTypeEnum value : values()) {
|
for (OrderSourceTypeEnum value : values()) {
|
||||||
if (value.getCode().equals(code)) {
|
if (value.getCode().equals(code)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
@ -1,46 +1,56 @@
|
|||||||
package com.youlai.mall.oms.enums;
|
package com.youlai.mall.oms.enums;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import com.youlai.common.base.IBaseEnum;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author huawei
|
* 订单状态枚举
|
||||||
* @desc
|
*
|
||||||
* @email huawei_code@163.com
|
* @author haoxr
|
||||||
* @date 2021/1/16
|
* @date 2022/11/28
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
public enum OrderStatusEnum implements IBaseEnum<Integer> {
|
||||||
public enum OrderStatusEnum {
|
|
||||||
|
|
||||||
PENDING_PAYMENT(101, "待支付"),
|
/**
|
||||||
USER_CANCEL(102, "用户取消"),
|
* 1. 订单创建阶段
|
||||||
AUTO_CANCEL(103, "系统自动取消"),
|
*/
|
||||||
|
PENDING_PAYMENT(10, "待支付"),
|
||||||
|
USER_CANCEL(11, "用户取消"),
|
||||||
|
AUTO_CANCEL(12, "系统自动取消"),
|
||||||
|
|
||||||
PAYED(201, "已支付"),
|
/**
|
||||||
APPLY_REFUND(202, "申请退款"),
|
* 2. 订单付款阶段
|
||||||
REFUNDED(203, "已退款"),
|
*/
|
||||||
|
PAYED(20, "已支付"),
|
||||||
|
APPLY_REFUND(21, "申请退款"),
|
||||||
|
REFUNDED(22, "已退款"),
|
||||||
|
|
||||||
DELIVERED(301, "已发货"),
|
/**
|
||||||
|
* 订单发货阶段
|
||||||
|
*/
|
||||||
|
DELIVERED(30, "已发货"),
|
||||||
|
|
||||||
USER_RECEIVE(401, "用户收货"),
|
/**
|
||||||
AUTO_RECEIVE(402, "系统自动收货"),
|
* 订单收货阶段
|
||||||
|
*/
|
||||||
|
USER_RECEIVE(40, "用户收货"),
|
||||||
|
AUTO_RECEIVE(41, "系统自动收货"),
|
||||||
|
|
||||||
FINISHED(901, "已完成");
|
/**
|
||||||
|
* 订单完结
|
||||||
|
*/
|
||||||
|
COMPLETED(99, "已完成");
|
||||||
|
|
||||||
|
|
||||||
|
OrderStatusEnum(int value, String label) {
|
||||||
|
this.value = value;
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private Integer code;
|
private Integer value;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private String text;
|
private String label;
|
||||||
|
|
||||||
|
|
||||||
public static OrderStatusEnum getValue(Integer code) {
|
|
||||||
for (OrderStatusEnum value : values()) {
|
|
||||||
if (value.getCode().equals(code)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,22 +48,7 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 分布式事务 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.cloud</groupId>
|
|
||||||
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>io.seata</groupId>
|
|
||||||
<artifactId>seata-spring-boot-starter</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.seata</groupId>
|
|
||||||
<artifactId>seata-spring-boot-starter</artifactId>
|
|
||||||
<version>${seata.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.youlai</groupId>
|
<groupId>com.youlai</groupId>
|
||||||
@ -104,6 +89,12 @@
|
|||||||
<groupId>com.github.binarywang</groupId>
|
<groupId>com.github.binarywang</groupId>
|
||||||
<artifactId>weixin-java-pay</artifactId>
|
<artifactId>weixin-java-pay</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.youlai</groupId>
|
||||||
|
<artifactId>common-seata</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||||||
import com.youlai.common.result.PageResult;
|
import com.youlai.common.result.PageResult;
|
||||||
import com.youlai.common.result.Result;
|
import com.youlai.common.result.Result;
|
||||||
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
||||||
|
import com.youlai.mall.oms.dto.SeataOrderDTO;
|
||||||
import com.youlai.mall.oms.pojo.dto.OrderDTO;
|
import com.youlai.mall.oms.pojo.dto.OrderDTO;
|
||||||
import com.youlai.mall.oms.pojo.entity.OmsOrder;
|
import com.youlai.mall.oms.pojo.entity.OmsOrder;
|
||||||
import com.youlai.mall.oms.pojo.entity.OmsOrderItem;
|
import com.youlai.mall.oms.pojo.entity.OmsOrderItem;
|
||||||
@ -24,7 +25,7 @@ import java.util.Optional;
|
|||||||
/**
|
/**
|
||||||
* @author huawei
|
* @author huawei
|
||||||
* @email huawei_code@163.com
|
* @email huawei_code@163.com
|
||||||
* @date 2020-12-30 22:31:10
|
* @date 2020/12/30
|
||||||
*/
|
*/
|
||||||
@Api(tags = "「管理端」订单管理")
|
@Api(tags = "「管理端」订单管理")
|
||||||
@RestController
|
@RestController
|
||||||
@ -62,11 +63,11 @@ public class OmsOrderController {
|
|||||||
return Result.success(orderDTO);
|
return Result.success(orderDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "修改订单状态", notes = "实验室模拟接口", hidden = true)
|
@ApiOperation(value = "「实验室」创建订单", notes = "实验室模拟接口", hidden = true)
|
||||||
@PutMapping("/{orderId}/status")
|
@PostMapping
|
||||||
public Result updateOrderStatus(@PathVariable Long orderId, @RequestParam Integer status,@RequestParam Boolean orderEx) {
|
public Result<String> createOrder(@RequestBody SeataOrderDTO orderDTO, @RequestParam Boolean openEx) {
|
||||||
boolean result = orderService.updateOrderStatus(orderId, status,orderEx);
|
String orderSn = orderService.createOrder(orderDTO, openEx);
|
||||||
return Result.judge(result);
|
return Result.success(orderSn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "获取订单信息", notes = "实验室模拟接口", hidden = true)
|
@ApiOperation(value = "获取订单信息", notes = "实验室模拟接口", hidden = true)
|
||||||
|
@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
|
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
||||||
|
import com.youlai.mall.oms.dto.SeataOrderDTO;
|
||||||
import com.youlai.mall.oms.enums.PayTypeEnum;
|
import com.youlai.mall.oms.enums.PayTypeEnum;
|
||||||
import com.youlai.mall.oms.pojo.entity.OmsOrder;
|
import com.youlai.mall.oms.pojo.entity.OmsOrder;
|
||||||
import com.youlai.mall.oms.pojo.query.OrderPageQuery;
|
import com.youlai.mall.oms.pojo.query.OrderPageQuery;
|
||||||
@ -36,7 +37,7 @@ public interface IOrderService extends IService<OmsOrder> {
|
|||||||
/**
|
/**
|
||||||
* 订单提交
|
* 订单提交
|
||||||
*/
|
*/
|
||||||
OrderSubmitVO submitOrder(OrderSubmitForm orderSubmitForm) ;
|
OrderSubmitVO submitOrder(OrderSubmitForm orderSubmitForm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单支付
|
* 订单支付
|
||||||
@ -84,18 +85,22 @@ public interface IOrderService extends IService<OmsOrder> {
|
|||||||
*/
|
*/
|
||||||
IPage<OmsOrder> listOrderPages(OrderPageQuery queryParams);
|
IPage<OmsOrder> listOrderPages(OrderPageQuery queryParams);
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改订单状态
|
|
||||||
*
|
|
||||||
* @param orderId 订单ID
|
|
||||||
* @param status 订单状态
|
|
||||||
* @param orderEx 订单是否异常
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean updateOrderStatus(Long orderId, Integer status,Boolean orderEx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取订单信息
|
* 「实验室」创建订单
|
||||||
|
* <p>
|
||||||
|
* 非商城业务
|
||||||
|
*
|
||||||
|
* @param orderDTO
|
||||||
|
* @param openEx
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String createOrder(SeataOrderDTO orderDTO, Boolean openEx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 「实验室」获取订单信息
|
||||||
|
* <p>
|
||||||
|
* 非商城业务
|
||||||
*
|
*
|
||||||
* @param orderId
|
* @param orderId
|
||||||
* @return
|
* @return
|
||||||
|
@ -8,7 +8,6 @@ import cn.hutool.core.util.StrUtil;
|
|||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
@ -21,15 +20,15 @@ import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
|
|||||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
import com.github.binarywang.wxpay.service.WxPayService;
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
import com.youlai.common.enums.BusinessTypeEnum;
|
import com.youlai.common.redis.BusinessSnGenerator;
|
||||||
import com.youlai.common.redis.BusinessNoGenerator;
|
|
||||||
import com.youlai.common.result.Result;
|
import com.youlai.common.result.Result;
|
||||||
import com.youlai.common.security.util.SecurityUtils;
|
import com.youlai.common.security.util.SecurityUtils;
|
||||||
import com.youlai.common.web.exception.ApiException;
|
import com.youlai.common.web.exception.ApiException;
|
||||||
import com.youlai.mall.oms.config.WxPayProperties;
|
import com.youlai.mall.oms.config.WxPayProperties;
|
||||||
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
import com.youlai.mall.oms.dto.OrderInfoDTO;
|
||||||
|
import com.youlai.mall.oms.dto.SeataOrderDTO;
|
||||||
import com.youlai.mall.oms.enums.OrderStatusEnum;
|
import com.youlai.mall.oms.enums.OrderStatusEnum;
|
||||||
import com.youlai.mall.oms.enums.OrderTypeEnum;
|
import com.youlai.mall.oms.enums.OrderSourceTypeEnum;
|
||||||
import com.youlai.mall.oms.enums.PayTypeEnum;
|
import com.youlai.mall.oms.enums.PayTypeEnum;
|
||||||
import com.youlai.mall.oms.mapper.OrderMapper;
|
import com.youlai.mall.oms.mapper.OrderMapper;
|
||||||
import com.youlai.mall.oms.pojo.dto.CartItemDTO;
|
import com.youlai.mall.oms.pojo.dto.CartItemDTO;
|
||||||
@ -58,7 +57,6 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
|||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
|
||||||
@ -78,9 +76,9 @@ import static com.youlai.mall.oms.constant.OmsConstants.*;
|
|||||||
* @author haoxr
|
* @author haoxr
|
||||||
* @date 2022/2/12
|
* @date 2022/2/12
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> implements IOrderService {
|
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> implements IOrderService {
|
||||||
|
|
||||||
private final WxPayProperties wxPayProperties;
|
private final WxPayProperties wxPayProperties;
|
||||||
@ -90,7 +88,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
private final StringRedisTemplate redisTemplate;
|
private final StringRedisTemplate redisTemplate;
|
||||||
private final ThreadPoolExecutor threadPoolExecutor;
|
private final ThreadPoolExecutor threadPoolExecutor;
|
||||||
private final MemberFeignClient memberFeignClient;
|
private final MemberFeignClient memberFeignClient;
|
||||||
private final BusinessNoGenerator businessNoGenerator;
|
private final BusinessSnGenerator businessSnGenerator;
|
||||||
private final SkuFeignClient skuFeignClient;
|
private final SkuFeignClient skuFeignClient;
|
||||||
private final RedissonClient redissonClient;
|
private final RedissonClient redissonClient;
|
||||||
private final WxPayService wxPayService;
|
private final WxPayService wxPayService;
|
||||||
@ -128,7 +126,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
CompletableFuture<Void> getOrderItemsFuture = CompletableFuture.runAsync(() -> {
|
CompletableFuture<Void> getOrderItemsFuture = CompletableFuture.runAsync(() -> {
|
||||||
// 请求参数传递给子线程
|
// 请求参数传递给子线程
|
||||||
RequestContextHolder.setRequestAttributes(attributes);
|
RequestContextHolder.setRequestAttributes(attributes);
|
||||||
List<OrderItemDTO> orderItems = this.getOrderItems(skuId,memberId);
|
List<OrderItemDTO> orderItems = this.getOrderItems(skuId, memberId);
|
||||||
orderConfirmVO.setOrderItems(orderItems);
|
orderConfirmVO.setOrderItems(orderItems);
|
||||||
}, threadPoolExecutor);
|
}, threadPoolExecutor);
|
||||||
|
|
||||||
@ -147,7 +145,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
// 进入订单确认页面生成唯一token,订单提交根据此token判断是否重复提交
|
// 进入订单确认页面生成唯一token,订单提交根据此token判断是否重复提交
|
||||||
CompletableFuture<Void> getOrderTokenFuture = CompletableFuture.runAsync(() -> {
|
CompletableFuture<Void> getOrderTokenFuture = CompletableFuture.runAsync(() -> {
|
||||||
RequestContextHolder.setRequestAttributes(attributes);
|
RequestContextHolder.setRequestAttributes(attributes);
|
||||||
String orderToken = businessNoGenerator.generate(BusinessTypeEnum.ORDER);
|
String orderToken = businessSnGenerator.generateSerialNo();
|
||||||
orderConfirmVO.setOrderToken(orderToken);
|
orderConfirmVO.setOrderToken(orderToken);
|
||||||
redisTemplate.opsForValue().set(ORDER_TOKEN_PREFIX + orderToken, orderToken);
|
redisTemplate.opsForValue().set(ORDER_TOKEN_PREFIX + orderToken, orderToken);
|
||||||
}, threadPoolExecutor);
|
}, threadPoolExecutor);
|
||||||
@ -186,7 +184,15 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
|
|
||||||
// 创建订单
|
// 创建订单
|
||||||
order = new OmsOrder().setOrderSn(orderToken) // 把orderToken赋值给订单编号
|
order = new OmsOrder().setOrderSn(orderToken) // 把orderToken赋值给订单编号
|
||||||
.setStatus(OrderStatusEnum.PENDING_PAYMENT.getCode()).setSourceType(OrderTypeEnum.APP.getCode()).setMemberId(SecurityUtils.getMemberId()).setRemark(orderSubmitForm.getRemark()).setPayAmount(orderSubmitForm.getPayAmount()).setTotalQuantity(orderItems.stream().map(OrderItemDTO::getCount).reduce(0, Integer::sum)).setTotalAmount(orderItems.stream().map(item -> item.getPrice() * item.getCount()).reduce(0L, Long::sum));
|
.setStatus(OrderStatusEnum.PENDING_PAYMENT.getValue())
|
||||||
|
.setSourceType(OrderSourceTypeEnum.APP.getCode())
|
||||||
|
.setMemberId(SecurityUtils.getMemberId())
|
||||||
|
.setRemark(orderSubmitForm.getRemark())
|
||||||
|
.setPayAmount(orderSubmitForm.getPayAmount())
|
||||||
|
.setTotalQuantity(orderItems.stream()
|
||||||
|
.map(OrderItemDTO::getCount).reduce(0, Integer::sum))
|
||||||
|
.setTotalAmount(orderItems.stream().map(item -> item.getPrice() * item.getCount())
|
||||||
|
.reduce(0L, Long::sum));
|
||||||
boolean result = this.save(order);
|
boolean result = this.save(order);
|
||||||
|
|
||||||
// 添加订单明细
|
// 添加订单明细
|
||||||
@ -225,7 +231,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
public <T> T pay(Long orderId, String appId, PayTypeEnum payTypeEnum) {
|
public <T> T pay(Long orderId, String appId, PayTypeEnum payTypeEnum) {
|
||||||
OmsOrder order = this.getById(orderId);
|
OmsOrder order = this.getById(orderId);
|
||||||
Assert.isTrue(order != null, "订单不存在");
|
Assert.isTrue(order != null, "订单不存在");
|
||||||
Assert.isTrue(OrderStatusEnum.PENDING_PAYMENT.getCode().equals(order.getStatus()), "订单不可支付,请检查订单状态");
|
Assert.isTrue(OrderStatusEnum.PENDING_PAYMENT.getValue().equals(order.getStatus()), "订单不可支付,请检查订单状态");
|
||||||
|
|
||||||
RLock lock = redissonClient.getLock(ORDER_SN_PREFIX + order.getOrderSn());
|
RLock lock = redissonClient.getLock(ORDER_SN_PREFIX + order.getOrderSn());
|
||||||
try {
|
try {
|
||||||
@ -266,7 +272,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
Assert.isTrue(Result.isSuccess(deductBalanceResult), "扣减账户余额失败");
|
Assert.isTrue(Result.isSuccess(deductBalanceResult), "扣减账户余额失败");
|
||||||
|
|
||||||
// 更新订单状态
|
// 更新订单状态
|
||||||
order.setStatus(OrderStatusEnum.PAYED.getCode());
|
order.setStatus(OrderStatusEnum.PAYED.getValue());
|
||||||
order.setPayType(PayTypeEnum.BALANCE.getValue());
|
order.setPayType(PayTypeEnum.BALANCE.getValue());
|
||||||
order.setPayTime(new Date());
|
order.setPayTime(new Date());
|
||||||
this.updateById(order);
|
this.updateById(order);
|
||||||
@ -318,7 +324,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
public boolean closeOrder(String orderToken) {
|
public boolean closeOrder(String orderToken) {
|
||||||
log.info("订单超时取消,orderToken:{}", orderToken);
|
log.info("订单超时取消,orderToken:{}", orderToken);
|
||||||
OmsOrder order = this.getOne(new LambdaQueryWrapper<OmsOrder>().eq(OmsOrder::getOrderSn, orderToken));
|
OmsOrder order = this.getOne(new LambdaQueryWrapper<OmsOrder>().eq(OmsOrder::getOrderSn, orderToken));
|
||||||
if (order == null || !OrderStatusEnum.PENDING_PAYMENT.getCode().equals(order.getStatus())) {
|
if (order == null || !OrderStatusEnum.PENDING_PAYMENT.getValue().equals(order.getStatus())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 如果已经有outTradeNo了就先进行关单
|
// 如果已经有outTradeNo了就先进行关单
|
||||||
@ -331,7 +337,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
throw new ApiException("微信关单异常");
|
throw new ApiException("微信关单异常");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
order.setStatus(OrderStatusEnum.AUTO_CANCEL.getCode());
|
order.setStatus(OrderStatusEnum.AUTO_CANCEL.getValue());
|
||||||
return this.updateById(order);
|
return this.updateById(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +349,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
throw new ApiException("订单不存在");
|
throw new ApiException("订单不存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OrderStatusEnum.PENDING_PAYMENT.getCode().equals(order.getStatus())) {
|
if (!OrderStatusEnum.PENDING_PAYMENT.getValue().equals(order.getStatus())) {
|
||||||
throw new ApiException("取消失败,订单状态不支持取消"); // 通过自定义异常,将异常信息抛出由异常处理器捕获显示给前端页面
|
throw new ApiException("取消失败,订单状态不支持取消"); // 通过自定义异常,将异常信息抛出由异常处理器捕获显示给前端页面
|
||||||
}
|
}
|
||||||
// 如果已经有outTradeNo了就先进行关单
|
// 如果已经有outTradeNo了就先进行关单
|
||||||
@ -356,7 +362,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
throw new ApiException("微信关单异常");
|
throw new ApiException("微信关单异常");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
order.setStatus(OrderStatusEnum.USER_CANCEL.getCode());
|
order.setStatus(OrderStatusEnum.USER_CANCEL.getValue());
|
||||||
boolean result = this.updateById(order);
|
boolean result = this.updateById(order);
|
||||||
if (result) {
|
if (result) {
|
||||||
// 释放被锁定的库存
|
// 释放被锁定的库存
|
||||||
@ -369,11 +375,11 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public boolean deleteOrder(Long id) {
|
public boolean deleteOrder(Long id) {
|
||||||
log.info("=======================订单删除,订单ID:{}=======================", id);
|
log.info("=======================订单删除,订单ID:{}=======================", id);
|
||||||
OmsOrder order = this.getById(id);
|
OmsOrder order = this.getById(id);
|
||||||
if (order != null && !OrderStatusEnum.AUTO_CANCEL.getCode().equals(order.getStatus()) && !OrderStatusEnum.USER_CANCEL.getCode().equals(order.getStatus())) {
|
if (order != null && !OrderStatusEnum.AUTO_CANCEL.getValue().equals(order.getStatus())
|
||||||
|
&& !OrderStatusEnum.USER_CANCEL.getValue().equals(order.getStatus())) {
|
||||||
throw new ApiException("订单删除失败,订单不存在或订单状态不支持删除");
|
throw new ApiException("订单删除失败,订单不存在或订单状态不支持删除");
|
||||||
}
|
}
|
||||||
return this.removeById(id);
|
return this.removeById(id);
|
||||||
@ -387,12 +393,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
final WxPayOrderNotifyV3Result.DecryptNotifyResult result = this.wxPayService.parseOrderNotifyV3Result(notifyData, signatureHeader).getResult();
|
final WxPayOrderNotifyV3Result.DecryptNotifyResult result = this.wxPayService.parseOrderNotifyV3Result(notifyData, signatureHeader).getResult();
|
||||||
log.debug("支付通知解密成功:[{}]", result.toString());
|
log.debug("支付通知解密成功:[{}]", result.toString());
|
||||||
// 根据商户订单号查询订单
|
// 根据商户订单号查询订单
|
||||||
QueryWrapper<OmsOrder> wrapper = new QueryWrapper<>();
|
OmsOrder orderDO = this.getOne(new LambdaQueryWrapper<OmsOrder>()
|
||||||
wrapper.lambda().eq(OmsOrder::getOutTradeNo, result.getOutTradeNo());
|
.eq(OmsOrder::getOutTradeNo, result.getOutTradeNo())
|
||||||
OmsOrder orderDO = this.getOne(wrapper);
|
);
|
||||||
// 支付成功处理
|
// 支付成功处理
|
||||||
if (WxPayConstants.WxpayTradeStatus.SUCCESS.equals(result.getTradeState())) {
|
if (WxPayConstants.WxpayTradeStatus.SUCCESS.equals(result.getTradeState())) {
|
||||||
orderDO.setStatus(OrderStatusEnum.PAYED.getCode());
|
orderDO.setStatus(OrderStatusEnum.PAYED.getValue());
|
||||||
orderDO.setTransactionId(result.getTransactionId());
|
orderDO.setTransactionId(result.getTransactionId());
|
||||||
orderDO.setPayTime(new Date());
|
orderDO.setPayTime(new Date());
|
||||||
this.updateById(orderDO);
|
this.updateById(orderDO);
|
||||||
@ -414,7 +420,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
OmsOrder orderDO = this.getOne(wrapper);
|
OmsOrder orderDO = this.getOne(wrapper);
|
||||||
// 退款成功处理
|
// 退款成功处理
|
||||||
if (WxPayConstants.RefundStatus.SUCCESS.equals(result.getRefundStatus())) {
|
if (WxPayConstants.RefundStatus.SUCCESS.equals(result.getRefundStatus())) {
|
||||||
orderDO.setStatus(OrderStatusEnum.REFUNDED.getCode());
|
orderDO.setStatus(OrderStatusEnum.REFUNDED.getValue());
|
||||||
orderDO.setRefundId(result.getRefundId());
|
orderDO.setRefundId(result.getRefundId());
|
||||||
this.updateById(orderDO);
|
this.updateById(orderDO);
|
||||||
}
|
}
|
||||||
@ -455,7 +461,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
* @param skuId 直接购买必有值,购物车结算必没值
|
* @param skuId 直接购买必有值,购物车结算必没值
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private List<OrderItemDTO> getOrderItems(Long skuId,Long memberId) {
|
private List<OrderItemDTO> getOrderItems(Long skuId, Long memberId) {
|
||||||
List<OrderItemDTO> orderItems;
|
List<OrderItemDTO> orderItems;
|
||||||
if (skuId != null) { // 直接购买
|
if (skuId != null) { // 直接购买
|
||||||
orderItems = new ArrayList<>();
|
orderItems = new ArrayList<>();
|
||||||
@ -486,7 +492,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
LockStockDTO lockStockDTO = new LockStockDTO();
|
LockStockDTO lockStockDTO = new LockStockDTO();
|
||||||
lockStockDTO.setOrderToken(orderToken);
|
lockStockDTO.setOrderToken(orderToken);
|
||||||
|
|
||||||
List<LockStockDTO.LockedSku> lockedSkuList = orderItems.stream().map(orderItem -> new LockStockDTO.LockedSku().setSkuId(orderItem.getSkuId()).setCount(orderItem.getCount())).collect(Collectors.toList());
|
List<LockStockDTO.LockedSku> lockedSkuList = orderItems.stream()
|
||||||
|
.map(orderItem -> new LockStockDTO
|
||||||
|
.LockedSku()
|
||||||
|
.setSkuId(orderItem.getSkuId())
|
||||||
|
.setCount(orderItem.getCount()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
lockStockDTO.setLockedSkuList(lockedSkuList);
|
lockStockDTO.setLockedSkuList(lockedSkuList);
|
||||||
skuFeignClient.lockStock(lockStockDTO);
|
skuFeignClient.lockStock(lockStockDTO);
|
||||||
@ -494,26 +505,42 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, OmsOrder> impleme
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 「实验室」修改订单状态
|
* 「实验室」创建订单
|
||||||
|
* <p>
|
||||||
|
* 非商城业务
|
||||||
*
|
*
|
||||||
* @param orderId 订单ID
|
* @param orderDTO
|
||||||
* @param status 订单状态
|
* @param openEx
|
||||||
* @param orderEx 订单是否异常
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
public String createOrder(SeataOrderDTO orderDTO, Boolean openEx) {
|
||||||
public boolean updateOrderStatus(Long orderId, Integer status, Boolean orderEx) {
|
|
||||||
boolean result = this.update(new LambdaUpdateWrapper<OmsOrder>().eq(OmsOrder::getId, orderId).set(OmsOrder::getStatus, status));
|
|
||||||
|
|
||||||
if (orderEx) {
|
// 扣减账户越
|
||||||
|
Long memberId = orderDTO.getMemberId();
|
||||||
|
Long amount = orderDTO.getAmount();
|
||||||
|
memberFeignClient.deductBalance(memberId, amount);
|
||||||
|
|
||||||
|
// 生成订单
|
||||||
|
String orderSn = businessSnGenerator.generateSerialNo();
|
||||||
|
new OmsOrder().setOrderSn(orderSn)
|
||||||
|
.setStatus(OrderStatusEnum.COMPLETED.getValue())
|
||||||
|
.setSourceType(OrderSourceTypeEnum.APP.getCode())
|
||||||
|
.setMemberId(memberId)
|
||||||
|
.setPayAmount(amount)
|
||||||
|
.setTotalQuantity(1)
|
||||||
|
.setTotalAmount(amount);
|
||||||
|
// 开启异常,制造运行时异常
|
||||||
|
if (openEx) {
|
||||||
int i = 1 / 0;
|
int i = 1 / 0;
|
||||||
}
|
}
|
||||||
return result;
|
return orderSn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取订单信息
|
* 「实验室」获取订单信息
|
||||||
|
* <p>
|
||||||
|
* 非商城业务
|
||||||
*
|
*
|
||||||
* @param orderId
|
* @param orderId
|
||||||
* @return
|
* @return
|
||||||
|
@ -58,10 +58,10 @@ public interface SkuFeignClient {
|
|||||||
* 「实验室」扣减商品库存
|
* 「实验室」扣减商品库存
|
||||||
*
|
*
|
||||||
* @param skuId
|
* @param skuId
|
||||||
* @param num 扣减数量
|
* @param count 扣减数量
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@PutMapping("/api/v1/sku/{skuId}/stock/_deduct")
|
@PutMapping("/api/v1/sku/{skuId}/stock/_deduct")
|
||||||
Result deductStock(@PathVariable Long skuId, @RequestParam Integer num);
|
Result deductStock(@PathVariable Long skuId, @RequestParam Integer count);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,12 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员Feign客户端
|
||||||
|
*
|
||||||
|
* @author haoxr
|
||||||
|
* @date 2022/11/29
|
||||||
|
*/
|
||||||
@FeignClient(name = "mall-ums", contextId = "member")
|
@FeignClient(name = "mall-ums", contextId = "member")
|
||||||
public interface MemberFeignClient {
|
public interface MemberFeignClient {
|
||||||
|
|
||||||
@ -61,7 +67,6 @@ public interface MemberFeignClient {
|
|||||||
@GetMapping("/app-api/v1/members/mobile/{mobile}")
|
@GetMapping("/app-api/v1/members/mobile/{mobile}")
|
||||||
Result<MemberAuthDTO> loadUserByMobile(@PathVariable String mobile);
|
Result<MemberAuthDTO> loadUserByMobile(@PathVariable String mobile);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取会员地址列表
|
* 获取会员地址列表
|
||||||
*
|
*
|
||||||
@ -71,16 +76,6 @@ public interface MemberFeignClient {
|
|||||||
@GetMapping("/app-api/v1/members/{memberId}/addresses")
|
@GetMapping("/app-api/v1/members/{memberId}/addresses")
|
||||||
Result<List<MemberAddressDTO>> listMemberAddresses(@PathVariable Long memberId);
|
Result<List<MemberAddressDTO>> listMemberAddresses(@PathVariable Long memberId);
|
||||||
|
|
||||||
/**
|
|
||||||
* 「实验室」修改会员余额
|
|
||||||
*
|
|
||||||
* @param memberId
|
|
||||||
* @param balance 余额(单位:分)
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@PutMapping("/api/v1/members/{memberId}/balance")
|
|
||||||
Result updateBalance(@PathVariable Long memberId, @RequestParam Integer balance);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 「实验室」扣减会员余额
|
* 「实验室」扣减会员余额
|
||||||
*
|
*
|
||||||
|
@ -81,17 +81,6 @@ public class UmsMemberController {
|
|||||||
return Result.judge(status);
|
return Result.judge(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ApiOperation(value = "修改会员余额", notes = "实验室模拟", hidden = true)
|
|
||||||
@PutMapping(value = "/{memberId}/balance")
|
|
||||||
public Result updateBalance(
|
|
||||||
@PathVariable Long memberId,
|
|
||||||
@RequestParam Long balance
|
|
||||||
) {
|
|
||||||
boolean result = memberService.updateBalance(memberId, balance);
|
|
||||||
return Result.judge(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation(value = "扣减会员余额", notes = "实验室模拟", hidden = true)
|
@ApiOperation(value = "扣减会员余额", notes = "实验室模拟", hidden = true)
|
||||||
@PutMapping(value = "/{memberId}/balance/_deduct")
|
@PutMapping(value = "/{memberId}/balance/_deduct")
|
||||||
public Result deductBalance(
|
public Result deductBalance(
|
||||||
|
6
pom.xml
6
pom.xml
@ -276,6 +276,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.youlai</groupId>
|
||||||
|
<artifactId>common-seata</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.whvcse</groupId>
|
<groupId>com.github.whvcse</groupId>
|
||||||
<artifactId>easy-captcha</artifactId>
|
<artifactId>easy-captcha</artifactId>
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
package com.youlai.common.enums;
|
|
||||||
|
|
||||||
import com.youlai.common.base.IBaseEnum;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 业务类型枚举
|
|
||||||
*
|
|
||||||
* @author haoxr
|
|
||||||
* @date 2021-02-17
|
|
||||||
*/
|
|
||||||
public enum BusinessTypeEnum implements IBaseEnum<Integer> {
|
|
||||||
|
|
||||||
USER(100, "用户"),
|
|
||||||
MEMBER(200, "会员"),
|
|
||||||
ORDER(300, "订单");
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private Integer value;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
private String label;
|
|
||||||
|
|
||||||
BusinessTypeEnum(Integer value, String label) {
|
|
||||||
this.value = value;
|
|
||||||
this.label = label;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
package com.youlai.common.redis;
|
package com.youlai.common.redis;
|
||||||
|
|
||||||
import com.youlai.common.constant.RedisConstants;
|
import com.youlai.common.constant.RedisConstants;
|
||||||
import com.youlai.common.enums.BusinessTypeEnum;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
@ -14,26 +13,24 @@ import java.time.format.DateTimeFormatter;
|
|||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class BusinessNoGenerator {
|
public class BusinessSnGenerator {
|
||||||
|
|
||||||
private final RedisTemplate redisTemplate;
|
private final RedisTemplate redisTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param businessType 业务类型枚举
|
|
||||||
* @param digit 业务序号位数
|
* @param digit 业务序号位数
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String generate(BusinessTypeEnum businessType, Integer digit) {
|
public String generateSerialNo(Integer digit) {
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||||
String date = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
|
String date = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
|
||||||
String key = RedisConstants.BUSINESS_NO_PREFIX + businessType.getValue() + ":" + date;
|
String key = RedisConstants.BUSINESS_NO_PREFIX +":" + date;
|
||||||
Long increment = redisTemplate.opsForValue().increment(key);
|
Long increment = redisTemplate.opsForValue().increment(key);
|
||||||
return date + businessType.getValue() + String.format("%0" + digit + "d", increment);
|
return date + String.format("%0" + digit + "d", increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generate(BusinessTypeEnum businessType) {
|
public String generateSerialNo(){
|
||||||
Integer defaultDigit = 6;
|
return this.generateSerialNo(6);
|
||||||
return generate(businessType, defaultDigit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
com.youlai.common.redis.RedisConfig,\
|
com.youlai.common.redis.RedisConfig,\
|
||||||
com.youlai.common.redis.BusinessNoGenerator,\
|
com.youlai.common.redis.BusinessSnGenerator,\
|
||||||
com.youlai.common.redis.RedissonConfig,\
|
com.youlai.common.redis.RedissonConfig,\
|
||||||
com.youlai.common.redis.RedisCacheConfig
|
com.youlai.common.redis.RedisCacheConfig
|
||||||
|
|
||||||
|
37
youlai-common/common-seata/pom.xml
Normal file
37
youlai-common/common-seata/pom.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>youlai-common</artifactId>
|
||||||
|
<groupId>com.youlai</groupId>
|
||||||
|
<version>2.1.4</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>common-seata</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>io.seata</groupId>
|
||||||
|
<artifactId>seata-spring-boot-starter</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.seata</groupId>
|
||||||
|
<artifactId>seata-spring-boot-starter</artifactId>
|
||||||
|
<version>${seata.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
@ -24,5 +24,6 @@
|
|||||||
<module>common-sms</module>
|
<module>common-sms</module>
|
||||||
<module>common-file</module>
|
<module>common-file</module>
|
||||||
<module>common-security</module>
|
<module>common-security</module>
|
||||||
|
<module>common-seata</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
Loading…
Reference in New Issue
Block a user