feat(order): 重构核销码逻辑并优化订单查询接口

- 核销码生成与验证逻辑重构,支持按订单项生成多个核销码- 新增核销码状态枚举,完善状态管理(待核销、已核销、已过期、已取消)
- 优化商户端订单列表查询逻辑,区分基于订单和订单项的租户查询
- 更新微信小程序配置appId与secret
- 订单商品查询改为使用sku快照,确保数据一致性
This commit is contained in:
huk 2025-09-23 16:02:08 +08:00
parent a74ed5dde0
commit eeb50d18b1
25 changed files with 325 additions and 371 deletions

View File

@ -70,13 +70,4 @@ public class AppOrderController {
return R.ok(); return R.ok();
} }
@Operation(summary = "生成核销码")
@GetMapping("/generate/{orderId}")
@Tag(name = "生成核销码")
public R generateCode(@PathVariable Long orderId) {
return verificationCodeService.generateVerificationCode(orderId);
}
} }

View File

@ -8,7 +8,7 @@ import com.wzj.soopin.order.domain.vo.OrderVO;
import com.wzj.soopin.order.service.IMerchantOrderService; import com.wzj.soopin.order.service.IMerchantOrderService;
import com.wzj.soopin.order.service.VerificationCodeService; import com.wzj.soopin.order.service.VerificationCodeService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
@ -39,41 +39,24 @@ public class AppMerchantOrderController {
* @return 核销结果 * @return 核销结果
*/ */
@GetMapping("/verify") @GetMapping("/verify")
@Tag(name = "核销接口") @Operation(summary = "扫码核销接口")
public R verifyCode(@RequestParam("code") String code) { public R verifyCode(@RequestParam("code") String code) {
verificationCodeService.verifyCode(code);
LoginUser loginUser = LoginHelper.getLoginUser();
if (loginUser == null) {
return R.fail("用户未登录");
}
if(loginUser.getTenantId() == null){
return R.fail("用户不是商户");
}
verificationCodeService.verifyCode(code, loginUser.getTenantId());
return R.ok("核销成功"); return R.ok("核销成功");
} }
/** /**
* 扫码核销接口 * 查询核销码对应的订单
* @return 核销结果 * @return 核销结果
*/ */
@GetMapping("/scan") @GetMapping("/scan")
@Tag(name = "扫码接口") @Operation(summary = "查询核销码对应的订单")
public R scan(@RequestParam("code") String code) { public R<OrderVO> scan(@RequestParam("code") String code) {
LoginUser loginUser = LoginHelper.getLoginUser();
if (loginUser == null) {
return R.fail("用户未登录");
}
if(loginUser.getTenantId() == null){
return R.fail("用户不是商户");
}
Order order = verificationCodeService.scan(code); Order order = verificationCodeService.scan(code);
return R.ok(orderBusiness.info(order.getId())); return R.ok(orderBusiness.info(order.getId()));
} }
@Tag(name ="查询订单列表")
@PostMapping("/page") @PostMapping("/page")
@Operation(summary = "查询当前商家订单列表")
public R<IPage<OrderVO>> page(@RequestBody OrderBo bo){ public R<IPage<OrderVO>> page(@RequestBody OrderBo bo){
LoginUser loginUser= LoginHelper.getLoginUser(); LoginUser loginUser= LoginHelper.getLoginUser();
bo.setTenantId(loginUser.getTenantId()); bo.setTenantId(loginUser.getTenantId());

View File

@ -385,8 +385,10 @@ wechat:
app-id: wxebcdaea31881caab # 应用ID app-id: wxebcdaea31881caab # 应用ID
secret: your_wechat_secret # 应用密钥 secret: your_wechat_secret # 应用密钥
mini-program: mini-program:
app-id: wx87a5db19138da60d # app-id: wx87a5db19138da60d
secret: 856ca8bae38ccaecc1353c9abedf6b41 # secret: 856ca8bae38ccaecc1353c9abedf6b41
app-id: wx2fb87f0f1f05d314
secret: 86fbcab880e4066ac5c75af6f4f003c2
http: http:
client: client:

View File

@ -4,6 +4,11 @@ package org.dromara.common.core.enums;
* 数字编码前缀扫码用 * 数字编码前缀扫码用
*/ */
public enum CodePrefix { public enum CodePrefix {
/**
* 订单
*/
DD,
/** /**
* 核销 * 核销
*/ */

View File

@ -61,4 +61,16 @@ public final class ServiceException extends RuntimeException {
this.detailMessage = detailMessage; this.detailMessage = detailMessage;
return this; return this;
} }
public static ServiceException of(String message) {
return new ServiceException(message);
}
public static ServiceException of(Integer code, String message) {
return new ServiceException(message, code);
}
public static ServiceException of(ResultCode resultCode) {
return new ServiceException(resultCode);
}
} }

View File

@ -1,13 +1,8 @@
package com.wzj.soopin.order.controller; package com.wzj.soopin.order.controller;
import com.wzj.soopin.order.service.VerificationCodeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@ -23,18 +18,4 @@ import org.springframework.web.bind.annotation.RestController;
public class VerificationCodeController { public class VerificationCodeController {
private final VerificationCodeService verificationCodeService;
/**
* 生成核销码
*/
@GetMapping("/generate/{orderId}")
@Operation(summary = "生成核销码")
public R generateCode(@PathVariable Long orderId) {
return verificationCodeService.generateVerificationCode(orderId);
}
} }

View File

@ -125,7 +125,6 @@ public class Order extends BaseAudit implements Serializable {
@Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") @Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime paymentTime; private LocalDateTime paymentTime;
@Schema(description = "优惠券ID") @Schema(description = "优惠券ID")
private Long memberCouponId; private Long memberCouponId;
@ -144,7 +143,6 @@ public class Order extends BaseAudit implements Serializable {
@Schema(description = "提现状态1->等待转账2->转帐中;3->转账成功;4->转账失败") @Schema(description = "提现状态1->等待转账2->转帐中;3->转账成功;4->转账失败")
private Integer withdrawStatus; private Integer withdrawStatus;
@Schema(description = "配送方式 1->到店核销2->自提;3->配送;") @Schema(description = "配送方式 1->到店核销2->自提;3->配送;")
private Integer distribution; private Integer distribution;

View File

@ -3,15 +3,20 @@ package com.wzj.soopin.order.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.wzj.soopin.order.emum.VerificationCodeStatus;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.*;
import org.dromara.common.core.domain.model.BaseAudit; import org.dromara.common.core.domain.model.BaseAudit;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@EqualsAndHashCode(callSuper = true)
@Schema(description = "核销码表对象") @Schema(description = "核销码表对象")
@Data @Data
@TableName("oms_verification_codes") @TableName("oms_verification_codes")
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class VerificationCodes extends BaseAudit { public class VerificationCodes extends BaseAudit {
@Schema(description = "ID") @Schema(description = "ID")
@ -24,7 +29,13 @@ public class VerificationCodes extends BaseAudit {
@Schema(description = "关联订单id") @Schema(description = "关联订单id")
private Long orderId; private Long orderId;
@Schema(description = "是否使用") @Schema(description = "订单子项id")
private Long orderItemId;
/**
* 状态 {@link VerificationCodeStatus}
*/
@Schema(description = "状态")
private Integer status; private Integer status;
@Schema(description = "用户id") @Schema(description = "用户id")

View File

@ -1,38 +0,0 @@
package com.wzj.soopin.order.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.dromara.common.core.domain.model.BaseAudit;
import java.time.LocalDateTime;
@Schema(description = "核销日志表对象")
@Data
@TableName("oms_verification_logs")
public class VerificationLogs extends BaseAudit {
@Schema(description = "ID")
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@Schema(description = "核销码id")
private Long codeId;
@Schema(description = "订单id")
private Long orderId;
@Schema(description = "商家ID")
private Long merchantId;
@Schema(description = "核销时间")
private LocalDateTime verificationTime;
@Schema(description = "核销结果")
private Integer result;
@Schema(description = "失败原因")
private String reason;
}

View File

@ -4,15 +4,15 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
/** /**
* 订单状态0->待付款1->待核销2->已支付3->已关闭4->退款中5->已退款 6->已取消 9->已分账10->无效订单 精确匹配 * 订单状态0->待付款1->支付中2->待核销3->已关闭4->退款中5->已退款 6->已取消 9->已分账10->无效订单 精确匹配
*/ */
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum OrderStatusEnum { public enum OrderStatusEnum {
UNPAID(0, "待支付"), UNPAID(0, "待支付"),
VERIFY(1, "待核销"), PAYMENT(1, "支付中"),
PAID(2, "已支付"), VERIFY(2, "待核销"),
CLOSED(3, "已关闭"), CLOSED(3, "已关闭"),
REFUNDED(4, "退款中"), REFUNDED(4, "退款中"),
REFUNDED_SUCCESS(5, "已退款"), REFUNDED_SUCCESS(5, "已退款"),

View File

@ -0,0 +1,30 @@
package com.wzj.soopin.order.emum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 核销码状态枚举
*/
@Getter
@AllArgsConstructor
public enum VerificationCodeStatus {
TO_BE_USED(0, "待核销"),
USED(1, "已核销"),
EXPIRED(2, "已过期"),
CANCELLED(3, "已取消");
private final Integer code;
private final String description;
public static VerificationCodeStatus getByCode(Integer code) {
for (VerificationCodeStatus value : VerificationCodeStatus.values()) {
if (value.code.equals(code)) {
return value;
}
}
return null;
}
}

View File

@ -60,4 +60,7 @@ public interface OrderItemMapper extends BaseMapper<OrderItem> {
"ORDER BY total_quantity DESC " + "ORDER BY total_quantity DESC " +
"LIMIT #{limit}") "LIMIT #{limit}")
List<Map<String, Object>> selectTopTradingProducts(int limit); List<Map<String, Object>> selectTopTradingProducts(int limit);
@Select("SELECT * FROM oms_order_item WHERE order_id = #{orderId}")
List<OrderItem> findByOrderId(Long orderId);
} }

View File

@ -35,7 +35,21 @@ public interface OrderMapper extends BaseMapper<Order> {
List<ManagerOrderVO> selectManagerOrderPage(ManagerOrderQueryForm request); List<ManagerOrderVO> selectManagerOrderPage(ManagerOrderQueryForm request);
IPage<OrderVO> getlist(@Param("page") Page<Order> page,@Param("query") OrderBo query); /**
* 通过订单所属租户查询订单列表
* @param page
* @param query
* @return
*/
IPage<OrderVO> getListByOrderTenant(@Param("page") Page<Order> page, @Param("query") OrderBo query);
/**
* 通过订单所属租户查询订单列表
* @param page
* @param query
* @return
*/
IPage<OrderVO> getListByOrderItemTenant(@Param("page") Page<Order> page, @Param("query") OrderBo query);
@Select("SELECT " + @Select("SELECT " +
"COUNT(*) AS count1, " + "COUNT(*) AS count1, " +

View File

@ -3,6 +3,8 @@ package com.wzj.soopin.order.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wzj.soopin.order.domain.entity.VerificationCodes; import com.wzj.soopin.order.domain.entity.VerificationCodes;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Map; import java.util.Map;
@ -16,4 +18,7 @@ public interface VerificationCodesMapper extends BaseMapper<VerificationCodes> {
Map<String, Object> getProduvtNameAndMemberId(String code); Map<String, Object> getProduvtNameAndMemberId(String code);
String getReason(String code); String getReason(String code);
@Select("select * from oms_verification_codes where code = #{code} limit 1")
VerificationCodes getByCode(@Param("code") String code);
} }

View File

@ -1,9 +0,0 @@
package com.wzj.soopin.order.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.wzj.soopin.order.domain.entity.VerificationLogs;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface VerificationLogsMapper extends BaseMapper<VerificationLogs> {
}

View File

@ -3,19 +3,19 @@ package com.wzj.soopin.order.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.wzj.soopin.order.domain.entity.Order; import com.wzj.soopin.order.domain.entity.Order;
import com.wzj.soopin.order.domain.entity.VerificationCodes; import com.wzj.soopin.order.domain.entity.VerificationCodes;
import com.wzj.soopin.order.domain.vo.ManagerOrderDetailVO;
import org.dromara.common.core.domain.R;
import java.util.List; import java.util.List;
public interface VerificationCodeService extends IService<VerificationCodes> { public interface VerificationCodeService extends IService<VerificationCodes> {
R generateVerificationCode(Long orderId); void generateVerificationCode(Order order);
void verifyCode(String code,String tenantId); void verifyCode(String code);
Order scan(String code); Order scan(String code);
List<VerificationCodes> getByOrderId(Long orderId); List<VerificationCodes> getByOrderId(Long orderId);
void Invalid(Long orderId, List<Long> orderItemIdList);
} }

View File

@ -1,7 +0,0 @@
package com.wzj.soopin.order.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.wzj.soopin.order.domain.entity.VerificationLogs;
public interface VerificationLogsService extends IService<VerificationLogs> {
}

View File

@ -1,25 +1,21 @@
package com.wzj.soopin.order.service.impl; package com.wzj.soopin.order.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wzj.soopin.order.domain.entity.OrderItem; import com.wzj.soopin.order.domain.entity.OrderItem;
import com.wzj.soopin.order.mapper.OrderItemMapper; import com.wzj.soopin.order.mapper.OrderItemMapper;
import com.wzj.soopin.order.service.OrderItemService; import com.wzj.soopin.order.service.OrderItemService;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.redis.redis.RedisCache; import org.dromara.common.redis.redis.RedisCache;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wzj.soopin.content.utils.RedisOperator;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
/** /**
* 订单中所包含的商品Service业务层处理 * 订单中所包含的商品Service业务层处理
* *
@ -35,8 +31,7 @@ public class OrderItemServiceImpl extends ServiceImpl<OrderItemMapper, OrderItem
@Override @Override
public List<OrderItem> findByOrderId(Long orderId) { public List<OrderItem> findByOrderId(Long orderId) {
return baseMapper.selectList(new QueryWrapper<OrderItem>().lambda() return baseMapper.findByOrderId(orderId);
.eq(OrderItem::getOrderId, orderId));
} }
@Override @Override

View File

@ -16,8 +16,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.goods.domain.entity.Product; import com.wzj.soopin.goods.domain.entity.Product;
import com.wzj.soopin.goods.domain.entity.Sku; import com.wzj.soopin.goods.domain.entity.Sku;
import com.wzj.soopin.goods.domain.entity.SkuSnapshot;
import com.wzj.soopin.goods.mapper.ProductMapper; import com.wzj.soopin.goods.mapper.ProductMapper;
import com.wzj.soopin.goods.mapper.SkuMapper; import com.wzj.soopin.goods.mapper.SkuMapper;
import com.wzj.soopin.goods.mapper.SkuSnapshotMapper;
import com.wzj.soopin.member.domain.po.Member; import com.wzj.soopin.member.domain.po.Member;
import com.wzj.soopin.member.mapper.MemberMapper; import com.wzj.soopin.member.mapper.MemberMapper;
import com.wzj.soopin.order.domain.bo.OrderBo; import com.wzj.soopin.order.domain.bo.OrderBo;
@ -31,6 +33,7 @@ import com.wzj.soopin.order.emum.AftersaleStatus;
import com.wzj.soopin.order.emum.OrderStatusEnum; import com.wzj.soopin.order.emum.OrderStatusEnum;
import com.wzj.soopin.order.mapper.*; import com.wzj.soopin.order.mapper.*;
import com.wzj.soopin.order.service.OrderService; import com.wzj.soopin.order.service.OrderService;
import com.wzj.soopin.order.service.VerificationCodeService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
@ -41,6 +44,7 @@ import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.domain.SysTenant; import org.dromara.system.domain.SysTenant;
import org.dromara.system.mapper.SysTenantMapper; import org.dromara.system.mapper.SysTenantMapper;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@ -68,20 +72,22 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
private final SkuMapper skuMapper; private final SkuMapper skuMapper;
private final SkuSnapshotMapper skuSnapshotMapper;
private final ProductMapper productMapper; private final ProductMapper productMapper;
private final OrderOperateHistoryMapper orderOperateHistoryMapper; private final OrderOperateHistoryMapper orderOperateHistoryMapper;
private final MemberMapper memberMapper; private final MemberMapper memberMapper;
private final OrderDeliveryHistoryMapper orderDeliveryHistoryMapper;
private final SysTenantMapper sysTenantMapper; private final SysTenantMapper sysTenantMapper;
private final AftersaleMapper aftersaleMapper; private final AftersaleMapper aftersaleMapper;
private final AftersaleItemMapper aftersaleItemMapper; private final AftersaleItemMapper aftersaleItemMapper;
private final VerificationCodeService verificationCodeService;
/** /**
* 订单前缀 * 订单前缀
*/ */
@ -100,7 +106,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
Order order = orderMapper.selectById(id); Order order = orderMapper.selectById(id);
Assert.notNull(order, () -> new ServiceException("无该订单信息")); Assert.notNull(order, () -> new ServiceException("无该订单信息"));
ManagerOrderDetailVO managerOrderDetailVO = new ManagerOrderDetailVO(); ManagerOrderDetailVO managerOrderDetailVO = new ManagerOrderDetailVO();
//封装订单信息 //封装订单信息
managerOrderDetailVO.setOrderId(id); managerOrderDetailVO.setOrderId(id);
@ -139,11 +144,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
} }
} }
QueryWrapper<OrderItem> qw = new QueryWrapper<>(); List<OrderItem> orderItemList = orderItemMapper.findByOrderId(id);
qw.eq("order_id", order.getId()); List<ManagerOrderProductVO> productList = orderItemList.stream().map(item -> {
List<OrderItem> orderItemList = orderItemMapper.selectList(qw);
List<ManagerOrderProductVO> productList = new ArrayList<>();
orderItemList.forEach(item -> {
ManagerOrderProductVO productVO = new ManagerOrderProductVO(); ManagerOrderProductVO productVO = new ManagerOrderProductVO();
productVO.setProductId(item.getProductId()); productVO.setProductId(item.getProductId());
productVO.setBuyNum(item.getQuantity()); productVO.setBuyNum(item.getQuantity());
@ -151,8 +153,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
productVO.setProductName(item.getProductName()); productVO.setProductName(item.getProductName());
productVO.setSalePrice(item.getSalePrice()); productVO.setSalePrice(item.getSalePrice());
productVO.setSpData(item.getSpData()); productVO.setSpData(item.getSpData());
productList.add(productVO); return productVO;
}); }).toList();
managerOrderDetailVO.setProductInfo(productList); managerOrderDetailVO.setProductInfo(productList);
return managerOrderDetailVO; return managerOrderDetailVO;
@ -281,6 +283,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
.payAmount(order.getPayAmount().subtract(refundBO.getTotalRefundAmount())) .payAmount(order.getPayAmount().subtract(refundBO.getTotalRefundAmount()))
.status(OrderStatusEnum.REFUNDED_SUCCESS.getValue()) .status(OrderStatusEnum.REFUNDED_SUCCESS.getValue())
.build()); .build());
// 修改核销码记录
verificationCodeService.Invalid(orderId, refundItemBoList.stream().map(RefundBO.RefundItemBO::getOrderItemId).toList());
// 更新售后记录 // 更新售后记录
Aftersale aftersale = aftersaleMapper.selectOne(Wrappers.lambdaQuery(Aftersale.class) Aftersale aftersale = aftersaleMapper.selectOne(Wrappers.lambdaQuery(Aftersale.class)
.eq(Aftersale::getOrderId, orderId).last("limit 1")); .eq(Aftersale::getOrderId, orderId).last("limit 1"));
@ -409,23 +413,43 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
} }
} }
/**
* 商户所属订单列表
* @param query
* @return
*/
@Override @Override
public IPage<OrderVO> merchantOrderList(OrderBo query) { public IPage<OrderVO> merchantOrderList(OrderBo query) {
return null; Assert.isTrue(query.getCurrent() != null && query.getSize() != null, "分页参数不能为空");
if(StrUtil.isBlank(query.getTenantId())){
query.setTenantId(TenantHelper.getTenantId());
}
IPage<OrderVO> resultPage = TenantHelper.ignore(() -> orderMapper.getListByOrderItemTenant(Page.of(query.getCurrent(), query.getSize()), query));
return getOrderVOIPage(resultPage);
} }
/**
* 团长所属订单列表
* @param query
* @return
*/
@Override @Override
public IPage<OrderVO> referenceMemberOrderList(OrderBo query) { public IPage<OrderVO> referenceMemberOrderList(OrderBo query) {
Assert.isTrue(query.getCurrent() != null && query.getSize() != null, "分页参数不能为空"); Assert.isTrue(query.getCurrent() != null && query.getSize() != null, "分页参数不能为空");
if(StrUtil.isBlank(query.getTenantId())){ if(StrUtil.isBlank(query.getTenantId())){
query.setTenantId(TenantHelper.getTenantId()); query.setTenantId(TenantHelper.getTenantId());
} }
IPage<OrderVO> resultPage = TenantHelper.ignore(() -> orderMapper.getlist(Page.of(query.getCurrent(), query.getSize()), query)); IPage<OrderVO> resultPage = TenantHelper.ignore(() -> orderMapper.getListByOrderTenant(Page.of(query.getCurrent(), query.getSize()), query));
return getOrderVOIPage(resultPage);
}
@NotNull
private IPage<OrderVO> getOrderVOIPage(IPage<OrderVO> resultPage) {
List<OrderVO> orderVOList = resultPage.getRecords(); List<OrderVO> orderVOList = resultPage.getRecords();
if (orderVOList.isEmpty()) { if (orderVOList.isEmpty()) {
return resultPage; return resultPage;
} }
// 获取所有订单id // 获取所有订单id
List<Long> orderIds = orderVOList.stream() List<Long> orderIds = orderVOList.stream()
.map(OrderVO::getId) .map(OrderVO::getId)
@ -440,42 +464,37 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
Map<Long, List<OrderItem>> orderItemMapByOrderId = orderItemList.stream() Map<Long, List<OrderItem>> orderItemMapByOrderId = orderItemList.stream()
.collect(Collectors.groupingBy(OrderItem::getOrderId)); .collect(Collectors.groupingBy(OrderItem::getOrderId));
// 获取所有sku_id // 获取所有sku的快照id
List<Long> skuIds = orderItemList.stream() List<Long> skuSnapshotIds = orderItemList.stream()
.map(OrderItem::getSkuId) .map(OrderItem::getSkuSnapshotId)
.collect(Collectors.toList()); .collect(Collectors.toList());
// 根据sku_id查询pms_sku表数据 // 根据sku_id查询pms_sku表数据
QueryWrapper<Sku> skuQueryWrapper = new QueryWrapper<>(); Map<Long, SkuSnapshot> skuSnapshotMap = skuSnapshotMapper.selectByIds(skuSnapshotIds).stream().collect(Collectors.toMap(SkuSnapshot::getId, ss -> ss));
skuQueryWrapper.in("id", skuIds);
List<Sku> skuList = skuMapper.selectList(skuQueryWrapper);
Map<Long, Sku> skuMapById = skuList.stream()
.collect(Collectors.toMap(Sku::getId, sku -> sku));
for (OrderVO orderVO : orderVOList) { for (OrderVO orderVO : orderVOList) {
List<Map<String, Object>> productList = new ArrayList<>(); List<Map<String, Object>> productList = new ArrayList<>();
List<OrderItem> orderItems = orderItemMapByOrderId.get(orderVO.getId()); List<OrderItem> orderItems = orderItemMapByOrderId.get(orderVO.getId());
if (orderItems != null) { if (orderItems != null) {
for (OrderItem orderItem : orderItems) { for (OrderItem orderItem : orderItems) {
Sku sku = skuMapById.get(orderItem.getSkuId()); SkuSnapshot skuSnapshot = skuSnapshotMap.get(orderItem.getSkuSnapshotId());
if (sku != null) { if (skuSnapshot != null) {
Map<String, Object> productMap = new HashMap<>(); Map<String, Object> productMap = new HashMap<>();
productMap.put("price", sku.getPrice()); productMap.put("price", skuSnapshot.getPrice());
productMap.put("pic", sku.getPic()); productMap.put("pic", skuSnapshot.getPic());
productMap.put("stock", sku.getStock()); productMap.put("spData", skuSnapshot.getSpData());
productMap.put("spData", sku.getSpData());
productList.add(productMap); productList.add(productMap);
} }
} }
} }
orderVO.setProductList(productList); orderVO.setProductList(productList);
} }
return resultPage; return resultPage;
} }
@Override @Override
public Order getByNo(String orderNo) { 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));

