Skip to content

Commit baf2031

Browse files
committed
feat: 添加消息加解密功能,支持安全模式和兼容模式
1 parent c023924 commit baf2031

7 files changed

Lines changed: 707 additions & 4 deletions

File tree

Cargo.lock

Lines changed: 112 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ sha1 = "0.10"
1919
hex = "0.4"
2020
urlencoding = "2.1"
2121
tracing = "0.1"
22+
aes = "0.8"
23+
cbc = "0.1"
24+
base64 = "0.22"
25+
rand = "0.8"
2226

2327
[dev-dependencies]
2428
tokio = { version = "1", features = ["full"] }

README.md

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- **文章发布** - 发布文章、群发消息
1717
- **二维码** - 生成带参数二维码
1818
- **签名验证** - 服务器回调签名校验
19+
- **消息加解密** - 支持安全模式/兼容模式,AES-256-CBC 加解密
1920

2021
## 安装
2122

@@ -29,6 +30,8 @@ tokio = { version = "1", features = ["full"] }
2930

3031
## 快速开始
3132

33+
### 明文模式
34+
3235
```rust
3336
use wechat_oa_sdk::{Config, WeChatClient};
3437

@@ -54,6 +57,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5457
}
5558
```
5659

60+
### 安全模式(消息加解密)
61+
62+
```rust
63+
use wechat_oa_sdk::{Config, WeChatClient};
64+
65+
let config = Config::new("your_app_id", "your_app_secret", "your_token")
66+
.with_encoding_aes_key("your_43_char_encoding_aes_key");
67+
let client = WeChatClient::new(config);
68+
```
69+
5770
## 使用示例
5871

5972
### 发送客服消息
@@ -171,6 +184,8 @@ std::fs::write("qrcode.jpg", image_data)?;
171184

172185
### 处理消息回调
173186

187+
#### 明文模式
188+
174189
```rust
175190
use wechat_oa_sdk::api::message::IncomingMessage;
176191
use wechat_oa_sdk::models::reply::TextReply;
@@ -206,23 +221,70 @@ match msg {
206221
}
207222
```
208223

224+
#### 安全模式(加密)
225+
226+
```rust
227+
use wechat_oa_sdk::api::message::IncomingMessage;
228+
use wechat_oa_sdk::models::reply::TextReply;
229+
230+
// 服务器验证(GET 请求,安全模式下需要解密 echostr)
231+
if client.verify_msg_signature(&msg_signature, &timestamp, &nonce, &echostr) {
232+
let decrypted = client.decrypt_echostr(&echostr)?;
233+
return Ok(decrypted);
234+
}
235+
236+
// 解密并解析消息(POST 请求)
237+
let msg = client.parse_encrypted_message(&xml_body, &msg_signature, &timestamp, &nonce)?;
238+
239+
match msg {
240+
IncomingMessage::Text(text) => {
241+
let reply = TextReply::new(
242+
&text.from_user_name,
243+
&text.to_user_name,
244+
"收到你的消息了!",
245+
);
246+
// 加密回复
247+
return Ok(reply.to_encrypted_xml(&client)?);
248+
}
249+
_ => {
250+
return Ok("success".to_string());
251+
}
252+
}
253+
```
254+
209255
## API 列表
210256

211257
### 基础
212258
| 方法 | 说明 |
213259
|------|------|
214260
| `access_token()` | 获取 Access Token |
215-
| `verify_signature()` | 验证消息签名 |
261+
| `verify_signature()` | 验证消息签名(明文模式) |
216262
| `get_callback_ip_list()` | 获取微信服务器 IP |
217263

218264
### 消息
219265
| 方法 | 说明 |
220266
|------|------|
221-
| `parse_message()` | 解析接收的消息 |
267+
| `parse_message()` | 解析接收的消息(明文模式) |
222268
| `send_text()` | 发送文本客服消息 |
223269
| `send_image()` | 发送图片客服消息 |
224270
| `send_template_message()` | 发送模板消息 |
225271

272+
### 消息加解密
273+
| 方法 | 说明 |
274+
|------|------|
275+
| `verify_msg_signature()` | 验证加密消息签名 |
276+
| `parse_encrypted_message()` | 解密并解析消息(安全/兼容模式) |
277+
| `decrypt_echostr()` | 解密服务器验证的 echostr |
278+
| `encrypt_reply()` | 加密回复消息(自定义 timestamp/nonce) |
279+
| `encrypt_reply_auto()` | 加密回复消息(自动生成 timestamp/nonce) |
280+
281+
所有 Reply 类型(TextReply、ImageReply、VoiceReply、VideoReply、NewsReply)均支持:
282+
| 方法 | 说明 |
283+
|------|------|
284+
| `to_xml()` | 生成明文 XML 回复 |
285+
| `to_encrypted_xml(client)` | 生成加密 XML 回复 |
286+
| `to_encrypted_xml_with(client, timestamp, nonce)` | 自定义参数的加密回复 |
287+
226288
### 素材
227289
| 方法 | 说明 |
228290
|------|------|
@@ -276,6 +338,7 @@ WECHAT_APP_ID=xxx WECHAT_APP_SECRET=xxx WECHAT_TOKEN=xxx cargo run --example int
276338
1. **IP 白名单**:调用 API 前需在公众号后台配置服务器 IP 白名单
277339
2. **账号权限**:部分接口需要认证订阅号或服务号才能使用
278340
3. **AppSecret 安全**:请勿泄露 AppSecret,建议使用环境变量管理
341+
4. **消息模式**:安全模式需要在公众号后台配置 EncodingAESKey,并在 Config 中通过 `with_encoding_aes_key()` 设置
279342

280343
## License
281344

0 commit comments

Comments
 (0)