py-lmobile-toolkit 3.0.0__tar.gz → 3.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (19) hide show
  1. py_lmobile_toolkit-3.0.2/PKG-INFO +229 -0
  2. py_lmobile_toolkit-3.0.2/README.md +175 -0
  3. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/pyproject.toml +1 -1
  4. py_lmobile_toolkit-3.0.2/src/py_lmobile_toolkit.egg-info/PKG-INFO +229 -0
  5. py_lmobile_toolkit-3.0.0/PKG-INFO +0 -314
  6. py_lmobile_toolkit-3.0.0/README.md +0 -260
  7. py_lmobile_toolkit-3.0.0/src/py_lmobile_toolkit.egg-info/PKG-INFO +0 -314
  8. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/LICENSE +0 -0
  9. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/setup.cfg +0 -0
  10. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit/__init__.py +0 -0
  11. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit/py.typed +0 -0
  12. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit/sms/__init__.py +0 -0
  13. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit/sms/auth.py +0 -0
  14. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit/sms/client.py +0 -0
  15. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit/sms/models.py +0 -0
  16. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit.egg-info/SOURCES.txt +0 -0
  17. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit.egg-info/dependency_links.txt +0 -0
  18. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit.egg-info/requires.txt +0 -0
  19. {py_lmobile_toolkit-3.0.0 → py_lmobile_toolkit-3.0.2}/src/py_lmobile_toolkit.egg-info/top_level.txt +0 -0
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.4
2
+ Name: py-lmobile-toolkit
3
+ Version: 3.0.2
4
+ Summary: 乐信(51welink)短信服务 Python SDK,提供同步和异步接口调用,支持签名认证
5
+ Author-email: Guolei <174000902@qq.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 郭磊
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://gitee.com/guolei19850528/py_lmobile_toolkit
29
+ Project-URL: Repository, https://gitee.com/guolei19850528/py_lmobile_toolkit.git
30
+ Project-URL: Documentation, https://www.lmobile.cn/ApiPages/index.html
31
+ Keywords: lmobile,51welink,python,client,api,短信,sms,乐信
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3.10
37
+ Classifier: Programming Language :: Python :: 3.11
38
+ Classifier: Programming Language :: Python :: 3.12
39
+ Classifier: Programming Language :: Python :: 3.13
40
+ Classifier: Operating System :: OS Independent
41
+ Classifier: Topic :: Communications
42
+ Classifier: Topic :: Communications :: Telephony
43
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
44
+ Requires-Python: >=3.10
45
+ Description-Content-Type: text/markdown
46
+ License-File: LICENSE
47
+ Requires-Dist: httpx>=0.24.0
48
+ Requires-Dist: pydantic>=2.0
49
+ Provides-Extra: dev
50
+ Requires-Dist: pytest>=7.0; extra == "dev"
51
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
52
+ Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
53
+ Dynamic: license-file
54
+
55
+ # py-lmobile-toolkit
56
+
57
+ #### 介绍
58
+
59
+ `py-lmobile-toolkit` 是乐信(51welink)短信开放平台的非官方 Python 客户端库,封装官方 HTTP API,提供同步客户端 `SmsClient` 和异步客户端 `AsyncSmsClient`(方法名完全一致,异步客户端支持 `async with` 上下文管理器),签名采用 MD5 + SHA256,响应模型基于 Pydantic v2。
60
+
61
+ - 项目主页:https://gitee.com/guolei19850528/py_lmobile_toolkit
62
+ - PyPI:https://pypi.org/project/py-lmobile-toolkit/
63
+ - 官方 API 文档:https://www.lmobile.cn/ApiPages/index.html
64
+ - 许可证:[MIT License](LICENSE)
65
+
66
+ #### 软件架构
67
+
68
+ ```
69
+ py_lmobile_toolkit/
70
+ ├── sms/
71
+ │ ├── __init__.py
72
+ │ ├── auth.py # 签名生成(MD5/SHA256/时间戳/随机数)
73
+ │ ├── client.py # SmsClient(同步)与 AsyncSmsClient(异步)
74
+ │ └── models.py # Pydantic 响应模型
75
+ ```
76
+
77
+ 核心组件:
78
+ - `SmsClientConfig`:客户端配置(base_url、account_id、password、product_id、smms_encrypt_key),基于 Pydantic 校验
79
+ - `SmsClient`:同步 HTTP 客户端,支持 `with` 上下文管理器
80
+ - `AsyncSmsClient`:异步 HTTP 客户端,支持 `async with` 上下文管理器,方法名与 `SmsClient` 完全一致
81
+ - `SmsBaseResponse` 及各接口响应模型:`Result` 字段标识成功/失败,`extra="allow"` 兼容 API 扩展字段
82
+
83
+ #### 安装教程
84
+
85
+ 推荐使用 uv:
86
+
87
+ ```bash
88
+ uv add py-lmobile-toolkit
89
+ ```
90
+
91
+ 或从本地源码安装(开发模式):
92
+
93
+ ```bash
94
+ uv pip install -e .
95
+ uv pip install -e ".[dev]"
96
+ ```
97
+
98
+ 或者使用 pip:
99
+
100
+ ```bash
101
+ pip install py-lmobile-toolkit
102
+ pip install -e .
103
+ pip install -e ".[dev]"
104
+ ```
105
+
106
+ #### 使用说明
107
+
108
+ ##### 快速开始
109
+
110
+ 同步调用:
111
+
112
+ ```python
113
+ from py_lmobile_toolkit.sms.client import SmsClient
114
+
115
+ with SmsClient(
116
+ account_id="your_account_id",
117
+ password="your_password",
118
+ product_id="your_product_id",
119
+ ) as sms:
120
+ response = sms.send_sms(
121
+ phone_nos="13800138000",
122
+ content="【乐信】您的验证码是:123456",
123
+ )
124
+ print(f"成功: {response.ok}, 结果码: {response.Result}")
125
+ ```
126
+
127
+ 异步调用:
128
+
129
+ ```python
130
+ import asyncio
131
+ from py_lmobile_toolkit.sms.client import AsyncSmsClient
132
+
133
+
134
+ async def main():
135
+ async with AsyncSmsClient(
136
+ account_id="your_account_id",
137
+ password="your_password",
138
+ product_id="your_product_id",
139
+ ) as sms:
140
+ response = await sms.send_sms(
141
+ phone_nos=["13800138000"],
142
+ content="【乐信】批量发送测试",
143
+ )
144
+ print(f"成功: {response.ok}, 结果码: {response.Result}")
145
+
146
+
147
+ asyncio.run(main())
148
+ ```
149
+
150
+ ##### 已实现的接口
151
+
152
+ | 分类 | 接口 | 同步方法 | 异步方法 | 响应模型 | 端点状态 |
153
+ |------|------|----------|----------|----------|----------|
154
+ | 短信API | 提交短信 | `send_sms` / `send` | `send_sms` / `send` | `SmsSendSmsResponse` | ✅ 已知可靠 |
155
+ | 短信API | 提交个性化短信(变量XML格式) | `send_personalized_xml` | `send_personalized_xml` | `SmsBaseResponse` | [待核实] |
156
+ | 短信API | 提交个性化短信(变量Json格式) | `send_personalized_json` | `send_personalized_json` | `SmsBaseResponse` | [待核实] |
157
+ | 短信API | 拉取状态报告 | `pull_status_report` | `pull_status_report` | `SmsPullReportResponse` | [待核实] |
158
+ | 短信API | 拉取上行信息 | `pull_mo_message` | `pull_mo_message` | `SmsPullMoResponse` | [待核实] |
159
+ | 短信API | 取消定时消息发送 | `cancel_scheduled_sms` | `cancel_scheduled_sms` | `SmsCancelScheduledResponse` | [待核实] |
160
+ | 模板短信API | 提交模板短信 | `submit_template_sms` | `submit_template_sms` | `SmsSubmitTemplateSmsResponse` | [待核实] |
161
+ | 模板短信API | 提交个性化模板短信 | `submit_personalized_template_sms` | `submit_personalized_template_sms` | `SmsBaseResponse` | [待核实] |
162
+ | 模板短信API | 短信模板报备 | `register_template` | `register_template` | `SmsRegisterTemplateResponse` | [待核实] |
163
+ | 模板短信API | 视频短信模板报备 | `register_video_template` | `register_video_template` | `SmsRegisterVideoTemplateResponse` | [待核实] |
164
+ | 模板短信API | 删除模板 | `delete_template` | `delete_template` | `SmsDeleteTemplateResponse` | [待核实] |
165
+ | 模板短信API | 查询模板 | `query_template` | `query_template` | `SmsQueryTemplateResponse` | [待核实] |
166
+ | 账号API | 查询余量 | `query_balance` | `query_balance` | `SmsBalanceResponse` | [待核实] |
167
+ | 账号API | 查询计费量 | `query_billing` | `query_billing` | `SmsBillingResponse` | [待核实] |
168
+ | 其他API | H5跳转小程序短链生成 | `generate_h5_miniprogram_short_link` | `generate_h5_miniprogram_short_link` | `SmsH5ShortLinkResponse` | [待核实] |
169
+ | 其他API | 更新H5跳小程序的AccessToken | `update_h5_miniprogram_access_token` | `update_h5_miniprogram_access_token` | `SmsUpdateAccessTokenResponse` | [待核实] |
170
+
171
+ 回调类接口(状态报告推送、上行推送、模板审核结果推送)为服务端 Webhook,非客户端调用接口,此处不提供客户端方法。
172
+
173
+ ##### 签名生成算法
174
+
175
+ 1. 密码 MD5 加密:`MD5(password + smms_encrypt_key)`,结果转大写
176
+ 2. 参数拼接(按顺序):`AccountId={account_id}&PhoneNos={first_phone}&Password={md5_password}&Random={random}&Timestamp={timestamp}`(`PhoneNos` 只取第一个手机号)
177
+ 3. SHA256 加密:对拼接后的字符串做 SHA256 哈希,作为 `AccessKey`
178
+
179
+ ```python
180
+ from py_lmobile_toolkit.sms.auth import timestamp, random_digits, sha256_signature
181
+
182
+ ts = timestamp()
183
+ digits = random_digits()
184
+ signature = sha256_signature(
185
+ account_id="your_account_id",
186
+ password="your_password",
187
+ phone_nos="13800138000",
188
+ random_digits=digits,
189
+ timestamp=ts,
190
+ smms_encrypt_key="SMmsEncryptKey",
191
+ )
192
+ ```
193
+
194
+ ##### 环境变量配置
195
+
196
+ 示例与测试通过 `.env` 读取以下变量:
197
+
198
+ | 变量名 | 说明 | 默认值 |
199
+ |--------|------|--------|
200
+ | `SMS_BASE_URL` | API 基础地址 | `https://api.51welink.com/` |
201
+ | `SMS_ACCOUNT_ID` | 账号 ID(必填) | — |
202
+ | `SMS_PASSWORD` | 账号密码(必填) | — |
203
+ | `SMS_PRODUCT_ID` | 产品 ID | `""` |
204
+ | `SMS_SMMS_ENCRYPT_KEY` | 加密密钥(MD5 盐值) | `SMmsEncryptKey` |
205
+
206
+ #### 参与贡献
207
+
208
+ 1. Fork 本仓库
209
+ 2. 新建 `Feat_xxx` 分支
210
+ 3. 提交代码
211
+ 4. 新增 Pull Request
212
+
213
+ #### 特技
214
+
215
+ - 同步客户端 `SmsClient` 与异步客户端 `AsyncSmsClient`,方法名完全一致
216
+ - 异步客户端支持 `async with` 上下文管理器
217
+ - 请求签名认证(MD5 密码 + SHA256 签名,AccessKey)
218
+ - 响应数据模型验证(Pydantic v2),所有模型开启 `extra="allow"`,兼容 API 扩展字段
219
+ - 覆盖官方文档导航中的全部客户端可调用接口(短信/模板短信/账号/其他 API)
220
+ - 接口端点以常量集中管理,便于按官方文档精确对齐
221
+ - 所有方法支持透传 `**kwargs` 给 httpx,方便覆盖 URL、请求头等
222
+ - 基于 Python 3.10+,依赖 `httpx>=0.24.0` 与 `pydantic>=2.0`
223
+
224
+ #### 相关链接
225
+
226
+ - [PyPI 项目页面](https://pypi.org/project/py-lmobile-toolkit/)
227
+ - [Gitee 代码仓库](https://gitee.com/guolei19850528/py_lmobile_toolkit)
228
+ - [乐信官方 API 文档](https://www.lmobile.cn/ApiPages/index.html)
229
+ - [英文文档](README.en.md)
@@ -0,0 +1,175 @@
1
+ # py-lmobile-toolkit
2
+
3
+ #### 介绍
4
+
5
+ `py-lmobile-toolkit` 是乐信(51welink)短信开放平台的非官方 Python 客户端库,封装官方 HTTP API,提供同步客户端 `SmsClient` 和异步客户端 `AsyncSmsClient`(方法名完全一致,异步客户端支持 `async with` 上下文管理器),签名采用 MD5 + SHA256,响应模型基于 Pydantic v2。
6
+
7
+ - 项目主页:https://gitee.com/guolei19850528/py_lmobile_toolkit
8
+ - PyPI:https://pypi.org/project/py-lmobile-toolkit/
9
+ - 官方 API 文档:https://www.lmobile.cn/ApiPages/index.html
10
+ - 许可证:[MIT License](LICENSE)
11
+
12
+ #### 软件架构
13
+
14
+ ```
15
+ py_lmobile_toolkit/
16
+ ├── sms/
17
+ │ ├── __init__.py
18
+ │ ├── auth.py # 签名生成(MD5/SHA256/时间戳/随机数)
19
+ │ ├── client.py # SmsClient(同步)与 AsyncSmsClient(异步)
20
+ │ └── models.py # Pydantic 响应模型
21
+ ```
22
+
23
+ 核心组件:
24
+ - `SmsClientConfig`:客户端配置(base_url、account_id、password、product_id、smms_encrypt_key),基于 Pydantic 校验
25
+ - `SmsClient`:同步 HTTP 客户端,支持 `with` 上下文管理器
26
+ - `AsyncSmsClient`:异步 HTTP 客户端,支持 `async with` 上下文管理器,方法名与 `SmsClient` 完全一致
27
+ - `SmsBaseResponse` 及各接口响应模型:`Result` 字段标识成功/失败,`extra="allow"` 兼容 API 扩展字段
28
+
29
+ #### 安装教程
30
+
31
+ 推荐使用 uv:
32
+
33
+ ```bash
34
+ uv add py-lmobile-toolkit
35
+ ```
36
+
37
+ 或从本地源码安装(开发模式):
38
+
39
+ ```bash
40
+ uv pip install -e .
41
+ uv pip install -e ".[dev]"
42
+ ```
43
+
44
+ 或者使用 pip:
45
+
46
+ ```bash
47
+ pip install py-lmobile-toolkit
48
+ pip install -e .
49
+ pip install -e ".[dev]"
50
+ ```
51
+
52
+ #### 使用说明
53
+
54
+ ##### 快速开始
55
+
56
+ 同步调用:
57
+
58
+ ```python
59
+ from py_lmobile_toolkit.sms.client import SmsClient
60
+
61
+ with SmsClient(
62
+ account_id="your_account_id",
63
+ password="your_password",
64
+ product_id="your_product_id",
65
+ ) as sms:
66
+ response = sms.send_sms(
67
+ phone_nos="13800138000",
68
+ content="【乐信】您的验证码是:123456",
69
+ )
70
+ print(f"成功: {response.ok}, 结果码: {response.Result}")
71
+ ```
72
+
73
+ 异步调用:
74
+
75
+ ```python
76
+ import asyncio
77
+ from py_lmobile_toolkit.sms.client import AsyncSmsClient
78
+
79
+
80
+ async def main():
81
+ async with AsyncSmsClient(
82
+ account_id="your_account_id",
83
+ password="your_password",
84
+ product_id="your_product_id",
85
+ ) as sms:
86
+ response = await sms.send_sms(
87
+ phone_nos=["13800138000"],
88
+ content="【乐信】批量发送测试",
89
+ )
90
+ print(f"成功: {response.ok}, 结果码: {response.Result}")
91
+
92
+
93
+ asyncio.run(main())
94
+ ```
95
+
96
+ ##### 已实现的接口
97
+
98
+ | 分类 | 接口 | 同步方法 | 异步方法 | 响应模型 | 端点状态 |
99
+ |------|------|----------|----------|----------|----------|
100
+ | 短信API | 提交短信 | `send_sms` / `send` | `send_sms` / `send` | `SmsSendSmsResponse` | ✅ 已知可靠 |
101
+ | 短信API | 提交个性化短信(变量XML格式) | `send_personalized_xml` | `send_personalized_xml` | `SmsBaseResponse` | [待核实] |
102
+ | 短信API | 提交个性化短信(变量Json格式) | `send_personalized_json` | `send_personalized_json` | `SmsBaseResponse` | [待核实] |
103
+ | 短信API | 拉取状态报告 | `pull_status_report` | `pull_status_report` | `SmsPullReportResponse` | [待核实] |
104
+ | 短信API | 拉取上行信息 | `pull_mo_message` | `pull_mo_message` | `SmsPullMoResponse` | [待核实] |
105
+ | 短信API | 取消定时消息发送 | `cancel_scheduled_sms` | `cancel_scheduled_sms` | `SmsCancelScheduledResponse` | [待核实] |
106
+ | 模板短信API | 提交模板短信 | `submit_template_sms` | `submit_template_sms` | `SmsSubmitTemplateSmsResponse` | [待核实] |
107
+ | 模板短信API | 提交个性化模板短信 | `submit_personalized_template_sms` | `submit_personalized_template_sms` | `SmsBaseResponse` | [待核实] |
108
+ | 模板短信API | 短信模板报备 | `register_template` | `register_template` | `SmsRegisterTemplateResponse` | [待核实] |
109
+ | 模板短信API | 视频短信模板报备 | `register_video_template` | `register_video_template` | `SmsRegisterVideoTemplateResponse` | [待核实] |
110
+ | 模板短信API | 删除模板 | `delete_template` | `delete_template` | `SmsDeleteTemplateResponse` | [待核实] |
111
+ | 模板短信API | 查询模板 | `query_template` | `query_template` | `SmsQueryTemplateResponse` | [待核实] |
112
+ | 账号API | 查询余量 | `query_balance` | `query_balance` | `SmsBalanceResponse` | [待核实] |
113
+ | 账号API | 查询计费量 | `query_billing` | `query_billing` | `SmsBillingResponse` | [待核实] |
114
+ | 其他API | H5跳转小程序短链生成 | `generate_h5_miniprogram_short_link` | `generate_h5_miniprogram_short_link` | `SmsH5ShortLinkResponse` | [待核实] |
115
+ | 其他API | 更新H5跳小程序的AccessToken | `update_h5_miniprogram_access_token` | `update_h5_miniprogram_access_token` | `SmsUpdateAccessTokenResponse` | [待核实] |
116
+
117
+ 回调类接口(状态报告推送、上行推送、模板审核结果推送)为服务端 Webhook,非客户端调用接口,此处不提供客户端方法。
118
+
119
+ ##### 签名生成算法
120
+
121
+ 1. 密码 MD5 加密:`MD5(password + smms_encrypt_key)`,结果转大写
122
+ 2. 参数拼接(按顺序):`AccountId={account_id}&PhoneNos={first_phone}&Password={md5_password}&Random={random}&Timestamp={timestamp}`(`PhoneNos` 只取第一个手机号)
123
+ 3. SHA256 加密:对拼接后的字符串做 SHA256 哈希,作为 `AccessKey`
124
+
125
+ ```python
126
+ from py_lmobile_toolkit.sms.auth import timestamp, random_digits, sha256_signature
127
+
128
+ ts = timestamp()
129
+ digits = random_digits()
130
+ signature = sha256_signature(
131
+ account_id="your_account_id",
132
+ password="your_password",
133
+ phone_nos="13800138000",
134
+ random_digits=digits,
135
+ timestamp=ts,
136
+ smms_encrypt_key="SMmsEncryptKey",
137
+ )
138
+ ```
139
+
140
+ ##### 环境变量配置
141
+
142
+ 示例与测试通过 `.env` 读取以下变量:
143
+
144
+ | 变量名 | 说明 | 默认值 |
145
+ |--------|------|--------|
146
+ | `SMS_BASE_URL` | API 基础地址 | `https://api.51welink.com/` |
147
+ | `SMS_ACCOUNT_ID` | 账号 ID(必填) | — |
148
+ | `SMS_PASSWORD` | 账号密码(必填) | — |
149
+ | `SMS_PRODUCT_ID` | 产品 ID | `""` |
150
+ | `SMS_SMMS_ENCRYPT_KEY` | 加密密钥(MD5 盐值) | `SMmsEncryptKey` |
151
+
152
+ #### 参与贡献
153
+
154
+ 1. Fork 本仓库
155
+ 2. 新建 `Feat_xxx` 分支
156
+ 3. 提交代码
157
+ 4. 新增 Pull Request
158
+
159
+ #### 特技
160
+
161
+ - 同步客户端 `SmsClient` 与异步客户端 `AsyncSmsClient`,方法名完全一致
162
+ - 异步客户端支持 `async with` 上下文管理器
163
+ - 请求签名认证(MD5 密码 + SHA256 签名,AccessKey)
164
+ - 响应数据模型验证(Pydantic v2),所有模型开启 `extra="allow"`,兼容 API 扩展字段
165
+ - 覆盖官方文档导航中的全部客户端可调用接口(短信/模板短信/账号/其他 API)
166
+ - 接口端点以常量集中管理,便于按官方文档精确对齐
167
+ - 所有方法支持透传 `**kwargs` 给 httpx,方便覆盖 URL、请求头等
168
+ - 基于 Python 3.10+,依赖 `httpx>=0.24.0` 与 `pydantic>=2.0`
169
+
170
+ #### 相关链接
171
+
172
+ - [PyPI 项目页面](https://pypi.org/project/py-lmobile-toolkit/)
173
+ - [Gitee 代码仓库](https://gitee.com/guolei19850528/py_lmobile_toolkit)
174
+ - [乐信官方 API 文档](https://www.lmobile.cn/ApiPages/index.html)
175
+ - [英文文档](README.en.md)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "py-lmobile-toolkit"
7
- version = "3.0.0"
7
+ version = "3.0.2"
8
8
  description = "乐信(51welink)短信服务 Python SDK,提供同步和异步接口调用,支持签名认证"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.4
2
+ Name: py-lmobile-toolkit
3
+ Version: 3.0.2
4
+ Summary: 乐信(51welink)短信服务 Python SDK,提供同步和异步接口调用,支持签名认证
5
+ Author-email: Guolei <174000902@qq.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 郭磊
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://gitee.com/guolei19850528/py_lmobile_toolkit
29
+ Project-URL: Repository, https://gitee.com/guolei19850528/py_lmobile_toolkit.git
30
+ Project-URL: Documentation, https://www.lmobile.cn/ApiPages/index.html
31
+ Keywords: lmobile,51welink,python,client,api,短信,sms,乐信
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3.10
37
+ Classifier: Programming Language :: Python :: 3.11
38
+ Classifier: Programming Language :: Python :: 3.12
39
+ Classifier: Programming Language :: Python :: 3.13
40
+ Classifier: Operating System :: OS Independent
41
+ Classifier: Topic :: Communications
42
+ Classifier: Topic :: Communications :: Telephony
43
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
44
+ Requires-Python: >=3.10
45
+ Description-Content-Type: text/markdown
46
+ License-File: LICENSE
47
+ Requires-Dist: httpx>=0.24.0
48
+ Requires-Dist: pydantic>=2.0
49
+ Provides-Extra: dev
50
+ Requires-Dist: pytest>=7.0; extra == "dev"
51
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
52
+ Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
53
+ Dynamic: license-file
54
+
55
+ # py-lmobile-toolkit
56
+
57
+ #### 介绍
58
+
59
+ `py-lmobile-toolkit` 是乐信(51welink)短信开放平台的非官方 Python 客户端库,封装官方 HTTP API,提供同步客户端 `SmsClient` 和异步客户端 `AsyncSmsClient`(方法名完全一致,异步客户端支持 `async with` 上下文管理器),签名采用 MD5 + SHA256,响应模型基于 Pydantic v2。
60
+
61
+ - 项目主页:https://gitee.com/guolei19850528/py_lmobile_toolkit
62
+ - PyPI:https://pypi.org/project/py-lmobile-toolkit/
63
+ - 官方 API 文档:https://www.lmobile.cn/ApiPages/index.html
64
+ - 许可证:[MIT License](LICENSE)
65
+
66
+ #### 软件架构
67
+
68
+ ```
69
+ py_lmobile_toolkit/
70
+ ├── sms/
71
+ │ ├── __init__.py
72
+ │ ├── auth.py # 签名生成(MD5/SHA256/时间戳/随机数)
73
+ │ ├── client.py # SmsClient(同步)与 AsyncSmsClient(异步)
74
+ │ └── models.py # Pydantic 响应模型
75
+ ```
76
+
77
+ 核心组件:
78
+ - `SmsClientConfig`:客户端配置(base_url、account_id、password、product_id、smms_encrypt_key),基于 Pydantic 校验
79
+ - `SmsClient`:同步 HTTP 客户端,支持 `with` 上下文管理器
80
+ - `AsyncSmsClient`:异步 HTTP 客户端,支持 `async with` 上下文管理器,方法名与 `SmsClient` 完全一致
81
+ - `SmsBaseResponse` 及各接口响应模型:`Result` 字段标识成功/失败,`extra="allow"` 兼容 API 扩展字段
82
+
83
+ #### 安装教程
84
+
85
+ 推荐使用 uv:
86
+
87
+ ```bash
88
+ uv add py-lmobile-toolkit
89
+ ```
90
+
91
+ 或从本地源码安装(开发模式):
92
+
93
+ ```bash
94
+ uv pip install -e .
95
+ uv pip install -e ".[dev]"
96
+ ```
97
+
98
+ 或者使用 pip:
99
+
100
+ ```bash
101
+ pip install py-lmobile-toolkit
102
+ pip install -e .
103
+ pip install -e ".[dev]"
104
+ ```
105
+
106
+ #### 使用说明
107
+
108
+ ##### 快速开始
109
+
110
+ 同步调用:
111
+
112
+ ```python
113
+ from py_lmobile_toolkit.sms.client import SmsClient
114
+
115
+ with SmsClient(
116
+ account_id="your_account_id",
117
+ password="your_password",
118
+ product_id="your_product_id",
119
+ ) as sms:
120
+ response = sms.send_sms(
121
+ phone_nos="13800138000",
122
+ content="【乐信】您的验证码是:123456",
123
+ )
124
+ print(f"成功: {response.ok}, 结果码: {response.Result}")
125
+ ```
126
+
127
+ 异步调用:
128
+
129
+ ```python
130
+ import asyncio
131
+ from py_lmobile_toolkit.sms.client import AsyncSmsClient
132
+
133
+
134
+ async def main():
135
+ async with AsyncSmsClient(
136
+ account_id="your_account_id",
137
+ password="your_password",
138
+ product_id="your_product_id",
139
+ ) as sms:
140
+ response = await sms.send_sms(
141
+ phone_nos=["13800138000"],
142
+ content="【乐信】批量发送测试",
143
+ )
144
+ print(f"成功: {response.ok}, 结果码: {response.Result}")
145
+
146
+
147
+ asyncio.run(main())
148
+ ```
149
+
150
+ ##### 已实现的接口
151
+
152
+ | 分类 | 接口 | 同步方法 | 异步方法 | 响应模型 | 端点状态 |
153
+ |------|------|----------|----------|----------|----------|
154
+ | 短信API | 提交短信 | `send_sms` / `send` | `send_sms` / `send` | `SmsSendSmsResponse` | ✅ 已知可靠 |
155
+ | 短信API | 提交个性化短信(变量XML格式) | `send_personalized_xml` | `send_personalized_xml` | `SmsBaseResponse` | [待核实] |
156
+ | 短信API | 提交个性化短信(变量Json格式) | `send_personalized_json` | `send_personalized_json` | `SmsBaseResponse` | [待核实] |
157
+ | 短信API | 拉取状态报告 | `pull_status_report` | `pull_status_report` | `SmsPullReportResponse` | [待核实] |
158
+ | 短信API | 拉取上行信息 | `pull_mo_message` | `pull_mo_message` | `SmsPullMoResponse` | [待核实] |
159
+ | 短信API | 取消定时消息发送 | `cancel_scheduled_sms` | `cancel_scheduled_sms` | `SmsCancelScheduledResponse` | [待核实] |
160
+ | 模板短信API | 提交模板短信 | `submit_template_sms` | `submit_template_sms` | `SmsSubmitTemplateSmsResponse` | [待核实] |
161
+ | 模板短信API | 提交个性化模板短信 | `submit_personalized_template_sms` | `submit_personalized_template_sms` | `SmsBaseResponse` | [待核实] |
162
+ | 模板短信API | 短信模板报备 | `register_template` | `register_template` | `SmsRegisterTemplateResponse` | [待核实] |
163
+ | 模板短信API | 视频短信模板报备 | `register_video_template` | `register_video_template` | `SmsRegisterVideoTemplateResponse` | [待核实] |
164
+ | 模板短信API | 删除模板 | `delete_template` | `delete_template` | `SmsDeleteTemplateResponse` | [待核实] |
165
+ | 模板短信API | 查询模板 | `query_template` | `query_template` | `SmsQueryTemplateResponse` | [待核实] |
166
+ | 账号API | 查询余量 | `query_balance` | `query_balance` | `SmsBalanceResponse` | [待核实] |
167
+ | 账号API | 查询计费量 | `query_billing` | `query_billing` | `SmsBillingResponse` | [待核实] |
168
+ | 其他API | H5跳转小程序短链生成 | `generate_h5_miniprogram_short_link` | `generate_h5_miniprogram_short_link` | `SmsH5ShortLinkResponse` | [待核实] |
169
+ | 其他API | 更新H5跳小程序的AccessToken | `update_h5_miniprogram_access_token` | `update_h5_miniprogram_access_token` | `SmsUpdateAccessTokenResponse` | [待核实] |
170
+
171
+ 回调类接口(状态报告推送、上行推送、模板审核结果推送)为服务端 Webhook,非客户端调用接口,此处不提供客户端方法。
172
+
173
+ ##### 签名生成算法
174
+
175
+ 1. 密码 MD5 加密:`MD5(password + smms_encrypt_key)`,结果转大写
176
+ 2. 参数拼接(按顺序):`AccountId={account_id}&PhoneNos={first_phone}&Password={md5_password}&Random={random}&Timestamp={timestamp}`(`PhoneNos` 只取第一个手机号)
177
+ 3. SHA256 加密:对拼接后的字符串做 SHA256 哈希,作为 `AccessKey`
178
+
179
+ ```python
180
+ from py_lmobile_toolkit.sms.auth import timestamp, random_digits, sha256_signature
181
+
182
+ ts = timestamp()
183
+ digits = random_digits()
184
+ signature = sha256_signature(
185
+ account_id="your_account_id",
186
+ password="your_password",
187
+ phone_nos="13800138000",
188
+ random_digits=digits,
189
+ timestamp=ts,
190
+ smms_encrypt_key="SMmsEncryptKey",
191
+ )
192
+ ```
193
+
194
+ ##### 环境变量配置
195
+
196
+ 示例与测试通过 `.env` 读取以下变量:
197
+
198
+ | 变量名 | 说明 | 默认值 |
199
+ |--------|------|--------|
200
+ | `SMS_BASE_URL` | API 基础地址 | `https://api.51welink.com/` |
201
+ | `SMS_ACCOUNT_ID` | 账号 ID(必填) | — |
202
+ | `SMS_PASSWORD` | 账号密码(必填) | — |
203
+ | `SMS_PRODUCT_ID` | 产品 ID | `""` |
204
+ | `SMS_SMMS_ENCRYPT_KEY` | 加密密钥(MD5 盐值) | `SMmsEncryptKey` |
205
+
206
+ #### 参与贡献
207
+
208
+ 1. Fork 本仓库
209
+ 2. 新建 `Feat_xxx` 分支
210
+ 3. 提交代码
211
+ 4. 新增 Pull Request
212
+
213
+ #### 特技
214
+
215
+ - 同步客户端 `SmsClient` 与异步客户端 `AsyncSmsClient`,方法名完全一致
216
+ - 异步客户端支持 `async with` 上下文管理器
217
+ - 请求签名认证(MD5 密码 + SHA256 签名,AccessKey)
218
+ - 响应数据模型验证(Pydantic v2),所有模型开启 `extra="allow"`,兼容 API 扩展字段
219
+ - 覆盖官方文档导航中的全部客户端可调用接口(短信/模板短信/账号/其他 API)
220
+ - 接口端点以常量集中管理,便于按官方文档精确对齐
221
+ - 所有方法支持透传 `**kwargs` 给 httpx,方便覆盖 URL、请求头等
222
+ - 基于 Python 3.10+,依赖 `httpx>=0.24.0` 与 `pydantic>=2.0`
223
+
224
+ #### 相关链接
225
+
226
+ - [PyPI 项目页面](https://pypi.org/project/py-lmobile-toolkit/)
227
+ - [Gitee 代码仓库](https://gitee.com/guolei19850528/py_lmobile_toolkit)
228
+ - [乐信官方 API 文档](https://www.lmobile.cn/ApiPages/index.html)
229
+ - [英文文档](README.en.md)