View File

@ -1,22 +1,25 @@
package com.wzj.soopin.order.service.impl; package com.wzj.soopin.order.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.text.StrBuilder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.order.domain.entity.Order; import com.wzj.soopin.order.domain.entity.Order;
import com.wzj.soopin.order.domain.entity.OrderItem;
import com.wzj.soopin.order.domain.entity.VerificationCodes; import com.wzj.soopin.order.domain.entity.VerificationCodes;
import com.wzj.soopin.order.domain.vo.ManagerOrderDetailVO;
import com.wzj.soopin.order.emum.OrderStatusEnum; import com.wzj.soopin.order.emum.OrderStatusEnum;
import com.wzj.soopin.order.emum.VerificationCodeStatus;
import com.wzj.soopin.order.mapper.OrderItemMapper;
import com.wzj.soopin.order.mapper.OrderMapper; import com.wzj.soopin.order.mapper.OrderMapper;
import com.wzj.soopin.order.mapper.VerificationCodesMapper; import com.wzj.soopin.order.mapper.VerificationCodesMapper;
import com.wzj.soopin.order.mapper.VerificationLogsMapper;
import com.wzj.soopin.order.service.OrderService;
import com.wzj.soopin.order.service.VerificationCodeService; import com.wzj.soopin.order.service.VerificationCodeService;
import com.wzj.soopin.order.utils.QrCodeGenerator;
import com.wzj.soopin.order.utils.StringUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.enums.CodePrefix; import org.dromara.common.core.enums.CodePrefix;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -31,196 +34,105 @@ import java.util.Objects;
@RequiredArgsConstructor @RequiredArgsConstructor
public class VerificationCodeServiceImpl extends ServiceImpl<VerificationCodesMapper, VerificationCodes> implements VerificationCodeService{ public class VerificationCodeServiceImpl extends ServiceImpl<VerificationCodesMapper, VerificationCodes> implements VerificationCodeService{
private final VerificationCodesMapper codeMapper; private final VerificationCodesMapper codeMapper;
private final OrderMapper orderMapper;
private final QrCodeGenerator qrCodeGenerator;
private final VerificationLogsMapper logMapper;
private final OrderService orderService; private final OrderMapper orderMapper;
private final OrderItemMapper orderItemMapper;
/** /**
* 生成核销码并关联订单 * 生成关联订单的核销码
*
* @return
*/ */
@Override @Override
public R generateVerificationCode(Long orderId) { public void generateVerificationCode(Order order) {
// 校验订单状态 List<OrderItem> orderItems = orderItemMapper.findByOrderId(order.getId());
Order order = orderMapper.selectById(orderId);
if (order == null || !Objects.equals(order.getStatus(), OrderStatusEnum.VERIFY.getValue())) {
return R.fail("订单状态异常");
}
// 生成唯一核销码
String codeValue = generateUniqueCode();
order.setCode(codeValue);
// 核销码过期时间7天后过期
LocalDateTime expireTime = LocalDateTime.now().plusDays(7); LocalDateTime expireTime = LocalDateTime.now().plusDays(7);
List<VerificationCodes> verificationCodesList = orderItems.stream().map(orderItem -> VerificationCodes
// 保存核销码到数据库 .builder()
VerificationCodes code = new VerificationCodes(); .orderId(order.getId())
code.setMemberId(order.getMemberId()); .orderItemId(orderItem.getId())
code.setMemberName(order.getMemberUsername()); .code(StrBuilder.create(CodePrefix.HXM.name()).append("-").append(UUID.fastUUID().toString(true).toUpperCase()).toString())
code.setCode(codeValue); .expireTime(expireTime)
code.setOrderId(orderId); .memberId(order.getMemberId())
code.setExpireTime(expireTime); .memberName(order.getMemberUsername())
code.setCreateTime(LocalDateTime.now()); .status(VerificationCodeStatus.TO_BE_USED.getCode())
// 未使用状态 .build()
code.setStatus(0); ).toList();
int insertResult = codeMapper.insert(code); codeMapper.insert(verificationCodesList);
if (insertResult != 1) {
return R.fail("核销码生成失败");
}
// // 构建保存路径
// String filePath = "qrcode/" + orderId + ".png";
// String qrCodeUrl = qrCodeGenerator.generateQrCode(
// "核销码:" + codeValue + ",订单ID:" + orderId,
// 200,
// 200,
// filePath
// );
// // 打印生成后的二维码URL
// log.info("生成的二维码URL: {}", qrCodeUrl);
// if (qrCodeUrl == null) {
// log.error("二维码生成失败");
// }
// // 将二维码URL保存到订单表中
// order.setCodeUrl(qrCodeUrl);
orderMapper.updateById(order);
return R.ok("核销码生成成功", code);
} }
/** /**
* 核销订单 * 查询核销码对应的订单
* @param code * @param code
*/ */
@Override @Override
public Order scan(String code) { public Order scan(String code) {
// 查询核销码 VerificationCodes verificationCodes = codeMapper.getByCode(code);
// 参数校验 Assert.notNull(verificationCodes, () -> ServiceException.of("核销码不存在"));
if (StringUtils.isBlank(code) ) { OrderItem orderItem = orderItemMapper.selectById(verificationCodes.getOrderItemId());
throw new IllegalArgumentException("参数不能为空"); Assert.notNull(orderItem, () -> ServiceException.of("订单项不存在"));
} // 仅所属商家有资格查询该核销码的订单
String tenantId = LoginHelper.getTenantId();
// 查询核销码 Assert.isTrue(orderItem.getTenantId().equals(tenantId), () -> ServiceException.of("无权查询该核销码的订单"));
VerificationCodes verificationCodes = codeMapper.selectOne( Assert.isTrue(verificationCodes.getStatus().equals(VerificationCodeStatus.TO_BE_USED.getCode()), () -> ServiceException.of("核销码" + VerificationCodeStatus.getByCode(verificationCodes.getStatus()).getDescription()));
new LambdaQueryWrapper<VerificationCodes>().eq(VerificationCodes::getCode, code)
);
if (verificationCodes == null) {
throw new IllegalArgumentException("核销码不存在");
}
// 检查核销码状态
if (verificationCodes.getStatus() == 1) {
throw new IllegalArgumentException("核销码已使用");
}
if (verificationCodes.getStatus() == 2) {
throw new IllegalArgumentException("核销码已过期");
}
// 检查核销码是否过期 // 检查核销码是否过期
if (LocalDateTime.now().isAfter(verificationCodes.getExpireTime())) { if (LocalDateTime.now().isAfter(verificationCodes.getExpireTime())) {
// 更新状态为已过期 // 更新状态为已过期
verificationCodes.setStatus(3); verificationCodes.setStatus(VerificationCodeStatus.EXPIRED.getCode());
verificationCodes.setReason("核销码已过期");
codeMapper.updateById(verificationCodes); codeMapper.updateById(verificationCodes);
throw new IllegalArgumentException("核销码已过期"); throw ServiceException.of("核销码已过期");
} }
// 检查订单状态 // 检查订单状态
Order order = orderMapper.selectById(verificationCodes.getOrderId()); Order order = orderMapper.selectById(verificationCodes.getOrderId());
if (order == null || !Objects.equals(order.getStatus(), OrderStatusEnum.VERIFY.getValue())) { Assert.isTrue(order != null && Objects.equals(order.getStatus(), OrderStatusEnum.VERIFY.getValue()), () -> ServiceException.of("订单状态异常,无法核销"));
throw new IllegalArgumentException("订单状态异常,无法核销");
}
if (verificationCodes.getStatus() == 1 || verificationCodes.getVerificationTime() != null) {
throw new IllegalArgumentException("该订单已被核销,核销时间:" + verificationCodes.getVerificationTime());
}
return order; return order;
} }
@Override @Override
public void verifyCode(String code,String tenantId) { public void verifyCode(String code) {
VerificationCodes verificationCodes = codeMapper.getByCode(code);
// 参数校验 Assert.notNull(verificationCodes, () -> ServiceException.of("核销码不存在"));
if (StringUtils.isBlank(code) || tenantId == null) { OrderItem orderItem = orderItemMapper.selectById(verificationCodes.getOrderItemId());
throw new IllegalArgumentException("参数不能为空"); Assert.notNull(orderItem, () -> ServiceException.of("订单项不存在"));
} // 仅所属商家有资格查询该核销码的订单
String tenantId = LoginHelper.getTenantId();
// 查询核销码 Assert.isTrue(orderItem.getTenantId().equals(tenantId), () -> ServiceException.of("无权查询该核销码的订单"));
VerificationCodes verificationCodes = codeMapper.selectOne( Assert.isTrue(verificationCodes.getStatus().equals(VerificationCodeStatus.TO_BE_USED.getCode()), () -> ServiceException.of("核销码" + VerificationCodeStatus.getByCode(verificationCodes.getStatus()).getDescription()));
new LambdaQueryWrapper<VerificationCodes>().eq(VerificationCodes::getCode, code)
);
if (verificationCodes == null) {
throw new IllegalArgumentException("核销码不存在");
}
// 检查核销码状态
if (verificationCodes.getStatus() == 1) {
throw new IllegalArgumentException("核销码已使用");
}
if (verificationCodes.getStatus() == 2) {
throw new IllegalArgumentException("核销码已过期");
}
// 检查订单状态
Order order = orderMapper.selectById(verificationCodes.getOrderId());
if (order == null || order.getStatus() != 6) {
throw new IllegalArgumentException("订单状态异常,无法核销");
}
// 检查核销码是否过期 // 检查核销码是否过期
if (LocalDateTime.now().isAfter(verificationCodes.getExpireTime())) { if (LocalDateTime.now().isAfter(verificationCodes.getExpireTime())) {
// 更新状态为已过期 // 更新状态为已过期
verificationCodes.setStatus(3); verificationCodes.setStatus(VerificationCodeStatus.EXPIRED.getCode());
verificationCodes.setReason("核销码已过期");
codeMapper.updateById(verificationCodes); codeMapper.updateById(verificationCodes);
throw new IllegalArgumentException("核销码已过期"); throw ServiceException.of("核销码已过期");
} }
if (verificationCodes.getStatus() == 1 || verificationCodes.getVerificationTime() != null) {
throw new IllegalArgumentException("该订单已被核销,核销时间:" + verificationCodes.getVerificationTime());
}
// 执行核销 // 执行核销
verificationCodes.setStatus(1); verificationCodes.setStatus(VerificationCodeStatus.USED.getCode());
verificationCodes.setUsedTime(LocalDateTime.now()); verificationCodes.setUsedTime(LocalDateTime.now());
verificationCodes.setUsedMerchantId(tenantId); verificationCodes.setUsedMerchantId(tenantId);
verificationCodes.setVerificationTime(LocalDateTime.now()); verificationCodes.setVerificationTime(LocalDateTime.now());
verificationCodes.setResult(1); codeMapper.updateById(verificationCodes);
int result = codeMapper.updateById(verificationCodes);
if (result != 1) {
throw new IllegalArgumentException("核销失败,请重试");
}
// 更新订单状态
order.setStatus(7);
order.setUsedTime(LocalDateTime.now());
orderMapper.updateById(order);
} }
/**
* 生成唯一核销码
*/
private String generateUniqueCode() {
String uuid = java.util.UUID.randomUUID().toString().replaceAll("-", "");
return CodePrefix.HXM.name()+"-" + uuid.substring(0, 16).toUpperCase();
}
@Override @Override
public List<VerificationCodes> getByOrderId(Long orderId) { public List<VerificationCodes> getByOrderId(Long orderId) {
LambdaQueryWrapper<VerificationCodes> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<VerificationCodes> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(VerificationCodes::getOrderId, orderId); wrapper.eq(VerificationCodes::getOrderId, orderId);
return codeMapper.selectList(wrapper); return codeMapper.selectList(wrapper);
} }
/**
* 作废核销码
* @param orderId 订单id
* @param orderItemIdList 订单项id列表
*/
@Override
public void Invalid(Long orderId, List<Long> orderItemIdList) {
codeMapper.update(Wrappers.lambdaUpdate(VerificationCodes.class)
.eq(VerificationCodes::getOrderId, orderId)
.in(VerificationCodes::getOrderItemId, orderItemIdList)
.set(VerificationCodes::getStatus, VerificationCodeStatus.CANCELLED.getCode()));
}
} }

