From 8774f6b948bea940ef9b12d407a1d303c3500469 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Thu, 27 Aug 2026 16:19:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=87=E4=BB=B6:=20sever?= =?UTF-8?q?=5Ftb=5FLinkedMall/generate.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sever_tb_LinkedMall/generate.md | 1801 +++++++++++++++++++++++++++++++ 1 file changed, 1801 insertions(+) create mode 100644 sever_tb_LinkedMall/generate.md diff --git a/sever_tb_LinkedMall/generate.md b/sever_tb_LinkedMall/generate.md new file mode 100644 index 0000000..0b5690e --- /dev/null +++ b/sever_tb_LinkedMall/generate.md @@ -0,0 +1,1801 @@ +根据文档分析,该API使用阿里云Darabonba OpenAPI SDK进行ROA签名调用(SDK内部自动处理签名),无需额外加密工具。我将直接生成所有代码文件。 + +--- + +// File: server_tb_LinkedMall/go.mod +```go +module server_tb_LinkedMall + +go 1.26 + +require ( + github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 + github.com/alibabacloud-go/tea/v2 v2.2.8 + github.com/gofiber/fiber/v2 v2.52.5 + github.com/google/uuid v1.6.0 + github.com/json-iterator/go v1.1.12 +) + +require ( + github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect + github.com/alibabacloud-go/debug v1.0.1 // indirect + github.com/alibabacloud-go/openapi-util v0.1.1 // indirect + github.com/andybalholm/brotli v1.1.1 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.57.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.28.0 // indirect +) +``` + +// File: server_tb_LinkedMall/pkg/crypto/crypto.go +```go +package crypto + +import ( + "crypto/rand" + "encoding/hex" + "fmt" + "time" +) + +// GenerateNonce 生成随机字符串,用于防重放 +func GenerateNonce() string { + buf := make([]byte, 16) + _, _ = rand.Read(buf) + return hex.EncodeToString(buf) +} + +// GenerateTimestamp 生成当前时间戳(毫秒) +func GenerateTimestamp() int64 { + return time.Now().UnixMilli() +} + +// FormatTimestamp 格式化时间戳为字符串 +func FormatTimestamp(ts int64) string { + return fmt.Sprintf("%d", ts) +} +``` + +// File: server_tb_LinkedMall/internal/config/config.go +```go +package config + +import ( + "os" +) + +// Config 应用配置 +type Config struct { + ServerPort string + AccessKeyId string + AccessKeySecret string + RegionId string + Endpoint string + BasePath string + DefaultPurchaserId string + CallbackURL string +} + +// LoadConfig 从环境变量加载配置 +func LoadConfig() *Config { + return &Config{ + ServerPort: getEnv("SERVER_PORT", "8080"), + AccessKeyId: getEnv("LINKEDMALL_AK", ""), + AccessKeySecret: getEnv("LINKEDMALL_SK", ""), + RegionId: getEnv("LINKEDMALL_REGION_ID", "cn-zhangjiakou"), + Endpoint: getEnv("LINKEDMALL_ENDPOINT", "linkedmall.cn-zhangjiakou.aliyuncs.com"), + BasePath: getEnv("LINKEDMALL_BASE_PATH", "/opensaas-s2b/opensaas-s2b-biz-trade/v2"), + DefaultPurchaserId: getEnv("LINKEDMALL_PURCHASER_ID", ""), + CallbackURL: getEnv("LINKEDMALL_CALLBACK_URL", ""), + } +} + +func getEnv(key, fallback string) string { + if v := os.Getenv(key); v != "" { + return v + } + return fallback +} +``` + +// File: server_tb_LinkedMall/internal/entities/request.go +```go +package entities + +// ============================================================ +// 通用请求结构 +// ============================================================ + +// PaginationReq 分页请求公共参数 +type PaginationReq struct { + PageNum int `json:"PageNum" query:"PageNum"` + PageSize int `json:"PageSize" query:"PageSize"` +} + +// PurchaserQuery 采购方ID查询参数 +type PurchaserQuery struct { + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` +} + +// ============================================================ +// 接口 1: ListPurchaserShops +// ============================================================ +type ListPurchaserShopsReq struct { + PageNum int `json:"PageNum" query:"PageNum"` + PageSize int `json:"PageSize" query:"PageSize"` +} + +// ============================================================ +// 接口 2: GetPurchaserShop +// ============================================================ +type GetPurchaserShopReq struct { + ShopId string `json:"ShopId" params:"ShopId"` +} + +// ============================================================ +// 接口 3: ListSelectionProducts +// ============================================================ +type ListSelectionProductsReq struct { + PageNum int `json:"PageNum" query:"PageNum"` + PageSize int `json:"PageSize" query:"PageSize"` + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` +} + +// ============================================================ +// 接口 4: GetSelectionProduct +// ============================================================ +type GetSelectionProductReq struct { + ProductId string `json:"ProductId" params:"ProductId"` + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` + DivisionCode string `json:"DivisionCode" query:"DivisionCode"` +} + +// ============================================================ +// 接口 5: GetSelectionProductSaleInfo +// ============================================================ +type GetSelectionProductSaleInfoReq struct { + ProductId string `json:"ProductId" params:"ProductId"` + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` + DivisionCode string `json:"DivisionCode" query:"DivisionCode"` +} + +// ============================================================ +// 接口 6: ListSelectionProductSaleInfos +// ============================================================ +type ListSelectionProductSaleInfosReq struct { + PurchaserId string `json:"PurchaserId"` + ProductIdList []string `json:"ProductIdList"` + DivisionCode string `json:"DivisionCode"` +} + +// ============================================================ +// 接口 7: ListSelectionSkuSaleInfos +// ============================================================ +type ListSelectionSkuSaleInfosReq struct { + PurchaserId string `json:"PurchaserId"` + SkuIdList []string `json:"SkuIdList"` + DivisionCode string `json:"DivisionCode"` +} + +// ============================================================ +// 接口 8: ListCategories +// ============================================================ +type ListCategoriesReq struct { + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` + ParentCategoryId string `json:"ParentCategoryId" query:"ParentCategoryId"` +} + +// ============================================================ +// 接口 9: SearchProducts +// ============================================================ +type SearchProductsReq struct { + Keyword string `json:"Keyword"` + CategoryId string `json:"CategoryId"` + PageNum int `json:"PageNum"` + PageSize int `json:"PageSize"` + PurchaserId string `json:"PurchaserId"` +} + +// ============================================================ +// 接口 10: SelectionGroupAddProduct +// ============================================================ +type SelectionGroupAddProductReq struct { + PurchaserId string `json:"PurchaserId"` + ShopId string `json:"ShopId"` + ProductIdList []string `json:"ProductIdList"` +} + +// ============================================================ +// 接口 11: SelectionGroupRemoveProduct +// ============================================================ +type SelectionGroupRemoveProductReq struct { + PurchaserId string `json:"PurchaserId"` + ShopId string `json:"ShopId"` + ProductIdList []string `json:"ProductIdList"` +} + +// ============================================================ +// 接口 12: RenderPurchaseOrder +// ============================================================ +type RenderPurchaseOrderReq struct { + PurchaserId string `json:"PurchaserId"` + ShopId string `json:"ShopId"` + DivisionCode string `json:"DivisionCode"` + ItemList []RenderOrderItem `json:"ItemList"` + ReceiverInfo ReceiverInfo `json:"ReceiverInfo"` +} + +type RenderOrderItem struct { + SkuId string `json:"SkuId"` + Quantity int64 `json:"Quantity"` +} + +type ReceiverInfo struct { + ReceiverName string `json:"ReceiverName"` + ReceiverPhone string `json:"ReceiverPhone"` + ProvinceCode string `json:"ProvinceCode"` + CityCode string `json:"CityCode"` + DistrictCode string `json:"DistrictCode"` + TownCode string `json:"TownCode"` + DetailAddress string `json:"DetailAddress"` +} + +// ============================================================ +// 接口 13: SplitPurchaseOrder +// ============================================================ +type SplitPurchaseOrderReq struct { + PurchaserId string `json:"PurchaserId"` + ShopId string `json:"ShopId"` + DivisionCode string `json:"DivisionCode"` + ItemList []RenderOrderItem `json:"ItemList"` + ReceiverInfo ReceiverInfo `json:"ReceiverInfo"` +} + +// ============================================================ +// 接口 14: CreatePurchaseOrder +// ============================================================ +type CreatePurchaseOrderReq struct { + PurchaserId string `json:"PurchaserId"` + ShopId string `json:"ShopId"` + OuterPurchaseOrderId string `json:"OuterPurchaseOrderId"` + DivisionCode string `json:"DivisionCode"` + ReceiverInfo ReceiverInfo `json:"ReceiverInfo"` + SubOrderList []CreateSubOrderItem `json:"SubOrderList"` +} + +type CreateSubOrderItem struct { + SkuId string `json:"SkuId"` + Quantity int64 `json:"Quantity"` +} + +// ============================================================ +// 接口 15: GetPurchaseOrderStatus +// ============================================================ +type GetPurchaseOrderStatusReq struct { + PurchaseOrderId string `json:"PurchaseOrderId" params:"PurchaseOrderId"` + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` +} + +// ============================================================ +// 接口 16: GetOrder +// ============================================================ +type GetOrderReq struct { + OrderId string `json:"OrderId" params:"OrderId"` + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` +} + +// ============================================================ +// 接口 17: QueryOrders +// ============================================================ +type QueryOrdersReq struct { + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` + PurchaseOrderId string `json:"PurchaseOrderId" query:"PurchaseOrderId"` + PageNum int `json:"PageNum" query:"PageNum"` + PageSize int `json:"PageSize" query:"PageSize"` + StartTime string `json:"StartTime" query:"StartTime"` + EndTime string `json:"EndTime" query:"EndTime"` +} + +// ============================================================ +// 接口 18: ListLogisticsOrders +// ============================================================ +type ListLogisticsOrdersReq struct { + OrderId string `json:"OrderId" params:"OrderId"` + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` +} + +// ============================================================ +// 接口 19: ConfirmDisburse +// ============================================================ +type ConfirmDisburseReq struct { + OrderId string `json:"OrderId" params:"OrderId"` + PurchaserId string `json:"PurchaserId"` +} + +// ============================================================ +// 接口 20: RenderRefundOrder +// ============================================================ +type RenderRefundOrderReq struct { + PurchaserId string `json:"PurchaserId"` + OrderId string `json:"OrderId"` + OrderItemId string `json:"OrderItemId"` + RefundQuantity int64 `json:"RefundQuantity"` + RefundType string `json:"RefundType"` +} + +// ============================================================ +// 接口 21: CreateRefundOrder +// ============================================================ +type CreateRefundOrderReq struct { + PurchaserId string `json:"PurchaserId"` + OrderId string `json:"OrderId"` + OrderItemId string `json:"OrderItemId"` + RefundQuantity int64 `json:"RefundQuantity"` + RefundAmount int64 `json:"RefundAmount"` + RefundType string `json:"RefundType"` + RefundReason string `json:"RefundReason"` + OuterRefundNo string `json:"OuterRefundNo"` +} + +// ============================================================ +// 接口 22: CancelRefundOrder +// ============================================================ +type CancelRefundOrderReq struct { + RefundOrderId string `json:"RefundOrderId" params:"RefundOrderId"` + PurchaserId string `json:"PurchaserId"` +} + +// ============================================================ +// 接口 23: GetRefundOrder +// ============================================================ +type GetRefundOrderReq struct { + RefundOrderId string `json:"RefundOrderId" params:"RefundOrderId"` + PurchaserId string `json:"PurchaserId" query:"PurchaserId"` +} + +// ============================================================ +// 接口 24: CreateGoodsShippingNotice +// ============================================================ +type CreateGoodsShippingNoticeReq struct { + RefundOrderId string `json:"RefundOrderId" params:"RefundOrderId"` + PurchaserId string `json:"PurchaserId"` + LogisticsCompany string `json:"LogisticsCompany"` + TrackingNumber string `json:"TrackingNumber"` +} + +// ============================================================ +// 接口 25: QueryChildDivisionCode +// ============================================================ +type QueryChildDivisionCodeReq struct { + ParentDivisionCode string `json:"ParentDivisionCode" query:"ParentDivisionCode"` +} + +// ============================================================ +// 回调通知 +// ============================================================ +type CallbackNotification struct { + EventCode string `json:"EventCode"` + PurchaseOrderId string `json:"PurchaseOrderId"` + OrderIdList []string `json:"OrderIdList"` + Status string `json:"Status"` + RequestId string `json:"RequestId"` +} +``` + +// File: server_tb_LinkedMall/internal/entities/response.go +```go +package entities + +// ============================================================ +// 公共响应结构 +// ============================================================ + +// CommonResponse 阿里云LinkedMall公共响应外层 +type CommonResponse struct { + RequestId string `json:"RequestId"` + Success bool `json:"Success"` + Code string `json:"Code"` + Message string `json:"Message"` + SubCode string `json:"SubCode"` + SubMessage string `json:"SubMessage"` + Data interface{} `json:"Data"` +} + +// APIResponse 服务端统一返回结构 +type APIResponse struct { + Success bool `json:"Success"` + Code string `json:"Code"` + Message string `json:"Message"` + RequestId string `json:"RequestId,omitempty"` + Data interface{} `json:"Data,omitempty"` +} + +// ============================================================ +// 接口 1: ListPurchaserShops +// ============================================================ +type ListPurchaserShopsRespData struct { + Total int64 `json:"Total"` + PageNum int `json:"PageNum"` + PageSize int `json:"PageSize"` + ShopList []PurchaserShopItem `json:"ShopList"` +} + +type PurchaserShopItem struct { + ShopId string `json:"ShopId"` + PurchaserId string `json:"PurchaserId"` + ShopName string `json:"ShopName"` + ShopStatus string `json:"ShopStatus"` +} + +// ============================================================ +// 接口 2: GetPurchaserShop +// ============================================================ +type GetPurchaserShopRespData struct { + ShopId string `json:"ShopId"` + PurchaserId string `json:"PurchaserId"` + ShopName string `json:"ShopName"` + ShopStatus string `json:"ShopStatus"` + ContactInfo string `json:"ContactInfo"` +} + +// ============================================================ +// 接口 3: ListSelectionProducts +// ============================================================ +type ListSelectionProductsRespData struct { + Total int64 `json:"Total"` + PageNum int `json:"PageNum"` + PageSize int `json:"PageSize"` + ProductList []SelectionProductItem `json:"ProductList"` +} + +type SelectionProductItem struct { + ProductId string `json:"ProductId"` + Title string `json:"Title"` + MainImage string `json:"MainImage"` + BrandName string `json:"BrandName"` + CategoryId string `json:"CategoryId"` +} + +// ============================================================ +// 接口 4: GetSelectionProduct +// ============================================================ +type GetSelectionProductRespData struct { + ProductId string `json:"ProductId"` + Title string `json:"Title"` + MainImage string `json:"MainImage"` + Images []string `json:"Images"` + BrandName string `json:"BrandName"` + CategoryId string `json:"CategoryId"` + Desc string `json:"Desc"` + SkuList []SelectionSkuItem `json:"SkuList"` + CanSale bool `json:"CanSale"` + StockQuantity int64 `json:"StockQuantity"` +} + +type SelectionSkuItem struct { + SkuId string `json:"SkuId"` + SkuSpec string `json:"SkuSpec"` + SalePrice int64 `json:"SalePrice"` + MarketPrice int64 `json:"MarketPrice"` + StockQuantity int64 `json:"StockQuantity"` +} + +// ============================================================ +// 接口 5: GetSelectionProductSaleInfo +// ============================================================ +type GetSelectionProductSaleInfoRespData struct { + ProductId string `json:"ProductId"` + Title string `json:"Title"` + CanSale bool `json:"CanSale"` + SalePrice int64 `json:"SalePrice"` + StockQuantity int64 `json:"StockQuantity"` +} + +// ============================================================ +// 接口 6: ListSelectionProductSaleInfos +// ============================================================ +type ListSelectionProductSaleInfosRespData struct { + ProductSaleInfoList []ProductSaleInfoItem `json:"ProductSaleInfoList"` +} + +type ProductSaleInfoItem struct { + ProductId string `json:"ProductId"` + CanSale bool `json:"CanSale"` + SalePrice int64 `json:"SalePrice"` + StockQuantity int64 `json:"StockQuantity"` +} + +// ============================================================ +// 接口 7: ListSelectionSkuSaleInfos +// ============================================================ +type ListSelectionSkuSaleInfosRespData struct { + SkuSaleInfoList []SkuSaleInfoItem `json:"SkuSaleInfoList"` +} + +type SkuSaleInfoItem struct { + SkuId string `json:"SkuId"` + CanSale bool `json:"CanSale"` + SalePrice int64 `json:"SalePrice"` + StockQuantity int64 `json:"StockQuantity"` +} + +// ============================================================ +// 接口 8: ListCategories +// ============================================================ +type ListCategoriesRespData struct { + CategoryList []CategoryItem `json:"CategoryList"` +} + +type CategoryItem struct { + CategoryId string `json:"CategoryId"` + CategoryName string `json:"CategoryName"` + ParentId string `json:"ParentId"` + Level int `json:"Level"` +} + +// ============================================================ +// 接口 9: SearchProducts +// ============================================================ +type SearchProductsRespData struct { + Total int64 `json:"Total"` + PageNum int `json:"PageNum"` + PageSize int `json:"PageSize"` + ProductList []SelectionProductItem `json:"ProductList"` +} + +// ============================================================ +// 接口 10: SelectionGroupAddProduct +// ============================================================ +type SelectionGroupAddProductRespData struct { + SuccessCount int `json:"SuccessCount"` + FailList []string `json:"FailList"` +} + +// ============================================================ +// 接口 11: SelectionGroupRemoveProduct +// ============================================================ +type SelectionGroupRemoveProductRespData struct { + SuccessCount int `json:"SuccessCount"` + FailList []string `json:"FailList"` +} + +// ============================================================ +// 接口 12: RenderPurchaseOrder +// ============================================================ +type RenderPurchaseOrderRespData struct { + TotalFee int64 `json:"TotalFee"` + TotalFreight int64 `json:"TotalFreight"` + ItemList []RenderResultItem `json:"ItemList"` + CanSale bool `json:"CanSale"` + UnSaleReason string `json:"UnSaleReason"` +} + +type RenderResultItem struct { + SkuId string `json:"SkuId"` + SalePrice int64 `json:"SalePrice"` + Quantity int64 `json:"Quantity"` + SubTotalFee int64 `json:"SubTotalFee"` + CanSale bool `json:"CanSale"` + UnSaleReason string `json:"UnSaleReason"` +} + +// ============================================================ +// 接口 13: SplitPurchaseOrder +// ============================================================ +type SplitPurchaseOrderRespData struct { + SubOrderList []SubOrderItem `json:"SubOrderList"` +} + +type SubOrderItem struct { + ShopId string `json:"ShopId"` + ItemList []RenderOrderItem `json:"ItemList"` + TotalFee int64 `json:"TotalFee"` + TotalFreight int64 `json:"TotalFreight"` +} + +// ============================================================ +// 接口 14: CreatePurchaseOrder +// ============================================================ +type CreatePurchaseOrderRespData struct { + PurchaseOrderId string `json:"PurchaseOrderId"` +} + +// ============================================================ +// 接口 15: GetPurchaseOrderStatus +// ============================================================ +type GetPurchaseOrderStatusRespData struct { + PurchaseOrderId string `json:"PurchaseOrderId"` + Status string `json:"Status"` + StatusDesc string `json:"StatusDesc"` +} + +// ============================================================ +// 接口 16: GetOrder +// ============================================================ +type GetOrderRespData struct { + OrderId string `json:"OrderId"` + PurchaseOrderId string `json:"PurchaseOrderId"` + ShopId string `json:"ShopId"` + OrderStatus string `json:"OrderStatus"` + TotalFee int64 `json:"TotalFee"` + FreightFee int64 `json:"FreightFee"` + ActualPayFee int64 `json:"ActualPayFee"` + ReceiverInfo ReceiverInfo `json:"ReceiverInfo"` + OrderItemList []OrderItemDetail `json:"OrderItemList"` + CreateTime string `json:"CreateTime"` +} + +type OrderItemDetail struct { + OrderItemId string `json:"OrderItemId"` + SkuId string `json:"SkuId"` + Title string `json:"Title"` + Quantity int64 `json:"Quantity"` + PayFee int64 `json:"PayFee"` + UnitPrice int64 `json:"UnitPrice"` +} + +// ============================================================ +// 接口 17: QueryOrders +// ============================================================ +type QueryOrdersRespData struct { + Total int64 `json:"Total"` + PageNum int `json:"PageNum"` + PageSize int `json:"PageSize"` + OrderList []GetOrderRespData `json:"OrderList"` +} + +// ============================================================ +// 接口 18: ListLogisticsOrders +// ============================================================ +type ListLogisticsOrdersRespData struct { + LogisticsList []LogisticsItem `json:"LogisticsList"` +} + +type LogisticsItem struct { + LogisticsCompany string `json:"LogisticsCompany"` + TrackingNumber string `json:"TrackingNumber"` + TrajectoryList []LogisticsTrajectory `json:"TrajectoryList"` +} + +type LogisticsTrajectory struct { + Time string `json:"Time"` + Context string `json:"Context"` + Location string `json:"Location"` +} + +// ============================================================ +// 接口 19: ConfirmDisburse +// ============================================================ +type ConfirmDisburseRespData struct { + Success bool `json:"Success"` +} + +// ============================================================ +// 接口 20: RenderRefundOrder +// ============================================================ +type RenderRefundOrderRespData struct { + RefundableAmount int64 `json:"RefundableAmount"` + RefundableQuantity int64 `json:"RefundableQuantity"` + CanRefund bool `json:"CanRefund"` + UnRefundReason string `json:"UnRefundReason"` +} + +// ============================================================ +// 接口 21: CreateRefundOrder +// ============================================================ +type CreateRefundOrderRespData struct { + RefundOrderId string `json:"RefundOrderId"` + Status string `json:"Status"` +} + +// ============================================================ +// 接口 22: CancelRefundOrder +// ============================================================ +type CancelRefundOrderRespData struct { + Success bool `json:"Success"` +} + +// ============================================================ +// 接口 23: GetRefundOrder +// ============================================================ +type GetRefundOrderRespData struct { + RefundOrderId string `json:"RefundOrderId"` + OrderId string `json:"OrderId"` + OrderItemId string `json:"OrderItemId"` + RefundQuantity int64 `json:"RefundQuantity"` + RefundAmount int64 `json:"RefundAmount"` + RefundType string `json:"RefundType"` + RefundStatus string `json:"RefundStatus"` + RefundReason string `json:"RefundReason"` + CreateTime string `json:"CreateTime"` +} + +// ============================================================ +// 接口 24: CreateGoodsShippingNotice +// ============================================================ +type CreateGoodsShippingNoticeRespData struct { + Success bool `json:"Success"` +} + +// ============================================================ +// 接口 25: QueryChildDivisionCode +// ============================================================ +type QueryChildDivisionCodeRespData struct { + DivisionList []DivisionItem `json:"DivisionList"` +} + +type DivisionItem struct { + DivisionCode string `json:"DivisionCode"` + DivisionName string `json:"DivisionName"` + Level int `json:"Level"` + ParentCode string `json:"ParentCode"` +} +``` + +// File: server_tb_LinkedMall/internal/biz/biz.go +```go +package biz + +import ( + "encoding/json" + "fmt" + + openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" + "github.com/alibabacloud-go/tea/v2" + + "server_tb_LinkedMall/internal/config" + "server_tb_LinkedMall/internal/entities" +) + +// LinkedMallBiz 业务逻辑层 - 封装对LinkedMall OpenAPI的调用 +type LinkedMallBiz struct { + client *openapi.Client + cfg *config.Config + basePath string +} + +// NewLinkedMallBiz 创建业务逻辑实例 +func NewLinkedMallBiz(cfg *config.Config) (*LinkedMallBiz, error) { + cli, err := newLinkedMallClient(cfg.AccessKeyId, cfg.AccessKeySecret, cfg.RegionId, cfg.Endpoint) + if err != nil { + return nil, fmt.Errorf("初始化LinkedMall客户端失败: %w", err) + } + return &LinkedMallBiz{ + client: cli, + cfg: cfg, + basePath: cfg.BasePath, + }, nil +} + +// newLinkedMallClient 创建Darabonba OpenAPI客户端 +func newLinkedMallClient(ak, sk, regionId, endpoint string) (*openapi.Client, error) { + config := &openapi.Config{ + AccessKeyId: tea.String(ak), + AccessKeySecret: tea.String(sk), + RegionId: tea.String(regionId), + Endpoint: tea.String(endpoint), + ReadTimeout: tea.Int(30000), + ConnectTimeout: tea.Int(10000), + } + return openapi.NewClient(config) +} + +// doRoaGet 发起ROA GET请求 +func (b *LinkedMallBiz) doRoaGet(path string, query map[string]*string) (*entities.CommonResponse, error) { + resp, err := b.client.RoaRequest( + tea.String("GET"), + tea.String(b.basePath+path), + query, + nil, // body + nil, // header + ) + if err != nil { + return nil, fmt.Errorf("ROA GET请求失败 [%s]: %w", path, err) + } + return b.parseResponse(resp) +} + +// doRoaPost 发起ROA POST请求 +func (b *LinkedMallBiz) doRoaPost(path string, body interface{}, query map[string]*string) (*entities.CommonResponse, error) { + jsonBytes, err := json.Marshal(body) + if err != nil { + return nil, fmt.Errorf("序列化请求Body失败: %w", err) + } + var bodyObj interface{} + if err := json.Unmarshal(jsonBytes, &bodyObj); err != nil { + return nil, fmt.Errorf("反序列化请求Body失败: %w", err) + } + resp, err := b.client.RoaRequest( + tea.String("POST"), + tea.String(b.basePath+path), + query, + bodyObj, + nil, + ) + if err != nil { + return nil, fmt.Errorf("ROA POST请求失败 [%s]: %w", path, err) + } + return b.parseResponse(resp) +} + +// parseResponse 解析公共响应 +func (b *LinkedMallBiz) parseResponse(resp interface{}) (*entities.CommonResponse, error) { + respBytes, err := json.Marshal(resp) + if err != nil { + return nil, fmt.Errorf("序列化响应失败: %w", err) + } + var commonResp entities.CommonResponse + if err := json.Unmarshal(respBytes, &commonResp); err != nil { + return nil, fmt.Errorf("解析公共响应失败: %w", err) + } + return &commonResp, nil +} + +// ============================================================ +// 接口实现:调用阿里云LinkedMall OpenAPI +// ============================================================ + +// 接口 1: ListPurchaserShops +func (b *LinkedMallBiz) ListPurchaserShops(req *entities.ListPurchaserShopsReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + if req.PageNum > 0 { + query["PageNum"] = tea.String(fmt.Sprintf("%d", req.PageNum)) + } + if req.PageSize > 0 { + query["PageSize"] = tea.String(fmt.Sprintf("%d", req.PageSize)) + } + return b.doRoaGet("/purchaser-shops", query) +} + +// 接口 2: GetPurchaserShop +func (b *LinkedMallBiz) GetPurchaserShop(req *entities.GetPurchaserShopReq) (*entities.CommonResponse, error) { + return b.doRoaGet(fmt.Sprintf("/purchaser-shops/%s", req.ShopId), nil) +} + +// 接口 3: ListSelectionProducts +func (b *LinkedMallBiz) ListSelectionProducts(req *entities.ListSelectionProductsReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + if req.PageNum > 0 { + query["PageNum"] = tea.String(fmt.Sprintf("%d", req.PageNum)) + } + if req.PageSize > 0 { + query["PageSize"] = tea.String(fmt.Sprintf("%d", req.PageSize)) + } + return b.doRoaGet("/selection-products", query) +} + +// 接口 4: GetSelectionProduct +func (b *LinkedMallBiz) GetSelectionProduct(req *entities.GetSelectionProductReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + if req.DivisionCode != "" { + query["DivisionCode"] = tea.String(req.DivisionCode) + } + return b.doRoaGet(fmt.Sprintf("/selection-products/%s", req.ProductId), query) +} + +// 接口 5: GetSelectionProductSaleInfo +func (b *LinkedMallBiz) GetSelectionProductSaleInfo(req *entities.GetSelectionProductSaleInfoReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + if req.DivisionCode != "" { + query["DivisionCode"] = tea.String(req.DivisionCode) + } + return b.doRoaGet(fmt.Sprintf("/selection-products/%s/sale-info", req.ProductId), query) +} + +// 接口 6: ListSelectionProductSaleInfos +func (b *LinkedMallBiz) ListSelectionProductSaleInfos(req *entities.ListSelectionProductSaleInfosReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/selection-products:batch-sale-info", req, nil) +} + +// 接口 7: ListSelectionSkuSaleInfos +func (b *LinkedMallBiz) ListSelectionSkuSaleInfos(req *entities.ListSelectionSkuSaleInfosReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/selection-skus:batch-sale-info", req, nil) +} + +// 接口 8: ListCategories +func (b *LinkedMallBiz) ListCategories(req *entities.ListCategoriesReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + if req.ParentCategoryId != "" { + query["ParentCategoryId"] = tea.String(req.ParentCategoryId) + } + return b.doRoaGet("/categories", query) +} + +// 接口 9: SearchProducts +func (b *LinkedMallBiz) SearchProducts(req *entities.SearchProductsReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/selection-products:search", req, nil) +} + +// 接口 10: SelectionGroupAddProduct +func (b *LinkedMallBiz) SelectionGroupAddProduct(req *entities.SelectionGroupAddProductReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/selection-group/products:add", req, nil) +} + +// 接口 11: SelectionGroupRemoveProduct +func (b *LinkedMallBiz) SelectionGroupRemoveProduct(req *entities.SelectionGroupRemoveProductReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/selection-group/products:remove", req, nil) +} + +// 接口 12: RenderPurchaseOrder +func (b *LinkedMallBiz) RenderPurchaseOrder(req *entities.RenderPurchaseOrderReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/purchase-orders:render", req, nil) +} + +// 接口 13: SplitPurchaseOrder +func (b *LinkedMallBiz) SplitPurchaseOrder(req *entities.SplitPurchaseOrderReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/purchase-orders:split-render", req, nil) +} + +// 接口 14: CreatePurchaseOrder +func (b *LinkedMallBiz) CreatePurchaseOrder(req *entities.CreatePurchaseOrderReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/purchase-orders", req, nil) +} + +// 接口 15: GetPurchaseOrderStatus +func (b *LinkedMallBiz) GetPurchaseOrderStatus(req *entities.GetPurchaseOrderStatusReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + return b.doRoaGet(fmt.Sprintf("/purchase-orders/%s/status", req.PurchaseOrderId), query) +} + +// 接口 16: GetOrder +func (b *LinkedMallBiz) GetOrder(req *entities.GetOrderReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + return b.doRoaGet(fmt.Sprintf("/orders/%s", req.OrderId), query) +} + +// 接口 17: QueryOrders +func (b *LinkedMallBiz) QueryOrders(req *entities.QueryOrdersReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + if req.PurchaseOrderId != "" { + query["PurchaseOrderId"] = tea.String(req.PurchaseOrderId) + } + if req.PageNum > 0 { + query["PageNum"] = tea.String(fmt.Sprintf("%d", req.PageNum)) + } + if req.PageSize > 0 { + query["PageSize"] = tea.String(fmt.Sprintf("%d", req.PageSize)) + } + if req.StartTime != "" { + query["StartTime"] = tea.String(req.StartTime) + } + if req.EndTime != "" { + query["EndTime"] = tea.String(req.EndTime) + } + return b.doRoaGet("/orders", query) +} + +// 接口 18: ListLogisticsOrders +func (b *LinkedMallBiz) ListLogisticsOrders(req *entities.ListLogisticsOrdersReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + return b.doRoaGet(fmt.Sprintf("/orders/%s/logistics", req.OrderId), query) +} + +// 接口 19: ConfirmDisburse +func (b *LinkedMallBiz) ConfirmDisburse(req *entities.ConfirmDisburseReq) (*entities.CommonResponse, error) { + body := map[string]string{"PurchaserId": req.PurchaserId} + return b.doRoaPost(fmt.Sprintf("/orders/%s:confirm-disburse", req.OrderId), body, nil) +} + +// 接口 20: RenderRefundOrder +func (b *LinkedMallBiz) RenderRefundOrder(req *entities.RenderRefundOrderReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/refund-orders:render", req, nil) +} + +// 接口 21: CreateRefundOrder +func (b *LinkedMallBiz) CreateRefundOrder(req *entities.CreateRefundOrderReq) (*entities.CommonResponse, error) { + return b.doRoaPost("/refund-orders", req, nil) +} + +// 接口 22: CancelRefundOrder +func (b *LinkedMallBiz) CancelRefundOrder(req *entities.CancelRefundOrderReq) (*entities.CommonResponse, error) { + body := map[string]string{"PurchaserId": req.PurchaserId} + return b.doRoaPost(fmt.Sprintf("/refund-orders/%s:cancel", req.RefundOrderId), body, nil) +} + +// 接口 23: GetRefundOrder +func (b *LinkedMallBiz) GetRefundOrder(req *entities.GetRefundOrderReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + query["PurchaserId"] = tea.String(req.PurchaserId) + return b.doRoaGet(fmt.Sprintf("/refund-orders/%s", req.RefundOrderId), query) +} + +// 接口 24: CreateGoodsShippingNotice +func (b *LinkedMallBiz) CreateGoodsShippingNotice(req *entities.CreateGoodsShippingNoticeReq) (*entities.CommonResponse, error) { + body := map[string]string{ + "PurchaserId": req.PurchaserId, + "LogisticsCompany": req.LogisticsCompany, + "TrackingNumber": req.TrackingNumber, + } + return b.doRoaPost(fmt.Sprintf("/refund-orders/%s:fill-logistics", req.RefundOrderId), body, nil) +} + +// 接口 25: QueryChildDivisionCode +func (b *LinkedMallBiz) QueryChildDivisionCode(req *entities.QueryChildDivisionCodeReq) (*entities.CommonResponse, error) { + query := make(map[string]*string) + if req.ParentDivisionCode != "" { + query["ParentDivisionCode"] = tea.String(req.ParentDivisionCode) + } + return b.doRoaGet("/divisions:children", query) +} +``` + +// File: server_tb_LinkedMall/internal/service/service.go +```go +package service + +import ( + "encoding/json" + + "server_tb_LinkedMall/internal/biz" + "server_tb_LinkedMall/internal/config" + "server_tb_LinkedMall/internal/entities" +) + +// LinkedMallService 服务层 - 封装业务逻辑,处理响应解析 +type LinkedMallService struct { + biz *biz.LinkedMallBiz +} + +// NewLinkedMallService 创建服务实例 +func NewLinkedMallService(cfg *config.Config) (*LinkedMallService, error) { + bizInstance, err := biz.NewLinkedMallBiz(cfg) + if err != nil { + return nil, err + } + return &LinkedMallService{biz: bizInstance}, nil +} + +// parseData 解析Data字段到目标结构体 +func (s *LinkedMallService) parseData(commonResp *entities.CommonResponse, target interface{}) error { + if commonResp.Data == nil { + return nil + } + dataBytes, err := json.Marshal(commonResp.Data) + if err != nil { + return err + } + return json.Unmarshal(dataBytes, target) +} + +// buildAPIResponse 构建统一API响应 +func (s *LinkedMallService) buildAPIResponse(commonResp *entities.CommonResponse, data interface{}) *entities.APIResponse { + resp := &entities.APIResponse{ + Success: commonResp.Success, + Code: commonResp.Code, + Message: commonResp.Message, + RequestId: commonResp.RequestId, + } + + if commonResp.Success && data != nil { + resp.Data = data + } + if !commonResp.Success { + if commonResp.SubCode != "" { + resp.Message = commonResp.SubMessage + } + } + return resp +} + +// ============================================================ +// 接口 1: ListPurchaserShops +// ============================================================ +func (s *LinkedMallService) ListPurchaserShops(req *entities.ListPurchaserShopsReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.ListPurchaserShops(req) + if err != nil { + return nil, err + } + var data entities.ListPurchaserShopsRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 2: GetPurchaserShop +func (s *LinkedMallService) GetPurchaserShop(req *entities.GetPurchaserShopReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.GetPurchaserShop(req) + if err != nil { + return nil, err + } + var data entities.GetPurchaserShopRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 3: ListSelectionProducts +func (s *LinkedMallService) ListSelectionProducts(req *entities.ListSelectionProductsReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.ListSelectionProducts(req) + if err != nil { + return nil, err + } + var data entities.ListSelectionProductsRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 4: GetSelectionProduct +func (s *LinkedMallService) GetSelectionProduct(req *entities.GetSelectionProductReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.GetSelectionProduct(req) + if err != nil { + return nil, err + } + var data entities.GetSelectionProductRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 5: GetSelectionProductSaleInfo +func (s *LinkedMallService) GetSelectionProductSaleInfo(req *entities.GetSelectionProductSaleInfoReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.GetSelectionProductSaleInfo(req) + if err != nil { + return nil, err + } + var data entities.GetSelectionProductSaleInfoRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 6: ListSelectionProductSaleInfos +func (s *LinkedMallService) ListSelectionProductSaleInfos(req *entities.ListSelectionProductSaleInfosReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.ListSelectionProductSaleInfos(req) + if err != nil { + return nil, err + } + var data entities.ListSelectionProductSaleInfosRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 7: ListSelectionSkuSaleInfos +func (s *LinkedMallService) ListSelectionSkuSaleInfos(req *entities.ListSelectionSkuSaleInfosReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.ListSelectionSkuSaleInfos(req) + if err != nil { + return nil, err + } + var data entities.ListSelectionSkuSaleInfosRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 8: ListCategories +func (s *LinkedMallService) ListCategories(req *entities.ListCategoriesReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.ListCategories(req) + if err != nil { + return nil, err + } + var data entities.ListCategoriesRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 9: SearchProducts +func (s *LinkedMallService) SearchProducts(req *entities.SearchProductsReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.SearchProducts(req) + if err != nil { + return nil, err + } + var data entities.SearchProductsRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 10: SelectionGroupAddProduct +func (s *LinkedMallService) SelectionGroupAddProduct(req *entities.SelectionGroupAddProductReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.SelectionGroupAddProduct(req) + if err != nil { + return nil, err + } + var data entities.SelectionGroupAddProductRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 11: SelectionGroupRemoveProduct +func (s *LinkedMallService) SelectionGroupRemoveProduct(req *entities.SelectionGroupRemoveProductReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.SelectionGroupRemoveProduct(req) + if err != nil { + return nil, err + } + var data entities.SelectionGroupRemoveProductRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 12: RenderPurchaseOrder +func (s *LinkedMallService) RenderPurchaseOrder(req *entities.RenderPurchaseOrderReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.RenderPurchaseOrder(req) + if err != nil { + return nil, err + } + var data entities.RenderPurchaseOrderRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 13: SplitPurchaseOrder +func (s *LinkedMallService) SplitPurchaseOrder(req *entities.SplitPurchaseOrderReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.SplitPurchaseOrder(req) + if err != nil { + return nil, err + } + var data entities.SplitPurchaseOrderRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 14: CreatePurchaseOrder +func (s *LinkedMallService) CreatePurchaseOrder(req *entities.CreatePurchaseOrderReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.CreatePurchaseOrder(req) + if err != nil { + return nil, err + } + var data entities.CreatePurchaseOrderRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 15: GetPurchaseOrderStatus +func (s *LinkedMallService) GetPurchaseOrderStatus(req *entities.GetPurchaseOrderStatusReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.GetPurchaseOrderStatus(req) + if err != nil { + return nil, err + } + var data entities.GetPurchaseOrderStatusRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 16: GetOrder +func (s *LinkedMallService) GetOrder(req *entities.GetOrderReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.GetOrder(req) + if err != nil { + return nil, err + } + var data entities.GetOrderRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 17: QueryOrders +func (s *LinkedMallService) QueryOrders(req *entities.QueryOrdersReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.QueryOrders(req) + if err != nil { + return nil, err + } + var data entities.QueryOrdersRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 18: ListLogisticsOrders +func (s *LinkedMallService) ListLogisticsOrders(req *entities.ListLogisticsOrdersReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.ListLogisticsOrders(req) + if err != nil { + return nil, err + } + var data entities.ListLogisticsOrdersRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 19: ConfirmDisburse +func (s *LinkedMallService) ConfirmDisburse(req *entities.ConfirmDisburseReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.ConfirmDisburse(req) + if err != nil { + return nil, err + } + var data entities.ConfirmDisburseRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 20: RenderRefundOrder +func (s *LinkedMallService) RenderRefundOrder(req *entities.RenderRefundOrderReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.RenderRefundOrder(req) + if err != nil { + return nil, err + } + var data entities.RenderRefundOrderRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 21: CreateRefundOrder +func (s *LinkedMallService) CreateRefundOrder(req *entities.CreateRefundOrderReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.CreateRefundOrder(req) + if err != nil { + return nil, err + } + var data entities.CreateRefundOrderRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 22: CancelRefundOrder +func (s *LinkedMallService) CancelRefundOrder(req *entities.CancelRefundOrderReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.CancelRefundOrder(req) + if err != nil { + return nil, err + } + var data entities.CancelRefundOrderRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 23: GetRefundOrder +func (s *LinkedMallService) GetRefundOrder(req *entities.GetRefundOrderReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.GetRefundOrder(req) + if err != nil { + return nil, err + } + var data entities.GetRefundOrderRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 24: CreateGoodsShippingNotice +func (s *LinkedMallService) CreateGoodsShippingNotice(req *entities.CreateGoodsShippingNoticeReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.CreateGoodsShippingNotice(req) + if err != nil { + return nil, err + } + var data entities.CreateGoodsShippingNoticeRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} + +// 接口 25: QueryChildDivisionCode +func (s *LinkedMallService) QueryChildDivisionCode(req *entities.QueryChildDivisionCodeReq) (*entities.APIResponse, error) { + commonResp, err := s.biz.QueryChildDivisionCode(req) + if err != nil { + return nil, err + } + var data entities.QueryChildDivisionCodeRespData + if commonResp.Success { + _ = s.parseData(commonResp, &data) + } + return s.buildAPIResponse(commonResp, &data), nil +} +``` + +// File: server_tb_LinkedMall/internal/middleware/middleware.go +```go +package middleware + +import ( + "github.com/gofiber/fiber/v2" + "github.com/google/uuid" +) + +// RequestID 为每个请求注入RequestID +func RequestID() fiber.Handler { + return func(c *fiber.Ctx) error { + rid := c.Get("X-Request-Id") + if rid == "" { + rid = uuid.New().String() + } + c.Set("X-Request-Id", rid) + c.Locals("requestId", rid) + return c.Next() + } +} + +// StandardResponse 统一响应格式中间件 +func StandardResponse() fiber.Handler { + return func(c *fiber.Ctx) error { + // 先执行handler + err := c.Next() + if err != nil { + // 处理handler返回的错误 + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "Success": false, + "Code": "INTERNAL_ERROR", + "Message": err.Error(), + }) + } + return nil + } +} + +// CORS 跨域中间件 +func CORS() fiber.Handler { + return func(c *fiber.Ctx) error { + c.Set("Access-Control-Allow-Origin", "*") + c.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") + c.Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Request-Id") + if c.Method() == "OPTIONS" { + return c.SendStatus(fiber.StatusNoContent) + } + return c.Next() + } +} +``` + +// File: server_tb_LinkedMall/internal/router/router.go +```go +package router + +import ( + "github.com/gofiber/fiber/v2" + + "server_tb_LinkedMall/internal/middleware" + "server_tb_LinkedMall/internal/service" +) + +// SetupRouter 注册所有路由 +func SetupRouter(app *fiber.App, svc *service.LinkedMallService) { + // 全局中间件 + app.Use(middleware.RequestID()) + app.Use(middleware.CORS()) + + // 健康检查 + app.Get("/health", func(c *fiber.Ctx) error { + return c.JSON(fiber.Map{"status": "ok"}) + }) + + // API v1 路由组 + api := app.Group("/api/v1", middleware.StandardResponse()) + + // ============================================================ + // 采购方店铺相关 + // ============================================================ + + // 接口 1: ListPurchaserShops - 分页获取采购方店铺列表 + api.Get("/purchaser-shops", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "ListPurchaserShops - 待实现"}) + }) + + // 接口 2: GetPurchaserShop - 获取单个采购店铺详情 + api.Get("/purchaser-shops/:shopId", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "GetPurchaserShop - 待实现"}) + }) + + // ============================================================ + // 选品池商品相关 + // ============================================================ + + // 接口 3: ListSelectionProducts - 分页查询选品池商品列表 + api.Get("/selection-products", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "ListSelectionProducts - 待实现"}) + }) + + // 接口 4: GetSelectionProduct - 查询选品池商品详情 + api.Get("/selection-products/:productId", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "GetSelectionProduct - 待实现"}) + }) + + // 接口 5: GetSelectionProductSaleInfo - 查询选品池商品销售信息 + api.Get("/selection-products/:productId/sale-info", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "GetSelectionProductSaleInfo - 待实现"}) + }) + + // 接口 6: ListSelectionProductSaleInfos - 批量查询商品销售信息 + api.Post("/selection-products:batch-sale-info", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "ListSelectionProductSaleInfos - 待实现"}) + }) + + // 接口 7: ListSelectionSkuSaleInfos - 批量SKU销售信息 + api.Post("/selection-skus:batch-sale-info", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "ListSelectionSkuSaleInfos - 待实现"}) + }) + + // 接口 8: ListCategories - 查询类目列表 + api.Get("/categories", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "ListCategories - 待实现"}) + }) + + // 接口 9: SearchProducts - 搜索选品池商品 + api.Post("/selection-products:search", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "SearchProducts - 待实现"}) + }) + + // 接口 10: SelectionGroupAddProduct - 选品池商品入库 + api.Post("/selection-group/products:add", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "SelectionGroupAddProduct - 待实现"}) + }) + + // 接口 11: SelectionGroupRemoveProduct - 选品池商品出库 + api.Post("/selection-group/products:remove", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "SelectionGroupRemoveProduct - 待实现"}) + }) + + // ============================================================ + // 采购单相关 + // ============================================================ + + // 接口 12: RenderPurchaseOrder - 采购单渲染(下单预校验) + api.Post("/purchase-orders:render", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "RenderPurchaseOrder - 待实现"}) + }) + + // 接口 13: SplitPurchaseOrder - 采购单渲染并拆单 + api.Post("/purchase-orders:split-render", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "SplitPurchaseOrder - 待实现"}) + }) + + // 接口 14: CreatePurchaseOrder - 创建采购单【异步】 + api.Post("/purchase-orders", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "CreatePurchaseOrder - 待实现"}) + }) + + // 接口 15: GetPurchaseOrderStatus - 获取采购单状态 + api.Get("/purchase-orders/:purchaseOrderId/status", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "GetPurchaseOrderStatus - 待实现"}) + }) + + // ============================================================ + // 订单相关 + // ============================================================ + + // 接口 16: GetOrder - 获取订单详情 + api.Get("/orders/:orderId", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "GetOrder - 待实现"}) + }) + + // 接口 17: QueryOrders - 查询订单列表 + api.Get("/orders", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "QueryOrders - 待实现"}) + }) + + // 接口 18: ListLogisticsOrders - 查询订单物流信息 + api.Get("/orders/:orderId/logistics", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "ListLogisticsOrders - 待实现"}) + }) + + // 接口 19: ConfirmDisburse - 确认收货 + api.Post("/orders/:orderId:confirm-disburse", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "ConfirmDisburse - 待实现"}) + }) + + // ============================================================ + // 售后相关 + // ============================================================ + + // 接口 20: RenderRefundOrder - 售后渲染预校验 + api.Post("/refund-orders:render", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "RenderRefundOrder - 待实现"}) + }) + + // 接口 21: CreateRefundOrder - 创建售后单 + api.Post("/refund-orders", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "CreateRefundOrder - 待实现"}) + }) + + // 接口 22: CancelRefundOrder - 取消售后单 + api.Post("/refund-orders/:refundOrderId:cancel", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "CancelRefundOrder - 待实现"}) + }) + + // 接口 23: GetRefundOrder - 获取售后单详情 + api.Get("/refund-orders/:refundOrderId", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "GetRefundOrder - 待实现"}) + }) + + // 接口 24: CreateGoodsShippingNotice - 回填退货物流运单 + api.Post("/refund-orders/:refundOrderId:fill-logistics", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "CreateGoodsShippingNotice - 待实现"}) + }) + + // ============================================================ + // 区域编码 + // ============================================================ + + // 接口 25: QueryChildDivisionCode - 查询子区域编码 + api.Get("/divisions:children", func(c *fiber.Ctx) error { + // TODO: 实现参数绑定和调用 + return c.JSON(fiber.Map{"message": "QueryChildDivisionCode - 待实现"}) + }) + + // ============================================================ + // 回调通知(供LinkedMall回调) + // ============================================================ + api.Post("/callback", func(c *fiber.Ctx) error { + // TODO: 实现回调处理逻辑 + return c.JSON(fiber.Map{"success": true}) + }) +} +``` + +// File: server_tb_LinkedMall/cmd/server/main.go +```go +package main + +import ( + "fmt" + "log" + + "github.com/gofiber/fiber/v2" + + "server_tb_LinkedMall/internal/config" + "server_tb_LinkedMall/internal/router" + "server_tb_LinkedMall/internal/service" +) + +func main() { + // 加载配置 + cfg := config.LoadConfig() + + // 检查必要配置 + if cfg.AccessKeyId == "" || cfg.AccessKeySecret == "" { + log.Fatal("环境变量 LINKEDMALL_AK 和 LINKEDMALL_SK 必须设置") + } + + // 初始化服务 + svc, err := service.NewLinkedMallService(cfg) + if err != nil { + log.Fatalf("初始化服务失败: %v", err) + } + + // 创建Fiber应用 + app := fiber.New(fiber.Config{ + AppName: "LinkedMall Server", + ErrorHandler: func(c *fiber.Ctx, err error) error { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "Success": false, + "Code": "SERVER_ERROR", + "Message": err.Error(), + }) + }, + }) + + // 注册路由 + router.SetupRouter(app, svc) + + // 启动服务 + addr := fmt.Sprintf(":%s", cfg.ServerPort) + log.Printf("启动服务,监听地址: %s", addr) + if err := app.Listen(addr); err != nil { + log.Fatalf("服务启动失败: %v", err) + } +} +``` + +// File: server_tb_LinkedMall/internal/test/example_test.go +```go +package test + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gofiber/fiber/v2" + + "server_tb_LinkedMall/internal/config" + "server_tb_LinkedMall/internal/entities" + "server_tb_LinkedMall/internal/router" + "server_tb_LinkedMall/internal/service" +) + +// setupTestApp 初始化测试应用 +func setupTestApp(t *testing.T) (*fiber.App, *service.LinkedMallService) { + t.Helper() + + cfg := &config.Config{ + ServerPort: "8080", + AccessKeyId: "test-ak", + AccessKeySecret: "test-sk", + RegionId: "cn-zhangjiakou", + Endpoint: "linkedmall.cn-zhangjiakou.aliyuncs.com", + BasePath: "/opensaas-s2b/opensaas-s2b-biz-trade/v2", + DefaultPurchaserId: "test-purchaser-id", + } + + svc, err := service.NewLinkedMallService(cfg) + if err != nil { + t.Skipf("跳过测试(无法初始化服务,可能需要有效AK/SK): %v", err) + } + + app := fiber.New() + router.SetupRouter(app, svc) + return app, svc +} + +// performRequest 执行测试HTTP请求 +func performRequest(app *fiber.App, method, path string, body interface{}) *http.Response { + var reqBody []byte + if body != nil { + reqBody, _ = json.Marshal(body) + } + + req := httptest.NewRequest(method, path, bytes.NewReader(reqBody)) + req.Header.Set("Content-Type", "application/json") + + resp, _ := app.Test(req, -1) + return resp +} + +// TestHealthCheck 健康检查测试 +func TestHealthCheck(t *testing.T) { + app, _ := setupTestApp(t) + resp \ No newline at end of file