Metadata-Version: 2.4
Name: snowland-topwms
Version: 0.1.0
Summary: TOPWMS 开放平台（顶妙 WMS）Python SDK (非官方SDK)，基于 snowland-http 实现限流与可插拔后端。
License: BSD-3-Clause
Project-URL: Homepage, https://gitee.com/snowlandltd/snowland-topwms
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: snowland-http
Provides-Extra: requests
Requires-Dist: requests>=2.25.0; extra == "requests"
Provides-Extra: httpx
Requires-Dist: httpx>=0.24.0; extra == "httpx"
Provides-Extra: aiohttp
Requires-Dist: aiohttp>=3.8.0; extra == "aiohttp"
Provides-Extra: all
Requires-Dist: requests>=2.25.0; extra == "all"
Requires-Dist: httpx>=0.24.0; extra == "all"
Requires-Dist: aiohttp>=3.8.0; extra == "all"
Dynamic: license-file

# snowland-topwms

TOPWMS 开放平台Python SDK(非官方)，基于 [snowland-http](https://github.com/snowland-ltd/snowland-http) 实现：

- **限流**：默认 300 次/分钟（文档硬性限制），超出 WMS 会报错。
- **可插拔后端**：`requests`（同步）/ `httpx`（同步+异步）/ `aiohttp`（异步），或 `auto` 自动探测。
- **自动鉴权**：`AppKey` 请求头 + 请求体 MD5 双重签名 `Signature`，调用方无需关心。
- **同步/异步**：每个接口均提供 `<name>` 与 `<name>_async` 两种方法。
- **Webhook 校验**：内置推送回调签名校验。

## 安装

本 SDK 依赖 `snowland-http`（已发布到 PyPI，安装时自动下载）。提供两种安装方式。


### 方式一：从 PyPI 安装

```bash
pip install "snowland-topwms[httpx]"
```

> 安装后直接 `import snowland_topwms` 即可，无需本地源码；
> `snowland-http` 及所选传输后端会一并自动安装。

## 快速开始

```python
from snowland_topwms import TopWmsClient

client = TopWmsClient(
    app_key="你的appKey",
    app_secret="你的appSecret",
    base_url="https://<host>/api/open/erp",   # 文档中的接口基址
)

# 商品 SKU 详情（参数一律以函数关键字参数传入，禁止整包 dict）
resp = client.get_goods_detail(goods_sku_outer_id="123")
print(resp.code, resp.message, resp.data)

# 异步
import asyncio
resp = asyncio.run(client.get_goods_detail_async(goods_sku_outer_id="123"))

# 未声明字段用 **kwargs 透传（key 即请求体原始字段名）
resp = client.list_inventory(warehouse_id="W1", page_no=1, pageSize=20)

# 文档未列出/自定义接口（同样关键字参数化）
resp = client.call_api("/some/custom/path", foo="bar")
```

## 鉴权说明

签名算法（来自官方「快速接入」）：

1. 将请求体 JSON 字符串进行 32 位 MD5 加密；
2. 将得到的 MD5 串与 `appSecret` 拼接；
3. 再次 32 位 MD5，结果作为 `Signature` 请求头。

`AppKey` 与 `Signature` 自动写入请求头，`Content-Type: application/json` 自动设置。
SDK 会对发送内容逐字节保持一致地参与签名，确保与服务端校验一致。

## 接口路径核对

所有接口路径与字段均已依据 [`doc/api.md`](doc/api.md) 引用的官方 OpenAPI 规范
（Apifox 分享文档，索引见 `doc/api.md`）核实，并通过联调测试确认路由正确，全部标注
`verified=True`。

端点声明按业务类型拆分在
[`snowland_topwms/api`](snowland_topwms/api) 各子模块中
（`base`/`warehouse`/`goods`/`inventory`/`stocking`/`return_order`/`logistics`/`outbound`），
由 [`snowland_topwms/endpoints.py`](snowland_topwms/endpoints.py) 聚合成总表，
客户端自动生成参数化方法。新增/修正接口只需改动对应分类模块，无需改动 `client.py`。

## 接收 WMS 消息推送（Webhook）

```python
from snowland_topwms import verify_signature

# 收到回调时，用原始请求体字符串校验签名
raw_body = request.get_data(as_text=True)   # Flask 示例
sig = request.headers.get("Signature")
if verify_signature(raw_body, "你的appSecret", sig):
    ...  # 合法回调
```

## 测试

```bash
pip install -e ".[all]"
python -m unittest discover -s tests -v
```
