// File: sdk_LinkedMall/go.mod ``` module sdk_LinkedMall go 1.21 require ( github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10 github.com/alibabacloud-go/tea/v2 v2.2.0 ) // Run `go mod tidy` to generate go.sum and resolve all transitive dependencies. // If you encounter network timeout, set GOPROXY=https://goproxy.cn,direct ``` // File: sdk_LinkedMall/types.go ```go package sdk_LinkedMall import "encoding/json" // ============================================================ // 公共响应结构体 // ============================================================ // CommonResponse 是所有接口返回的统一外层包装 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 json.RawMessage `json:"Data"` } // ============================================================ // 采购方店铺 (Purchaser Shop) // ============================================================ // ListPurchaserShopsReq 分页获取采购方店铺列表的请求参数(Query) type ListPurchaserShopsReq struct { PageNum int `json:"PageNum,omitempty"` // 页码,默认1 PageSize int `json:"PageSize,omitempty"` // 每页条数,最大100 } // ListPurchaserShopsRespData 分页获取采购方店铺列表的响应Data type ListPurchaserShopsRespData struct { Total int64 `json:"Total"` PageNum int `json:"PageNum"` PageSize int `json:"PageSize"` ShopList []PurchaserShopItem `json:"ShopList"` } // PurchaserShopItem 采购方店铺信息 type PurchaserShopItem struct { ShopId string `json:"ShopId"` PurchaserId string `json:"PurchaserId"` ShopName string `json:"ShopName"` ShopStatus string `json:"ShopStatus"` } // GetPurchaserShopRespData 获取单个采购店铺详情的响应Data type GetPurchaserShopRespData struct { ShopId string `json:"ShopId"` PurchaserId string `json:"PurchaserId"` ShopName string `json:"ShopName"` ShopStatus string `json:"ShopStatus"` ContactInfo string `json:"ContactInfo"` } // ============================================================ // 选品池商品 (Selection Product) // ============================================================ // ListSelectionProductsReq 分页查询选品池商品列表的请求参数(Query) type ListSelectionProductsReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID,必填 PageNum int `json:"PageNum,omitempty"` // 页码 PageSize int `json:"PageSize,omitempty"` // 每页条数,最大100 } // ListSelectionProductsRespData 分页查询选品池商品列表的响应Data type ListSelectionProductsRespData struct { Total int64 `json:"Total"` PageNum int `json:"PageNum"` PageSize int `json:"PageSize"` ProductList []SelectionProductItem `json:"ProductList"` } // SelectionProductItem 选品池商品摘要信息 type SelectionProductItem struct { ProductId string `json:"ProductId"` Title string `json:"Title"` MainImage string `json:"MainImage"` BrandName string `json:"BrandName"` CategoryId string `json:"CategoryId"` } // GetSelectionProductRespData 查询选品池商品详情的响应Data 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"` // 传入divisionCode才有效,该区域是否可售 StockQuantity int64 `json:"StockQuantity"` // 总库存数量 } // SelectionSkuItem SKU信息 type SelectionSkuItem struct { SkuId string `json:"SkuId"` SkuSpec string `json:"SkuSpec"` SalePrice int64 `json:"SalePrice"` // 单位分 MarketPrice int64 `json:"MarketPrice"` // 单位分 StockQuantity int64 `json:"StockQuantity"` // 库存数量 } // GetSelectionProductSaleInfoRespData 查询选品池商品销售信息的响应Data type GetSelectionProductSaleInfoRespData struct { CanSale bool `json:"CanSale"` StockQuantity int64 `json:"StockQuantity"` SkuList []SelectionSkuItem `json:"SkuList"` } // ListSelectionProductSaleInfosReq 批量查询商品销售信息的请求Body type ListSelectionProductSaleInfosReq struct { PurchaserId string `json:"PurchaserId"` ProductIdList []string `json:"ProductIdList"` DivisionCode string `json:"DivisionCode,omitempty"` } // ProductSaleInfo 商品销售信息 type ProductSaleInfo struct { ProductId string `json:"ProductId"` CanSale bool `json:"CanSale"` StockQuantity int64 `json:"StockQuantity"` SkuList []SelectionSkuItem `json:"SkuList"` } // ListSelectionProductSaleInfosRespData 批量查询商品销售信息的响应Data type ListSelectionProductSaleInfosRespData struct { ProductSaleInfoList []ProductSaleInfo `json:"ProductSaleInfoList"` } // ListSelectionSkuSaleInfosReq 批量查询SKU销售信息的请求Body type ListSelectionSkuSaleInfosReq struct { PurchaserId string `json:"PurchaserId"` SkuIdList []string `json:"SkuIdList"` DivisionCode string `json:"DivisionCode,omitempty"` } // SkuSaleInfo SKU销售信息 type SkuSaleInfo struct { SkuId string `json:"SkuId"` SalePrice int64 `json:"SalePrice"` MarketPrice int64 `json:"MarketPrice"` StockQuantity int64 `json:"StockQuantity"` CanSale bool `json:"CanSale"` } // ListSelectionSkuSaleInfosRespData 批量查询SKU销售信息的响应Data type ListSelectionSkuSaleInfosRespData struct { SkuSaleInfoList []SkuSaleInfo `json:"SkuSaleInfoList"` } // SearchProductsReq 搜索选品池商品的请求Body type SearchProductsReq struct { Keyword string `json:"Keyword,omitempty"` // 关键词 CategoryId string `json:"CategoryId,omitempty"` // 类目ID PageNum int `json:"PageNum,omitempty"` // 页码 PageSize int `json:"PageSize,omitempty"` // 每页条数 PurchaserId string `json:"PurchaserId"` // 采购方ID,必填 } // SearchProductsRespData 搜索选品池商品的响应Data type SearchProductsRespData struct { Total int64 `json:"Total"` PageNum int `json:"PageNum"` PageSize int `json:"PageSize"` ProductList []SelectionProductItem `json:"ProductList"` } // ============================================================ // 类目 (Category) // ============================================================ // ListCategoriesReq 查询类目列表的请求参数(Query) type ListCategoriesReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID,必填 ParentCategoryId string `json:"ParentCategoryId,omitempty"` // 父类目ID,不传查一级类目 } // CategoryItem 类目信息 type CategoryItem struct { CategoryId string `json:"CategoryId"` CategoryName string `json:"CategoryName"` ParentId string `json:"ParentId"` Level int `json:"Level"` } // ListCategoriesRespData 查询类目列表的响应Data type ListCategoriesRespData struct { CategoryList []CategoryItem `json:"CategoryList"` } // ============================================================ // 选品池入库/出库 (Selection Group) // ============================================================ // SelectionGroupAddProductReq 选品池商品入库请求Body type SelectionGroupAddProductReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID,必填 ShopId string `json:"ShopId"` // 店铺ID,必填 ProductIdList []string `json:"ProductIdList"` // 商品ID列表,必填 } // SelectionGroupRemoveProductReq 选品池商品出库请求Body type SelectionGroupRemoveProductReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID,必填 ShopId string `json:"ShopId"` // 店铺ID,必填 ProductIdList []string `json:"ProductIdList"` // 商品ID列表,必填 } // ============================================================ // 采购单 (Purchase Order) // ============================================================ // RenderPurchaseOrderReq 采购单渲染请求Body type RenderPurchaseOrderReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID ShopId string `json:"ShopId"` // 店铺ID DivisionCode string `json:"DivisionCode"` // 五级乡镇编码 ItemList []RenderOrderItem `json:"ItemList"` // 商品列表 ReceiverInfo ReceiverInfo `json:"ReceiverInfo"` // 收货人信息 } // RenderOrderItem 渲染采购单的商品条目 type RenderOrderItem struct { SkuId string `json:"SkuId"` // SKU ID Quantity int64 `json:"Quantity"` // 数量 } // ReceiverInfo 收货人信息 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"` // 详细地址 } // RenderPurchaseOrderRespData 采购单渲染的响应Data type RenderPurchaseOrderRespData struct { TotalAmount int64 `json:"TotalAmount"` // 总金额,单位分 TotalFreight int64 `json:"TotalFreight"` // 总运费,单位分 ItemValidResult []ItemValidResultItem `json:"ItemValidResult"` // 商品校验结果 RenderItemList []RenderOrderItemResult `json:"RenderItemList"` // 渲染后的商品列表 } // ItemValidResultItem 商品校验结果 type ItemValidResultItem struct { SkuId string `json:"SkuId"` Valid bool `json:"Valid"` // 是否有效 Reason string `json:"Reason"` // 不可售原因 } // RenderOrderItemResult 渲染后的商品条目 type RenderOrderItemResult struct { SkuId string `json:"SkuId"` SalePrice int64 `json:"SalePrice"` // 实时售价,单位分 Quantity int64 `json:"Quantity"` SubTotal int64 `json:"SubTotal"` // 小计,单位分 } // SplitPurchaseOrderReq 采购单渲染并拆单的请求Body(与RenderPurchaseOrderReq结构一致) type SplitPurchaseOrderReq = RenderPurchaseOrderReq // SplitOrderItem 拆单后的子单 type SplitOrderItem struct { SubOrderId string `json:"SubOrderId"` // 子单ID SkuId string `json:"SkuId"` Quantity int64 `json:"Quantity"` SalePrice int64 `json:"SalePrice"` // 单位分 SubTotal int64 `json:"SubTotal"` // 单位分 Freight int64 `json:"Freight"` // 运费,单位分 } // SplitPurchaseOrderRespData 采购单渲染并拆单的响应Data type SplitPurchaseOrderRespData struct { TotalAmount int64 `json:"TotalAmount"` // 总金额,单位分 TotalFreight int64 `json:"TotalFreight"` // 总运费,单位分 SubOrderList []SplitOrderItem `json:"SubOrderList"` // 子单列表 } // CreatePurchaseOrderReq 创建采购单请求Body type CreatePurchaseOrderReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID ShopId string `json:"ShopId"` // 店铺ID OuterPurchaseOrderId string `json:"OuterPurchaseOrderId"` // 外部业务唯一单号,幂等 DivisionCode string `json:"DivisionCode"` // 五级乡镇编码 ReceiverInfo ReceiverInfo `json:"ReceiverInfo"` // 收货人信息 SubOrderList []CreateSubOrderItem `json:"SubOrderList"` // 子单列表 } // CreateSubOrderItem 创建采购单的子单条目 type CreateSubOrderItem struct { SkuId string `json:"SkuId"` Quantity int64 `json:"Quantity"` } // CreatePurchaseOrderRespData 创建采购单的响应Data type CreatePurchaseOrderRespData struct { PurchaseOrderId string `json:"PurchaseOrderId"` // 阿里云采购单号 } // GetPurchaseOrderStatusReq 获取采购单状态的请求参数(Query + Path) type GetPurchaseOrderStatusReq struct { PurchaseOrderId string `json:"-"` // 采购单ID,Path参数 PurchaserId string `json:"PurchaserId"` // 采购方ID,Query参数 } // GetPurchaseOrderStatusRespData 获取采购单状态的响应Data type GetPurchaseOrderStatusRespData struct { PurchaseOrderId string `json:"PurchaseOrderId"` Status string `json:"Status"` // INIT / PROCESS / SUCCESS / FAIL / CLOSED } // ============================================================ // 订单 (Order) // ============================================================ // GetOrderReq 获取订单详情的请求参数 type GetOrderReq struct { OrderId string `json:"-"` // 订单ID,Path参数 PurchaserId string `json:"PurchaserId"` // 采购方ID,Query参数 } // GetOrderRespData 获取订单详情的响应Data type GetOrderRespData struct { OrderId string `json:"OrderId"` PurchaseOrderId string `json:"PurchaseOrderId"` PurchaserId string `json:"PurchaserId"` ShopId string `json:"ShopId"` OrderStatus string `json:"OrderStatus"` TotalAmount int64 `json:"TotalAmount"` // 实付金额,单位分 TotalFreight int64 `json:"TotalFreight"` // 运费,单位分 ReceiverInfo ReceiverInfo `json:"ReceiverInfo"` OrderItemList []OrderItemDetail `json:"OrderItemList"` CreateTime string `json:"CreateTime"` PayTime string `json:"PayTime"` } // OrderItemDetail 订单商品明细 type OrderItemDetail struct { OrderItemId string `json:"OrderItemId"` SkuId string `json:"SkuId"` ProductId string `json:"ProductId"` ProductName string `json:"ProductName"` Quantity int64 `json:"Quantity"` SalePrice int64 `json:"SalePrice"` // 单位分 SubTotal int64 `json:"SubTotal"` // 单位分 ItemStatus string `json:"ItemStatus"` RefundQuantity int64 `json:"RefundQuantity"` } // QueryOrdersReq 查询订单列表的请求参数(Query) type QueryOrdersReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID,必填 PurchaseOrderId string `json:"PurchaseOrderId,omitempty"` // 采购单ID PageNum int `json:"PageNum,omitempty"` // 页码 PageSize int `json:"PageSize,omitempty"` // 每页条数 StartTime string `json:"StartTime,omitempty"` // 开始时间 EndTime string `json:"EndTime,omitempty"` // 结束时间 } // QueryOrdersRespData 查询订单列表的响应Data type QueryOrdersRespData struct { Total int64 `json:"Total"` PageNum int `json:"PageNum"` PageSize int `json:"PageSize"` OrderList []OrderSummaryItem `json:"OrderList"` } // OrderSummaryItem 订单摘要信息 type OrderSummaryItem struct { OrderId string `json:"OrderId"` PurchaseOrderId string `json:"PurchaseOrderId"` OrderStatus string `json:"OrderStatus"` TotalAmount int64 `json:"TotalAmount"` // 单位分 CreateTime string `json:"CreateTime"` PayTime string `json:"PayTime"` } // ============================================================ // 物流 (Logistics) // ============================================================ // ListLogisticsOrdersReq 查询订单物流信息的请求参数 type ListLogisticsOrdersReq struct { OrderId string `json:"-"` // 订单ID,Path参数 PurchaserId string `json:"PurchaserId"` // 采购方ID,Query参数 } // ListLogisticsOrdersRespData 查询订单物流信息的响应Data type ListLogisticsOrdersRespData struct { LogisticsList []LogisticsInfo `json:"LogisticsList"` } // LogisticsInfo 物流信息 type LogisticsInfo struct { LogisticsCompany string `json:"LogisticsCompany"` // 物流公司 TrackingNumber string `json:"TrackingNumber"` // 运单号 Traces []LogisticsTrace `json:"Traces"` // 物流轨迹 } // LogisticsTrace 物流轨迹 type LogisticsTrace struct { Time string `json:"Time"` // 轨迹时间 Location string `json:"Location"` // 轨迹地点 Action string `json:"Action"` // 轨迹描述 } // ============================================================ // 确认收货 (Confirm Disburse) // ============================================================ // ConfirmDisburseReq 确认收货的请求Body type ConfirmDisburseReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID } // ============================================================ // 售后单 (Refund Order) // ============================================================ // RenderRefundOrderReq 售后渲染预校验的请求Body type RenderRefundOrderReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID OrderId string `json:"OrderId"` // 订单ID OrderItemId string `json:"OrderItemId"` // 订单商品明细ID RefundQuantity int64 `json:"RefundQuantity"` // 退款数量 RefundType string `json:"RefundType"` // 退款类型(仅退款/退货退款) } // RenderRefundOrderRespData 售后渲染预校验的响应Data type RenderRefundOrderRespData struct { Valid bool `json:"Valid"` // 是否可售后 MaxRefundQuantity int64 `json:"MaxRefundQuantity"` // 最大可退数量 MaxRefundAmount int64 `json:"MaxRefundAmount"` // 最大可退金额,单位分 RefundReason string `json:"RefundReason"` // 不可售原因 } // CreateRefundOrderReq 创建售后单的请求Body type CreateRefundOrderReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID OrderId string `json:"OrderId"` // 订单ID OrderItemId string `json:"OrderItemId"` // 订单商品明细ID RefundQuantity int64 `json:"RefundQuantity"` // 退款数量 RefundAmount int64 `json:"RefundAmount"` // 退款金额,单位分 RefundType string `json:"RefundType"` // 退款类型 RefundReason string `json:"RefundReason"` // 退款原因 OuterRefundNo string `json:"OuterRefundNo"` // 外部售后单号 } // CreateRefundOrderRespData 创建售后单的响应Data type CreateRefundOrderRespData struct { RefundOrderId string `json:"RefundOrderId"` // 售后单ID } // CancelRefundOrderReq 取消售后单的请求Body type CancelRefundOrderReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID } // CancelRefundOrderRespData 取消售后单的响应Data type CancelRefundOrderRespData struct { RefundOrderId string `json:"RefundOrderId"` Status string `json:"Status"` } // GetRefundOrderReq 获取售后单详情的请求参数 type GetRefundOrderReq struct { RefundOrderId string `json:"-"` // 售后单ID,Path参数 PurchaserId string `json:"PurchaserId"` // 采购方ID,Query参数 } // GetRefundOrderRespData 获取售后单详情的响应Data type GetRefundOrderRespData struct { RefundOrderId string `json:"RefundOrderId"` OrderId string `json:"OrderId"` OrderItemId string `json:"OrderItemId"` PurchaserId string `json:"PurchaserId"` RefundType string `json:"RefundType"` RefundStatus string `json:"RefundStatus"` RefundQuantity int64 `json:"RefundQuantity"` RefundAmount int64 `json:"RefundAmount"` // 单位分 RefundReason string `json:"RefundReason"` OuterRefundNo string `json:"OuterRefundNo"` CreateTime string `json:"CreateTime"` } // CreateGoodsShippingNoticeReq 回填退货物流运单的请求Body type CreateGoodsShippingNoticeReq struct { PurchaserId string `json:"PurchaserId"` // 采购方ID LogisticsCompany string `json:"LogisticsCompany"` // 物流公司 TrackingNumber string `json:"TrackingNumber"` // 运单号 } // CreateGoodsShippingNoticeRespData 回填退货物流运单的响应Data type CreateGoodsShippingNoticeRespData struct { Result bool `json:"Result"` } // ============================================================ // 区域编码 (Division Code) // ============================================================ // QueryChildDivisionCodeReq 查询子区域编码的请求参数(Query) type QueryChildDivisionCodeReq struct { ParentDivisionCode string `json:"ParentDivisionCode,omitempty"` // 父区域编码,不传返回省级 } // DivisionInfo 区域编码信息 type DivisionInfo struct { DivisionCode string `json:"DivisionCode"` // 区域编码 DivisionName string `json:"DivisionName"` // 区域名称 Level int `json:"Level"` // 层级:1-省,2-市,3-区,4-乡镇 ParentCode string `json:"ParentCode"` // 父区域编码 } // QueryChildDivisionCodeRespData 查询子区域编码的响应Data type QueryChildDivisionCodeRespData struct { DivisionList []DivisionInfo `json:"DivisionList"` } // ============================================================ // 通用操作响应 // ============================================================ // OperationRespData 通用操作响应Data(入库/出库/确认收货等) type OperationRespData struct { Result bool `json:"Result"` } ``` // File: sdk_LinkedMall/errors.go ```go package sdk_LinkedMall import "fmt" // APIError 表示API返回的业务错误 type APIError struct { Code string `json:"Code"` // 错误码 Message string `json:"Message"` // 错误信息 SubCode string `json:"SubCode"` // 子错误码 SubMessage string `json:"SubMessage"` // 子错误信息 RequestId string `json:"RequestId"` // 请求ID } func (e *APIError) Error() string { return fmt.Sprintf("linkedmall API error: code=%s, message=%s, subCode=%s, subMessage=%s, requestId=%s", e.Code, e.Message, e.SubCode, e.SubMessage, e.RequestId) } // IsSuccess 判断是否业务成功 func (e *APIError) IsSuccess() bool { return e.Code == "SUCCESS" } // 预定义错误码常量 const ( ErrCodeShopTypeInvalid = "ShopTypeInvalid" ErrCodeSkuPriceNotLatest = "SkuPriceUnique" ErrCodePurchaseOrderNotFound = "PurchaseOrderNotFound" ErrCodeRefundNumberExceed = "RefundNumberMustLessThanOrder" ErrCodeRefundAmountExceed = "RefundAmountMustLessThanOrder" ErrCodeNoPrivilege = "HasNoPrivilege" ErrCodeOrderNotFound = "OrderNotFound" ErrCodeShopNotFound = "ShopNotFind" ErrCodeSavePurchaseOrderError = "SavePurchaseOrderError" ErrCodeOuterPurchaseOrderIdExist = "OuterPurchaseOrderIdExist" ) // ErrResp 用于解析错误响应 type ErrResp struct { Code string `json:"Code"` Message string `json:"Message"` SubCode string `json:"SubCode"` SubMessage string `json:"SubMessage"` RequestId string `json:"RequestId"` } ``` // File: sdk_LinkedMall/crypto.go ```go package sdk_LinkedMall // 本文件预留用于加密相关功能。 // // 当前SDK使用阿里云 darabonba-openapi 客户端发起ROA签名调用, // 签名过程由底层客户端自动处理,业务层无需实现签名算法。 // // 如需使用国密(SM2/SM3/SM4)或其他加密算法,可在此文件中添加实现。 // 建议使用 github.com/tjfoc/gmsm 库进行国密算法实现。 // // 示例: // import "github.com/tjfoc/gmsm/sm3" // func SM3Hash(data []byte) []byte { // h := sm3.New() // h.Write(data) // return h.Sum(nil) // } ``` // File: sdk_LinkedMall/client.go ```go package sdk_LinkedMall import ( "encoding/json" "fmt" "io" "net/http" "strconv" "strings" openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/v2" ) const ( defaultRegionId = "cn-zhangjiakou" defaultEndpoint = "linkedmall.cn-zhangjiakou.aliyuncs.com" basePath = "/opensaas-s2b/opensaas-s2b-biz-trade/v2" readTimeout = 30000 connectTimeout = 10000 ) // Client LinkedMall SDK 客户端 type Client struct { inner *openapi.Client } // NewClient 创建一个新的LinkedMall SDK客户端 // // 使用RAM子账号的AccessKey初始化,禁止使用主账号AK。 // 示例: // // cli, err := NewClient("your-access-key-id", "your-access-key-secret") // if err != nil { // panic(err) // } func NewClient(accessKeyId, accessKeySecret string) (*Client, error) { config := &openapi.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), RegionId: tea.String(defaultRegionId), Endpoint: tea.String(defaultEndpoint), ReadTimeout: tea.Int(readTimeout), ConnectTimeout: tea.Int(connectTimeout), } c, err := openapi.NewClient(config) if err != nil { return nil, fmt.Errorf("failed to create openapi client: %w", err) } return &Client{inner: c}, nil } // buildPath 构建完整的请求路径 func buildPath(suffix string) string { return basePath + suffix } // toQueryMap 将结构体转为查询参数map func toQueryMap(params interface{}) map[string]*string { result := make(map[string]*string) if params == nil { return result } // 使用json标签序列化后转为map data, _ := json.Marshal(params) var rawMap map[string]interface{} if err := json.Unmarshal(data, &rawMap); err != nil { return result } for k, v := range rawMap { switch val := v.(type) { case string: if val != "" { result[k] = tea.String(val) } case float64: if val != 0 { result[k] = tea.String(strconv.FormatInt(int64(val), 10)) } case bool: result[k] = tea.String(strconv.FormatBool(val)) default: // 忽略复杂类型 } } return result } // doRequest 执行HTTP请求并返回响应体字节 func (c *Client) doRequest(method, path string, query map[string]*string, body interface{}) ([]byte, error) { resp, err := c.inner.RoaRequest( tea.String(method), tea.String(path), query, body, nil, ) if err != nil { return nil, fmt.Errorf("roa request failed: %w", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { bodyBytes, _ := io.ReadAll(resp.Body) return nil, fmt.Errorf("unexpected http status %d, body: %s", resp.StatusCode, string(bodyBytes)) } return io.ReadAll(resp.Body) } // parseResponse 解析通用响应,如果业务失败返回 *APIError func (c *Client) parseResponse(data []byte, target interface{}) error { var commonResp CommonResponse if err := json.Unmarshal(data, &commonResp); err != nil { return fmt.Errorf("failed to parse common response: %w, body: %s", err, string(data)) } if !commonResp.Success { return &APIError{ Code: commonResp.Code, Message: commonResp.Message, SubCode: commonResp.SubCode, SubMessage: commonResp.SubMessage, RequestId: commonResp.RequestId, } } if target != nil && len(commonResp.Data) > 0 { if err := json.Unmarshal(commonResp.Data, target); err != nil { return fmt.Errorf("failed to parse data field: %w, data: %s", err, string(commonResp.Data)) } } return nil } // ============================================================ // 采购方店铺 (Purchaser Shop) // ============================================================ // ListPurchaserShops 分页获取采购方店铺列表 func (c *Client) ListPurchaserShops(req *ListPurchaserShopsReq) (*ListPurchaserShopsRespData, error) { path := buildPath("/purchaser-shops") query := toQueryMap(req) data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result ListPurchaserShopsRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // GetPurchaserShop 获取单个采购店铺详情 func (c *Client) GetPurchaserShop(shopId string) (*GetPurchaserShopRespData, error) { path := buildPath("/purchaser-shops/" + shopId) data, err := c.doRequest("GET", path, nil, nil) if err != nil { return nil, err } var result GetPurchaserShopRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // 选品池商品 (Selection Product) // ============================================================ // ListSelectionProducts 分页查询选品池商品列表 func (c *Client) ListSelectionProducts(req *ListSelectionProductsReq) (*ListSelectionProductsRespData, error) { path := buildPath("/selection-products") query := toQueryMap(req) data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result ListSelectionProductsRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // GetSelectionProduct 查询选品池商品详情 // // divisionCode 为可选参数,传入五级乡镇区域编码后可返回该区域可售状态和库存。 func (c *Client) GetSelectionProduct(productId, purchaserId, divisionCode string) (*GetSelectionProductRespData, error) { path := buildPath("/selection-products/" + productId) query := map[string]*string{ "PurchaserId": tea.String(purchaserId), } if divisionCode != "" { query["DivisionCode"] = tea.String(divisionCode) } data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result GetSelectionProductRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // GetSelectionProductSaleInfo 查询选品池商品销售信息 func (c *Client) GetSelectionProductSaleInfo(productId, purchaserId, divisionCode string) (*GetSelectionProductSaleInfoRespData, error) { path := buildPath("/selection-products/" + productId + "/sale-info") query := map[string]*string{ "PurchaserId": tea.String(purchaserId), } if divisionCode != "" { query["DivisionCode"] = tea.String(divisionCode) } data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result GetSelectionProductSaleInfoRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ListSelectionProductSaleInfos 批量查询商品销售信息 func (c *Client) ListSelectionProductSaleInfos(req *ListSelectionProductSaleInfosReq) (*ListSelectionProductSaleInfosRespData, error) { path := buildPath("/selection-products:batch-sale-info") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result ListSelectionProductSaleInfosRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ListSelectionSkuSaleInfos 批量查询SKU销售信息 func (c *Client) ListSelectionSkuSaleInfos(req *ListSelectionSkuSaleInfosReq) (*ListSelectionSkuSaleInfosRespData, error) { path := buildPath("/selection-skus:batch-sale-info") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result ListSelectionSkuSaleInfosRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ListCategories 查询类目列表 func (c *Client) ListCategories(req *ListCategoriesReq) (*ListCategoriesRespData, error) { path := buildPath("/categories") query := toQueryMap(req) data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result ListCategoriesRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // SearchProducts 搜索选品池商品 func (c *Client) SearchProducts(req *SearchProductsReq) (*SearchProductsRespData, error) { path := buildPath("/selection-products:search") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result SearchProductsRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // 选品池入库/出库 // ============================================================ // SelectionGroupAddProduct 选品池商品入库 func (c *Client) SelectionGroupAddProduct(req *SelectionGroupAddProductReq) (*OperationRespData, error) { path := buildPath("/selection-group/products:add") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result OperationRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // SelectionGroupRemoveProduct 选品池商品出库 func (c *Client) SelectionGroupRemoveProduct(req *SelectionGroupRemoveProductReq) (*OperationRespData, error) { path := buildPath("/selection-group/products:remove") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result OperationRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // 采购单 (Purchase Order) // ============================================================ // RenderPurchaseOrder 采购单渲染(下单预校验) // // 下单前必须调用,获取实时价格、校验商品是否可售。 func (c *Client) RenderPurchaseOrder(req *RenderPurchaseOrderReq) (*RenderPurchaseOrderRespData, error) { path := buildPath("/purchase-orders:render") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result RenderPurchaseOrderRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // SplitPurchaseOrder 采购单渲染并拆单 // // 返回拆成多份子单结构,用于前端展示,拆单结果用于创建采购单入参。 func (c *Client) SplitPurchaseOrder(req *SplitPurchaseOrderReq) (*SplitPurchaseOrderRespData, error) { path := buildPath("/purchase-orders:split-render") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result SplitPurchaseOrderRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // CreatePurchaseOrder 创建采购单【异步】 // // 重要:接口只返回采购单号,不代表下单成功,必须等待回调通知,再查询订单接口。 // 禁止在同步返回后直接标记本地订单成功。 func (c *Client) CreatePurchaseOrder(req *CreatePurchaseOrderReq) (*CreatePurchaseOrderRespData, error) { path := buildPath("/purchase-orders") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result CreatePurchaseOrderRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // GetPurchaseOrderStatus 获取采购单状态 // // 状态枚举:INIT(初始化)、PROCESS(处理中)、SUCCESS(成功)、FAIL(失败)、CLOSED(已关闭) func (c *Client) GetPurchaseOrderStatus(purchaseOrderId, purchaserId string) (*GetPurchaseOrderStatusRespData, error) { path := buildPath("/purchase-orders/" + purchaseOrderId + "/status") query := map[string]*string{ "PurchaserId": tea.String(purchaserId), } data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result GetPurchaseOrderStatusRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // 订单 (Order) // ============================================================ // GetOrder 获取订单详情 func (c *Client) GetOrder(orderId, purchaserId string) (*GetOrderRespData, error) { path := buildPath("/orders/" + orderId) query := map[string]*string{ "PurchaserId": tea.String(purchaserId), } data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result GetOrderRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // QueryOrders 查询订单列表 func (c *Client) QueryOrders(req *QueryOrdersReq) (*QueryOrdersRespData, error) { path := buildPath("/orders") query := toQueryMap(req) data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result QueryOrdersRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ListLogisticsOrders 查询订单物流信息 func (c *Client) ListLogisticsOrders(orderId, purchaserId string) (*ListLogisticsOrdersRespData, error) { path := buildPath("/orders/" + orderId + "/logistics") query := map[string]*string{ "PurchaserId": tea.String(purchaserId), } data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result ListLogisticsOrdersRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ConfirmDisburse 确认收货 func (c *Client) ConfirmDisburse(orderId, purchaserId string) (*OperationRespData, error) { path := buildPath("/orders/" + orderId + ":confirm-disburse") body := map[string]*string{ "PurchaserId": tea.String(purchaserId), } data, err := c.doRequest("POST", path, nil, body) if err != nil { return nil, err } var result OperationRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // 售后单 (Refund Order) // ============================================================ // RenderRefundOrder 售后渲染预校验 func (c *Client) RenderRefundOrder(req *RenderRefundOrderReq) (*RenderRefundOrderRespData, error) { path := buildPath("/refund-orders:render") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result RenderRefundOrderRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // CreateRefundOrder 创建售后单 func (c *Client) CreateRefundOrder(req *CreateRefundOrderReq) (*CreateRefundOrderRespData, error) { path := buildPath("/refund-orders") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result CreateRefundOrderRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // CancelRefundOrder 取消售后单 func (c *Client) CancelRefundOrder(refundOrderId, purchaserId string) (*CancelRefundOrderRespData, error) { path := buildPath("/refund-orders/" + refundOrderId + ":cancel") body := map[string]*string{ "PurchaserId": tea.String(purchaserId), } data, err := c.doRequest("POST", path, nil, body) if err != nil { return nil, err } var result CancelRefundOrderRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // GetRefundOrder 获取售后单详情 func (c *Client) GetRefundOrder(refundOrderId, purchaserId string) (*GetRefundOrderRespData, error) { path := buildPath("/refund-orders/" + refundOrderId) query := map[string]*string{ "PurchaserId": tea.String(purchaserId), } data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result GetRefundOrderRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // CreateGoodsShippingNotice 回填退货物流运单 func (c *Client) CreateGoodsShippingNotice(refundOrderId string, req *CreateGoodsShippingNoticeReq) (*CreateGoodsShippingNoticeRespData, error) { path := buildPath("/refund-orders/" + refundOrderId + ":fill-logistics") data, err := c.doRequest("POST", path, nil, req) if err != nil { return nil, err } var result CreateGoodsShippingNoticeRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // 区域编码 (Division Code) // ============================================================ // QueryChildDivisionCode 查询子区域编码 // // 不传ParentDivisionCode返回省级编码; // 传入省返回市,传入市返回区,传入区返回乡镇(五级)。 // 下单、商品可售校验必须拿到乡镇级DivisionCode。 func (c *Client) QueryChildDivisionCode(parentDivisionCode string) (*QueryChildDivisionCodeRespData, error) { path := buildPath("/divisions:children") var query map[string]*string if parentDivisionCode != "" { query = map[string]*string{ "ParentDivisionCode": tea.String(parentDivisionCode), } } data, err := c.doRequest("GET", path, query, nil) if err != nil { return nil, err } var result QueryChildDivisionCodeRespData if err := c.parseResponse(data, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // 回调解析工具 // ============================================================ // CallbackEvent 回调通知事件结构体 type CallbackEvent struct { EventCode string `json:"EventCode"` // 事件类型 PurchaseOrderId string `json:"PurchaseOrderId"` // 采购单ID OrderIdList []string `json:"OrderIdList"` // 附属真实订单ID数组 Status string `json:"Status"` // 状态 RequestId string `json:"RequestId"` // 请求ID } // ParseCallbackEvent 解析回调通知的JSON Body // // 业务侧在回调接口中接收阿里云POST请求,解析事件后做本地状态同步。 // 处理完成后需返回 {"success":true} 告知阿里云消费成功。 func ParseCallbackEvent(body []byte) (*CallbackEvent, error) { var event CallbackEvent if err := json.Unmarshal(body, &event); err != nil { return nil, fmt.Errorf("failed to parse callback event: %w", err) } return &event, nil } // CallbackSuccessResponse 回调成功响应 // // 业务处理完回调事件后,返回此结构告知阿里云消费成功。 func CallbackSuccessResponse() string { return `{"success":true}` } // IsAPIError 判断错误是否为指定错误码 func IsAPIError(err error, code string) bool { if apiErr, ok := err.(*APIError); ok { return apiErr.Code == code } return false } // ============================================================ // 辅助函数 // ============================================================ // ToQueryString 将结构体转为URL查询字符串(仅用于调试) func ToQueryString(params interface{}) string { query := toQueryMap(params) if len(query) == 0 { return "" } var parts []string for k, v := range query { if v != nil { parts = append(parts, k+"="+*v) } } return strings.Join(parts, "&") } ``` // File: sdk_LinkedMall/example_test.go ```go package sdk_LinkedMall import ( "fmt" "log" "os" ) // ExampleNewClient 演示如何创建客户端 func ExampleNewClient() { // 从环境变量获取AK,禁止硬编码 accessKeyId := os.Getenv("LINKEDMALL_AK_ID") accessKeySecret := os.Getenv("LINKEDMALL_AK_SECRET") cli, err := NewClient(accessKeyId, accessKeySecret) if err != nil { log.Fatalf("failed to create client: %v", err) } _ = cli fmt.Println("client created successfully") // Output: client created successfully } ```