订单相关接口

This commit is contained in:
litianxiang
2026-05-20 11:09:31 +08:00
parent bdec74a9b1
commit 98c3d98d08
15 changed files with 334 additions and 4 deletions

View File

@@ -5,4 +5,7 @@ public class CommonConstants {
public static final int MINIO_PATH_TIMEOUT = 7 * 24 * 60 * 60; // minio图片临时访问地址 7 天过期second
public static final int TOKEN_EXPIRE_TIME = 7 * 24; // token 7 天过期Hour
public static final String INTERNAL_CALL_HEADER = "X-Internal-Call";
public static final String INTERNAL_CALL_VALUE = "true";
}

View File

@@ -19,6 +19,6 @@ public class AuthPrincipalVo implements Serializable {
private String source;
private Integer status;
private String language;
private String country;
private String region;
private List<String> authorities;
}

View File

@@ -116,7 +116,7 @@ public class BuyerAccountServiceImpl implements IBuyerAccountService {
principal.setUsername(account.getUsername());
principal.setSource("BUYER");
principal.setLanguage(account.getLanguage());
principal.setCountry(account.getCountry());
principal.setRegion(account.getRegion());
String token = tokenGenerateUtils.createToken(principal);
long ttlMs = tokenGenerateUtils.getJwtExpiration();

View File

@@ -0,0 +1,17 @@
package com.aida.buyer.module.feign.annotation;
import java.lang.annotation.*;
/**
* 标记 Feign 接口方法,表示该调用是内部服务间调用。
* <p>
* 被此注解标记的 Feign 方法会在请求时自动携带内部调用 Header
* 用于标识为可信的内部服务调用。
*
* @see com.aida.buyer.module.feign.interceptor.InternalCallInterceptor
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InternalCall {
}

View File

@@ -0,0 +1,18 @@
package com.aida.buyer.module.feign.config;
import com.aida.buyer.module.feign.interceptor.InternalCallInterceptor;
import feign.RequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Feign 全局配置:注册所有 Feign 拦截器。
*/
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor internalCallInterceptor() {
return new InternalCallInterceptor();
}
}

View File

@@ -0,0 +1,34 @@
package com.aida.buyer.module.feign.interceptor;
import com.aida.buyer.common.constants.CommonConstants;
import com.aida.buyer.module.feign.annotation.InternalCall;
import feign.MethodMetadata;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.core.annotation.AnnotationUtils;
/**
* Feign 请求拦截器:为标记了 {@link InternalCall} 注解的方法自动注入内部调用 Header。
* <p>
* 当 Feign Client 方法标注了 {@code @InternalCall} 时,
* 会在请求中自动添加 {@link CommonConstants#INTERNAL_CALL_HEADER} Header
* 供服务端的 {@code @InternalOnly} 校验使用。
*/
public class InternalCallInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
MethodMetadata methodMetadata = template.methodMetadata();
if (methodMetadata == null) {
return;
}
try {
java.lang.reflect.Method feignMethod = methodMetadata.method();
if (feignMethod != null && AnnotationUtils.findAnnotation(feignMethod, InternalCall.class) != null) {
template.header(CommonConstants.INTERNAL_CALL_HEADER, CommonConstants.INTERNAL_CALL_VALUE);
}
} catch (Exception ignored) {
}
}
}

View File

@@ -24,7 +24,7 @@ public class ListingController {
private final ListingService listingService;
@Operation(summary = "商城首页商品分页列表", description = "面向所有卖家,支持分类筛选、多字段排序、分页")
@Operation(summary = "数字资产商品分页列表", description = "")
@PostMapping("/mall")
public PageResponse<ListingMallVO> getMallListings(
@RequestBody ListingMallQueryDTO dto) {
@@ -38,7 +38,7 @@ public class ListingController {
return listingService.getListingDetail(id);
}
@Operation(summary = "获取店铺商品列表", description = "按 status=1、deleted=0、designFor 筛选,返回店铺已发布商品分页列表")
@Operation(summary = "获取店铺商品列表", description = "返回店铺已发布商品分页列表")
@GetMapping("/shop/seller")
public PageResponse<ListingPageVO> getShopListings(
@Parameter(description = "设计师用户ID") @RequestParam Long sellerId,

View File

@@ -0,0 +1,41 @@
package com.aida.buyer.module.order.controller;
import com.aida.buyer.common.result.PageResponse;
import com.aida.buyer.common.result.Response;
import com.aida.buyer.module.order.service.IBuyerOrderService;
import com.aida.buyer.module.order.vo.BuyerOrderVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "Buyer Order", description = "买家订单管理")
@RestController
@RequestMapping("/buyer/order")
@RequiredArgsConstructor
public class BuyerOrderController {
private final IBuyerOrderService buyerOrderService;
@GetMapping("/page")
@Operation(summary = "分页查询当前买家的订单列表")
public Response<PageResponse<BuyerOrderVO>> getMyOrders(
@RequestParam(defaultValue = "1") long page,
@RequestParam(defaultValue = "10") long size,
@RequestParam(required = false) Integer status) {
return buyerOrderService.getMyOrders(page, size, status);
}
@PostMapping("/create")
@Operation(summary = "创建订单,付款,用于单品结算和购物车结算")
public Response<Void> createOrder(@RequestBody List<Long> listingIds) {
return buyerOrderService.createOrder(listingIds);
}
}

View File

@@ -0,0 +1,23 @@
package com.aida.buyer.module.order.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
@Schema(description = "创建订单请求参数")
public class CreateOrderDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "商品ID列表")
private List<Long> listingIds;
@Schema(description = "买家ID")
private Long buyerId;
@Schema(description = "买家账号")
private String buyerUsername;
}

