shopee

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 25, 2026 License: MIT Imports: 13 Imported by: 0

README

go-shopee

Go Reference CI Go Report Card codecov

A small, dependency-free Go client for the Shopee Open Platform v2 API — the seller / shop API documented at open.shopee.com/developer-guide.

It handles the fiddly parts (v2 HMAC-SHA256 request signing, the OAuth token flow, regional hosts) so you can call shop / order / product endpoints with typed Go methods. Standard library only — no third-party dependencies.

This is the Open Platform (seller) API, not the Shopee Affiliate API.

Install

go get github.com/ultramcu/go-shopee

Requires Go 1.21+.

Quick start

package main

import (
	"context"
	"fmt"
	"log"

	shopee "github.com/ultramcu/go-shopee"
)

func main() {
	c := shopee.NewClient(shopee.Config{
		PartnerID:  10001,
		PartnerKey: "your-partner-key",
		Region:     shopee.RegionGlobal, // or RegionSandbox for testing
	})
	ctx := context.Background()

	// 1. Send the seller to the authorization URL. Shopee redirects them back
	//    to your callback with ?code=...&shop_id=...
	fmt.Println(c.AuthURL("https://your.app/shopee/callback"))

	// 2. Exchange the code for tokens (stored on the client on success).
	if _, err := c.GetAccessToken(ctx, codeFromCallback, shopID); err != nil {
		log.Fatal(err)
	}

	// 3. Call shop-scoped APIs.
	info, err := c.GetShopInfo(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(info.ShopName, info.Region)
}

Already have tokens? Skip the OAuth steps and set them directly:

c := shopee.NewClient(shopee.Config{
	PartnerID:   10001,
	PartnerKey:  "your-partner-key",
	Region:      shopee.RegionGlobal,
	ShopID:      123456,
	AccessToken: "access-token",
})

Refresh before the access token expires:

tok, err := c.RefreshAccessToken(ctx, refreshToken, shopID)

Signing

The v2 signature is computed and attached automatically on every call. For reference, the signed base string is:

  • Public APIs: partner_id + api_path + timestamp
  • Shop APIs: partner_id + api_path + timestamp + access_token + shop_id

then sign = hex(HMAC-SHA256(base, partner_key)), sent alongside partner_id, timestamp (and access_token + shop_id for shop APIs). The formula is pinned by a unit test, and the test suite verifies the exact sign reaches the server end-to-end.

Supported endpoints

Area Methods
Auth AuthURL, GetAccessToken, RefreshAccessToken
Shop GetShopInfo
Order GetOrderList, GetOrderDetail
Product GetItemList, GetItemBaseInfo

This is an MVP focused on the most-used endpoints with a clean, well-tested foundation; more modules can be added the same way (each is a thin typed wrapper over the signed request layer). Contributions welcome.

Regions

Region selects the host: RegionGlobal (live), RegionSandbox (global test), RegionChina, RegionChinaSandbox. Use Config.BaseURL to point at any other host (or a test server).

Errors

A non-empty API error envelope is returned as an *APIError (Err, Message, RequestID); use errors.As. Transport / decoding problems are returned as ordinary wrapped errors.

License

MITSPDX-License-Identifier: MIT.

Documentation

Overview

Package shopee is a small, dependency-free Go client for the Shopee Open Platform v2 API — the seller / shop API documented at https://open.shopee.com/developer-guide.

It handles v2 request signing (HMAC-SHA256), the OAuth token flow (authorize → code → access / refresh token), regional hosts (global, China, and their sandboxes), and a focused set of shop, order and product endpoints. The transport is the Go standard library only — no third-party dependencies.

Authorize a shop

c := shopee.NewClient(shopee.Config{
    PartnerID:  10001,
    PartnerKey: "your-partner-key",
    Region:     shopee.RegionGlobal,
})
// Send the seller to c.AuthURL(redirect); Shopee redirects back with
// ?code=...&shop_id=...
tok, err := c.GetAccessToken(ctx, code, shopID)

Call a shop API

c.SetAccessToken(tok.AccessToken)
c.SetShopID(shopID)
info, err := c.GetShopInfo(ctx)

Refresh the access token before it expires with RefreshAccessToken.

Example

Example shows the full flow: authorize a shop, exchange the code for tokens, then call a shop-scoped API.

package main

import (
	"context"
	"fmt"
	"log"

	shopee "github.com/ultramcu/go-shopee"
)

func main() {
	c := shopee.NewClient(shopee.Config{
		PartnerID:  10001,
		PartnerKey: "your-partner-key",
		Region:     shopee.RegionGlobal,
	})

	// 1. Redirect the seller here; Shopee sends them back to your callback
	//    with ?code=...&shop_id=...
	fmt.Println(c.AuthURL("https://your.app/shopee/callback"))

	// 2. Exchange the code (read from the callback) for tokens. On success the
	//    client stores the access token + shop id.
	ctx := context.Background()
	tok, err := c.GetAccessToken(ctx, "code-from-callback", 123456)
	if err != nil {
		log.Fatal(err)
	}

	// 3. Call a shop API.
	info, err := c.GetShopInfo(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(tok.ExpireIn, info.ShopName)
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	// Err is the machine-readable error code, e.g. "error_auth",
	// "error_param", "error_permission".
	Err string
	// Message is the human-readable description, when provided.
	Message string
	// RequestID identifies the call on Shopee's side; quote it in support
	// tickets.
	RequestID string
}

APIError is returned when the Shopee API responds with a non-empty `error` field in its response envelope. The zero-value HTTP transport / decoding problems are returned as ordinary wrapped errors instead.

func (*APIError) Error

func (e *APIError) Error() string

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a Shopee Open Platform v2 API client. It is safe for concurrent use as long as the auth context (AccessToken / ShopID) is not mutated concurrently with in-flight requests.

func NewClient

func NewClient(cfg Config) *Client

NewClient returns a Client configured with cfg.

func (*Client) AuthURL

func (c *Client) AuthURL(redirectURL string) string

AuthURL returns the URL to redirect a seller to so they can authorize your app for their shop. After the seller authorizes, Shopee redirects the browser to redirectURL with `code` and `shop_id` query parameters; exchange the code for tokens with GetAccessToken.

func (*Client) GetAccessToken

func (c *Client) GetAccessToken(ctx context.Context, code string, shopID int64) (*TokenResponse, error)

GetAccessToken exchanges the authorization code (from the AuthURL redirect) for an access/refresh token pair for shopID. On success the new tokens and shopID are also stored on the client, so subsequent shop-scoped calls work without further setup.

func (*Client) GetItemBaseInfo

func (c *Client) GetItemBaseInfo(ctx context.Context, itemIDs []int64) (*ItemBaseInfoResult, error)

GetItemBaseInfo fetches base info for up to 50 item ids.

func (*Client) GetItemList

func (c *Client) GetItemList(ctx context.Context, p ItemListParams) (*ItemListResult, error)

GetItemList lists the shop's item ids and statuses.

func (*Client) GetOrderDetail

func (c *Client) GetOrderDetail(
	ctx context.Context,
	orderSNList []string,
	optionalFields ...string,
) (*OrderDetailResult, error)

GetOrderDetail fetches full details for up to 50 order serial numbers. optionalFields are sent as response_optional_fields, e.g. "item_list", "buyer_username", "recipient_address" — Shopee omits some fields unless requested.

func (*Client) GetOrderList

func (c *Client) GetOrderList(ctx context.Context, p OrderListParams) (*OrderListResult, error)

GetOrderList lists order serial numbers within a time window.

Example

ExampleClient_GetOrderList lists orders in a time window for an already-authorized shop.

package main

import (
	"context"
	"fmt"
	"log"

	shopee "github.com/ultramcu/go-shopee"
)

func main() {
	c := shopee.NewClient(shopee.Config{
		PartnerID:   10001,
		PartnerKey:  "your-partner-key",
		Region:      shopee.RegionGlobal,
		ShopID:      123456,
		AccessToken: "access-token",
	})
	res, err := c.GetOrderList(context.Background(), shopee.OrderListParams{
		TimeRangeField: "create_time",
		TimeFrom:       1609459200,
		TimeTo:         1609545600,
		PageSize:       50,
		OrderStatus:    "READY_TO_SHIP",
	})
	if err != nil {
		log.Fatal(err)
	}
	for _, o := range res.OrderList {
		fmt.Println(o.OrderSN)
	}
}

func (*Client) GetShopInfo

func (c *Client) GetShopInfo(ctx context.Context) (*ShopInfo, error)

GetShopInfo returns information about the authorized shop. Requires a valid access token and shop id (set via OAuth or SetAccessToken / SetShopID).

func (*Client) RefreshAccessToken

func (c *Client) RefreshAccessToken(ctx context.Context, refreshToken string, shopID int64) (*TokenResponse, error)

RefreshAccessToken obtains a fresh access/refresh token pair using a refresh token for shopID. On success the new tokens are stored on the client. Refresh tokens are single-use: keep the returned RefreshToken for the next refresh.

func (*Client) SetAccessToken

func (c *Client) SetAccessToken(token string)

SetAccessToken updates the access token used for shop-scoped requests.

func (*Client) SetShopID

func (c *Client) SetShopID(shopID int64)

SetShopID updates the shop id used for shop-scoped requests.

func (*Client) ShopID

func (c *Client) ShopID() int64

ShopID reports the configured shop id.

type Config

type Config struct {
	PartnerID   int64
	PartnerKey  string
	Region      Region
	ShopID      int64
	AccessToken string

	// HTTPClient is used for all requests; defaults to a client with a 30s
	// timeout.
	HTTPClient *http.Client
	// BaseURL overrides the host derived from Region. Useful for a region
	// without a dedicated constant, or for pointing tests at a local server.
	BaseURL string
	// contains filtered or unexported fields
}

Config configures a Client. PartnerID and PartnerKey come from the Shopee Open Platform console and are always required. ShopID and AccessToken are obtained from the OAuth flow (see AuthURL / GetAccessToken) and are required for shop-scoped APIs; they can also be set later with SetShopID / SetAccessToken.

type ItemBaseInfo

type ItemBaseInfo struct {
	ItemID      int64           `json:"item_id"`
	CategoryID  int64           `json:"category_id"`
	ItemName    string          `json:"item_name"`
	Description string          `json:"description"`
	ItemSKU     string          `json:"item_sku"`
	ItemStatus  string          `json:"item_status"`
	CreateTime  int64           `json:"create_time"`
	UpdateTime  int64           `json:"update_time"`
	Weight      string          `json:"weight"`
	PriceInfo   []PriceInfo     `json:"price_info"`
	StockInfoV2 json.RawMessage `json:"stock_info_v2"`
}

ItemBaseInfo is a subset of an item from product/get_item_base_info. StockInfoV2 is kept raw because its shape varies by region/version.

type ItemBaseInfoResult

type ItemBaseInfoResult struct {
	ItemList []ItemBaseInfo `json:"item_list"`
}

ItemBaseInfoResult is the product/get_item_base_info response.

type ItemListEntry

type ItemListEntry struct {
	ItemID     int64  `json:"item_id"`
	ItemStatus string `json:"item_status"`
	UpdateTime int64  `json:"update_time"`
}

ItemListEntry is one entry of product/get_item_list.

type ItemListParams

type ItemListParams struct {
	Offset   int
	PageSize int // 1..100
	// ItemStatus filters by status, e.g. "NORMAL", "BANNED", "UNLIST",
	// "REVIEWING". Empty defaults to "NORMAL".
	ItemStatus string
}

ItemListParams are the parameters for GetItemList.

type ItemListResult

type ItemListResult struct {
	Item        []ItemListEntry `json:"item"`
	TotalCount  int             `json:"total_count"`
	HasNextPage bool            `json:"has_next_page"`
	NextOffset  int             `json:"next_offset"`
}

ItemListResult is the product/get_item_list response. Paginate with NextOffset while HasNextPage is true.

type OrderDetail

type OrderDetail struct {
	OrderSN         string      `json:"order_sn"`
	Region          string      `json:"region"`
	Currency        string      `json:"currency"`
	TotalAmount     float64     `json:"total_amount"`
	OrderStatus     string      `json:"order_status"`
	BuyerUserID     int64       `json:"buyer_user_id"`
	BuyerUsername   string      `json:"buyer_username"`
	PaymentMethod   string      `json:"payment_method"`
	ShippingCarrier string      `json:"shipping_carrier"`
	CreateTime      int64       `json:"create_time"`
	UpdateTime      int64       `json:"update_time"`
	ItemList        []OrderItem `json:"item_list"`
}

OrderDetail is a subset of an order from order/get_order_detail.

type OrderDetailResult

type OrderDetailResult struct {
	OrderList []OrderDetail `json:"order_list"`
}

OrderDetailResult is the order/get_order_detail response.

type OrderItem

type OrderItem struct {
	ItemID                 int64   `json:"item_id"`
	ItemName               string  `json:"item_name"`
	ItemSKU                string  `json:"item_sku"`
	ModelID                int64   `json:"model_id"`
	ModelName              string  `json:"model_name"`
	ModelQuantityPurchased int     `json:"model_quantity_purchased"`
	ModelOriginalPrice     float64 `json:"model_original_price"`
	ModelDiscountedPrice   float64 `json:"model_discounted_price"`
}

OrderItem is one line item within an order.

type OrderListItem

type OrderListItem struct {
	OrderSN string `json:"order_sn"`
}

OrderListItem is one entry of order/get_order_list.

type OrderListParams

type OrderListParams struct {
	// TimeRangeField is "create_time" or "update_time".
	TimeRangeField string
	TimeFrom       int64 // unix seconds, inclusive
	TimeTo         int64 // unix seconds; the window may span at most 15 days
	PageSize       int   // 1..100
	Cursor         string
	// OrderStatus optionally filters by status, e.g. "UNPAID",
	// "READY_TO_SHIP", "SHIPPED", "COMPLETED", "CANCELLED". Empty = all.
	OrderStatus string
}

OrderListParams are the parameters for GetOrderList.

type OrderListResult

type OrderListResult struct {
	OrderList  []OrderListItem `json:"order_list"`
	More       bool            `json:"more"`
	NextCursor string          `json:"next_cursor"`
}

OrderListResult is the order/get_order_list response. Paginate with NextCursor while More is true.

type PriceInfo

type PriceInfo struct {
	Currency      string  `json:"currency"`
	OriginalPrice float64 `json:"original_price"`
	CurrentPrice  float64 `json:"current_price"`
}

PriceInfo is the pricing block of an item.

type Region

type Region int

Region selects which Shopee Open Platform host the client talks to.

const (
	// RegionGlobal is the live host for all non-China regions
	// (partner.shopeemobile.com).
	RegionGlobal Region = iota
	// RegionSandbox is the global test host (partner.test-stable.shopeemobile.com).
	RegionSandbox
	// RegionChina is the live China host (openplatform.shopee.cn).
	RegionChina
	// RegionChinaSandbox is the China test host
	// (openplatform.test-stable.shopee.cn).
	RegionChinaSandbox
)

type ShopInfo

type ShopInfo struct {
	ShopName   string `json:"shop_name"`
	Region     string `json:"region"`
	Status     string `json:"status"` // e.g. "NORMAL", "BANNED", "FROZEN"
	IsCB       bool   `json:"is_cb"`  // cross-border shop
	IsSIP      bool   `json:"is_sip"`
	MerchantID int64  `json:"merchant_id"`
	AuthTime   int64  `json:"auth_time"`   // unix seconds the shop authorized
	ExpireTime int64  `json:"expire_time"` // unix seconds the authorization expires
}

ShopInfo is a subset of the shop/get_shop_info response.

type TokenResponse

type TokenResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	// ExpireIn is the number of seconds until the access token expires
	// (typically 4 hours). Refresh before then with RefreshAccessToken.
	ExpireIn int64 `json:"expire_in"`
}

TokenResponse holds the tokens returned by the auth-token endpoints.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL