Metadata-Version: 2.4
Name: snowland-shopeeapi
Version: 0.1.0
Summary: Async Shopee OpenAPI SDK based on aiohttp, supporting production and sandbox environments.
Author: snowland
License: BSD-3-Clause
Project-URL: Homepage, https://gitee.com/snowlandltd/snowland-shopeeapi
Project-URL: Repository, https://gitee.com/snowlandltd/snowland-shopeeapi
Keywords: shopee,sdk,aiohttp,async,ecommerce
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: snowland-http[aiohttp]>=0.1.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"

# snowland-shopeeapi

基于 [aiohttp](https://docs.aiohttp.org/) 的 Shopee OpenAPI (Partner API) v2 异步 SDK，同时支持**正式环境**与**沙箱环境**。

## 特性

- 纯 `async/await` 异步实现，基于 aiohttp
- 自动处理 Shopee 请求签名（HMAC-SHA256）
- 内置 `Environment.PRODUCTION` / `Environment.SANDBOX` 两套域名
- 开箱即用的 API 分组：授权、店铺、商品、订单、物流
- 统一异常处理（`ShopeeAPIError`）

## 安装

```bash
pip install snowland-shopeeapi
# 开发/测试依赖
pip install "snowland-shopeeapi[dev]"
```

本 SDK 的底层 HTTP 依赖 [`snowland-http`](https://gitee.com/snowlandltd/snowland-http)（异步 `aiohttp` 后端）。
若从源码安装本仓库，请同时安装其本地依赖：

```bash
pip install -e ../snowland-http[aiohttp]
```

## 快速开始

```python
import asyncio
from snowland_shopeeapi import ShopeeClient, Environment

PARTNER_ID = 123456
PARTNER_KEY = "your_partner_key"
SHOP_ID = 789012
REDIRECT_URL = "https://your-callback.com/cb"

async def main():
    async with ShopeeClient(PARTNER_ID, PARTNER_KEY, Environment.SANDBOX) as client:
        # 1) 引导商家授权，拼接授权 URL
        auth_url = client.build_auth_url(REDIRECT_URL)
        print("请商家访问:", auth_url)

        # 2) 用授权回调拿到的 code 换取 token
        code = "auth_code_from_callback"
        token = await client.auth.get_token(code, SHOP_ID)
        access_token = token["access_token"]

        # 3) 调用店铺接口
        info = await client.shop.get_shop_info(access_token, SHOP_ID)
        print(info)

        # 4) 刷新即将过期的 token
        refreshed = await client.auth.refresh_token(
            token["refresh_token"], access_token, SHOP_ID
        )
        print(refreshed)

asyncio.run(main())
```

## 环境切换

```python
from snowland_shopeeapi import Environment

# 正式环境
client = ShopeeClient(PARTNER_ID, PARTNER_KEY, Environment.PRODUCTION)

# 沙箱环境（默认）
client = ShopeeClient(PARTNER_ID, PARTNER_KEY, Environment.SANDBOX)
```

## 支持的 API 分组

| 分组 | 示例方法 |
| --- | --- |
| `client.auth` | `get_token(code, shop_id)`、`refresh_token(...)` |
| `client.shop` | `get_shop_info`、`get_profile`、`update_shop` |
| `client.product` | `get_item_list`、`get_item_base_info`、`add_item`、`update_item`、`delete_item` |
| `client.order` | `get_order_list`、`get_order_detail` |
| `client.logistics` | `get_shipping_parameter`、`create_shipping_document`、`get_tracking_number` |
| `client.returns` | `get_return_list`、`get_return_detail`、`confirm_return`、`dispute_return` |
| `client.conversation` | `get_conversation_list`、`get_messages`、`send_message`、`reply_message` |
| `client.discount` | `add_discount`、`update_discount`、`delete_discount`、`get_discount_list`、`get_discount`、`add_discount_item`、`update_discount_item`、`delete_discount_item` |

所有店铺级接口都需要传入 `access_token` 与 `shop_id`。

## 连接池、限流与重试

底层 HTTP（连接池、限流）由 `snowland-http` 提供：默认使用 `aiohttp` 异步后端，
并通过 `max_rate`（每秒请求数）与 `burst`（突发上限）开启令牌桶限流，主动避免触发 Shopee 接口限流。

SDK 在此基础上对瞬时故障自动重试：网络错误、超时、HTTP 429/5xx，以及 Shopee 限流错误码
（`RATE_LIMIT_EXCEEDED` 等）。重试采用指数退避（`retry_backoff * 2^(n-1)`），并在收到 `429` 时优先采用响应头 `Retry-After`。

```python
client = ShopeeClient(
    PARTNER_ID, PARTNER_KEY, Environment.SANDBOX,
    max_rate=10, burst=5,
    enable_retry=True, max_retries=3, retry_backoff=0.5,
)
```

## 自定义请求

需要调用尚未封装的接口时，可直接使用底层方法：

```python
data = await client.request(
    "POST", "/api/v2/xxx/some_path",
    json={"foo": "bar"}, access_token=access_token, shop_id=SHOP_ID,
)
```

## 测试

```bash
python -m unittest discover -s tests
```

## 许可证

BSD-3-Clause
