Metadata-Version: 2.4
Name: py-lmobile-toolkit
Version: 3.0.6
Summary: 乐信（51welink）短信服务 Python SDK，提供同步和异步接口调用，支持签名认证 / Lmobile (51welink) SMS Python SDK, sync/async client with signature authentication
Author-email: Guolei <174000902@qq.com>
License: MIT License
        
        Copyright (c) 2026 郭磊
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://gitee.com/guolei19850528/py_lmobile_toolkit
Project-URL: Repository, https://gitee.com/guolei19850528/py_lmobile_toolkit.git
Project-URL: Documentation, https://www.lmobile.cn/ApiPages/index.html
Project-URL: Package, https://pypi.org/project/py-lmobile-toolkit/
Keywords: lmobile,51welink,python,client,api,短信,sms,乐信
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Communications :: Chat
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.24.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: ruff>=0.6.0; extra == "dev"
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
Dynamic: license-file

# py-lmobile-toolkit

[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![PyPI](https://img.shields.io/badge/pypi-py--lmobile--toolkit-blue.svg)](https://pypi.org/project/py-lmobile-toolkit/)
[![Python](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/)
[![Lmobile](https://img.shields.io/badge/Lmobile-51welink-green.svg)](https://www.lmobile.cn/)

## 文档语言

- [中文 (README.md)](README.md)
- [English (README.en.md)](README.en.md)

## 介绍

**py-lmobile-toolkit** 是一个乐信（51welink）短信服务 Python SDK，提供 **同步和异步** 接口调用，支持基于 MD5 + SHA256 的签名认证。

py-lmobile-toolkit 让你极其简单地与乐信短信 API 交互。无需手动拼接 URL，无需手动构建签名字符串，所有请求参数与响应均基于 Pydantic v2 进行自动校验，支持同步和异步客户端。

### 核心特性

- **双模客户端**：同时提供同步（`SmsClient`）与异步（`AsyncSmsClient`）客户端，方法名完全一致，支持 `with` / `async with` 上下文管理器。
- **短信发送**：支持普通短信、个性化短信（XML/JSON 变量格式）、模板短信发送。
- **模板管理**：支持短信模板报备（含视频短信模板）、查询、删除模板。
- **账号查询**：支持查询账户余量与计费量。
- **状态报告与上行**：支持拉取状态报告、拉取上行（MO）信息、取消定时消息发送。
- **H5 跳小程序**：支持 H5 跳转小程序短链生成与 AccessToken 更新。
- **签名认证**：内置密码 MD5 加密与 AccessKey SHA256 签名生成，完全兼容乐信 EncryptionSubmit 签名规则。
- **Pydantic v2 响应模型**：所有 API 响应基于 Pydantic v2 构建，字段自动校验，类型安全，`ok` 属性一键判断请求是否成功。
- **基于 httpx**：底层 HTTP 客户端使用 httpx，支持同步与异步请求，并支持透传额外请求参数。

### 参考文档

- [乐信 API 接口文档](https://www.lmobile.cn/ApiPages/index.html)

## 软件架构

```
py-lmobile-toolkit/
├── pyproject.toml              # 项目构建配置（PEP 621 / setuptools）
├── README.md                   # 项目说明文档（中文）
├── README.en.md                # 项目说明文档（英文）
├── LICENSE                     # MIT 许可证
├── uv.lock                     # 依赖锁定文件
├── src/
│   └── py_lmobile_toolkit/     # 源代码包
│       ├── __init__.py         # 包入口
│       ├── py.typed            # PEP 561 类型标记
│       └── sms/                # 短信服务模块
│           ├── __init__.py     # SMS 模块入口
│           ├── client.py       # SmsClient / AsyncSmsClient / SmsClientConfig
│           ├── models.py       # Pydantic v2 响应模型定义
│           └── auth.py         # 签名认证工具（MD5 / SHA256 / 时间戳 / 随机数）
├── tests/                      # 测试用例
└── examples/                   # 演示代码
```

## 安装教程

推荐使用 [uv](https://github.com/astral-sh/uv) 进行安装：

### 1. 基础安装（推荐 uv）

```bash
uv pip install py-lmobile-toolkit
```

### 2. 开发环境安装（包含测试、代码检查工具）

```bash
uv pip install py-lmobile-toolkit[dev]
```

### 3. 基础安装（pip）

```bash
pip install py-lmobile-toolkit
```

### 4. 开发环境安装（pip，包含测试、代码检查工具）

```bash
pip install py-lmobile-toolkit[dev]
```

### 5. 从源码安装

```bash
git clone https://gitee.com/guolei19850528/py_lmobile_toolkit.git
cd py_lmobile_toolkit
uv pip install -e .
```

## 使用说明

### 一、创建客户端

乐信短信 SDK 适用于短信发送、模板管理、账号查询等场景，只需配置 `account_id` 与 `password` 即可使用。

#### 1. 同步客户端

```python
from py_lmobile_toolkit.sms.client import SmsClient

client = SmsClient(
    account_id="你的AccountID",
    password="你的密码",
    product_id="你的ProductID",
)
```

推荐使用上下文管理器，自动管理 HTTP 连接池：

```python
with SmsClient(
    account_id="你的AccountID",
    password="你的密码",
) as client:
    # 使用 client 发送短信
    pass
```

#### 2. 异步客户端

```python
from py_lmobile_toolkit.sms.client import AsyncSmsClient

async_client = AsyncSmsClient(
    account_id="你的AccountID",
    password="你的密码",
    product_id="你的ProductID",
)
```

推荐使用异步上下文管理器：

```python
async with AsyncSmsClient(
    account_id="你的AccountID",
    password="你的密码",
) as client:
    # 使用 client 发送短信
    pass
```

---

### 二、发送短信

#### 1. 发送普通短信

同步：

```python
from py_lmobile_toolkit.sms.client import SmsClient

with SmsClient(
    account_id="你的AccountID",
    password="你的密码",
) as client:
    resp = client.send_sms(
        phone_nos="13800000000",
        content="【乐信】您的验证码是 123456",
    )
    print(f"发送结果: {resp.ok}, 响应: {resp.Result}")
```

异步：

```python
import asyncio
from py_lmobile_toolkit.sms.client import AsyncSmsClient

async def main():
    async with AsyncSmsClient(
        account_id="你的AccountID",
        password="你的密码",
    ) as client:
        resp = await client.send_sms(
            phone_nos="13800000000",
            content="【乐信】您的验证码是 123456",
        )
        print(f"发送结果: {resp.ok}, 响应: {resp.Result}")

asyncio.run(main())
```

`send` 为 `send_sms` 的别名，两者完全一致。

#### 2. 发送个性化短信（变量 XML 格式）

```python
resp = client.send_personalized_xml(
    phone_nos="13800000000",
    xml_content="<sms><phone>13800000000</phone><content>验证码123456</content></sms>",
)
print(f"发送结果: {resp.ok}")
```

#### 3. 发送个性化短信（变量 JSON 格式）

```python
resp = client.send_personalized_json(
    phone_nos="13800000000",
    json_content='{"phone":"13800000000","content":"验证码123456"}',
)
print(f"发送结果: {resp.ok}")
```

---

### 三、模板短信

#### 1. 提交模板短信

```python
resp = client.submit_template_sms(
    phone_nos="13800000000",
    template_id="你的模板ID",
    template_params=["123456", "5"],
)
print(f"发送结果: {resp.ok}")
```

#### 2. 提交个性化模板短信

```python
resp = client.submit_personalized_template_sms(
    phone_nos="13800000000",
    template_id="你的模板ID",
    template_params=["123456", "5"],
)
print(f"发送结果: {resp.ok}")
```

#### 3. 短信模板报备

```python
resp = client.register_template(
    template_name="验证码模板",
    template_content="您的验证码是{code}，{minutes}分钟内有效",
    template_type=0,
)
print(f"报备结果: {resp.ok}")
```

#### 4. 视频短信模板报备

```python
resp = client.register_video_template(
    template_name="视频短信模板",
    template_content="视频短信内容",
    video_url="https://example.com/video.mp4",
)
print(f"报备结果: {resp.ok}")
```

#### 5. 查询模板

```python
resp = client.query_template(template_id="你的模板ID")
print(f"查询结果: {resp.ok}")
```

#### 6. 删除模板

```python
resp = client.delete_template(template_id="你的模板ID")
print(f"删除结果: {resp.ok}")
```

---

### 四、账号查询

#### 1. 查询余量

```python
resp = client.query_balance()
print(f"账户余量: {resp.balance}")
```

#### 2. 查询计费量

```python
resp = client.query_billing()
print(f"计费条数: {resp.count}, 计费金额: {resp.amount}")
```

---

### 五、状态报告与上行信息

#### 1. 拉取状态报告

```python
resp = client.pull_status_report()
print(f"状态报告: {resp.ok}")
```

#### 2. 拉取上行信息

```python
resp = client.pull_mo_message()
print(f"上行信息: {resp.ok}")
```

#### 3. 取消定时消息发送

```python
resp = client.cancel_scheduled_sms(msg_id="你的定时消息ID")
print(f"取消结果: {resp.ok}")
```

---

### 六、H5 跳转小程序

#### 1. 生成短链

```python
resp = client.generate_h5_miniprogram_short_link(
    original_url="https://example.com/page",
)
print(f"短链: {resp.shortUrl}")
```

#### 2. 更新 AccessToken

```python
resp = client.update_h5_miniprogram_access_token()
print(f"AccessToken: {resp.accessToken}, 过期时间: {resp.expireTime}")
```

---

### 七、异常处理

所有 API 调用失败时会抛出相应异常（httpx 网络异常或 Pydantic 校验异常）：

```python
import httpx
from pydantic import ValidationError
from py_lmobile_toolkit.sms.client import SmsClient

try:
    with SmsClient(
        account_id="你的AccountID",
        password="你的密码",
    ) as client:
        resp = client.send_sms(
            phone_nos="13800000000",
            content="测试短信",
        )
        if not resp.ok:
            print(f"发送失败: {resp.Result}")
except httpx.HTTPError as e:
    print(f"网络错误: {e}")
except ValidationError as e:
    print(f"参数校验错误: {e}")
```

---

### 八、贡献指南

1. Fork 本仓库
2. 新建 `Feat_xxx` 分支
3. 提交代码
4. 新建 Pull Request

### 九、许可证

本项目采用 [MIT 许可证](LICENSE)。
