refactor(order): 重构订单模块并添加退款功能
- 重构了订单相关实体类和VO类,优化了字段设计 - 新增了AftersaleStatus枚举类,用于表示售后状态- 在OrderService中实现了退款功能 - 优化了订单查询相关SQL和Mapper方法 -调整了分账相关逻辑,增加了回退状态
This commit is contained in:
parent
76342416ad
commit
cb05c45909
@ -150,11 +150,5 @@ public class OrderController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
@Tag(name = "订单退款")
|
||||
@GetMapping("/refund")
|
||||
public R refund(@RequestParam Long orderId, @RequestParam(required = false) String reason) {
|
||||
log.info("订单退款开始,订单ID: {}", orderId);
|
||||
return orderService.refund(orderId,reason);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,11 +38,13 @@ public class OrderBo extends BaseBO<Order> {
|
||||
@Schema(description ="支付方式:0->未支付;1->支付宝;2->微信 精确匹配")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description ="订单状态:0->待付款;1->待核销;2->已完成;3->已关闭;4->退款中;5->已退款 6->已取消 9->已分账;10->无效订单 精确匹配")
|
||||
/**
|
||||
* 订单状态枚举类型见{@link com.wzj.soopin.order.emum.OrderStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
@Schema(description ="退款状态,枚举值:1:无售后或售后关闭,2:售后处理中,3:退款中,4: 退款成功 精确匹配")
|
||||
private Integer aftersaleStatus;
|
||||
@Schema(description="是否处于退款状态")
|
||||
private Boolean aftersale;
|
||||
|
||||
|
||||
@Schema(description ="省份/直辖市 精确匹配")
|
||||
@ -72,10 +74,6 @@ public class OrderBo extends BaseBO<Order> {
|
||||
@Schema(description ="商家备注 精确匹配")
|
||||
private String MEMBER_ID;
|
||||
|
||||
|
||||
@Schema(description ="删除状态:0->未删除;1->已删除 精确匹配")
|
||||
private Integer deleteStatus;
|
||||
|
||||
@Schema(description ="支付时间 精确匹配")
|
||||
private LocalDateTime paymentTime;
|
||||
|
||||
@ -102,8 +100,7 @@ public class OrderBo extends BaseBO<Order> {
|
||||
.eq(tenantId != null, Order::getTenantId, tenantId)
|
||||
.eq(payType != null, Order::getPayType, payType)
|
||||
.eq(status != null, Order::getStatus, status)
|
||||
.eq(aftersaleStatus != null, Order::getAftersaleStatus, aftersaleStatus)
|
||||
.eq(deleteStatus != null, Order::getDeleteStatus, deleteStatus)
|
||||
.eq(aftersale != null, Order::getAftersale, aftersale)
|
||||
.between(startTime != null && endTime != null, Order::getCreateTime, startTime, endTime)
|
||||
.ge(startTime != null && endTime == null, Order::getCreateTime, startTime)
|
||||
.le(endTime != null && startTime == null, Order::getCreateTime, endTime);
|
||||
|
@ -0,0 +1,79 @@
|
||||
package com.wzj.soopin.order.domain.bo;
|
||||
|
||||
import com.wzj.soopin.order.domain.entity.Order;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.dromara.common.excel.annotation.Excel;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 退款请求
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class RefundBO {
|
||||
/**
|
||||
* 订单ID
|
||||
*/
|
||||
@NotNull(message = "订单ID不能为空")
|
||||
private Long orderId;
|
||||
|
||||
/**
|
||||
* 退款项
|
||||
*/
|
||||
@NotNull(message = "退款项不能为空")
|
||||
@Valid
|
||||
private List<RefundItemBO> refundItemBoList;
|
||||
|
||||
/**
|
||||
* 退款原因
|
||||
*/
|
||||
private String refundReason;
|
||||
|
||||
/**
|
||||
* 订单信息
|
||||
*/
|
||||
@Schema(description = "订单信息", hidden = true)
|
||||
private Order order;
|
||||
|
||||
/**
|
||||
* 退款总金额
|
||||
*/
|
||||
@Schema(description = "退款总金额", hidden = true)
|
||||
private BigDecimal totalRefundAmount;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class RefundItemBO {
|
||||
|
||||
/**
|
||||
* 订单子项ID
|
||||
*/
|
||||
@NotNull(message = "订单子项ID不能为空")
|
||||
private Long orderItemId;
|
||||
|
||||
/**
|
||||
* 退款金额,单位:元
|
||||
*/
|
||||
@NotNull(message = "退款金额不能为空")
|
||||
private BigDecimal refundAmount;
|
||||
|
||||
/**
|
||||
* 退货数量
|
||||
*/
|
||||
@NotNull(message = "退货数量不能为空")
|
||||
private Integer quantity;
|
||||
}
|
||||
}
|
@ -2,10 +2,14 @@ package com.wzj.soopin.order.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.core.domain.model.BaseAudit;
|
||||
import org.dromara.common.excel.annotation.Excel;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
@ -13,10 +17,13 @@ import java.math.BigDecimal;
|
||||
*
|
||||
* @author zcc
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "订单售后对象")
|
||||
@Data
|
||||
@TableName("oms_aftersale_item")
|
||||
public class AftersaleItem extends BaseAudit {
|
||||
@Builder
|
||||
public class AftersaleItem extends BaseAudit implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
|
@ -2,13 +2,12 @@ package com.wzj.soopin.order.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.*;
|
||||
import org.dromara.common.core.domain.model.BaseAudit;
|
||||
import org.dromara.common.excel.annotation.Excel;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ -17,14 +16,16 @@ import java.time.LocalDateTime;
|
||||
*
|
||||
* @author zcc
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "订单表对象")
|
||||
@Data
|
||||
@TableName("oms_order")
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Order extends BaseAudit {
|
||||
public class Order extends BaseAudit implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "订单id")
|
||||
@ -76,9 +77,11 @@ public class Order extends BaseAudit {
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "退款状态,枚举值:1:无售后或售后关闭,2:售后处理中,3:退款中,4: 退款成功")
|
||||
@Excel(name = "退款状态,枚举值:1:无售后或售后关闭,2:售后处理中,3:退款中,4: 退款成功")
|
||||
private Integer aftersaleStatus;
|
||||
/**
|
||||
* 是否处于退款状态
|
||||
*/
|
||||
@Schema(description="是否处于退款状态")
|
||||
private Boolean aftersale;
|
||||
|
||||
|
||||
|
||||
@ -118,10 +121,6 @@ public class Order extends BaseAudit {
|
||||
@Excel(name = "订单备注")
|
||||
private String note;
|
||||
|
||||
@Schema(description = "删除状态:0->未删除;1->已删除")
|
||||
@Excel(name = "删除状态:0->未删除;1->已删除")
|
||||
private Integer deleteStatus;
|
||||
|
||||
@Schema(description = "支付时间")
|
||||
@Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime paymentTime;
|
||||
|
@ -35,11 +35,13 @@ public class OrderQuery {
|
||||
@Schema(description = "支付方式:0->未支付;1->支付宝;2->微信 精确匹配")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description = "订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单 精确匹配")
|
||||
/**
|
||||
* 订单状态枚举类型见{@link com.wzj.soopin.order.emum.OrderStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "退款状态,枚举值:1:无售后或售后关闭,2:售后处理中,3:退款中,4: 退款成功 精确匹配")
|
||||
private Integer aftersaleStatus;
|
||||
@Schema(description="是否处于退款状态")
|
||||
private Boolean aftersale;
|
||||
|
||||
@Schema(description = "物流公司 精确匹配")
|
||||
private String deliveryCompany;
|
||||
@ -86,9 +88,6 @@ public class OrderQuery {
|
||||
@Schema(description = "确认收货状态:0->未确认;1->已确认 精确匹配")
|
||||
private Integer confirmStatus;
|
||||
|
||||
@Schema(description = "删除状态:0->未删除;1->已删除 精确匹配")
|
||||
private Integer deleteStatus;
|
||||
|
||||
@Schema(description = "支付时间 精确匹配")
|
||||
private LocalDateTime paymentTime;
|
||||
|
||||
|
@ -38,8 +38,8 @@ public class ManagerOrderVO {
|
||||
@Schema(name = "status", description = "订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单", required = true, implementation = Integer.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "退款状态,枚举值:1:无售后或售后关闭,2:售后处理中,3:退款中,4: 退款成功")
|
||||
private Integer aftersaleStatus;
|
||||
@Schema(description="是否处于退款状态")
|
||||
private Boolean aftersale;
|
||||
|
||||
@Schema(name = "pic", description = "商品图片", required = true, implementation = String.class)
|
||||
private String pic;
|
||||
@ -119,8 +119,8 @@ public class ManagerOrderVO {
|
||||
if (status != null) {
|
||||
queryWrapper.eq(Order::getStatus, status);
|
||||
}
|
||||
if (aftersaleStatus != null) {
|
||||
queryWrapper.eq(Order::getAftersaleStatus, aftersaleStatus);
|
||||
if (aftersale != null) {
|
||||
queryWrapper.eq(Order::getAftersale, aftersale);
|
||||
}
|
||||
if (totalAmount != null) {
|
||||
queryWrapper.eq(Order::getTotalAmount, totalAmount);
|
||||
|
@ -61,13 +61,13 @@ public class OrderVO extends BaseAudit {
|
||||
@Excel(name = "支付方式:0->未支付;1->支付宝;2->微信")
|
||||
private Integer payType;
|
||||
|
||||
@Schema(description ="订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单")
|
||||
@Excel(name = "订单状态:0->待付款;1->待发货;2->已发货;3->已完成;4->已关闭;5->无效订单")
|
||||
/**
|
||||
* 订单状态枚举类型见{@link com.wzj.soopin.order.emum.OrderStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
@Schema(description ="退款状态,枚举值:1:无售后或售后关闭,2:售后处理中,3:退款中,4: 退款成功")
|
||||
@Excel(name = "退款状态,枚举值:1:无售后或售后关闭,2:售后处理中,3:退款中,4: 退款成功")
|
||||
private Integer aftersaleStatus;
|
||||
@Schema(description="是否处于退款状态")
|
||||
private Boolean aftersale;
|
||||
|
||||
|
||||
@Schema(description ="省份/直辖市")
|
||||
@ -102,11 +102,6 @@ public class OrderVO extends BaseAudit {
|
||||
@Excel(name = "订单备注")
|
||||
private String note;
|
||||
|
||||
|
||||
@Schema(description ="发删除状态:0->未删除;1->已删除")
|
||||
@Excel(name = "删除状态:0->未删除;1->已删除")
|
||||
private Integer deleteStatus;
|
||||
|
||||
@Schema(description ="支付时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
|
@ -0,0 +1,22 @@
|
||||
package com.wzj.soopin.order.emum;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 售后状态枚举
|
||||
* 0->待处理;1->退款中;2->已退款;3->已拒绝
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum AftersaleStatus {
|
||||
|
||||
UNPAID(0, "待处理"),
|
||||
VERIFY(1, "退款中"),
|
||||
PAID(2, "已退款"),
|
||||
CLOSED(3, "已拒绝");
|
||||
|
||||
private final Integer code;
|
||||
|
||||
private final String desc;
|
||||
}
|
@ -4,7 +4,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 订单状态:0->待付款;1->待核销;2->已完成;3->已关闭;4->退款中;5->已退款 6->已取消 9->已分账;10->无效订单 精确匹配
|
||||
* 订单状态:0->待付款;1->待核销;2->已支付;3->已关闭;4->退款中;5->已退款 6->已取消 9->已分账;10->无效订单 精确匹配
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
|
@ -39,7 +39,7 @@ public interface OrderMapper extends BaseMapper<Order> {
|
||||
|
||||
@Select("SELECT " +
|
||||
"COUNT(*) AS count1, " +
|
||||
"SUM(CASE WHEN aftersale_status = 2 THEN 1 ELSE 0 END) AS count2 " +
|
||||
"SUM(aftersale = 1) AS count2 " +
|
||||
"FROM oms_order")
|
||||
Map<String, Object> countOrder();
|
||||
|
||||
|
@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.wzj.soopin.order.domain.bo.OrderBo;
|
||||
import com.wzj.soopin.order.domain.bo.RefundBO;
|
||||
import com.wzj.soopin.order.domain.bo.SaveOrderBO;
|
||||
import com.wzj.soopin.order.domain.entity.Order;
|
||||
import com.wzj.soopin.order.domain.vo.ManagerOrderDetailVO;
|
||||
@ -32,7 +33,5 @@ public interface OrderService extends IService<Order> {
|
||||
|
||||
void cancel(Long orderId);
|
||||
|
||||
R refund(Long orderId, String reason);
|
||||
|
||||
|
||||
void refund(RefundBO refundBO);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.wzj.soopin.goods.domain.entity.Product;
|
||||
@ -22,6 +23,7 @@ import com.wzj.soopin.member.domain.po.Member;
|
||||
import com.wzj.soopin.member.mapper.MemberMapper;
|
||||
import com.wzj.soopin.member.mapper.MemberWechatMapper;
|
||||
import com.wzj.soopin.order.domain.bo.OrderBo;
|
||||
import com.wzj.soopin.order.domain.bo.RefundBO;
|
||||
import com.wzj.soopin.order.domain.bo.SaveOrderBO;
|
||||
import com.wzj.soopin.order.domain.bo.SaveOrderSkuItemBO;
|
||||
import com.wzj.soopin.order.domain.entity.*;
|
||||
@ -29,6 +31,7 @@ import com.wzj.soopin.order.domain.form.DeliverProductForm;
|
||||
import com.wzj.soopin.order.domain.form.ManagerOrderQueryForm;
|
||||
import com.wzj.soopin.order.domain.query.OrderH5Query;
|
||||
import com.wzj.soopin.order.domain.vo.*;
|
||||
import com.wzj.soopin.order.emum.AftersaleStatus;
|
||||
import com.wzj.soopin.order.emum.OrderStatusEnum;
|
||||
import com.wzj.soopin.order.mapper.*;
|
||||
import com.wzj.soopin.order.service.OrderService;
|
||||
@ -48,6 +51,7 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
@ -58,7 +62,6 @@ import java.util.stream.Collectors;
|
||||
/**
|
||||
* 订单表Service业务层处理
|
||||
*
|
||||
*
|
||||
* @author zcc
|
||||
*/
|
||||
@Service
|
||||
@ -66,21 +69,30 @@ import java.util.stream.Collectors;
|
||||
@RequiredArgsConstructor
|
||||
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
|
||||
private final OrderMapper orderMapper;
|
||||
|
||||
private final OrderItemMapper orderItemMapper;
|
||||
|
||||
private final SkuMapper skuMapper;
|
||||
|
||||
private final ProductMapper productMapper;
|
||||
|
||||
private final OrderOperateHistoryMapper orderOperateHistoryMapper;
|
||||
|
||||
private final MemberMapper memberMapper;
|
||||
|
||||
private final OrderDeliveryHistoryMapper orderDeliveryHistoryMapper;
|
||||
|
||||
private final SysTenantMapper sysTenantMapper;
|
||||
|
||||
private final AftersaleMapper aftersaleMapper;
|
||||
|
||||
private final AftersaleItemMapper aftersaleItemMapper;
|
||||
|
||||
/**
|
||||
* 订单前缀
|
||||
*/
|
||||
private final static String ORDER_SN_PREFIX = "WZJ";
|
||||
|
||||
private final ProductMapper productMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 查询订单表
|
||||
@ -95,7 +107,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
Assert.notNull(order, () -> new ServiceException("无该订单信息"));
|
||||
|
||||
|
||||
|
||||
ManagerOrderDetailVO managerOrderDetailVO = new ManagerOrderDetailVO();
|
||||
//封装订单信息
|
||||
managerOrderDetailVO.setOrderId(id);
|
||||
@ -157,7 +168,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
* 查询订单表列表
|
||||
*
|
||||
* @param query 查询条件
|
||||
* @param page 分页条件
|
||||
* @param page 分页条件
|
||||
* @return 订单表
|
||||
*/
|
||||
public PageImpl<ManagerOrderVO> selectList(ManagerOrderQueryForm query, Pageable page) {
|
||||
@ -168,16 +179,16 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
//// query.setUserPhone(AesCryptoUtils.encrypt(aesKey, query.getUserPhone()));
|
||||
// }
|
||||
List<ManagerOrderVO> managerOrderVOList = orderMapper.selectManagerOrderPage(query);
|
||||
if (CollectionUtil.isEmpty(managerOrderVOList)){
|
||||
if (CollectionUtil.isEmpty(managerOrderVOList)) {
|
||||
return new PageImpl<>(managerOrderVOList, page, 0);
|
||||
}
|
||||
long total = managerOrderVOList.size();
|
||||
Map<Long, ManagerOrderVO> orderMap = managerOrderVOList.stream().collect(Collectors.toMap(ManagerOrderVO::getId, it -> it, (v1,v2) -> v2, LinkedHashMap::new));
|
||||
long total = managerOrderVOList.size();
|
||||
Map<Long, ManagerOrderVO> orderMap = managerOrderVOList.stream().collect(Collectors.toMap(ManagerOrderVO::getId, it -> it, (v1, v2) -> v2, LinkedHashMap::new));
|
||||
//查orderItem
|
||||
QueryWrapper<OrderItem> qw = new QueryWrapper<>();
|
||||
qw.in("order_id", orderMap.keySet());
|
||||
Map<Long, List<OrderItem>> groupedOrderItemMap = orderItemMapper.selectList(qw)
|
||||
.stream().collect(Collectors.groupingBy(OrderItem::getOrderId));
|
||||
.stream().collect(Collectors.groupingBy(OrderItem::getOrderId));
|
||||
groupedOrderItemMap.keySet().forEach(key -> {
|
||||
ManagerOrderVO managerOrderVO = orderMap.get(key);
|
||||
managerOrderVO.setBuyNum(0);
|
||||
@ -206,6 +217,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public OrderVO saveOrder(SaveOrderBO saveOrderBO) {
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
List<SaveOrderSkuItemBO> skuItemBOList = saveOrderBO.getSkuItemBOList();
|
||||
@ -217,6 +229,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
.stream().collect(Collectors.toMap(Product::getId, it -> it, (v1, v2) -> v2, LinkedHashMap::new));
|
||||
for (Sku sku : skus) {
|
||||
Integer quantity = map.get(sku.getId());
|
||||
Assert.isTrue(quantity < sku.getStock(), () -> new ServiceException("下单商品库存不足"));
|
||||
skuMapper.updateStockById(sku.getId(), LocalDateTime.now(), quantity);
|
||||
BigDecimal multiply = sku.getPrice().multiply(new BigDecimal(quantity));
|
||||
totalAmount = totalAmount.add(multiply);
|
||||
}
|
||||
@ -240,7 +254,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
.skuId(sku.getId())
|
||||
.productName(product != null ? product.getName() : "")
|
||||
.pic(sku.getPic())
|
||||
.salePrice(product != null ? product.getPrice() : null)
|
||||
.salePrice(sku.getPrice())
|
||||
.quantity(map.get(sku.getId()))
|
||||
.build();
|
||||
}).toList();
|
||||
@ -257,6 +271,52 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
orderMapper.updateById(Order.builder().id(orderId).status(OrderStatusEnum.CLOSED.getValue()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refund(RefundBO refundBO) {
|
||||
Long orderId = refundBO.getOrderId();
|
||||
String refundReason = refundBO.getRefundReason();
|
||||
List<RefundBO.RefundItemBO> refundItemBoList = refundBO.getRefundItemBoList();
|
||||
Order order = refundBO.getOrder();
|
||||
// 修改订单状态
|
||||
orderMapper.updateById(Order.builder()
|
||||
.id(orderId)
|
||||
.aftersale(false)
|
||||
.payAmount(order.getPayAmount().subtract(refundBO.getTotalRefundAmount()))
|
||||
.status(OrderStatusEnum.REFUNDED_SUCCESS.getValue())
|
||||
.build());
|
||||
|
||||
// 更新售后记录
|
||||
Aftersale aftersale = aftersaleMapper.selectOne(Wrappers.lambdaQuery(Aftersale.class)
|
||||
.eq(Aftersale::getOrderId, orderId).last("limit 1"));
|
||||
if(aftersale == null){
|
||||
aftersale = new Aftersale();
|
||||
aftersale.setMemberId(order.getMemberId());
|
||||
aftersale.setOrderId(orderId);
|
||||
aftersale.setReturnAmount(refundBO.getTotalRefundAmount());
|
||||
aftersale.setQuantity(refundItemBoList.size());
|
||||
aftersale.setType(1);
|
||||
aftersale.setStatus(AftersaleStatus.PAID.getCode());
|
||||
aftersale.setReason(refundReason);
|
||||
aftersale.setAuthFlag(2);
|
||||
aftersaleMapper.insert(aftersale);
|
||||
}else{
|
||||
aftersale.setReturnAmount(refundBO.getTotalRefundAmount());
|
||||
aftersale.setStatus(AftersaleStatus.PAID.getCode());
|
||||
aftersale.setQuantity(refundItemBoList.size());
|
||||
aftersaleMapper.updateById(aftersale);
|
||||
}
|
||||
Long aftersaleId = aftersale.getId();
|
||||
List<AftersaleItem> aftersaleItems = refundItemBoList.stream().map(item -> AftersaleItem.builder()
|
||||
.aftersaleId(aftersaleId)
|
||||
.memberId(order.getMemberId())
|
||||
.orderId(orderId)
|
||||
.orderItemId(item.getOrderItemId())
|
||||
.returnAmount(item.getRefundAmount())
|
||||
.quantity(item.getQuantity())
|
||||
.build()).toList();
|
||||
aftersaleItemMapper.insert(aftersaleItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单sn
|
||||
*/
|
||||
@ -275,17 +335,15 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
* @return 结果
|
||||
*/
|
||||
public R<Order> update(Order order) {
|
||||
int update = orderMapper.updateById(order);
|
||||
if (update>1){
|
||||
int update = orderMapper.updateById(order);
|
||||
if (update > 1) {
|
||||
return R.fail("订单修改失败");
|
||||
}else {
|
||||
} else {
|
||||
return R.ok(order);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public R saveMerchantNote(Order order) {
|
||||
// 1. 查询现有订单
|
||||
@ -301,7 +359,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
int affectedRows = orderMapper.update(null, qw);
|
||||
|
||||
if (affectedRows > 0) {
|
||||
orderMapper.selectById(order.getId());
|
||||
orderMapper.selectById(order.getId());
|
||||
return R.ok();
|
||||
}
|
||||
return R.fail("更新失败");
|
||||
@ -357,7 +415,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
public IPage<OrderVO> getlist(Page<Order> page, OrderBo query) {
|
||||
|
||||
Long tenantId = Long.valueOf(LoginHelper.getTenantId());
|
||||
IPage<OrderVO> resultPage = orderMapper.getlist(page,query,tenantId);
|
||||
IPage<OrderVO> resultPage = orderMapper.getlist(page, query, tenantId);
|
||||
List<OrderVO> orderVOList = resultPage.getRecords();
|
||||
if (orderVOList.isEmpty()) {
|
||||
return resultPage;
|
||||
@ -415,7 +473,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
|
||||
@Override
|
||||
public Order getByNo(String orderNo) {
|
||||
return baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderSn,orderNo));
|
||||
return baseMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderSn, orderNo));
|
||||
}
|
||||
|
||||
// public void sendMessage(Order order) {
|
||||
@ -440,49 +498,5 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 处理退款逻辑
|
||||
* @param orderId 订单ID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R refund(Long orderId, String reason) {
|
||||
if (orderId == null) {
|
||||
return R.fail("订单ID不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
// 根据订单ID获取订单信息
|
||||
Order order = orderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
return R.fail("未找到对应订单");
|
||||
}
|
||||
if (order.getAftersaleStatus() !=1){
|
||||
return R.fail("订单未处于待售后状态");
|
||||
}
|
||||
|
||||
// // 设置售后状态
|
||||
order.setAftersaleStatus(2);
|
||||
orderMapper.updateById(order);
|
||||
|
||||
// 创建售后记录
|
||||
Aftersale aftersale = new Aftersale();
|
||||
aftersale.setMemberId(order.getMemberId());
|
||||
aftersale.setOrderId(orderId);
|
||||
aftersale.setReturnAmount(order.getPayAmount());
|
||||
aftersale.setQuantity(1);
|
||||
aftersale.setType(1);
|
||||
aftersale.setStatus(0);
|
||||
aftersale.setReason(reason);
|
||||
aftersale.setAuthFlag(0);
|
||||
|
||||
aftersaleMapper.insert(aftersale);
|
||||
|
||||
return R.ok("退款申请已提交",aftersale);
|
||||
} catch (Exception e) {
|
||||
log.error("处理退款时出错,订单ID: " + orderId, e);
|
||||
return R.fail("退款处理失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="payAmount" column="pay_amount"/>
|
||||
<result property="payType" column="pay_type"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="aftersaleStatus" column="aftersale_status"/>
|
||||
<result property="aftersale" column="aftersale"/>
|
||||
<result property="deliveryCompany" column="delivery_company"/>
|
||||
<result property="deliverySn" column="delivery_sn"/>
|
||||
<result property="autoConfirmDay" column="auto_confirm_day"/>
|
||||
@ -29,7 +29,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="receiverDetailAddress" column="receiver_detail_address"/>
|
||||
<result property="note" column="note"/>
|
||||
<result property="confirmStatus" column="confirm_status"/>
|
||||
<result property="deleteStatus" column="delete_status"/>
|
||||
<result property="paymentTime" column="payment_time"/>
|
||||
<result property="deliveryTime" column="delivery_time"/>
|
||||
<result property="receiveTime" column="receive_time"/>
|
||||
@ -44,7 +43,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectOrderVo">
|
||||
select id, member_id, member_username, total_amount, purchase_price, pay_amount, freight_amount, pay_type, status, aftersale_status, delivery_company, delivery_sn, auto_confirm_day, receiver_name, receiver_phone, receiver_post_code, receiver_province, receiver_city, receiver_district, receiver_province_id, receiver_city_id, receiver_district_id, receiver_detail_address, note, confirm_status, delete_status, payment_time, delivery_time, receive_time, create_by, create_time, update_by, update_time from oms_order
|
||||
select id, member_id, member_username, total_amount, purchase_price, pay_amount, freight_amount, pay_type, status, aftersale, delivery_company, delivery_sn, auto_confirm_day, receiver_name, receiver_phone, receiver_post_code, receiver_province, receiver_city, receiver_district, receiver_province_id, receiver_city_id, receiver_district_id, receiver_detail_address, note, confirm_status, payment_time, delivery_time, receive_time, create_by, create_time, update_by, update_time from oms_order
|
||||
</sql>
|
||||
<update id="cancelBatch">
|
||||
<foreach collection="list" item="item" index="index" open="" close="" separator=";">
|
||||
@ -94,7 +93,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
select
|
||||
a.id,
|
||||
a.order_sn orderSn,
|
||||
a.aftersale_status aftersaleStatus,
|
||||
a.aftersale aftersale,
|
||||
a.status,
|
||||
a.member_username userName,
|
||||
a.total_amount totalAmount,
|
||||
@ -125,7 +124,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
from oms_order a
|
||||
-- left join oms_order_item b on a.id = b.order_id
|
||||
left join ums_member c on a.member_id = c.id
|
||||
where a.aftersale_status = 1
|
||||
where a.aftersale = 1
|
||||
<if test="orderSn != null and orderSn != ''">
|
||||
and a.order_sn = #{orderSn}
|
||||
</if>
|
||||
@ -165,7 +164,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
total_amount,
|
||||
pay_amount,
|
||||
status,
|
||||
aftersale_status,
|
||||
aftersale,
|
||||
note,
|
||||
delivery_sn,
|
||||
coupon_amount,
|
||||
@ -186,10 +185,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</if>
|
||||
<if test="status>-1 and status<3">
|
||||
and status=#{status}
|
||||
and aftersale_status=1
|
||||
</if>
|
||||
<if test="status==-2">
|
||||
and aftersale_status in (2, 3)
|
||||
</if>
|
||||
order by create_time desc
|
||||
</select>
|
||||
@ -203,7 +198,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
pay_amount,
|
||||
coupon_amount,
|
||||
status,
|
||||
aftersale_status,
|
||||
aftersale,
|
||||
note,
|
||||
delivery_sn,
|
||||
create_time,
|
||||
@ -216,15 +211,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
receiver_detail_address
|
||||
from oms_order
|
||||
where
|
||||
delete_status=0
|
||||
and id=#{orderId}
|
||||
id=#{orderId}
|
||||
</select>
|
||||
<select id="countByStatusAndMemberId" resultType="com.wzj.soopin.order.domain.vo.CountOrderVO">
|
||||
select
|
||||
IFNULL(sum(case when status=0 and aftersale_status=1 then 1 else 0 end),0) unpaid,
|
||||
IFNULL(sum(case when status=1 and aftersale_status=1 then 1 else 0 end),0) nosend,
|
||||
IFNULL(sum(case when status=2 and aftersale_status=1 then 1 else 0 end),0) noget,
|
||||
IFNULL(sum(case when aftersale_status in (2,3) then 1 else 0 end),0) aftersale
|
||||
IFNULL(sum(case when status=0 and aftersale = 1 then 1 else 0 end),0) unpaid,
|
||||
IFNULL(sum(case when status=1 and aftersale=1 then 1 else 0 end),0) nosend,
|
||||
IFNULL(sum(case when status=2 and aftersale=1 then 1 else 0 end),0) noget,
|
||||
IFNULL(sum(case when aftersale in (2,3) then 1 else 0 end),0) aftersale
|
||||
from oms_order
|
||||
where member_id=#{memberId} and delete_status=0
|
||||
</select>
|
||||
@ -233,7 +227,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
IFNULL(count(id), 0) orderCount,
|
||||
IFNULL(sum(pay_amount), 0) orderAmount
|
||||
from oms_order
|
||||
where status in (1,2,3) and aftersale_status=1 and member_id=#{memberId}
|
||||
where status in (1,2,3) and aftersale = 1 and member_id=#{memberId}
|
||||
</select>
|
||||
<select id="statWaitDelivered" resultType="java.lang.Integer">
|
||||
select IFNULL(count(id), 0) from oms_order where status=1 and aftersale_status=1
|
||||
@ -311,8 +305,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="query.withdrawStatus != null and query.withdrawStatus != ''">
|
||||
AND o.withdraw_status LIKE CONCAT('%', #{query.withdrawStatus}, '%')
|
||||
</if>
|
||||
<if test="query.aftersaleStatus != null and query.aftersaleStatus != ''">
|
||||
AND o.aftersale_status LIKE CONCAT('%', #{query.aftersaleStatus}, '%')
|
||||
<if test="query.aftersale != null and query.aftersale != ''">
|
||||
AND o.aftersale LIKE CONCAT('%', #{query.aftersale}, '%')
|
||||
</if>
|
||||
<if test="query.startTime != null">
|
||||
AND o.create_time >= #{query.startTime, jdbcType=TIMESTAMP}
|
||||
|
@ -277,7 +277,7 @@ public class SysTenantServiceImpl implements ISysTenantService {
|
||||
SysUser user = new SysUser();
|
||||
user.setTenantId(tenantId);
|
||||
user.setUserName(bo.getUsername());
|
||||
user.setNickName(bo.getUsername());
|
||||
user.setNickName(bo.getContactUserName());
|
||||
user.setPassword(BCrypt.hashpw(bo.getPassword()));
|
||||
user.setDeptId(deptId);
|
||||
user.setPhonenumber(bo.getContactPhone());
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.wzj.soopin.transaction.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import com.wzj.soopin.transaction.domain.bo.MerchantAddBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.PaymentBO;
|
||||
import com.wzj.soopin.order.domain.bo.RefundBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.EasyPayRequest;
|
||||
import com.wzj.soopin.transaction.domain.vo.EasypayTransResultVO;
|
||||
import com.wzj.soopin.transaction.domain.vo.EasypayPrePayVO;
|
||||
@ -80,13 +80,13 @@ public class TransEasypayController {
|
||||
/**
|
||||
* 实时退款
|
||||
*
|
||||
* @param orderId 订单id
|
||||
* @param refundBO 退款信息
|
||||
*/
|
||||
@Log(title = "易生支付-实时退款", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/refund/{orderId}")
|
||||
@SaCheckPermission(value = "trans:easypay:refund",mode = SaMode.OR, orRole = TenantConstants.TENANT_ADMIN_ROLE_KEY)
|
||||
public R refund(@PathVariable("orderId") Long orderId) throws ServerException {
|
||||
easypayService.refund(orderId);
|
||||
public R refund(@RequestBody RefundBO refundBO) throws ServerException {
|
||||
easypayService.refund(refundBO);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import lombok.Data;
|
||||
import org.dromara.common.core.domain.BaseBO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分账规则明细
|
||||
@ -66,22 +67,28 @@ public class DivideDetailBO extends BaseBO<DivideDetail> {
|
||||
*/
|
||||
@Schema(description = "金额分配比例")
|
||||
@ExcelProperty(value = "金额分配比例", order = 5)
|
||||
|
||||
private BigDecimal moneyPercent;
|
||||
/**
|
||||
* 手续费分配比例
|
||||
*/
|
||||
@Schema(description = "手续费分配比例")
|
||||
@ExcelProperty(value = "手续费分配比例", order = 5)
|
||||
|
||||
private BigDecimal feePercent;
|
||||
/**
|
||||
* 账户类型 1 平台 2 商户 3 代理人
|
||||
* */
|
||||
|
||||
/**
|
||||
* 账户类型
|
||||
* */
|
||||
private Integer type;
|
||||
|
||||
|
||||
/**
|
||||
* 分账完成时间
|
||||
*/
|
||||
@Schema(description = "分账完成时间")
|
||||
@ExcelProperty(value = "分账完成时间", order = 5)
|
||||
private LocalDateTime separateTime;
|
||||
|
||||
|
||||
@Schema(description = "账户id")
|
||||
@ExcelProperty(value = "账户id", order = 6)
|
||||
private Long accountId;
|
||||
|
@ -0,0 +1,42 @@
|
||||
package com.wzj.soopin.transaction.domain.bo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 分账回退参数
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class SeparateRefundBO {
|
||||
/**
|
||||
* 支付方式
|
||||
*/
|
||||
private String payType;
|
||||
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 原分账总单流水
|
||||
*/
|
||||
private String oriSeparateBatchTrace;
|
||||
/**
|
||||
* 原分账子单流水号
|
||||
*/
|
||||
private String oriSeparateTrade;
|
||||
/**
|
||||
* 原业务日期
|
||||
*/
|
||||
private String oriTransDate;
|
||||
/**
|
||||
* 回退金额
|
||||
*/
|
||||
private long refundAmount;
|
||||
|
||||
}
|
@ -27,8 +27,7 @@ public class PayInfo {
|
||||
*/
|
||||
private String bizType;
|
||||
/**
|
||||
* 支付方式
|
||||
* @See com.wzj.soopin.transaction.enums.easypay.PayType
|
||||
* 支付方式 见 {@link com.wzj.soopin.transaction.enums.easypay.PayType}
|
||||
*/
|
||||
private String payType;
|
||||
/**
|
||||
|
@ -0,0 +1,57 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.refund.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.PayInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.ReqInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 分账回退请求参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateRefundReqBody {
|
||||
/**
|
||||
* 支付信息
|
||||
*/
|
||||
private PayInfo payInfo;
|
||||
/**
|
||||
* 请求方信息
|
||||
*/
|
||||
private ReqInfo reqInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private ReqOrderInfo reqOrderInfo;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class ReqOrderInfo {
|
||||
/**
|
||||
* 商户订单号,商户生成请求易生的流水号
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 原分账总单流水
|
||||
*/
|
||||
private String oriSeparateBatchTrace;
|
||||
/**
|
||||
* 原分账子单流水号
|
||||
*/
|
||||
private String oriSeparateTrade;
|
||||
/**
|
||||
* 原业务日期
|
||||
*/
|
||||
private String oriTransDate;
|
||||
/**
|
||||
* 回退金额
|
||||
*/
|
||||
private long refundAmount;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.separate.refund.resp;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 分账回退响应参数
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SeparateRefundRespBody {
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private RespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* 返回码信息
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public static class RespOrderInfo {
|
||||
/**
|
||||
* 商户订单号
|
||||
*/
|
||||
private String orgTrace;
|
||||
/**
|
||||
* 原商户订单号
|
||||
*/
|
||||
private String oriOrgTrace;
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package com.wzj.soopin.transaction.domain.bo.easypay.trade.notice.req;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.jsapi.req.Promo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.RespStateInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易结果通知请求体
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class TradeNoticeReqBody {
|
||||
/**
|
||||
* ali业务参数
|
||||
*/
|
||||
private AliQueryRespParamInfoVO aliRespParamInfo;
|
||||
/**
|
||||
* toC营销信息
|
||||
*/
|
||||
private List<MarketingParamInfo> marketingRespParamInfoList;
|
||||
/**
|
||||
* toB营销信息
|
||||
*/
|
||||
private List<Promo> promos;
|
||||
/**
|
||||
* 银联业务参数
|
||||
*/
|
||||
private QrRespParamInfoVO qrRespParamInfo;
|
||||
/**
|
||||
* 基础订单信息
|
||||
*/
|
||||
private TradeQueryRespOrderInfo respOrderInfo;
|
||||
/**
|
||||
* 返回码信息,规则详见F.1
|
||||
*/
|
||||
private RespStateInfo respStateInfo;
|
||||
/**
|
||||
* 风险控制信息
|
||||
*/
|
||||
private RiskInfo riskParamInfo;
|
||||
/**
|
||||
* 清算信息
|
||||
*/
|
||||
private SettleRespParamInfo settleRespParamInfo;
|
||||
/**
|
||||
* wx业务参数
|
||||
*/
|
||||
private WxQueryRespParamInfoVO wxRespParamInfo;
|
||||
}
|
@ -9,9 +9,9 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.dromara.common.core.domain.model.BaseAudit;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分账规则明细
|
||||
@ -95,6 +95,13 @@ public class DivideDetail extends BaseAudit {
|
||||
@ExcelProperty(value = "分账子单流水号", order = 5)
|
||||
private String separateTrade;
|
||||
|
||||
/**
|
||||
* 分账完成时间
|
||||
*/
|
||||
@Schema(description = "分账完成时间")
|
||||
@ExcelProperty(value = "分账完成时间", order = 5)
|
||||
private LocalDateTime separateTime;
|
||||
|
||||
@Schema(description = "账户code")
|
||||
@ExcelProperty(value = "账户code", order = 6)
|
||||
private String accountCode;
|
||||
|
@ -8,6 +8,7 @@ import org.dromara.common.core.domain.model.BaseAudit;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分账规则明细
|
||||
@ -53,6 +54,22 @@ public class DivideDetailVO extends BaseEntity {
|
||||
@Schema(description = "手续费")
|
||||
@ExcelProperty(value = "手续费", order = 5)
|
||||
private BigDecimal fee;
|
||||
|
||||
/**
|
||||
* 分账完成时间
|
||||
*/
|
||||
@Schema(description = "分账完成时间")
|
||||
@ExcelProperty(value = "分账完成时间", order = 5)
|
||||
private LocalDateTime separateTime;
|
||||
|
||||
/**
|
||||
* 分账子单流水号
|
||||
*/
|
||||
@Schema(description = "分账子单流水号")
|
||||
@ExcelProperty(value = "分账子单流水号", order = 5)
|
||||
private String separateTrade;
|
||||
|
||||
|
||||
/**
|
||||
* 金额分配比例
|
||||
*/
|
||||
@ -65,12 +82,12 @@ public class DivideDetailVO extends BaseEntity {
|
||||
*/
|
||||
@Schema(description = "手续费分配比例")
|
||||
@ExcelProperty(value = "手续费分配比例", order = 5)
|
||||
|
||||
private BigDecimal feePercent;
|
||||
/**
|
||||
* 账户类型 1 平台 2 商户 3 代理人
|
||||
* */
|
||||
|
||||
/**
|
||||
* 账户类型
|
||||
*
|
||||
* */
|
||||
private Integer type;
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@ public enum DivideStatus {
|
||||
PROCESSING(1, "分账中"),
|
||||
SUCCESS(2, "分账成功"),
|
||||
FAIL(3, "分账失败"),
|
||||
REFUNDED(4, "已退款");
|
||||
REFUNDED(4, "已回退");
|
||||
|
||||
private final int code;
|
||||
|
||||
|
@ -18,8 +18,5 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface DivideDetailMapper extends BaseMapperPlus<DivideDetail, DivideDetailVO> {
|
||||
|
||||
@Select("select * from trans_divide_detail where divide_id = #{divideId} and del_flag = '0' ")
|
||||
List<DivideDetail> selectByDivideId(@Param("divideId") Long divideId);
|
||||
|
||||
BigDecimal getMoney(@Param("accountId") Long accountId, @Param("status") Integer status);
|
||||
}
|
||||
|
@ -3,7 +3,9 @@ package com.wzj.soopin.transaction.service;
|
||||
|
||||
import com.wzj.soopin.transaction.domain.bo.MerchantAddBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.PaymentBO;
|
||||
import com.wzj.soopin.order.domain.bo.RefundBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.SeparateApplyBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.SeparateRefundBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.EasyPayRequest;
|
||||
import com.wzj.soopin.transaction.domain.vo.EasypayAccountVO;
|
||||
import com.wzj.soopin.transaction.domain.vo.EasypayTransResultVO;
|
||||
@ -38,9 +40,9 @@ public interface IEasypayService {
|
||||
|
||||
/**
|
||||
* 易生退款
|
||||
* @param orderId
|
||||
* @param refundBO
|
||||
*/
|
||||
void refund(Long orderId);
|
||||
void refund(RefundBO refundBO);
|
||||
|
||||
/**
|
||||
* 退款查询
|
||||
@ -64,6 +66,8 @@ public interface IEasypayService {
|
||||
|
||||
void merchantBinding(String mchtCode);
|
||||
|
||||
boolean separateRefund(SeparateRefundBO separateRefundBO);
|
||||
|
||||
/**
|
||||
* 获取易生账户
|
||||
* @param memberId
|
||||
|
@ -153,8 +153,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
|
||||
if (divide == null) {
|
||||
return null;
|
||||
}
|
||||
divideDetailMapper.selectByDivideId(divideId);
|
||||
List<DivideDetail> detailList = divideDetailMapper.selectByDivideId(divideId);
|
||||
List<DivideDetail> detailList = divideDetailMapper.selectList(Wrappers.lambdaQuery(DivideDetail.class).eq(DivideDetail::getDivideId, divideId));
|
||||
divide.setDetails(detailConvert.toVO(detailList));
|
||||
return divide;
|
||||
}
|
||||
@ -282,7 +281,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
|
||||
.money(sellerAmount)
|
||||
.moneyPercent(divideRate)
|
||||
.feePercent(ruleDetailVO.getFeePercent())
|
||||
.type(DivideRuleDetailType.SELLER.getValue())
|
||||
.type(TenantType.MERCHANT.getType())
|
||||
.status(DivideStatus.PENDING.getCode())
|
||||
.build();
|
||||
divideDetailMapper.insert(divideDetail);
|
||||
@ -323,7 +322,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
|
||||
.money(proxyAmount)
|
||||
.moneyPercent(rule.getMoneyPercent())
|
||||
.feePercent(rule.getFeePercent())
|
||||
.type(DivideRuleDetailType.PROXY.getValue())
|
||||
.type(TenantType.AGENT.getType())
|
||||
.status(DivideStatus.PENDING.getCode())
|
||||
.build();
|
||||
divideDetailMapper.insert(divideDetail);
|
||||
@ -364,7 +363,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
|
||||
.money(referencAmount)
|
||||
.moneyPercent(rule.getMoneyPercent())
|
||||
.feePercent(rule.getFeePercent())
|
||||
.type(DivideRuleDetailType.REFERENCE.getValue())
|
||||
.type(TenantType.REFERENCE.getType())
|
||||
.status(DivideStatus.PENDING.getCode())
|
||||
.build();
|
||||
divideDetailMapper.insert(divideDetail);
|
||||
@ -405,7 +404,7 @@ public class DivideServiceImpl extends ServiceImpl<DivideMapper, Divide> impleme
|
||||
.money(platformAmount)
|
||||
.moneyPercent(rule.getMoneyPercent())
|
||||
.feePercent(rule.getFeePercent())
|
||||
.type(DivideRuleDetailType.PLATFORM.getValue())
|
||||
.type(TenantType.PLATFORM.getType())
|
||||
.status(DivideStatus.PENDING.getCode())
|
||||
.build();
|
||||
divideDetailMapper.insert(divideDetail);
|
||||
|
@ -8,7 +8,6 @@ import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.text.StrBuilder;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.Sign;
|
||||
@ -17,15 +16,17 @@ import cn.hutool.http.HttpRequest;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.wzj.soopin.order.domain.bo.RefundBO;
|
||||
import com.wzj.soopin.order.domain.entity.Order;
|
||||
import com.wzj.soopin.order.domain.entity.OrderItem;
|
||||
import com.wzj.soopin.order.emum.OrderStatusEnum;
|
||||
import com.wzj.soopin.order.mapper.OrderMapper;
|
||||
import com.wzj.soopin.order.service.OrderItemService;
|
||||
import com.wzj.soopin.order.service.OrderService;
|
||||
import com.wzj.soopin.transaction.config.EasypayConfig;
|
||||
import com.wzj.soopin.transaction.config.WechatMiniProgramConfig;
|
||||
import com.wzj.soopin.transaction.domain.bo.MerchantAddBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.PaymentBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.SeparateApplyBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.SeparateItemBO;
|
||||
import com.wzj.soopin.transaction.domain.bo.*;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.*;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.merchant.add.*;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.merchant.binding.MerchantBindingReqBody;
|
||||
@ -39,6 +40,7 @@ import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.req.SeparateR
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp.SeparateApplyRespBody;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp.SeparateRespInfoList;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.separate.apply.resp.SeparateRespOrderInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.separate.refund.resp.SeparateRefundRespBody;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.jsapi.req.*;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.jsapi.resp.JsApiRespBody;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.jsapi.resp.JsapiRespOrderInfo;
|
||||
@ -46,30 +48,27 @@ import com.wzj.soopin.transaction.domain.bo.easypay.trade.jsapi.resp.WxJsApiResp
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.query.req.TradeQueryReqBody;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp.TradeQueryRespBody;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.trade.query.resp.TradeQueryRespOrderInfo;
|
||||
import com.wzj.soopin.transaction.domain.bo.easypay.separate.refund.req.SeparateRefundReqBody;
|
||||
import com.wzj.soopin.transaction.domain.entity.WxAuthResponse;
|
||||
import com.wzj.soopin.transaction.domain.po.Divide;
|
||||
import com.wzj.soopin.transaction.domain.po.DivideDetail;
|
||||
import com.wzj.soopin.transaction.domain.po.DivideRule;
|
||||
import com.wzj.soopin.transaction.domain.po.PayOrder;
|
||||
import com.wzj.soopin.transaction.domain.vo.*;
|
||||
import com.wzj.soopin.transaction.enums.DivideRuleStatus;
|
||||
import com.wzj.soopin.transaction.enums.DivideStatus;
|
||||
import com.wzj.soopin.transaction.enums.TransState;
|
||||
import com.wzj.soopin.transaction.enums.easypay.*;
|
||||
import com.wzj.soopin.transaction.mapper.DivideDetailMapper;
|
||||
import com.wzj.soopin.transaction.mapper.DivideMapper;
|
||||
import com.wzj.soopin.transaction.mapper.DivideRuleMapper;
|
||||
import com.wzj.soopin.transaction.mapper.PayOrderMapper;
|
||||
import com.wzj.soopin.transaction.service.IEasypayService;
|
||||
import com.wzj.soopin.transaction.util.SnowFlake;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.enums.FormatsType;
|
||||
import org.dromara.common.core.enums.TenantType;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.service.ConfigService;
|
||||
import org.dromara.common.core.utils.DateUtils;
|
||||
import org.dromara.common.core.utils.ServletUtils;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -99,7 +98,9 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
|
||||
private final WxAuthService wxAuthService;
|
||||
|
||||
private final OrderMapper orderMapper;
|
||||
private final OrderService orderService;
|
||||
|
||||
private final OrderItemService orderItemService;
|
||||
|
||||
private final PayOrderMapper payOrderMapper;
|
||||
|
||||
@ -196,7 +197,6 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
* 发起支付
|
||||
*
|
||||
* @param paymentBO
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -248,9 +248,10 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
payOrder.setTransState(TransState.PAYMENT.getCode());
|
||||
payOrderMapper.updateById(payOrder);
|
||||
//关联订单的最新支付单
|
||||
orderMapper.updateById(Order.builder()
|
||||
orderService.updateById(Order.builder()
|
||||
.id(payOrder.getOrderId())
|
||||
.payId(payOrder.getId())
|
||||
.payAmount(BigDecimal.valueOf(payOrder.getTransAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))
|
||||
.status(OrderStatusEnum.VERIFY.getValue())
|
||||
.build());
|
||||
// 生成返回前端的预支付信息
|
||||
@ -270,7 +271,6 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 根据支付类型校验请求参数是否完整
|
||||
*
|
||||
@ -321,7 +321,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
* @param apiReqBody
|
||||
*/
|
||||
private PayOrder setReqOrderInfo(JsApiReqBody apiReqBody, PaymentBO paymentBO) {
|
||||
Order order = orderMapper.selectById(paymentBO.getOrderId());
|
||||
Order order = orderService.getById(paymentBO.getOrderId());
|
||||
Assert.notNull(order, () -> new ServiceException("订单不存在"));
|
||||
Assert.isTrue(Objects.equals(order.getStatus(), OrderStatusEnum.UNPAID.getValue()), () -> new ServiceException("订单已支付"));
|
||||
// 订单中的金额单位为元,需转换为分
|
||||
@ -392,7 +392,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public EasypayTransResultVO paymentQuery(Long orderId) throws ServerException {
|
||||
Order order = orderMapper.selectById(orderId);
|
||||
Order order = orderService.getById(orderId);
|
||||
Assert.notNull(order, () -> new ServiceException("订单不存在"));
|
||||
EasypayTransResultVO paymentResultVO = EasypayTransResultVO.builder()
|
||||
.orderId(order.getId())
|
||||
@ -401,7 +401,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
.transState(TransState.PENDING.getCode())
|
||||
.build();
|
||||
PayOrder payOrder = payOrderMapper.selectById(order.getPayId());
|
||||
if(payOrder == null){
|
||||
if (payOrder == null) {
|
||||
return paymentResultVO;
|
||||
}
|
||||
paymentResultVO.setTransState(TransState.PAYMENT.getCode());
|
||||
@ -448,9 +448,9 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
.transState(TransState.PAID.getCode())
|
||||
.build();
|
||||
payOrderMapper.updateById(payOrderUpdate);
|
||||
orderMapper.updateById(Order.builder()
|
||||
orderService.updateById(Order.builder()
|
||||
.id(order.getId())
|
||||
.status(TransState.PAID.getCode())
|
||||
.status(OrderStatusEnum.PAID.getValue())
|
||||
.build());
|
||||
paymentResultVO.setTransState(TransState.PAID.getCode());
|
||||
}
|
||||
@ -476,7 +476,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
TradeQueryRespOrderInfo respOrderInfo = tradeQueryRespBody.getRespOrderInfo();
|
||||
PayOrder payOrder = payOrderMapper.selectById(String.valueOf(respOrderInfo.getOrgTrace()));
|
||||
if (payOrder != null) {
|
||||
Order order = orderMapper.selectById(payOrder.getOrderId());
|
||||
Order order = orderService.getById(payOrder.getOrderId());
|
||||
if (order != null) {
|
||||
// 支付完成 进入终态
|
||||
if (StrUtil.equalsAny(respStateInfo.getTransState(), RSP_BODY_TRANS_OK, RSP_BODY_TRANS_OK_WETCAT, RSP_BODY_TRANS_PARTIALLY_OK)) {
|
||||
@ -490,7 +490,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
.transState(TransState.PAID.getCode())
|
||||
.build());
|
||||
// 更新订单信息
|
||||
orderMapper.updateById(Order.builder()
|
||||
orderService.updateById(Order.builder()
|
||||
.id(order.getId())
|
||||
.status(OrderStatusEnum.PAID.getValue())
|
||||
.paymentTime(LocalDateTimeUtil.parse(StrBuilder.create(respOrderInfo.getDateEnd()).append(respOrderInfo.getTimeEnd()).toString(), "yyyyMMddHHmmss"))
|
||||
@ -514,17 +514,70 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void refund(Long orderId) {
|
||||
Order order = orderMapper.selectById(orderId);
|
||||
public void refund(RefundBO refundBO) {
|
||||
Long orderId = refundBO.getOrderId();
|
||||
Order order = orderService.getById(orderId);
|
||||
Assert.notNull(order, () -> new ServiceException("订单不存在"));
|
||||
PayOrder payOrder = payOrderMapper.selectById(order.getPayId());
|
||||
Assert.notNull(payOrder, () -> new ServiceException("订单不存在"));
|
||||
Assert.isTrue(payOrder.getTransState() == TransState.PAID.getCode(), () -> new ServiceException("订单未支付,不可发起退款"));
|
||||
// 更新支付订单状态为退款中
|
||||
payOrderMapper.updateById(PayOrder.builder()
|
||||
.id(payOrder.getId())
|
||||
.transState(TransState.REFUND_PENDING.getCode())
|
||||
.build());
|
||||
// 订单已支付或已分账状态才可发起退款
|
||||
boolean orderDivided = Objects.equals(order.getStatus(), OrderStatusEnum.PAID.getValue()) || Objects.equals(order.getStatus(), OrderStatusEnum.DIVIDED.getValue());
|
||||
// 更新商品订单和支付订单状态为退款中
|
||||
orderService.updateById(Order.builder().id(orderId).status(OrderStatusEnum.REFUNDED.getValue()).build());
|
||||
payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.REFUND_PENDING.getCode()).build());
|
||||
refundBO.setOrder(order);
|
||||
List<OrderItem> orderItems = orderItemService.findByOrderId(orderId);
|
||||
BigDecimal refundAmount = BigDecimal.ZERO;
|
||||
List<RefundBO.RefundItemBO> refundItemBoList = refundBO.getRefundItemBoList();
|
||||
for (RefundBO.RefundItemBO refundItemBO : refundItemBoList) {
|
||||
Long orderItemId = refundItemBO.getOrderItemId();
|
||||
OrderItem orderItem = orderItems.stream().filter(item -> item.getId().equals(orderItemId)).findFirst().orElse(null);
|
||||
Assert.notNull(orderItem, () -> new ServiceException("订单项不存在"));
|
||||
Assert.isTrue(refundItemBO.getRefundAmount().compareTo(orderItem.getSalePrice()) <= 0, () -> new ServiceException("订单项退款金额超出支付金额"));
|
||||
refundAmount = refundAmount.add(refundItemBO.getRefundAmount());
|
||||
// 已分账的订单需要先回退订单子项的分账在退款
|
||||
if (orderDivided) {
|
||||
Divide divide = divideMapper.selectOne(Wrappers.lambdaQuery(Divide.class)
|
||||
.eq(Divide::getOrderId, orderId)
|
||||
.eq(Divide::getOrderItemId, orderItemId)
|
||||
.eq(Divide::getStatus, DivideStatus.SUCCESS.getCode())
|
||||
.last("limit 1"));
|
||||
Assert.notNull(divide, () -> new ServiceException("订单项未分账"));
|
||||
List<DivideDetail> detailList = divideDetailMapper.selectList(Wrappers.lambdaQuery(DivideDetail.class).eq(DivideDetail::getDivideId, divide.getId()));
|
||||
Assert.notEmpty(detailList, () -> new ServiceException("未发现订单项分账明细"));
|
||||
//如果退款金额小于实际订单子项金额,回退商家的分账即可
|
||||
if (refundItemBO.getRefundAmount().compareTo(divide.getOrderItemMoney()) < 0) {
|
||||
DivideDetail merchantDivideDetail = detailList.stream().filter(detail -> detail.getType() == TenantType.MERCHANT.getType())
|
||||
.findFirst().orElseThrow(() -> new ServiceException("商家分账信息丢失"));
|
||||
SeparateRefundBO separateRefundBO = SeparateRefundBO.builder()
|
||||
.payType(payOrder.getPayType())
|
||||
.orgTrace(StrBuilder.create(TRACE_PREFIX).append(SnowFlake.getIdStr()).toString())
|
||||
.oriSeparateBatchTrace(divide.getSeparateBatchTrace())
|
||||
.oriSeparateTrade(merchantDivideDetail.getSeparateTrade())
|
||||
.oriTransDate(LocalDateTimeUtil.format(merchantDivideDetail.getSeparateTime(), "yyyyMMdd"))
|
||||
.refundAmount(refundItemBO.getRefundAmount().multiply(BigDecimal.valueOf(100)).longValue())
|
||||
.build();
|
||||
separateRefund(separateRefundBO);
|
||||
} else {
|
||||
// 退款金额等于实际订单子项金额,则回退全部的分账。
|
||||
detailList.forEach(detail -> {
|
||||
// 分账金额(分) = 订单子项实际销售金额(元) * 100 * 分账比例(百分比值 / 100 ) = 订单子项实际销售金额(元) * 分账比例百分比值
|
||||
long amount = orderItem.getSalePrice().multiply(BigDecimal.valueOf(detail.getMoneyPercent())).longValue();
|
||||
SeparateRefundBO separateRefundBO = SeparateRefundBO.builder()
|
||||
.payType(payOrder.getPayType())
|
||||
.orgTrace(StrBuilder.create(TRACE_PREFIX).append(SnowFlake.getIdStr()).toString())
|
||||
.oriSeparateBatchTrace(divide.getSeparateBatchTrace())
|
||||
.oriSeparateTrade(detail.getSeparateTrade())
|
||||
.oriTransDate(LocalDateTimeUtil.format(detail.getSeparateTime(), "yyyyMMdd"))
|
||||
.refundAmount(amount)
|
||||
.build();
|
||||
separateRefund(separateRefundBO);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
refundBO.setTotalRefundAmount(refundAmount);
|
||||
EasyPayRequestHeader reqHeader = generateEasyPayRequestHeader();
|
||||
RefundApplyReqBody refundApplyReqBody = RefundApplyReqBody.builder()
|
||||
.reqInfo(ReqInfo.builder().mchtCode(easypayConfig.getMchtCode()).build())
|
||||
@ -533,7 +586,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
.orgTrace(StrBuilder.create(TRACE_PREFIX).append(SnowFlake.getIdStr()).toString())
|
||||
.oriOrgTrace(String.valueOf(order.getPayId()))
|
||||
.oriTransDate(DateUtils.parseDateToStr(FormatsType.YYYYMMDD, payOrder.getEndTransDate()))
|
||||
.refundAmount(payOrder.getTransAmount())
|
||||
.refundAmount(refundAmount.multiply(BigDecimal.valueOf(100)).longValue())
|
||||
.build())
|
||||
.build();
|
||||
String reqSign = getSignStr(reqHeader, refundApplyReqBody);
|
||||
@ -559,7 +612,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
if (StrUtil.equalsAny(respStateInfo.getTransState(), RSP_BODY_TRANS_OK)) {
|
||||
// 更新支付单退款状态
|
||||
payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.REFUNDED.getCode()).refundDate(new Date()).build());
|
||||
orderMapper.updateStatusById(order.getId(), OrderStatusEnum.REFUNDED.getValue());
|
||||
orderService.refund(refundBO);
|
||||
}
|
||||
} else {
|
||||
log.error("易生退款失败:{}", respStateInfo.getRespDesc());
|
||||
@ -575,7 +628,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
|
||||
@Override
|
||||
public EasypayTransResultVO refundQuery(Long orderId) {
|
||||
Order order = orderMapper.selectById(orderId);
|
||||
Order order = orderService.getById(orderId);
|
||||
Assert.notNull(order, () -> new ServiceException("订单不存在"));
|
||||
PayOrder payOrder = payOrderMapper.selectById(order.getPayId());
|
||||
Assert.notNull(payOrder, () -> new ServiceException("订单不存在"));
|
||||
@ -697,7 +750,6 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
* @param respOrderInfo
|
||||
*/
|
||||
private void handleSeparateInfo(SeparateApplyBO separateApplyBO, SeparateRespOrderInfo respOrderInfo) {
|
||||
Long orderId = separateApplyBO.getOrderId();
|
||||
Map<String, SeparateItemBO> separateItemBOMap = separateApplyBO.getSeparateItemBOList().stream().collect(Collectors.toMap(SeparateItemBO::getSeparateTrade, o -> o));
|
||||
List<DivideDetail> updateDetailList = new ArrayList<>();
|
||||
List<SeparateRespInfoList> separateRespInfoList = respOrderInfo.getSeparateRespInfoList();
|
||||
@ -731,15 +783,17 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
.status(DivideStatus.PROCESSING.getCode()).build();
|
||||
if (itemOkCount == separateItemBOMap.size()) {
|
||||
divideUpdate.setStatus(DivideStatus.SUCCESS.getCode());
|
||||
orderMapper.updateStatusById(orderId, OrderStatusEnum.DIVIDED.getValue());
|
||||
orderService.updateById(Order.builder()
|
||||
.id(separateApplyBO.getOrderId())
|
||||
.status(OrderStatusEnum.DIVIDED.getValue())
|
||||
.build());
|
||||
}
|
||||
divideMapper.updateById(divideUpdate);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 上传图片至易生
|
||||
* 上传图片至易生
|
||||
*/
|
||||
@Override
|
||||
public String merchantPicUpload(MultipartFile pic) throws IOException {
|
||||
@ -782,7 +836,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分账商户
|
||||
* 添加分账商户
|
||||
*/
|
||||
@Override
|
||||
public void merchantAdd(MerchantAddBO merchantAddBO) {
|
||||
@ -828,6 +882,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
|
||||
/**
|
||||
* 绑定分账商户
|
||||
*
|
||||
* @param mchtCode
|
||||
*/
|
||||
@Override
|
||||
@ -857,8 +912,7 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
verify(easyPayResponse.getRspHeader(), easyPayResponse.getRspBody(), easyPayResponse.getRspSign());
|
||||
MerchantAddApplyRespBody merchantAddApplyRespBody = JSON.parseObject(JSONObject.toJSONString(easyPayResponse.getRspBody()), MerchantAddApplyRespBody.class);
|
||||
if (StrUtil.equals(RSP_BODY_RESP_OK, merchantAddApplyRespBody.getRetCode())) {
|
||||
// TODO 更新商户绑定信息
|
||||
// updateMerchantBinding(mchtCode);
|
||||
log.info("绑定商户[{}]成功:{}", mchtCode, merchantAddApplyRespBody.getRetMsg());
|
||||
} else {
|
||||
log.error("绑定商户失败:{}", merchantAddApplyRespBody.getRetMsg());
|
||||
throw new ServiceException("绑定商户失败:" + merchantAddApplyRespBody.getRetMsg());
|
||||
@ -869,6 +923,54 @@ public class EasypayServiceImpl implements IEasypayService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账回退
|
||||
*
|
||||
* @param separateRefundBO
|
||||
*/
|
||||
@Override
|
||||
public boolean separateRefund(SeparateRefundBO separateRefundBO) {
|
||||
boolean flag = false;
|
||||
EasyPayRequestHeader reqHeader = generateEasyPayRequestHeader();
|
||||
SeparateRefundReqBody separateApplyReqBody = SeparateRefundReqBody.builder()
|
||||
.reqInfo(ReqInfo.builder().mchtCode(easypayConfig.getMchtCode()).build())
|
||||
.payInfo(PayInfo.builder().transDate(DateUtils.parseDateToStr(FormatsType.YYYYMMDD, new Date())).payType(separateRefundBO.getPayType()).build())
|
||||
.reqOrderInfo(BeanUtil.copyProperties(separateRefundBO, SeparateRefundReqBody.ReqOrderInfo.class))
|
||||
.build();
|
||||
String reqSign = getSignStr(reqHeader, separateApplyReqBody);
|
||||
EasyPayRequest easyRequest = EasyPayRequest.builder()
|
||||
.reqHeader(reqHeader)
|
||||
.reqBody(separateApplyReqBody)
|
||||
.reqSign(reqSign)
|
||||
.build();
|
||||
log.debug("调用易生分账回退接口请求:{}", JSONObject.toJSONString(easyRequest));
|
||||
String url = StrBuilder.create(easypayConfig.getApiPathPrefix()).append("/trade/separate/cancel").toString();
|
||||
String body = HttpRequest.post(url)
|
||||
.timeout(3000)
|
||||
.body(JSON.toJSONString(easyRequest))
|
||||
.execute()
|
||||
.body();
|
||||
log.debug("调用易生分账回退接口响应:{}", body);
|
||||
EasyPayResponse easyPayResponse = JSONObject.parseObject(body, EasyPayResponse.class);
|
||||
if (StrUtil.equals(RSP_HEADER_OK, easyPayResponse.getRspHeader().getRspCode())) {
|
||||
verify(easyPayResponse.getRspHeader(), easyPayResponse.getRspBody(), easyPayResponse.getRspSign());
|
||||
SeparateRefundRespBody separateRefundRespBody = JSON.parseObject(JSONObject.toJSONString(easyPayResponse.getRspBody()), SeparateRefundRespBody.class);
|
||||
RespStateInfo respStateInfo = separateRefundRespBody.getRespStateInfo();
|
||||
if (StrUtil.equals(RSP_BODY_RESP_OK, respStateInfo.getRespCode())) {
|
||||
if (StrUtil.equalsAny(respStateInfo.getTransState(), RSP_BODY_TRANS_OK)) {
|
||||
flag = true;
|
||||
}
|
||||
} else {
|
||||
log.error("分账回退失败:{}", respStateInfo.getRespDesc());
|
||||
throw new ServiceException("分账回退失败:" + respStateInfo.getRespDesc());
|
||||
}
|
||||
} else {
|
||||
log.error("易生分账回退通讯失败:{}", easyPayResponse.getRspHeader().getRspInfo());
|
||||
throw new ServiceException("易生分账回退通讯失败:" + easyPayResponse.getRspHeader().getRspInfo());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EasypayAccountVO getEasypayAccount(Long memberId) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user