View File

@@ -0,0 +1,39 @@
package com.aida.buyer.module.order.feign;
import com.aida.buyer.common.result.PageResponse;
import com.aida.buyer.common.result.Response;
import com.aida.buyer.module.feign.annotation.InternalCall;
import com.aida.buyer.module.order.dto.CreateOrderDTO;
import com.aida.buyer.module.order.vo.BuyerOrderVO;
import com.aida.buyer.module.order.vo.CreateOrderResultVO;
import com.aida.buyer.module.order.dto.UpdateOrderStatusDTO;
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 订单服务 Feign Client
*/
@FeignClient(name = "aida-seller", contextId = "order", path = "/order")
public interface OrderFeignClient {
@PostMapping("/buyer/orders")
Response<PageResponse<BuyerOrderVO>> getOrdersByBuyerId(
@RequestParam Long buyerId,
@RequestParam(defaultValue = "1") long page,
@RequestParam(defaultValue = "10") long size,
@RequestParam(required = false) Integer status);
@PostMapping("/create")
Response<CreateOrderResultVO> createOrder(@RequestBody CreateOrderDTO dto);
@InternalCall
@PutMapping("/status/batch")
Response<Void> updateOrderStatus(@RequestBody UpdateOrderStatusDTO dto);
}

View File

@@ -0,0 +1,14 @@
package com.aida.buyer.module.order.service;
import com.aida.buyer.common.result.PageResponse;
import com.aida.buyer.common.result.Response;
import com.aida.buyer.module.order.vo.BuyerOrderVO;
import java.util.List;
public interface IBuyerOrderService {
Response<PageResponse<BuyerOrderVO>> getMyOrders(long page, long size, Integer status);
Response<Void> createOrder(List<Long> listingIds);
}

View File

@@ -0,0 +1,50 @@
package com.aida.buyer.module.order.service.impl;
import com.aida.buyer.common.context.UserContext;
import com.aida.buyer.common.exception.BusinessException;
import com.aida.buyer.common.result.PageResponse;
import com.aida.buyer.common.result.Response;
import com.aida.buyer.module.account.entity.BuyerAccount;
import com.aida.buyer.module.account.mapper.BuyerAccountMapper;
import com.aida.buyer.module.order.dto.CreateOrderDTO;
import com.aida.buyer.module.order.feign.OrderFeignClient;
import com.aida.buyer.module.order.service.IBuyerOrderService;
import com.aida.buyer.module.order.vo.BuyerOrderVO;
import com.aida.buyer.module.order.vo.CreateOrderResultVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class BuyerOrderServiceImpl implements IBuyerOrderService {
private final OrderFeignClient orderFeignClient;
private final BuyerAccountMapper buyerAccountMapper;
@Override
public Response<PageResponse<BuyerOrderVO>> getMyOrders(long page, long size, Integer status) {
Long buyerId = UserContext.getBuyerId();
return orderFeignClient.getOrdersByBuyerId(buyerId, page, size, status);
}
@Override
public Response<Void> createOrder(List<Long> listingIds) {
Long buyerId = UserContext.getBuyerId();
BuyerAccount account = buyerAccountMapper.selectById(buyerId);
CreateOrderDTO dto = new CreateOrderDTO();
dto.setListingIds(listingIds);
dto.setBuyerId(buyerId);
dto.setBuyerUsername(account.getUsername());
Response<CreateOrderResultVO> orderResp = orderFeignClient.createOrder(dto);
if (orderResp == null || orderResp.getErrCode() != 0) {
throw new BusinessException("创建订单失败");
}
CreateOrderResultVO result = orderResp.getData();
// TODO:调用支付模块传入buyerIdresult.getOrderIds()result.getTotalAmount()
return Response.success();
}
}

View File

@@ -0,0 +1,33 @@
package com.aida.buyer.module.order.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema(description = "买家订单商品明细")
public class BuyerOrderItemVO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "订单商品ID")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@Schema(description = "商品缩略图URL")
private String thumbnailUrl;
@Schema(description = "商品名称")
private String listingName;
@Schema(description = "商品分类列表")
private List<String> productCategory;
@Schema(description = "成交单价HK$")
private BigDecimal price;
}

View File

@@ -0,0 +1,37 @@
package com.aida.buyer.module.order.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Schema(description = "买家订单信息")
public class BuyerOrderVO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "订货号")
@JsonSerialize(using = ToStringSerializer.class)
private Long orderId;
@Schema(description = "订单更新时间")
private LocalDateTime updateTime;
@Schema(description = "订单总金额HK$")
private BigDecimal totalPrice;
@Schema(description = "订单状态0-未支付1-已支付2-已取消")
private Integer status;
@Schema(description = "店铺名称")
private String shopName;
@Schema(description = "商品明细列表")
private List<BuyerOrderItemVO> items;
}

View File

@@ -0,0 +1,21 @@
package com.aida.buyer.module.order.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema(description = "创建订单结果")
public class CreateOrderResultVO implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "订单ID列表按卖家分组")
private List<Long> orderIds;
@Schema(description = "所有订单总金额HK$")
private BigDecimal totalAmount;
}