View File

@ -1,14 +0,0 @@
package com.wzj.soopin.order.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.order.domain.entity.VerificationLogs;
import com.wzj.soopin.order.mapper.VerificationLogsMapper;
import com.wzj.soopin.order.service.VerificationLogsService;
import org.springframework.stereotype.Service;
/**
* @author fengxiaohang
*/
@Service
public class VerificationLogsServiceImpl extends ServiceImpl<VerificationLogsMapper, VerificationLogs> implements VerificationLogsService {
}

View File

@ -257,7 +257,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select> </select>
<select id="getlist" resultType="com.wzj.soopin.order.domain.vo.OrderVO"> <select id="getListByOrderTenant" resultType="com.wzj.soopin.order.domain.vo.OrderVO">
SELECT SELECT
o.id, o.id,
o.member_id, o.member_id,
@ -287,7 +287,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
LEFT JOIN ums_member um ON o.member_id = um.id LEFT JOIN ums_member um ON o.member_id = um.id
LEFT JOIN sys_tenant st ON o.tenant_id = st.tenant_id LEFT JOIN sys_tenant st ON o.tenant_id = st.tenant_id
LEFT JOIN oms_order_item oi ON o.id = oi.order_id LEFT JOIN oms_order_item oi ON o.id = oi.order_id
LEFT JOIN pms_product pp ON oi.product_id = pp.id AND pp.publish_status = 1 LEFT JOIN pms_product_snapshot pp ON oi.product_id = pp.id
<where> <where>
<if test="query.tenantId != null and query.tenantId != ''"> <if test="query.tenantId != null and query.tenantId != ''">
AND o.tenant_id = #{query.tenantId} AND o.tenant_id = #{query.tenantId}
@ -322,4 +322,69 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</where> </where>
</select> </select>
<select id="getListByOrderItemTenant" resultType="com.wzj.soopin.order.domain.vo.OrderVO">
SELECT
o.id,
o.member_id,
o.order_sn,
o.total_amount,
o.pay_amount,
o.status,
o.aftersale,
o.create_time,
o.payment_time,
o.receive_time,
o.receiver_province,
o.receiver_city,
o.receiver_district,
o.receiver_detail_address,
um.nickname AS memberNickname,
um.phone_encrypted AS memberPhoneEncrypted,
st.contact_user_name AS tenantContactName,
st.contact_phone AS tenantContactPhone,
oi.id AS itemId,
oi.product_id AS productId,
pp.brand_id AS productBrandId,
pp.name AS productName,
pp.price AS productPrice
FROM oms_order_item oi
LEFT JOIN oms_order o ON oi.order_id = o.id
LEFT JOIN ums_member um ON o.member_id = um.id
LEFT JOIN sys_tenant st ON o.tenant_id = st.tenant_id
LEFT JOIN pms_product_snapshot pp ON oi.product_id = pp.id
<where>
<if test="query.tenantId != null and query.tenantId != ''">
AND oi.tenant_id = #{query.tenantId}
</if>
<if test="query.orderSn != null and query.orderSn != ''">
AND o.order_sn LIKE CONCAT('%', #{query.orderSn}, '%')
</if>
<if test="query.memberId != null and query.memberId != ''">
AND o.member_id LIKE CONCAT('%', #{query.memberId}, '%')
</if>
<if test="query.memberPhoneEncrypted != null and query.memberPhoneEncrypted != ''">
AND um.phone_encrypted LIKE CONCAT('%', #{query.memberPhoneEncrypted}, '%')
</if>
<if test="query.status != null">
AND o.status = #{query.status}
</if>
<if test="query.type != null">
AND o.type = #{query.type}
</if>
<if test="query.withdrawStatus != null and query.withdrawStatus != ''">
AND o.withdraw_status LIKE CONCAT('%', #{query.withdrawStatus}, '%')
</if>
<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}
</if>
<if test="query.endTime != null">
AND o.create_time &lt;= #{query.endTime, jdbcType=TIMESTAMP}
</if>
</where>
</select>
</mapper> </mapper>

View File

@ -59,7 +59,7 @@ public class TransEasypayController {
@SaIgnore @SaIgnore
@Operation(summary = "易生支付-发起支付") @Operation(summary = "易生支付-发起支付")
public R<EasypayPrePayVO> trade(@RequestBody PaymentBO paymentBO) throws ServerException { public R<EasypayPrePayVO> trade(@RequestBody PaymentBO paymentBO) throws ServerException {
EasypayPrePayVO easypayPrePayVO = easypayService.payment(paymentBO); EasypayPrePayVO easypayPrePayVO = easypayService.prePayment(paymentBO);
return R.ok(easypayPrePayVO); return R.ok(easypayPrePayVO);
} }

View File

@ -24,7 +24,7 @@ public interface IEasypayService {
* @param paymentBO * @param paymentBO
* @return * @return
*/ */
EasypayPrePayVO payment(PaymentBO paymentBO) throws ServerException; EasypayPrePayVO prePayment(PaymentBO paymentBO) throws ServerException;
/** /**
* 查询订单支付结果 * 查询订单支付结果

View File

@ -25,6 +25,7 @@ import com.wzj.soopin.order.emum.OrderStatusEnum;
import com.wzj.soopin.order.service.AftersaleService; import com.wzj.soopin.order.service.AftersaleService;
import com.wzj.soopin.order.service.OrderItemService; import com.wzj.soopin.order.service.OrderItemService;
import com.wzj.soopin.order.service.OrderService; import com.wzj.soopin.order.service.OrderService;
import com.wzj.soopin.order.service.VerificationCodeService;
import com.wzj.soopin.transaction.config.EasypayConfig; import com.wzj.soopin.transaction.config.EasypayConfig;
import com.wzj.soopin.transaction.config.WechatMiniProgramConfig; import com.wzj.soopin.transaction.config.WechatMiniProgramConfig;
import com.wzj.soopin.transaction.domain.bo.*; import com.wzj.soopin.transaction.domain.bo.*;
@ -108,6 +109,8 @@ public class EasypayServiceImpl implements IEasypayService {
private final OrderService orderService; private final OrderService orderService;
private final VerificationCodeService verificationCodeService;
private final OrderItemService orderItemService; private final OrderItemService orderItemService;
private final AftersaleService aftersaleService; private final AftersaleService aftersaleService;
@ -211,7 +214,7 @@ public class EasypayServiceImpl implements IEasypayService {
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public EasypayPrePayVO payment(PaymentBO paymentBO) throws ServerException { public EasypayPrePayVO prePayment(PaymentBO paymentBO) throws ServerException {
checkPaymentParamByPayType(paymentBO); checkPaymentParamByPayType(paymentBO);
EasyPayRequestHeader reqHeader = generateEasyPayRequestHeader(); EasyPayRequestHeader reqHeader = generateEasyPayRequestHeader();
@ -261,10 +264,10 @@ public class EasypayServiceImpl implements IEasypayService {
payOrderMapper.updateById(payOrder); payOrderMapper.updateById(payOrder);
//关联订单的最新支付单 //关联订单的最新支付单
orderService.updateById(Order.builder() orderService.updateById(Order.builder()
.id(payOrder.getOrderId()) .id(paymentBO.getOrderId())
.payId(payOrder.getId()) .payId(payOrder.getId())
.payAmount(BigDecimal.valueOf(payOrder.getTransAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)) .payAmount(BigDecimal.valueOf(payOrder.getTransAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP))
.status(OrderStatusEnum.VERIFY.getValue()) .status(OrderStatusEnum.PAYMENT.getValue())
.build()); .build());
// 生成返回前端的预支付信息 // 生成返回前端的预支付信息
return generatePrePayVO(paymentBO.getPayType(), jsApiRespBody); return generatePrePayVO(paymentBO.getPayType(), jsApiRespBody);
@ -449,22 +452,11 @@ public class EasypayServiceImpl implements IEasypayService {
if (StrUtil.equals(RSP_BODY_RESP_OK, respStateInfo.getRespCode())) { if (StrUtil.equals(RSP_BODY_RESP_OK, respStateInfo.getRespCode())) {
// 支付完成 进入终态 // 支付完成 进入终态
if (StrUtil.equalsAny(respStateInfo.getTransState(), RSP_BODY_TRANS_OK, RSP_BODY_TRANS_OK_WETCAT, RSP_BODY_TRANS_PARTIALLY_OK)) { if (StrUtil.equalsAny(respStateInfo.getTransState(), RSP_BODY_TRANS_OK, RSP_BODY_TRANS_OK_WETCAT, RSP_BODY_TRANS_PARTIALLY_OK)) {
TradeQueryRespOrderInfo respOrderInfo = tradeQueryRespBody.getRespOrderInfo(); updateOrderPaid(payOrder, tradeQueryRespBody.getRespOrderInfo(), order);
// 更新支付订单信息到数据库 } else if (!StrUtil.equals(respStateInfo.getTransState(), RSP_BODY_TRANS_PROCESSING)) {
PayOrder payOrderUpdate = PayOrder.builder() // 不是成功且不是支付中统一认为支付失败支付状态重置为待支付
.id(payOrder.getId()) orderService.updateById(Order.builder().id(order.getId()).status(OrderStatusEnum.UNPAID.getValue()).build());
.endTransDate(DateUtil.parse(StrBuilder.create(respOrderInfo.getDateEnd()).append(respOrderInfo.getTimeEnd()).toString())) payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.PENDING.getCode()).build());
.easypayTrace(respOrderInfo.getOutTrace())
.pcTrace(respOrderInfo.getPcTrace())
.unTrace(respOrderInfo.getUnTrace())
.transState(TransState.PAID.getCode())
.build();
payOrderMapper.updateById(payOrderUpdate);
orderService.updateById(Order.builder()
.id(order.getId())
.status(OrderStatusEnum.PAID.getValue())
.build());
paymentResultVO.setTransState(TransState.PAID.getCode());
} }
} else { } else {
log.error("查询支付结果失败:{}", respStateInfo.getRespDesc()); log.error("查询支付结果失败:{}", respStateInfo.getRespDesc());
@ -492,24 +484,10 @@ public class EasypayServiceImpl implements IEasypayService {
if (order != null) { if (order != null) {
// 支付完成 进入终态 // 支付完成 进入终态
if (StrUtil.equalsAny(respStateInfo.getTransState(), RSP_BODY_TRANS_OK, RSP_BODY_TRANS_OK_WETCAT, RSP_BODY_TRANS_PARTIALLY_OK)) { if (StrUtil.equalsAny(respStateInfo.getTransState(), RSP_BODY_TRANS_OK, RSP_BODY_TRANS_OK_WETCAT, RSP_BODY_TRANS_PARTIALLY_OK)) {
// 更新支付订单信息 updateOrderPaid(payOrder, respOrderInfo, order);
payOrderMapper.updateById(PayOrder.builder() } else if (!StrUtil.equals(respStateInfo.getTransState(), RSP_BODY_TRANS_PROCESSING)) {
.id(payOrder.getId()) // 不是成功且不是支付中统一认为支付失败支付状态重置为待支付
.endTransDate(DateUtil.parse(StrBuilder.create(respOrderInfo.getDateEnd()).append(respOrderInfo.getTimeEnd()).toString())) orderService.updateById(Order.builder().id(order.getId()).status(OrderStatusEnum.UNPAID.getValue()).build());
.easypayTrace(respOrderInfo.getOutTrace())
.pcTrace(respOrderInfo.getPcTrace())
.unTrace(respOrderInfo.getUnTrace())
.transState(TransState.PAID.getCode())
.build());
// 更新订单信息
orderService.updateById(Order.builder()
.id(order.getId())
.status(OrderStatusEnum.PAID.getValue())
.paymentTime(LocalDateTimeUtil.parse(StrBuilder.create(respOrderInfo.getDateEnd()).append(respOrderInfo.getTimeEnd()).toString(), "yyyyMMddHHmmss"))
.payType(PayType.getByValue(payOrder.getPayType()).getChannel())
.build());
} else {
// 支付失败支付状态重置为待支付
payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.PENDING.getCode()).build()); payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.PENDING.getCode()).build());
} }
} else { } else {
@ -524,6 +502,27 @@ public class EasypayServiceImpl implements IEasypayService {
} }
} }
private void updateOrderPaid(PayOrder payOrder, TradeQueryRespOrderInfo respOrderInfo, Order order) {
// 更新支付订单信息
payOrderMapper.updateById(PayOrder.builder()
.id(payOrder.getId())
.endTransDate(DateUtil.parse(StrBuilder.create(respOrderInfo.getDateEnd()).append(respOrderInfo.getTimeEnd()).toString()))
.easypayTrace(respOrderInfo.getOutTrace())
.pcTrace(respOrderInfo.getPcTrace())
.unTrace(respOrderInfo.getUnTrace())
.transState(TransState.PAID.getCode())
.build());
// 生成订单核销码信息
verificationCodeService.generateVerificationCode(order);
// 更新订单信息
orderService.updateById(Order.builder()
.id(order.getId())
.status(OrderStatusEnum.VERIFY.getValue())
.paymentTime(LocalDateTimeUtil.parse(StrBuilder.create(respOrderInfo.getDateEnd()).append(respOrderInfo.getTimeEnd()).toString(), "yyyyMMddHHmmss"))
.payType(PayType.getByValue(payOrder.getPayType()).getChannel())
.build());
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void refund(RefundBO refundBO) { public void refund(RefundBO refundBO) {
@ -534,7 +533,7 @@ public class EasypayServiceImpl implements IEasypayService {
Assert.notNull(payOrder, () -> new ServiceException("订单不存在")); Assert.notNull(payOrder, () -> new ServiceException("订单不存在"));
Assert.isTrue(payOrder.getTransState() == TransState.PAID.getCode(), () -> new ServiceException("订单未支付,不可发起退款")); Assert.isTrue(payOrder.getTransState() == TransState.PAID.getCode(), () -> new ServiceException("订单未支付,不可发起退款"));
// 订单已支付或已分账状态才可发起退款 // 订单已支付或已分账状态才可发起退款
boolean orderDivided = Objects.equals(order.getStatus(), OrderStatusEnum.PAID.getValue()) || Objects.equals(order.getStatus(), OrderStatusEnum.DIVIDED.getValue()); boolean orderDivided = Objects.equals(order.getStatus(), OrderStatusEnum.VERIFY.getValue()) || Objects.equals(order.getStatus(), OrderStatusEnum.DIVIDED.getValue());
// 更新商品订单和支付订单状态为退款中 // 更新商品订单和支付订单状态为退款中
orderService.updateById(Order.builder().id(orderId).status(OrderStatusEnum.REFUNDED.getValue()).build()); orderService.updateById(Order.builder().id(orderId).status(OrderStatusEnum.REFUNDED.getValue()).build());
payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.REFUND_PENDING.getCode()).build()); payOrderMapper.updateById(PayOrder.builder().id(payOrder.getId()).transState(TransState.REFUND_PENDING.getCode()).build());
@ -1044,7 +1043,6 @@ public class EasypayServiceImpl implements IEasypayService {
} }
@Override @Override
public void addSubAppidConfig(String subMchtCode) { public void addSubAppidConfig(String subMchtCode) {
EasyPayRequestHeader reqHeader = generateEasyPayRequestHeader(); EasyPayRequestHeader reqHeader = generateEasyPayRequestHeader();
@ -1084,8 +1082,6 @@ public class EasypayServiceImpl implements IEasypayService {
} }
@Override @Override
public EasypayAccountVO getEasypayAccount(Long memberId) { public EasypayAccountVO getEasypayAccount(Long memberId) {
return EasypayAccountVO.builder().balance(new BigDecimal(1000)).build(); return EasypayAccountVO.builder().balance(new BigDecimal(1000)).build();