sdk_LinkedMall-20260828093422/sdk_LinkedMall/valid.md

1329 lines
43 KiB
Markdown
Raw 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.

// 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:"-"` // 采购单IDPath参数
PurchaserId string `json:"PurchaserId"` // 采购方IDQuery参数
}
// 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:"-"` // 订单IDPath参数
PurchaserId string `json:"PurchaserId"` // 采购方IDQuery参数
}
// 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:"-"` // 订单IDPath参数
PurchaserId string `json:"PurchaserId"` // 采购方IDQuery参数
}
// 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:"-"` // 售后单IDPath参数
PurchaserId string `json:"PurchaserId"` // 采购方IDQuery参数
}
// 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
}
```