sever_tb_LinkedMall-2026082.../sever_tb_LinkedMall/generate.md

1801 lines
60 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

根据文档分析该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