sdk_LinkedMall-20260828161641/sdk_LinkedMall/generate.md

1280 lines
45 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.

我先分析文档:该文档明确说明使用通用 OpenApiClientdarabonba-openapi/v2发起 ROA 调用ROA 签名由 SDK 内部自动处理,业务无需自行实现签名/加密算法。因此本次不调用加密工具crypto.go 中提供与数据安全int64 金额精度、JSON 序列化)相关的辅助函数,并保留加解密扩展位。
下面一次性生成全部 6 个文件。
// File: sdk_LinkedMall/go.mod
```go
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
)
```
// File: sdk_LinkedMall/types.go
```go
package sdk_LinkedMall
import "encoding/json"
// CommonResponse 是所有接口统一返回的外层结构体。
//
// 注意HTTP 200 不代表业务成功,必须判断 Success 字段是否为 true。
// Code 为 SUCCESS 表示业务调用成功;否则看 SubCode、SubMessage 定位失败原因。
// Data 为业务数据,不同接口 Data 内部结构不同,可配合各接口的响应数据类型使用,
// 或调用 DataAs 方法解码到目标结构体。
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"`
}
// DataAs 将 Data 字段解码到目标结构体 out 中。
func (r *CommonResponse) DataAs(out interface{}) error {
if r == nil || r.Data == nil {
return nil
}
b, err := json.Marshal(r.Data)
if err != nil {
return err
}
return json.Unmarshal(b, out)
}
// rawResponse 用于内部解析响应Data 使用 json.RawMessage 以支持按接口类型解码。
type rawResponse 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"`
}
// ---------- 采购方店铺 ----------
// ListPurchaserShopsRequest 分页获取采购方店铺列表请求。
type ListPurchaserShopsRequest struct {
PageNum int `json:"PageNum"`
PageSize int `json:"PageSize"`
}
// ListPurchaserShopsRespData 分页获取采购方店铺列表响应数据。
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"`
}
// GetPurchaserShopRequest 获取单个采购店铺详情请求。
type GetPurchaserShopRequest struct {
ShopId string `json:"-"`
}
// GetPurchaserShopRespData 获取单个采购店铺详情响应数据。
type GetPurchaserShopRespData struct {
ShopId string `json:"ShopId"`
PurchaserId string `json:"PurchaserId"`
ShopName string `json:"ShopName"`
ShopStatus string `json:"ShopStatus"`
ContactInfo string `json:"ContactInfo"`
}
// ---------- 选品池商品 ----------
// ListSelectionProductsRequest 分页查询选品池商品列表请求。
type ListSelectionProductsRequest struct {
PageNum int `json:"PageNum"`
PageSize int `json:"PageSize"`
PurchaserId string `json:"PurchaserId"`
}
// ListSelectionProductsRespData 分页查询选品池商品列表响应数据。
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"`
}
// GetSelectionProductRequest 查询选品池商品详情请求。
type GetSelectionProductRequest struct {
ProductId string `json:"-"`
PurchaserId string `json:"PurchaserId"`
DivisionCode string `json:"DivisionCode"`
}
// GetSelectionProductRespData 查询选品池商品详情响应数据。
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"`
}
// 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"`
}
// ---------- 类目 ----------
// ListCategoriesRequest 查询类目列表请求。
type ListCategoriesRequest struct {
PurchaserId string `json:"PurchaserId"`
ParentCategoryId string `json:"ParentCategoryId"`
}
// ListCategoriesRespData 查询类目列表响应数据。
type ListCategoriesRespData struct {
CategoryList []CategoryItem `json:"CategoryList"`
}
// CategoryItem 类目项。
type CategoryItem struct {
CategoryId string `json:"CategoryId"`
CategoryName string `json:"CategoryName"`
ParentId string `json:"ParentId"`
Level int `json:"Level"`
Leaf bool `json:"Leaf"`
}
// ---------- 搜索 ----------
// SearchProductsRequest 搜索选品池商品请求。
type SearchProductsRequest struct {
Keyword string `json:"Keyword"`
CategoryId string `json:"CategoryId"`
PageNum int `json:"PageNum"`
PageSize int `json:"PageSize"`
PurchaserId string `json:"PurchaserId"`
}
// SearchProductsRespData 搜索选品池商品响应数据。
type SearchProductsRespData struct {
Total int64 `json:"Total"`
PageNum int `json:"PageNum"`
PageSize int `json:"PageSize"`
ProductList []SelectionProductItem `json:"ProductList"`
}
// ---------- 选品池入库/出库 ----------
// SelectionGroupAddProductRequest 选品池商品入库请求。
type SelectionGroupAddProductRequest struct {
PurchaserId string `json:"PurchaserId"`
ShopId string `json:"ShopId"`
ProductIdList []string `json:"ProductIdList"`
}
// SelectionGroupRemoveProductRequest 选品池商品出库请求。
type SelectionGroupRemoveProductRequest struct {
PurchaserId string `json:"PurchaserId"`
ShopId string `json:"ShopId"`
ProductIdList []string `json:"ProductIdList"`
}
// SelectionGroupChangeProductRespData 选品池商品入库/出库响应数据。
type SelectionGroupChangeProductRespData struct {
SuccessCount int `json:"SuccessCount"`
}
// ---------- 采购单渲染 ----------
// RenderPurchaseOrderReq 采购单渲染(下单预校验)请求。
// SplitPurchaseOrder 请求体结构与之一致。
type RenderPurchaseOrderReq struct {
PurchaserId string `json:"PurchaserId"`
ShopId string `json:"ShopId"`
DivisionCode string `json:"DivisionCode"`
ItemList []RenderOrderItem `json:"ItemList"`
ReceiverInfo ReceiverInfo `json:"ReceiverInfo"`
}
// RenderOrderItem 渲染请求中的商品项。
type RenderOrderItem struct {
SkuId string `json:"SkuId"`
Quantity int64 `json:"Quantity"`
}
// ReceiverInfo 收货人信息。DivisionCode 必须使用五级(乡镇街道)编码。
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 采购单渲染响应数据。
type RenderPurchaseOrderRespData struct {
CanSale bool `json:"CanSale"`
UnSaleReason string `json:"UnSaleReason"`
TotalAmount int64 `json:"TotalAmount"`
FreightAmount int64 `json:"FreightAmount"`
ItemList []RenderResultItem `json:"ItemList"`
}
// RenderResultItem 渲染结果中的商品明细。
type RenderResultItem struct {
SkuId string `json:"SkuId"`
ProductId string `json:"ProductId"`
Quantity int64 `json:"Quantity"`
SalePrice int64 `json:"SalePrice"`
CanSale bool `json:"CanSale"`
UnSaleReason string `json:"UnSaleReason"`
}
// ---------- 拆单 ----------
// SplitPurchaseOrderRespData 采购单渲染并拆单响应数据。
type SplitPurchaseOrderRespData struct {
SubOrderList []SplitSubOrderItem `json:"SubOrderList"`
}
// SplitSubOrderItem 拆单后的子单商品项。
type SplitSubOrderItem struct {
ShopId string `json:"ShopId"`
SkuId string `json:"SkuId"`
Quantity int64 `json:"Quantity"`
SalePrice int64 `json:"SalePrice"`
}
// ---------- 创建采购单 ----------
// CreatePurchaseOrderReq 创建采购单请求。
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"`
}
// CreateSubOrderItem 创建采购单子单商品项。
type CreateSubOrderItem struct {
SkuId string `json:"SkuId"`
Quantity int64 `json:"Quantity"`
}
// CreatePurchaseOrderRespData 创建采购单响应数据。
type CreatePurchaseOrderRespData struct {
PurchaseOrderId string `json:"PurchaseOrderId"`
}
// 采购单状态枚举。
const (
PurchaseOrderStatusInit = "INIT"
PurchaseOrderStatusProcess = "PROCESS"
PurchaseOrderStatusSuccess = "SUCCESS"
PurchaseOrderStatusFail = "FAIL"
PurchaseOrderStatusClosed = "CLOSED"
)
// GetPurchaseOrderStatusRequest 获取采购单状态请求。
type GetPurchaseOrderStatusRequest struct {
PurchaseOrderId string `json:"-"`
PurchaserId string `json:"PurchaserId"`
}
// GetPurchaseOrderStatusRespData 获取采购单状态响应数据。
type GetPurchaseOrderStatusRespData struct {
PurchaseOrderId string `json:"PurchaseOrderId"`
Status string `json:"Status"`
OrderIdList []string `json:"OrderIdList"`
}
// ---------- 订单 ----------
// GetOrderRequest 获取订单详情请求。
type GetOrderRequest struct {
OrderId string `json:"-"`
PurchaserId string `json:"PurchaserId"`
}
// GetOrderRespData 获取订单详情响应数据。
type GetOrderRespData struct {
OrderId string `json:"OrderId"`
PurchaseOrderId string `json:"PurchaseOrderId"`
Status string `json:"Status"`
TotalAmount int64 `json:"TotalAmount"`
PayAmount int64 `json:"PayAmount"`
FreightAmount int64 `json:"FreightAmount"`
CreateTime string `json:"CreateTime"`
ItemList []OrderItem `json:"ItemList"`
ReceiverInfo OrderReceiverInfo `json:"ReceiverInfo"`
}
// OrderItem 订单商品明细。
type OrderItem struct {
OrderItemId string `json:"OrderItemId"`
ProductId string `json:"ProductId"`
SkuId string `json:"SkuId"`
SkuSpec string `json:"SkuSpec"`
Title string `json:"Title"`
Quantity int64 `json:"Quantity"`
PayAmount int64 `json:"PayAmount"`
}
// OrderReceiverInfo 订单收货信息。
type OrderReceiverInfo 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"`
}
// QueryOrdersRequest 查询订单列表请求。
type QueryOrdersRequest struct {
PurchaserId string `json:"PurchaserId"`
PurchaseOrderId string `json:"PurchaseOrderId"`
PageNum int `json:"PageNum"`
PageSize int `json:"PageSize"`
StartTime string `json:"StartTime"`
EndTime string `json:"EndTime"`
}
// QueryOrdersRespData 查询订单列表响应数据。
type QueryOrdersRespData struct {
Total int64 `json:"Total"`
PageNum int `json:"PageNum"`
PageSize int `json:"PageSize"`
OrderList []OrderSummary `json:"OrderList"`
}
// OrderSummary 订单列表项。
type OrderSummary struct {
OrderId string `json:"OrderId"`
Status string `json:"Status"`
PayAmount int64 `json:"PayAmount"`
CreateTime string `json:"CreateTime"`
}
// ---------- 物流 ----------
// ListLogisticsOrdersRequest 查询订单物流信息请求。
type ListLogisticsOrdersRequest struct {
OrderId string `json:"-"`
PurchaserId string `json:"PurchaserId"`
}
// ListLogisticsOrdersRespData 查询订单物流信息响应数据。
type ListLogisticsOrdersRespData struct {
LogisticsList []LogisticsInfo `json:"LogisticsList"`
}
// LogisticsInfo 物流信息。
type LogisticsInfo struct {
TrackingNumber string `json:"TrackingNumber"`
CompanyName string `json:"CompanyName"`
Traces []LogisticsTrace `json:"Traces"`
}
// LogisticsTrace 物流轨迹节点。
type LogisticsTrace struct {
Time string `json:"Time"`
Location string `json:"Location"`
Description string `json:"Description"`
}
// ---------- 确认收货 ----------
// ConfirmDisburseRequest 确认收货请求。
type ConfirmDisburseRequest struct {
OrderId string `json:"-"`
PurchaserId string `json:"PurchaserId"`
}
// ---------- 售后 ----------
// RenderRefundOrderReq 售后渲染预校验请求。
type RenderRefundOrderReq struct {
PurchaserId string `json:"PurchaserId"`
OrderId string `json:"OrderId"`
OrderItemId string `json:"OrderItemId"`
RefundQuantity int64 `json:"RefundQuantity"`
RefundType string `json:"RefundType"`
}
// RenderRefundOrderRespData 售后渲染预校验响应数据。
type RenderRefundOrderRespData struct {
CanRefund bool `json:"CanRefund"`
RefundAmount int64 `json:"RefundAmount"`
MaxRefundQuantity int64 `json:"MaxRefundQuantity"`
UnRefundReason string `json:"UnRefundReason"`
}
// CreateRefundOrderReq 创建售后单请求。
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"`
}
// CreateRefundOrderRespData 创建售后单响应数据。
type CreateRefundOrderRespData struct {
RefundOrderId string `json:"RefundOrderId"`
}
// CancelRefundOrderRequest 取消售后单请求。
type CancelRefundOrderRequest struct {
RefundOrderId string `json:"-"`
PurchaserId string `json:"PurchaserId"`
}
// GetRefundOrderRequest 获取售后单详情请求。
type GetRefundOrderRequest struct {
RefundOrderId string `json:"-"`
PurchaserId string `json:"PurchaserId"`
}
// GetRefundOrderRespData 获取售后单详情响应数据。
type GetRefundOrderRespData struct {
RefundOrderId string `json:"RefundOrderId"`
OrderId string `json:"OrderId"`
OrderItemId string `json:"OrderItemId"`
Status string `json:"Status"`
RefundQuantity int64 `json:"RefundQuantity"`
RefundAmount int64 `json:"RefundAmount"`
RefundType string `json:"RefundType"`
RefundReason string `json:"RefundReason"`
}
// CreateGoodsShippingNoticeReq 回填退货物流运单请求。
type CreateGoodsShippingNoticeReq struct {
PurchaserId string `json:"PurchaserId"`
LogisticsCompany string `json:"LogisticsCompany"`
TrackingNumber string `json:"TrackingNumber"`
}
// ---------- 区域 ----------
// QueryChildDivisionCodeRequest 查询子区域编码请求。
type QueryChildDivisionCodeRequest struct {
ParentDivisionCode string `json:"ParentDivisionCode"`
}
// QueryChildDivisionCodeRespData 查询子区域编码响应数据。
type QueryChildDivisionCodeRespData struct {
DivisionList []DivisionItem `json:"DivisionList"`
}
// DivisionItem 区域编码项。
type DivisionItem struct {
DivisionCode string `json:"DivisionCode"`
DivisionName string `json:"DivisionName"`
Level int `json:"Level"`
ParentCode string `json:"ParentCode"`
}
// ---------- 回调通知 ----------
// CallbackEvent 阿里云消息回调事件。
// 业务侧消费成功后需返回 {"success":true},否则阿里云会重试推送。
type CallbackEvent struct {
EventCode string `json:"EventCode"`
PurchaseOrderId string `json:"PurchaseOrderId"`
OrderIdList []string `json:"OrderIdList"`
Status string `json:"Status"`
RequestId string `json:"RequestId"`
}
// 回调事件编码枚举。
const (
EventCodePurchaseOrderChange = "PURCHASE_ORDER_CHANGE"
EventCodeOrderStatusChange = "ORDER_STATUS_CHANGE"
EventCodeRefundOrderChange = "REFUND_ORDER_CHANGE"
)
```
// File: sdk_LinkedMall/client.go
```go
// Package sdk_LinkedMall 是 LinkedMall OpenAPI 的 Go SDK。
// 当前覆盖指定的 22 个接口,覆盖:采购方店铺、选品池、类目、搜索、
// 采购单(渲染/拆单/创建/状态)、订单、物流、确认收货、售后、区域编码等。
//
// 客户端基于阿里云通用 OpenAPI 客户端darabonba-openapi/v2发起 ROA 调用,
// ROA 签名由底层客户端自动完成。所有接口返回统一外层结构 CommonResponse
// 必须判断 Success 字段为 true 才代表业务成功。
package sdk_LinkedMall
import (
"context"
"encoding/json"
"fmt"
"io"
"reflect"
"strconv"
"strings"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
"github.com/alibabacloud-go/tea/v2"
)
// 常量定义。
const (
// RegionID 为华北3张家口
RegionID = "cn-zhangjiakou"
// Endpoint 为网关访问地址。
Endpoint = "linkedmall.cn-zhangjiakou.aliyuncs.com"
// APIVersion 为 API 版本号。
APIVersion = "linkedmall/2023-09-30"
// BasePath 为 HTTP 基础路径前缀。
BasePath = "/opensaas-s2b/opensaas-s2b-biz-trade/v2"
)
// Client 是 LinkedMall OpenAPI 客户端。
//
// 通过 RAM 子账号 AccessKey 初始化,禁止使用主账号 AccessKey
// 签名类型为 ROA 签名,由底层 darabonba-openapi/v2 客户端自动处理,业务无需自行实现。
type Client struct {
api *openapi.Client
}
// NewClient 使用 RAM 子账号 AccessKeyId / AccessKeySecret 创建客户端。
//
// 建议通过环境变量注入密钥,避免硬编码到代码中。
func NewClient(accessKeyID, accessKeySecret string) (*Client, error) {
config := &openapi.Config{
AccessKeyId: tea.String(accessKeyID),
AccessKeySecret: tea.String(accessKeySecret),
RegionId: tea.String(RegionID),
Endpoint: tea.String(Endpoint),
ReadTimeout: tea.Int(30000),
ConnectTimeout: tea.Int(10000),
}
api, err := openapi.NewClient(config)
if err != nil {
return nil, fmt.Errorf("create openapi client: %w", err)
}
return &Client{api: api}, nil
}
// NewLinkedMallClient 是 NewClient 的别名,便于文档示例直接使用。
func NewLinkedMallClient(accessKeyID, accessKeySecret string) (*Client, error) {
return NewClient(accessKeyID, accessKeySecret)
}
// doRoa 发起一次 ROA 请求并解析统一的公共响应结构。
//
// dataOut 用于接收业务 Data传入对应响应数据类型的指针
// 若为 nil则 Data 保持为 json.RawMessage。
func (c *Client) doRoa(ctx context.Context, method, path string, query map[string]*string, body interface{}, dataOut interface{}) (*CommonResponse, error) {
if err := ctx.Err(); err != nil {
return nil, err
}
fullPath := BasePath + path
var bodyBytes []byte
var err error
if body != nil {
bodyBytes, err = MarshalJSON(body)
if err != nil {
return nil, fmt.Errorf("marshal request body: %w", err)
}
}
resp, err := c.api.RoaRequest(tea.String(method), tea.String(fullPath), query, bodyBytes, nil)
if err != nil {
return nil, fmt.Errorf("roa request failed [%s %s]: %w", method, fullPath, err)
}
if resp == nil || resp.Body == nil {
return nil, fmt.Errorf("roa request returned empty response [%s %s]", method, fullPath)
}
respBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read response body: %w", err)
}
var raw rawResponse
if err := json.Unmarshal(respBytes, &raw); err != nil {
return nil, fmt.Errorf("unmarshal response [%s %s] body=%s: %w", method, fullPath, string(respBytes), err)
}
out := &CommonResponse{
RequestId: raw.RequestId,
Success: raw.Success,
Code: raw.Code,
Message: raw.Message,
SubCode: raw.SubCode,
SubMessage: raw.SubMessage,
}
if len(raw.Data) > 0 {
if dataOut != nil {
if err := json.Unmarshal(raw.Data, dataOut); err != nil {
return nil, fmt.Errorf("unmarshal response Data [%s %s]: %w", method, fullPath, err)
}
out.Data = dataOut
} else {
out.Data = raw.Data
}
}
return out, nil
}
// structToQuery 将请求结构体转换为 ROA query 参数。
// 仅序列化带 json tag 且非零值的字段json:"-" 或空值字段被忽略。
func structToQuery(v interface{}) map[string]*string {
query := make(map[string]*string)
if v == nil {
return query
}
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr {
if rv.IsNil() {
return query
}
rv = rv.Elem()
}
if rv.Kind() != reflect.Struct {
return query
}
rt := rv.Type()
for i := 0; i < rv.NumField(); i++ {
sf := rt.Field(i)
if !sf.IsExported() {
continue
}
name := sf.Tag.Get("json")
if name == "" || name == "-" {
continue
}
if idx := strings.Index(name, ","); idx >= 0 {
name = name[:idx]
}
if name == "" {
continue
}
fv := rv.Field(i)
switch fv.Kind() {
case reflect.String:
if s := fv.String(); s != "" {
query[name] = tea.String(s)
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if n := fv.Int(); n != 0 {
query[name] = tea.String(strconv.FormatInt(n, 10))
}
case reflect.Bool:
if fv.Bool() {
query[name] = tea.String("true")
}
}
}
return query
}
// buildPath 将路径中的 {Param} 占位符替换为实际值。
func buildPath(path string, params map[string]string) string {
for k, v := range params {
path = strings.ReplaceAll(path, "{"+k+"}", v)
}
return path
}
// ListPurchaserShops 分页获取采购方店铺列表。
//
// 请求字段PageNum页码默认1、PageSize每页条数最大100
// 返回 Data 为 *ListPurchaserShopsRespData。
// 必须判断 resp.Success 为 true 才算业务成功。
func (c *Client) ListPurchaserShops(ctx context.Context, req *ListPurchaserShopsRequest) (*CommonResponse, error) {
return c.doRoa(ctx, "GET", "/purchaser-shops", structToQuery(req), nil, &ListPurchaserShopsRespData{})
}
// GetPurchaserShop 获取单个采购店铺详情。
//
// ShopId 为路径参数。返回 Data 为 *GetPurchaserShopRespData。
func (c *Client) GetPurchaserShop(ctx context.Context, req *GetPurchaserShopRequest) (*CommonResponse, error) {
path := buildPath("/purchaser-shops/{ShopId}", map[string]string{"ShopId": req.ShopId})
return c.doRoa(ctx, "GET", path, structToQuery(req), nil, &GetPurchaserShopRespData{})
}
// ListSelectionProducts 分页查询选品池商品列表。
//
// 请求字段PageNum、PageSize最大100、PurchaserId必填
// 返回 Data 为 *ListSelectionProductsRespData。
func (c *Client) ListSelectionProducts(ctx context.Context, req *ListSelectionProductsRequest) (*CommonResponse, error) {
return c.doRoa(ctx, "GET", "/selection-products", structToQuery(req), nil, &ListSelectionProductsRespData{})
}
// GetSelectionProduct 查询选品池商品详情。
//
// ProductId 为路径参数;支持传入五级乡镇 DivisionCode 校验该区域是否可售。
// 返回 Data 为 *GetSelectionProductRespData。
func (c *Client) GetSelectionProduct(ctx context.Context, req *GetSelectionProductRequest) (*CommonResponse, error) {
path := buildPath("/selection-products/{ProductId}", map[string]string{"ProductId": req.ProductId})
return c.doRoa(ctx, "GET", path, structToQuery(req), nil, &GetSelectionProductRespData{})
}
// ListCategories 查询类目列表。
//
// 不传 ParentCategoryId 时查询一级类目。返回 Data 为 *ListCategoriesRespData。
func (c *Client) ListCategories(ctx context.Context, req *ListCategoriesRequest) (*CommonResponse, error) {
return c.doRoa(ctx, "GET", "/categories", structToQuery(req), nil, &ListCategoriesRespData{})
}
// SearchProducts 搜索选品池商品。
//
// 返回 Data 为 *SearchProductsRespData。
func (c *Client) SearchProducts(ctx context.Context, req *SearchProductsRequest) (*CommonResponse, error) {
return c.doRoa(ctx, "POST", "/selection-products:search", nil, req, &SearchProductsRespData{})
}
// SelectionGroupAddProduct 选品池商品入库。
//
// 返回 Data 为 *SelectionGroupChangeProductRespData。
func (c *Client) SelectionGroupAddProduct(ctx context.Context, req *SelectionGroupAddProductRequest) (*CommonResponse, error) {
return c.doRoa(ctx, "POST", "/selection-group/products:add", nil, req, &SelectionGroupChangeProductRespData{})
}
// SelectionGroupRemoveProduct 选品池商品出库。
//
// 返回 Data 为 *SelectionGroupChangeProductRespData。
func (c *Client) SelectionGroupRemoveProduct(ctx context.Context, req *SelectionGroupRemoveProductRequest) (*CommonResponse, error) {
return c.doRoa(ctx, "POST", "/selection-group/products:remove", nil, req, &SelectionGroupChangeProductRespData{})
}
// RenderPurchaseOrder 采购单渲染(下单预校验)。
//
// 下单前必须调用,获取实时价格、校验商品是否可售。
// 返回 Data 为 *RenderPurchaseOrderRespData。
func (c *Client) RenderPurchaseOrder(ctx context.Context, req *RenderPurchaseOrderReq) (*CommonResponse, error) {
return c.doRoa(ctx, "POST", "/purchase-orders:render", nil, req, &RenderPurchaseOrderRespData{})
}
// SplitPurchaseOrder 采购单渲染并拆单。
//
// 请求体结构与 RenderPurchaseOrderReq 完全一致。
// 返回 Data 为 *SplitPurchaseOrderRespData拆单结果用于创建采购单入参。
func (c *Client) SplitPurchaseOrder(ctx context.Context, req *RenderPurchaseOrderReq) (*CommonResponse, error) {
return c.doRoa(ctx, "POST", "/purchase-orders:split-render", nil, req, &SplitPurchaseOrderRespData{})
}
// CreatePurchaseOrder 创建采购单【异步】。
//
// 注意:接口只返回采购单号,不代表下单成功,必须等待回调通知后再查询订单接口。
// 返回 Data 为 *CreatePurchaseOrderRespDataPurchaseOrderId
func (c *Client) CreatePurchaseOrder(ctx context.Context, req *CreatePurchaseOrderReq) (*CommonResponse, error) {
return c.doRoa(ctx, "POST", "/purchase-orders", nil, req, &CreatePurchaseOrderRespData{})
}
// GetPurchaseOrderStatus 获取采购单状态。
//
// PurchaseOrderId 为路径参数。返回 Data 为 *GetPurchaseOrderStatusRespData。
// 状态枚举INIT、PROCESS、SUCCESS、FAIL、CLOSED。
func (c *Client) GetPurchaseOrderStatus(ctx context.Context, req *GetPurchaseOrderStatusRequest) (*CommonResponse, error) {
path := buildPath("/purchase-orders/{PurchaseOrderId}/status", map[string]string{"PurchaseOrderId": req.PurchaseOrderId})
return c.doRoa(ctx, "GET", path, structToQuery(req), nil, &GetPurchaseOrderStatusRespData{})
}
// GetOrder 获取订单详情。
//
// OrderId 为路径参数。返回 Data 为 *GetOrderRespData。
func (c *Client) GetOrder(ctx context.Context, req *GetOrderRequest) (*CommonResponse, error) {
path := buildPath("/orders/{OrderId}", map[string]string{"OrderId": req.OrderId})
return c.doRoa(ctx, "GET", path, structToQuery(req), nil, &GetOrderRespData{})
}
// QueryOrders 查询订单列表。
//
// 返回 Data 为 *QueryOrdersRespData。
func (c *Client) QueryOrders(ctx context.Context, req *QueryOrdersRequest) (*CommonResponse, error) {
return c.doRoa(ctx, "GET", "/orders", structToQuery(req), nil, &QueryOrdersRespData{})
}
// ListLogisticsOrders 查询订单物流信息。
//
// OrderId 为路径参数。返回 Data 为 *ListLogisticsOrdersRespData。
func (c *Client) ListLogisticsOrders(ctx context.Context, req *ListLogisticsOrdersRequest) (*CommonResponse, error) {
path := buildPath("/orders/{OrderId}/logistics", map[string]string{"OrderId": req.OrderId})
return c.doRoa(ctx, "GET", path, structToQuery(req), nil, &ListLogisticsOrdersRespData{})
}
// ConfirmDisburse 确认收货。
//
// OrderId 为路径参数,请求体为 {"PurchaserId":"xxx"}。
func (c *Client) ConfirmDisburse(ctx context.Context, req *ConfirmDisburseRequest) (*CommonResponse, error) {
path := buildPath("/orders/{OrderId}:confirm-disburse", map[string]string{"OrderId": req.OrderId})
body := map[string]string{"PurchaserId": req.PurchaserId}
return c.doRoa(ctx, "POST", path, nil, body, nil)
}
// RenderRefundOrder 售后渲染预校验。
//
// 返回 Data 为 *RenderRefundOrderRespData。
func (c *Client) RenderRefundOrder(ctx context.Context, req *RenderRefundOrderReq) (*CommonResponse, error) {
return c.doRoa(ctx, "POST", "/refund-orders:render", nil, req, &RenderRefundOrderRespData{})
}
// CreateRefundOrder 创建售后单。
//
// 返回 Data 为 *CreateRefundOrderRespDataRefundOrderId
func (c *Client) CreateRefundOrder(ctx context.Context, req *CreateRefundOrderReq) (*CommonResponse, error) {
return c.doRoa(ctx, "POST", "/refund-orders", nil, req, &CreateRefundOrderRespData{})
}
// CancelRefundOrder 取消售后单。
//
// RefundOrderId 为路径参数,请求体为 {"PurchaserId":"xxx"}。
func (c *Client) CancelRefundOrder(ctx context.Context, req *CancelRefundOrderRequest) (*CommonResponse, error) {
path := buildPath("/refund-orders/{RefundOrderId}:cancel", map[string]string{"RefundOrderId": req.RefundOrderId})
body := map[string]string{"PurchaserId": req.PurchaserId}
return c.doRoa(ctx, "POST", path, nil, body, nil)
}
// GetRefundOrder 获取售后单详情。
//
// RefundOrderId 为路径参数。返回 Data 为 *GetRefundOrderRespData。
func (c *Client) GetRefundOrder(ctx context.Context, req *GetRefundOrderRequest) (*CommonResponse, error) {
path := buildPath("/refund-orders/{RefundOrderId}", map[string]string{"RefundOrderId": req.RefundOrderId})
return c.doRoa(ctx, "GET", path, structToQuery(req), nil, &GetRefundOrderRespData{})
}
// CreateGoodsShippingNotice 回填退货物流运单。
//
// RefundOrderId 为路径参数。
func (c *Client) CreateGoodsShippingNotice(ctx context.Context, req *CreateGoodsShippingNoticeReq) (*CommonResponse, error) {
path := buildPath("/refund-orders/{RefundOrderId}:fill-logistics", map[string]string{"RefundOrderId": req.RefundOrderId})
return c.doRoa(ctx, "POST", path, nil, req, nil)
}
// QueryChildDivisionCode 查询子区域编码。
//
// 不传 ParentDivisionCode 返回省级;传入省返回市,传入市返回区,传入区返回乡镇(五级)。
// 下单、商品可售校验必须使用乡镇级 DivisionCode。
// 返回 Data 为 *QueryChildDivisionCodeRespData。
func (c *Client) QueryChildDivisionCode(ctx context.Context, req *QueryChildDivisionCodeRequest) (*CommonResponse, error) {
return c.doRoa(ctx, "GET", "/divisions:children", structToQuery(req), nil, &QueryChildDivisionCodeRespData{})
}
// ParseCallbackEvent 解析阿里云消息回调的请求体。
//
// 收到回调后应返回 CallbackSuccessBody(),否则阿里云会重试推送。
// 同一事件可能多次推送,业务侧回调处理需做好幂等。
func ParseCallbackEvent(body []byte) (*CallbackEvent, error) {
var evt CallbackEvent
if err := json.Unmarshal(body, &evt); err != nil {
return nil, fmt.Errorf("parse callback event: %w", err)
}
return &evt, nil
}
// CallbackSuccessBody 返回告知阿里云消费成功的响应体 {"success":true}。
func CallbackSuccessBody() []byte {
return []byte(`{"success":true}`)
}
```
// File: sdk_LinkedMall/crypto.go
```go
package sdk_LinkedMall
import (
"bytes"
"encoding/json"
)
// 关于加解密与签名:
//
// 本 SDK 基于阿里云通用 OpenAPI 客户端darabonba-openapi/v2发起 ROA 调用,
// ROA 签名AccessKeyId / AccessKeySecret 签名)由客户端内部自动完成,
// 业务侧无需自行实现签名算法,因此本文件不包含额外的签名/加密实现。
//
// 本文件保留与数据安全相关的辅助函数,供后续扩展加解密、签名能力时使用:
// - MarshalJSON / UnmarshalJSON确保金额等 int64 字段在 JSON 序列化/反序列化过程中
// 不会丢失精度(接口金额单位统一为分,使用 int64禁止使用 float64
// MarshalJSON 将对象安全序列化为 JSON 字节。
// 与标准库 encoding/json.Marshal 的区别:关闭了 HTML 转义,保证输出紧凑且不转义特殊字符。
func MarshalJSON(v interface{}) ([]byte, error) {
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
enc.SetEscapeHTML(false)
if err := enc.Encode(v); err != nil {
return nil, err
}
// json.Encoder.Encode 会在末尾追加一个换行符,这里去掉。
return bytes.TrimRight(buf.Bytes(), "\n"), nil
}
// UnmarshalJSON 使用 UseNumber 解析 JSON避免 int64 金额被转换为 float64 丢失精度。
func UnmarshalJSON(data []byte, v interface{}) error {
dec := json.NewDecoder(bytes.NewReader(data))
dec.UseNumber()
return dec.Decode(v)
}
```
// File: sdk_LinkedMall/errors.go
```go
package sdk_LinkedMall
import "fmt"
// 业务错误码常量。
const (
// CodeShopTypeInvalid SKU 属于经销集采店铺,不可下单,应过滤该 SKU。
CodeShopTypeInvalid = "ShopTypeInvalid"
// CodeSkuPriceUnique SKU 价格非最新,需重新调用 RenderPurchaseOrder 获取最新价格后再下单。
CodeSkuPriceUnique = "SkuPriceUnique"
// CodePurchaseOrderNotFound 采购单号不存在,需核对入参 PurchaseOrderId。
CodePurchaseOrderNotFound = "PurchaseOrderNotFound"
// CodeRefundNumberMustLessThanOrder 退款数量大于订单商品数量,需修正退款数量。
CodeRefundNumberMustLessThanOrder = "RefundNumberMustLessThanOrder"
// CodeRefundAmountMustLessThanOrder 退款金额大于实付金额,需修正退款金额。
CodeRefundAmountMustLessThanOrder = "RefundAmountMustLessThanOrder"
// CodeHasNoPrivilege RAM 无接口权限,需检查 RAM 授权策略。
CodeHasNoPrivilege = "HasNoPrivilege"
// CodeOrderNotFound 订单 ID 不存在,需核对 OrderId。
CodeOrderNotFound = "OrderNotFound"
// CodeShopNotFind 店铺不存在,需核对 ShopId / PurchaserId。
CodeShopNotFind = "ShopNotFind"
// CodeSavePurchaseOrderError 保存采购单服务端异常,建议短间隔重试。
CodeSavePurchaseOrderError = "SavePurchaseOrderError"
// CodeOuterPurchaseOrderIdExist 外部业务单号重复,需更换 OuterPurchaseOrderId 并做好幂等。
CodeOuterPurchaseOrderIdExist = "OuterPurchaseOrderIdExist"
)
// APIError 表示业务侧返回的错误。
type APIError struct {
RequestId string
Code string
Message string
SubCode string
SubMessage string
}
// Error 实现 error 接口。
func (e *APIError) Error() string {
return fmt.Sprintf(
"linkedmall api error [requestId=%s code=%s subCode=%s]: %s %s",
e.RequestId, e.Code, e.SubCode, e.Message, e.SubMessage,
)
}
// CheckSuccess 校验响应是否业务成功。
//
// 返回 nil 表示 Success 为 true业务成功
// 否则返回 *APIError携带 Code / SubCode / SubMessage 便于定位原因。
func CheckSuccess(resp *CommonResponse) error {
if resp == nil {
return fmt.Errorf("linkedmall: empty response")
}
if resp.Success {
return nil
}
return &APIError{
RequestId: resp.RequestId,
Code: resp.Code,
Message: resp.Message,
SubCode: resp.SubCode,
SubMessage: resp.SubMessage,
}
}
// IsCode 判断响应是否命中指定错误码。
func IsCode(resp *CommonResponse, code string) bool {
return resp != nil && resp.Code == code
}
```
// File: sdk_LinkedMall/example_test.go
```go
package sdk_LinkedMall
import (
"context"
"fmt"
"os"
"testing"
)
// TestNewClient 校验客户端初始化(不发起网络请求)。
func TestNewClient(t *testing.T) {
cli, err := NewClient("test-access-key-id", "test-access-key-secret")
if err != nil {
t.Fatalf("NewClient() error = %v", err)
}
if cli == nil {
t.Fatal("NewClient() returned nil client")
}
}
// TestNewLinkedMallClient 校验别名构造函数。
func TestNewLinkedMallClient(t *testing.T) {
cli, err := NewLinkedMallClient("test-access-key-id", "test-access-key-secret")
if err != nil {
t.Fatalf("NewLinkedMallClient() error = %v", err)
}
if cli == nil {
t.Fatal("NewLinkedMallClient() returned nil client")
}
}
// TestStructToQuery 校验请求结构体到 query 参数的转换。
func TestStructToQuery(t *testing.T) {
req := &ListPurchaserShopsRequest{PageNum: 1, PageSize: 20}
q := structToQuery(req)
if got := q["PageNum"]; got == nil || *got != "1" {
t.Errorf("PageNum = %v, want 1", got)
}
if got := q["PageSize"]; got == nil || *got != "20" {
t.Errorf("PageSize = %v, want 20", got)
}
}
// TestStructToQuerySkipEmpty 校验零值字段被忽略。
func TestStructToQuerySkipEmpty(t *testing.T) {
req := &ListSelectionProductsRequest{PurchaserId: "p-001"}
q := structToQuery(req)
if q["PageNum"] != nil {
t.Errorf("PageNum should be omitted, got %v", *q["PageNum"])
}
if got := q["PurchaserId"]; got == nil || *got != "p-001" {
t.Errorf("PurchaserId = %v, want p-001", got)
}
}
// TestBuildPath 校验路径占位符替换。
func TestBuildPath(t *testing.T) {
path := buildPath("/orders/{OrderId}/logistics", map[string]string{"OrderId": "O123"})
if path != "/orders/O123/logistics" {
t.Errorf("buildPath() = %s, want /orders/O123/logistics", path)
}
}
// TestMarshalJSON 校验 int64 金额序列化不丢失精度。
func TestMarshalJSON(t *testing.T) {
b, err := MarshalJSON(map[string]int64{"amount": 123456789})
if err != nil {
t.Fatalf("MarshalJSON() error = %v", err)
}
if string(b) != `{"amount":123456789}` {
t.Errorf("MarshalJSON() = %s, want {\"amount\":123456789}", string(b))
}
}
// TestParseCallbackEvent 校验回调事件解析。
func TestParseCallbackEvent(t *testing.T) {
body := []byte(`{
"EventCode":"PURCHASE_ORDER_CHANGE",
"PurchaseOrderId":"PO123",
"OrderIdList":["O1","O2"],
"Status":"SUCCESS",
"RequestId":"R1"
}`)
evt, err := ParseCallbackEvent(body)
if err != nil {
t.Fatalf("ParseCallbackEvent() error = %v", err)
}
if evt.EventCode != EventCodePurchaseOrderChange {
t.Errorf("EventCode = %s, want %s", evt.EventCode, EventCodePurchaseOrderChange)
}
if evt.PurchaseOrderId != "PO123" || len(evt.OrderIdList) != 2 {
t.Errorf("unexpected callback event: %+v", evt)
}
if got := string(CallbackSuccessBody()); got != `{"success":true}` {
t.Errorf("CallbackSuccessBody() = %s", got)
}
}
// TestCheckSuccess 校验业务成功判断与错误码匹配。
func TestCheckSuccess(t *testing.T) {
ok := &CommonResponse{Success: true, Code: "SUCCESS", RequestId: "r1"}
if err := CheckSuccess(ok); err != nil {
t.Errorf("CheckSuccess(success) error = %v", err)
}
fail := &CommonResponse{
Success: false, Code: CodeOrderNotFound,
Message: "order not found", SubCode: "OrderNotFound",
}
err := CheckSuccess(fail)
if err == nil {
t.Fatal("CheckSuccess(fail) should return error")
}
if !IsCode(fail, CodeOrderNotFound) {
t.Error("IsCode(OrderNotFound) should be true")
}
}
// businessFlowDocumented 展示完整业务调用流程,仅供阅读参考,不会在测试中执行。
//
// 完整流程:
// 1. QueryChildDivisionCode 获取五级乡镇 divisionCode收货地址对应的区域编码
// 2. ListSelectionProducts / SearchProducts 获取选品池商品 SkuId
// 3. RenderPurchaseOrder 预渲染校验商品可售、价格
// 4. SplitPurchaseOrder 获取拆单结果
// 5. CreatePurchaseOrder 传入外部唯一业务单号 OuterPurchaseOrderId拿到 PurchaseOrderId
// 6. 等待阿里云消息回调通知
// 7. 收到回调后调用 GetPurchaseOrderStatus 查看采购单状态;
// 拿到附属 OrderId 后调用 GetOrder 同步订单入库本地库
// 8. 后续:查物流、确认收货;产生售后调用售后接口
//
// 注意CreatePurchaseOrder 同步返回成功不代表下单成功,禁止直接标记本地订单成功。
func businessFlowDocumented() {
ctx := context.Background()
// 密钥建议从环境变量注入,禁止硬编码。
cli, err := NewLinkedMallClient(
os.Getenv("LINKEDMALL_ACCESS_KEY_ID"),
os.Getenv("LINKEDMALL_ACCESS_KEY_SECRET"),
)
if err != nil {
panic(err)
}
// 1. 获取五级乡镇 divisionCode省->市->区->乡镇逐级查询)。
provinceResp, err := cli.QueryChildDivisionCode(ctx, &QueryChildDivisionCodeRequest{})
if err != nil {
panic(err)
}
if err := CheckSuccess(provinceResp); err != nil {
panic(err)
}
_ = provinceResp.Data.(*QueryChildDivisionCodeRespData)
// 2. 搜索选品池商品,得到 SkuId。
searchResp, err := cli.SearchProducts(ctx, &SearchProductsRequest{
Keyword: "示例商品",
PageNum: 1,
PageSize: 20,
PurchaserId: "your-purchaser-id",
})
if err != nil {
panic(err)
}
if err := CheckSuccess(searchResp); err != nil {
panic(err)
}
products := searchResp.Data.(*SearchProductsRespData).ProductList
// 3. 采购单渲染预校验。
renderResp, err := cli.RenderPurchaseOrder(ctx, &RenderPurchaseOrderReq{
PurchaserId: "your-purchaser-id",
ShopId: "your-shop-id",
DivisionCode: "乡镇级五级编码",
ItemList: []RenderOrderItem{
{SkuId: products[0].ProductId + "-sku", Quantity: 1},
},
ReceiverInfo: ReceiverInfo{
ReceiverName: "张三",
ReceiverPhone: "13800000000",
ProvinceCode: "130000",
CityCode: "130100",
DistrictCode: "130102",
TownCode: "130102001",
DetailAddress: "示例街道 1 号",
},
})
if err != nil {
panic(err)
}
if err := CheckSuccess(renderResp); err != nil {
panic(err)
}
// 4. 拆单(可选,拆单结果作为创建采购单入参)。
splitResp, err := cli.SplitPurchaseOrder(ctx, &RenderPurchaseOrderReq{
PurchaserId: "your-purchaser-id",
ShopId: "your-shop-id",
DivisionCode: "乡镇级五级编码",
ItemList: renderResp.Data.(*RenderPurchaseOrderRespData).ItemList,
})
if err != nil {
panic(err)
}
if err := CheckSuccess(splitResp); err != nil {
panic(err)
}
// 5. 创建采购单(异步),使用全局唯一外部单号做幂等。
createResp, err := cli.CreatePurchaseOrder(ctx, &CreatePurchaseOrderReq{
PurchaserId: "your-purchaser-id",
ShopId: "your-shop-id",
OuterPurchaseOrderId: "unique-outer-order-id-001",
DivisionCode: "乡镇级五级编码",
ReceiverInfo: ReceiverInfo{
ReceiverName: "张三",
ReceiverPhone: "13800000000",
ProvinceCode: "130000",
CityCode: "130100",
DistrictCode: "130102",
TownCode: "130102001",
DetailAddress: "示例街道 1 号",
},
SubOrderList: splitResp.Data.(*SplitPurchaseOrderRespData).SubOrderList,
})
if err != nil {
panic(err)
}
if err := CheckSuccess(createResp); err != nil {
panic(err)
}
purchaseOrderID := createResp.Data.(*CreatePurchaseOrderRespData).PurchaseOrderId
_ = purchaseOrderID
// 6. 等待阿里云消息回调通知POST 到业务回调地址)。
// EventCode=PURCHASE_ORDER_CHANGE 时,用 ParseCallbackEvent 解析并返回
// CallbackSuccessBody()。
//
// 7. 收到回调后调用 GetPurchaseOrderStatus 查看采购单状态;
// 拿到附属 OrderId 后调用 GetOrder 同步订单入库本地库。
// 8. 后续ListLogisticsOrders 查物流、ConfirmDisburse 确认收货;
// 产生售后时依次调用 RenderRefundOrder、CreateRefundOrder 等接口。
fmt.Println("purchase order created:", purchaseOrderID)
}
```
=== SDK 生成完成 ===
所有 6 个文件已完整生成:`go.mod`、`client.go`、`types.go`、`crypto.go`、`errors.go`、`example_test.go`。
关键说明:
1. **工具调用**:本文档明确声明 ROA 签名由 `darabonba-openapi/v2` 客户端内部自动处理,业务无需实现签名/加密算法,因此未调用加解密工具;`crypto.go` 提供了 int64 金额精度安全的 JSON 序列化/反序列化辅助函数(金额单位统一为分,禁止 float64
2. **接口范围**:严格按任务清单实现 22 个接口,未包含文档中额外列出的 GetSelectionProductSaleInfo / ListSelectionProductSaleInfos / ListSelectionSkuSaleInfos。
3. **异步采购单**`CreatePurchaseOrder` 只返回 PurchaseOrderId必须等待回调`ParseCallbackEvent` / `CallbackSuccessBody`)后再查询,回调需幂等。
4. **业务校验**:所有方法返回 `*CommonResponse`,必须判断 `Success==true`;可用 `CheckSuccess` / `IsCode` 辅助判断错误码。
5. **编译运行**`go mod tidy` 拉取 `darabonba-openapi/v2`、`tea/v2` 后即可编译,单元测试均不发起网络请求。