|
# NewLife.WeChat
NewLife.WeChat 是一个基于 NewLife.Core å’Œ XCode 的微信开å‘工具类库,æä¾›å¾®ä¿¡å…¬ä¼—å·ã€å°ç¨‹åºç‰åŠŸèƒ½çš„é›†æˆæ”¯æŒã€‚
## 功能特性
- ✅ 基于 NewLife.Core æ ¸å¿ƒåº“ï¼Œæä¾›å¼ºå¤§çš„基础功能
- ✅ 使用 XCode 实体模型管ç†é…置,支æŒå¤šç§æ•°æ®åº“
- ✅ 支æŒå¤šåº”用é…置管ç†ï¼ˆå…¬ä¼—å·ã€å°ç¨‹åºã€APP)
- ✅ AccessToken 自动管ç†å’Œç¼“å˜ï¼ˆæå‰5分钟过期)
- ✅ 用户信æ¯èŽ·å–(OpenIdã€UnionId)
- ✅ UnionId è·¨åº”ç”¨å…³è”æŸ¥è¯¢
- ✅ æ¨¡æ¿æ¶ˆæ¯å‘é€ï¼ˆå…¬ä¼—å·æ¨¡æ¿æ¶ˆæ¯ã€å°ç¨‹åºè®¢é˜…消æ¯ï¼‰
- ✅ æ‰¹é‡æ¶ˆæ¯å‘逿”¯æŒ
- 🔄 更多微信 API 支æŒï¼ˆå¼€å‘ä¸ï¼‰
## æ ¸å¿ƒåŠŸèƒ½
### 1. AccessToken 管ç†
- 自动缓å˜ï¼Œå‡å°‘ API 调用
- æå‰5分钟过期,é¿å…临界问题
- å¹¶å‘安全,防æ¢é‡å¤è¯·æ±‚
- 支æŒå¼ºåˆ¶åˆ·æ–°
### 2. 用户信æ¯èŽ·å–
- 网页授æƒèŽ·å–用户信æ¯
- è‡ªåŠ¨è§£æž OpenId å’Œ UnionId
- å˜å‚¨åˆ°æ•°æ®åº“,便于管ç†
### 3. UnionId å…³è”æŸ¥è¯¢
- 通过 UnionId 实现跨应用用户识别
- 支æŒå…¬ä¼—å·ã€å°ç¨‹åºã€APP 用户关è”
- é€‚ç”¨äºŽè·¨åº”ç”¨æ¶ˆæ¯æŽ¨é€ã€æ•°æ®åŒæ¥ç‰åœºæ™¯
### 4. æ¨¡æ¿æ¶ˆæ¯å‘é€
- 支æŒå…¬ä¼—å·æ¨¡æ¿æ¶ˆæ¯
- 支æŒå°ç¨‹åºè®¢é˜…消æ¯
- æ”¯æŒæ‰¹é‡å‘é€
- è‡ªåŠ¨èŽ·å– AccessToken
- 完整的错误处ç†å’Œé‡è¯•机制
## 快速开始
### 安装
```bash
dotnet add package NewLife.WeChat
```
### é…置数æ®åº“连接
在é…置文件(如 `appsettings.json`)ä¸é…置数æ®åº“连接:
```json
{
"ConnectionStrings": {
"WeChat": "Data Source=Data/WeChat.db"
}
}
```
### åˆå§‹åŒ–é…ç½®
```csharp
using NewLife.WeChat.Entities;
// 创建公众å·é…ç½®
var config = new 微信é…ç½®
{
AppName = "我的公众å·",
AppId = "wx1234567890",
AppSecret = "your_app_secret",
AppCategory = 1, // 1=公众å·
IsEnabled = true
};
config.Insert();
```
### 使用示例
```csharp
using NewLife.WeChat.Services;
var service = new WeChatService();
// 1. èŽ·å– AccessToken
var token = await service.GetAccessTokenAsync("wx1234567890");
// 2. 获å–用户信æ¯
var userInfo = await service.GetUserInfoByCodeAsync("wx1234567890", code);
// 3. 跨应用查询
var miniOpenId = service.GetOpenIdByUnionId(userInfo.UnionId, "wx_mini_123456");
// 4. å‘逿¨¡æ¿æ¶ˆæ¯
var data = new
{
first = new { value = "您的订å•已完æˆ" },
keyword1 = new { value = "202401010001" },
keyword2 = new { value = "ï¿¥99.00" },
remark = new { value = "感谢支æŒï¼" }
};
await service.SendTemplateMessageAsync(
"wx1234567890",
userInfo.OpenId,
"template_order_success",
data,
"https://example.com/order/202401010001"
);
```
## 文档
- [快速开始指å—](/NewLife/NewLife.WeChat/Blob/master/docs/QuickStart.md) - 详细的使用教程
- [架构设计文档](/NewLife/NewLife.WeChat/Blob/master/docs/Architecture.md) - 系统架构和设计说明
- [æ ¸å¿ƒåŠŸèƒ½å®žçŽ°](/NewLife/NewLife.WeChat/Blob/master/docs/CoreFunctions.md) - æ ¸å¿ƒåŠŸèƒ½å®žçŽ°ç»†èŠ‚
## API 列表
### WeChatService æ ¸å¿ƒæœåŠ¡
| 方法 | 说明 |
|------|------|
| `GetAccessTokenAsync` | 获å–访问令牌(自动缓å˜ï¼‰ |
| `RefreshAccessTokenAsync` | 刷新访问令牌 |
| `GetUserInfoByCodeAsync` | 通过授æƒç 获å–ç”¨æˆ·ä¿¡æ¯ |
| `GetUserDetailAsync` | 获å–ç”¨æˆ·è¯¦ç»†ä¿¡æ¯ |
| `GetOpenIdByUnionId` | æ ¹æ® UnionId 查询指定应用的 OpenId |
| `GetAllOpenIdsByUnionId` | èŽ·å– UnionId å…³è”的所有 OpenId |
| `SendTemplateMessageAsync` | å‘é€å…¬ä¼—å·æ¨¡æ¿æ¶ˆæ¯ |
| `SendSubscribeMessageAsync` | å‘é€å°ç¨‹åºè®¢é˜…æ¶ˆæ¯ |
| `SendBatchTemplateMessagesAsync` | 批é‡å‘逿¨¡æ¿æ¶ˆæ¯ |
### 实体类
| 实体 | 说明 |
|------|------|
| `微信é…ç½®` | 微信应用é…置表 |
| `微信用户` | 微信用户表(OpenIdã€UnionId) |
| `å¾®ä¿¡æ¨¡æ¿æ¶ˆæ¯é…ç½®` | æ¨¡æ¿æ¶ˆæ¯é…置表 |
## æŠ€æœ¯æ ˆ
- .NET 10.0
- NewLife.Core - æ ¸å¿ƒåŸºç¡€åº“
- XCode - æ•°æ®è®¿é—®å±‚框架
## å¼€å‘计划
### ✅ 已完æˆ
- [x] 项目架构设计
- [x] 实体模型实现(微信é…ç½®ã€å¾®ä¿¡ç”¨æˆ·ã€æ¨¡æ¿æ¶ˆæ¯é…置)
- [x] AccessToken 管ç†ï¼ˆèŽ·å–ã€ç¼“å˜ã€åˆ·æ–°ï¼‰
- [x] 用户信æ¯èŽ·å–(OpenIdã€UnionId)
- [x] UnionId è·¨åº”ç”¨å…³è”æŸ¥è¯¢
- [x] æ¨¡æ¿æ¶ˆæ¯å‘é€ï¼ˆå…¬ä¼—å·ã€å°ç¨‹åºï¼‰
- [x] æ‰¹é‡æ¶ˆæ¯å‘é€
### 🔄 进行ä¸
- [ ] 消æ¯ç®¡ç†ï¼ˆæŽ¥æ”¶ã€å›žå¤ï¼‰
- [ ] èœå•管ç†
- [ ] ç´ æç®¡ç†
### 📋 计划ä¸
- [ ] 支付功能
- [ ] å®¢æœæ¶ˆæ¯
- [ ] å°ç¨‹åºç 生æˆ
- [ ] ä¼ä¸šå¾®ä¿¡æ”¯æŒ
- [ ] å‘é€è®°å½•和统计
## 贡献
欢迎æäº¤ Issue å’Œ Pull Requestï¼
## 许å¯è¯
MIT License
---
**维护者**: NewLife å¼€å‘团队
**主页**: https://git.newlifex.com/NewLife/NewLife.WeChat
remark = new { value = "感谢支æŒï¼" }
};
await service.SendTemplateMessageAsync(
"wx1234567890",
userInfo.OpenId,
"template_order_success",
data,
"https://example.com/order/202401010001"
);
```
}
}
```
### 创建微信é…ç½®
```csharp
using NewLife.WeChat.Entities;
using NewLife.WeChat.Models;
// 创建公众å·é…ç½®
var config = new 微信é…ç½®
{
AppName = "我的公众å·",
AppId = "wx1234567890abcdef",
AppSecret = "your_app_secret_here",
AppCategory = WeChatAppCategory.公众å·,
TenantId = 1,
IsEnabled = true,
Token = "your_token",
Remark = "测试公众å·"
};
config.Insert();
// 创建å°ç¨‹åºé…ç½®
var miniConfig = new 微信é…ç½®
{
AppName = "我的å°ç¨‹åº",
AppId = "wx9876543210fedcba",
AppSecret = "your_mini_app_secret",
AppCategory = WeChatAppCategory.MiniProgram,
TenantId = 1,
IsEnabled = true,
Remark = "测试å°ç¨‹åº"
};
miniConfig.Insert();
// 创建APPé…ç½®
var appConfig = new 微信é…ç½®
{
AppName = "我的移动应用",
AppId = "wxapp123456789",
AppSecret = "your_app_secret",
AppCategory = WeChatAppCategory.APP,
TenantId = 1,
IsEnabled = true,
Remark = "移动APP应用"
};
appConfig.Insert();
```
### 查询é…ç½®
```csharp
// æ ¹æ® AppId 查询
var config = 微信é…ç½®.FindByAppId("wx1234567890abcdef");
// 查询所有å¯ç”¨çš„é…ç½®
var configs = 微信é…ç½®.FindAllEnabled();
// æ ¹æ®åº”用分类查询
var officialAccounts = 微信é…ç½®.FindAllByCategory(WeChatAppCategory.公众å·);
var miniPrograms = 微信é…ç½®.FindAllByCategory(WeChatAppCategory.MiniProgram);
var apps = 微信é…ç½®.FindAllByCategory(WeChatAppCategory.APP);
// æ ¹æ®ç§Ÿæˆ·æŸ¥è¯¢
var tenantConfigs = 微信é…ç½®.FindAllByTenant(1);
// 高级查询
var list = 微信é…ç½®.Search(
appname: null,
appid: null,
apptype: null,
category: WeChatAppCategory.公众å·,
tenantId: 1,
enabled: true,
start: DateTime.MinValue,
end: DateTime.MaxValue,
key: "测试",
page: new PageParameter { PageIndex = 1, PageSize = 20 }
);
```
### AccessToken 管ç†
```csharp
var config = 微信é…ç½®.FindByAppId("wx1234567890abcdef");
// 设置 AccessToken
config.SetAccessToken("access_token_value", 7200);
// èŽ·å– AccessToken
var token = config.GetAccessToken();
```
### 微信用户管ç†
```csharp
using NewLife.WeChat.Entities;
// æ ¹æ® AppId å’Œ OpenId 查找用户
var user = 微信用户.FindByOpenId("wx1234567890abcdef", "openid123");
// 查找åŒä¸€ UnionId 的所有用户(跨应用)
var users = 微信用户.FindAllByUnionId("unionid123");
// åŒæ¥ç”¨æˆ·ä¿¡æ¯ï¼ˆä»Žå¾®ä¿¡API获å–åŽæ›´æ–°ï¼‰
var userInfo = new Dictionary<String, Object>
{
["unionid"] = "unionid123",
["nickname"] = "å¼ ä¸‰",
["headimgurl"] = "http://...",
["sex"] = 1,
["country"] = "ä¸å›½",
["province"] = "广东",
["city"] = "深圳",
["subscribe"] = 1,
["subscribe_time"] = 1234567890
};
var syncedUser = 微信用户.Sync("wx1234567890abcdef", "openid123", userInfo);
// 查询所有已关注用户
var subscribedUsers = 微信用户.FindAllSubscribed();
// 高级查询
var list = 微信用户.Search(
appid: "wx1234567890abcdef",
openid: null,
unionid: null,
nickname: "å¼ ",
isSubscribe: true,
start: DateTime.MinValue,
end: DateTime.MaxValue,
key: "深圳",
page: new PageParameter { PageIndex = 1, PageSize = 20 }
);
```
## 项目结构
```
NewLife.WeChat/
├── Entities/ # XCode 实体模型
│ ├── 微信é…ç½®.cs # é…置实体定义
│ ├── 微信é…ç½®.Biz.cs # é…置业务逻辑
│ ├── 微信用户.cs # 用户实体定义
│ └── 微信用户.Biz.cs # 用户业务逻辑
├── docs/ # 文档
│ └── Architecture.md # 架构设计文档
└── README.md # 项目说明
```
## æ•°æ®åº“支æŒ
得益于 XCode 的支æŒï¼Œæœ¬é¡¹ç›®æ”¯æŒä»¥ä¸‹æ•°æ®åº“:
- SQLite(默认)
- MySQL
- SQL Server
- PostgreSQL
- Oracle
- ç‰ç‰...
## 架构设计
详细的架构设计请å‚考 [架构文档](/NewLife/NewLife.WeChat/Blob/master/docs/Architecture.md)。
## ä¾èµ–项
- [NewLife.Core](https://github.com/NewLifeX/X) - æ ¸å¿ƒåŸºç¡€åº“
- [NewLife.XCode](https://github.com/NewLifeX/X) - æ•°æ®è®¿é—®å±‚框架
## å¼€å‘计划
- [x] 基础架构æå»º
- [x] 微信é…置实体模型
- [ ] AccessToken 自动刷新æœåŠ¡
- [ ] å¾®ä¿¡å…¬ä¼—å· API å°è£…
- [ ] 微信å°ç¨‹åº API å°è£…
- [ ] 微信支付支æŒ
- [ ] ä¼ä¸šå¾®ä¿¡æ”¯æŒ
## 贡献
欢迎æäº¤ Issue å’Œ Pull Requestï¼
## 许å¯è¯
MIT License
## è”系方å¼
- 官网:https://newlifex.com
- QQ群:1600800
- æºç :https://git.newlifex.com/NewLife/NewLife.WeChat
|