# 第三方 (99_Third)
最后更新: 2024-09-20
# 📚 概述
DarkM 框架的第三方模块提供了与第三方服务集成的统一接口。目前支持极光推送(JPush)、WPS Web Office 等第三方服务,实现消息推送、在线文档预览等功能。
源代码位置: DarkM/src/Framework/Third
# 🏗️ 模块架构
# 项目结构
Third/
├── Third.Abstractions/ # 抽象层(接口、模型、配置)
│ ├── IJiguangService.cs # 极光服务接口
│ └── Model/ # 数据模型
│ ├── JPushConfig.cs # 极光推送配置
│ ├── MessageResult.cs # 消息结果
│ └── ... # 其他模型
│
├── Third.Integration/ # 集成层(DI 注册)
│ └── ServiceCollectionExtensions.cs # DI 扩展
│
├── Third.JPush/ # 极光推送实现
│ └── Handler/
│ └── JiguangServiceImpl.cs # 极光服务实现
│
├── Third.OfficeAbstractions/ # Office 抽象层
│ └── Version3/ # V3 版本
│ ├── Config/ # 配置
│ ├── Model/ # 模型
│ └── Util/ # 工具类
│
├── Third.WPSWebOffice/ # WPS Web Office 实现
│ └── Handler/
│ └── WpsWebOfficeHandler.cs # WPS 处理器
│
├── Third.Spire.Office/ # Spire.Office 实现
│ └── Handler/
│ └── SpireOfficeHandler.cs # Spire 处理器
│
├── Third.Source/ # 源码参考
│ └── ... # 第三方 SDK 源码
│
└── Third.Upload/ # 文件上传
└── Handler/
└── UploadHandler.cs # 上传处理器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 🔧 核心接口
# IJiguangService(极光服务)
/// <summary>
/// 极光服务接口
/// </summary>
public interface IJiguangService
{
#region 通用方法
/// <summary>
/// 推送消息
/// </summary>
/// <param name="config">极光配置</param>
/// <param name="platform">推送平台:all/ios/android</param>
/// <param name="txt">发送消息的文字</param>
/// <param name="byType">发送类型:all/tag/alias/registration</param>
/// <param name="androidTitle">安卓自定义消息标题(IOS 不支持)</param>
/// <param name="extras">扩展参数</param>
/// <param name="targets">发送目标数组</param>
/// <returns>推送结果</returns>
MessageResult PushMessage(
JPushConfig config,
string platform,
string txt,
string byType,
string androidTitle,
IDictionary<string, string> extras,
params string[] targets);
/// <summary>
/// 查询消息发送状态
/// </summary>
/// <param name="messsageId">消息编号</param>
/// <returns>查询结果</returns>
MessageResult GetMessageStatus(
JPushConfig config,
string messsageId);
#endregion
#region 按不同纬度推送消息
/// <summary>
/// 推送消息:推送全部的人
/// </summary>
MessageResult PushAll(
JPushConfig config,
string txt,
string androidTitle = null,
string link = null);
/// <summary>
/// 推送消息:按标签推送
/// 标签类型:CustomerType[PrePC/RT/PC/SA/VipBIZ] / 性别 [F/M]
/// </summary>
MessageResult PushByTag(
JPushConfig config,
string txt,
string androidTitle,
IDictionary<string, string> extras = null,
params string[] targets);
/// <summary>
/// 推送消息:按昵称推送(一般定义为 PCNO)
/// </summary>
MessageResult PushByAlias(
JPushConfig config,
string txt,
string androidTitle,
IDictionary<string, string> extras = null,
params string[] targets);
/// <summary>
/// 推送消息:按照注册的设备编号推送
/// </summary>
MessageResult PushByRegistration(
JPushConfig config,
string txt,
string androidTitle,
IDictionary<string, string> extras = null,
params string[] targets);
#endregion
/// <summary>
/// 通过极光推送,推送消息到指定的客户端
/// </summary>
MessageResult Push(
JPushConfig config,
string toUser,
string context,
string title,
string link);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# JPushConfig(极光推送配置)
public class JPushConfig
{
/// <summary>
/// 应用 ID
/// </summary>
public string AppId { get; set; }
/// <summary>
/// 应用密钥
/// </summary>
public string AppSecret { get; set; }
/// <summary>
/// 是否生产环境(IOS)
/// </summary>
public string APNSProduction { get; set; }
/// <summary>
/// 标签(逗号分隔)
/// </summary>
public string Tags { get; set; }
/// <summary>
/// 极光标签列表
/// </summary>
public List<string> JiguangTags =>
Tags.IsNull() ? new List<string>() : Tags.Split(',').ToList();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# MessageResult(消息结果)
public class MessageResult
{
/// <summary>
/// 消息 ID
/// </summary>
public string MsgId { get; set; }
/// <summary>
/// 发送编号("0"表示成功)
/// </summary>
public string SendNo { get; set; }
/// <summary>
/// 消息内容
/// </summary>
public string Message { get; set; }
/// <summary>
/// 请求内容
/// </summary>
public string Request { get; set; }
/// <summary>
/// 是否成功
/// </summary>
public bool IsResultOK()
{
return "0".Equals(SendNo);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 🏗️ 依赖注入
# 自动注册机制
// Third.Integration/ServiceCollectionExtensions.cs
public static class ServiceCollectionExtensions
{
/// <summary>
/// 添加第三方相关服务
/// </summary>
public static IServiceCollection AddThird(
this IServiceCollection services,
IConfiguration cfg)
{
// 加载极光推送实现
var assembly = AssemblyHelper.LoadByNameEndString(
$".Lib.Third.JPush.Handler.JiguangServiceImpl");
if (assembly != null)
{
// 注册 IJiguangService 实现
var handlerType = assembly.GetTypes()
.FirstOrDefault(m => typeof(IJiguangService).IsAssignableFrom(m));
if (handlerType != null)
{
services.AddSingleton(typeof(IJiguangService), handlerType);
}
}
return services;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 💡 使用示例
# 1. 配置第三方模块
// appsettings.json
{
"Third": {
"JPush": {
"AppId": "your-app-id",
"AppSecret": "your-app-secret",
"APNSProduction": "false",
"Tags": "PrePC,RT,PC"
},
"WPS": {
"AppId": "your-wps-app-id",
"AppSecret": "your-wps-app-secret"
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2. 注册服务
// Program.cs 或 Startup.cs
var builder = WebApplication.CreateBuilder(args);
// 添加第三方服务
builder.Services.AddThird(builder.Configuration);
var app = builder.Build();
1
2
3
4
5
6
7
2
3
4
5
6
7
# 3. 推送全部用户
public class PushNotificationService
{
private readonly IJiguangService _jiguangService;
private readonly JPushConfig _jpushConfig;
private readonly ILogger<PushNotificationService> _logger;
public PushNotificationService(
IJiguangService jiguangService,
IOptions<JPushConfig> jpushConfig,
ILogger<PushNotificationService> logger)
{
_jiguangService = jiguangService;
_jpushConfig = jpushConfig.Value;
_logger = logger;
}
/// <summary>
/// 推送通知给全部用户
/// </summary>
public MessageResult PushToAll(string message, string link = null)
{
var result = _jiguangService.PushAll(
_jpushConfig,
message,
"新消息通知",
link);
if (result.IsResultOK())
{
_logger.LogInformation(
"推送成功 - MsgId: {MsgId}, SendNo: {SendNo}",
result.MsgId,
result.SendNo);
}
else
{
_logger.LogWarning(
"推送失败 - Message: {Message}, Request: {Request}",
result.Message,
result.Request);
}
return result;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 4. 按标签推送
public class TargetedPushService
{
private readonly IJiguangService _jiguangService;
private readonly JPushConfig _jpushConfig;
public TargetedPushService(
IJiguangService jiguangService,
IOptions<JPushConfig> jpushConfig)
{
_jiguangService = jiguangService;
_jpushConfig = jpushConfig.Value;
}
/// <summary>
/// 按客户类型推送
/// </summary>
public MessageResult PushByCustomerType(
string customerType,
string message)
{
return _jiguangService.PushByTag(
_jpushConfig,
message,
"客户通知",
extras: new Dictionary<string, string>
{
["type"] = "customer_notification",
["customerType"] = customerType
},
customerType); // 如:PrePC, RT, PC, SA, VipBIZ
}
/// <summary>
/// 按性别推送
/// </summary>
public MessageResult PushByGender(
string gender,
string message)
{
return _jiguangService.PushByTag(
_jpushConfig,
message,
"性别定向推送",
extras: new Dictionary<string, string>
{
["type"] = "gender_notification",
["gender"] = gender
},
gender); // F 或 M
}
/// <summary>
/// 按用户别名推送(PCNO)
/// </summary>
public MessageResult PushByAlias(
string pcno,
string message)
{
return _jiguangService.PushByAlias(
_jpushConfig,
message,
"个人通知",
extras: new Dictionary<string, string>
{
["type"] = "personal_notification",
["pcno"] = pcno
},
pcno);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 5. 推送订单通知
public class OrderNotificationService
{
private readonly IJiguangService _jiguangService;
private readonly JPushConfig _jpushConfig;
public OrderNotificationService(
IJiguangService jiguangService,
IOptions<JPushConfig> jpushConfig)
{
_jiguangService = jiguangService;
_jpushConfig = jpushConfig.Value;
}
/// <summary>
/// 推送订单状态变更通知
/// </summary>
public MessageResult PushOrderStatusChange(
string userAlias,
string orderNo,
string status,
string link)
{
var message = $"您的订单 {orderNo} 状态已变更为:{status}";
return _jiguangService.Push(
_jpushConfig,
userAlias,
message,
"订单通知",
link);
}
/// <summary>
/// 推送物流通知
/// </summary>
public MessageResult PushShippingNotification(
string userAlias,
string orderNo,
string courierCompany,
string trackingNo)
{
var message = $"您的订单 {orderNo} 已发货," +
$"快递公司:{courierCompany}," +
$"单号:{trackingNo}";
return _jiguangService.Push(
_jpushConfig,
userAlias,
message,
"物流通知",
$"/order/{orderNo}/tracking");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 6. 查询推送状态
public class PushStatusService
{
private readonly IJiguangService _jiguangService;
private readonly JPushConfig _jpushConfig;
public PushStatusService(
IJiguangService jiguangService,
IOptions<JPushConfig> jpushConfig)
{
_jiguangService = jiguangService;
_jpushConfig = jpushConfig.Value;
}
/// <summary>
/// 查询推送状态
/// </summary>
public MessageResult QueryPushStatus(string msgId)
{
return _jiguangService.GetMessageStatus(
_jpushConfig,
msgId);
}
/// <summary>
/// 批量查询推送状态
/// </summary>
public List<MessageResult> QueryBatchStatus(List<string> msgIds)
{
var results = new List<MessageResult>();
foreach (var msgId in msgIds)
{
var result = QueryPushStatus(msgId);
results.Add(result);
}
return results;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 7. 推送控制器
[Route("api/[controller]")]
[ApiController]
public class PushController : ModuleController
{
private readonly PushNotificationService _pushService;
private readonly TargetedPushService _targetedService;
private readonly OrderNotificationService _orderService;
private readonly PushStatusService _statusService;
public PushController(
PushNotificationService pushService,
TargetedPushService targetedService,
OrderNotificationService orderService,
PushStatusService statusService)
{
_pushService = pushService;
_targetedService = targetedService;
_orderService = orderService;
_statusService = statusService;
}
/// <summary>
/// 推送给全部用户
/// </summary>
[HttpPost("push-all")]
public IResultModel PushAll([FromBody] PushAllRequest request)
{
var result = _pushService.PushToAll(request.Message, request.Link);
if (result.IsResultOK())
{
return ResultModel.Success(new
{
msgId = result.MsgId,
sendNo = result.SendNo
});
}
else
{
return ResultModel.Error($"推送失败:{result.Message}");
}
}
/// <summary>
/// 按标签推送
/// </summary>
[HttpPost("push-by-tag")]
public IResultModel PushByTag([FromBody] PushByTagRequest request)
{
var result = _targetedService.PushByCustomerType(
request.Tag,
request.Message);
if (result.IsResultOK())
{
return ResultModel.Success(new
{
msgId = result.MsgId,
sendNo = result.SendNo
});
}
else
{
return ResultModel.Error($"推送失败:{result.Message}");
}
}
/// <summary>
/// 推送订单通知
/// </summary>
[HttpPost("push-order")]
public IResultModel PushOrder([FromBody] PushOrderRequest request)
{
var result = _orderService.PushOrderStatusChange(
request.UserAlias,
request.OrderNo,
request.Status,
request.Link);
if (result.IsResultOK())
{
return ResultModel.Success(new
{
msgId = result.MsgId
});
}
else
{
return ResultModel.Error($"推送失败:{result.Message}");
}
}
/// <summary>
/// 查询推送状态
/// </summary>
[HttpGet("query-status/{msgId}")]
public IResultModel QueryStatus(string msgId)
{
var result = _statusService.QueryPushStatus(msgId);
return ResultModel.Success(new
{
msgId = result.MsgId,
sendNo = result.SendNo,
message = result.Message,
isSuccess = result.IsResultOK()
});
}
}
public class PushAllRequest
{
public string Message { get; set; }
public string Link { get; set; }
}
public class PushByTagRequest
{
public string Tag { get; set; }
public string Message { get; set; }
}
public class PushOrderRequest
{
public string UserAlias { get; set; }
public string OrderNo { get; set; }
public string Status { get; set; }
public string Link { get; set; }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# 🔧 第三方服务对比
# Third.JPush(极光推送)
特点:
- ✅ 国内覆盖率高
- ✅ 支持 Android/iOS 双平台
- ✅ 支持多种推送方式(全部/标签/别名/设备)
- ✅ 实时推送到达率高
- ✅ 完善的统计功能
- ⚠️ 需要实名认证
- ⚠️ 免费版有推送限制
适用场景:
- APP 消息推送
- 订单通知
- 活动通知
- 系统通知
推送方式:
| 方式 | 说明 | 适用场景 |
|---|---|---|
| PushAll | 推送全部用户 | 系统公告、活动通知 |
| PushByTag | 按标签推送 | 客户类型定向、性别定向 |
| PushByAlias | 按别名推送 | 个人通知、订单通知 |
| PushByRegistration | 按设备推送 | 设备相关通知 |
# Third.WPSWebOffice(WPS 在线文档)
特点:
- ✅ 支持多种 Office 格式
- ✅ 在线预览和编辑
- ✅ 支持水印功能
- ✅ 支持权限控制
- ⚠️ 需要 WPS 账号
- ⚠️ 企业版需要付费
适用场景:
- 文档在线预览
- 在线协作编辑
- 企业文档管理
# Third.Spire.Office(Spire.Office)
特点:
- ✅ 支持 Office 文档处理
- ✅ 无需安装 Office
- ✅ 支持多种格式转换
- ⚠️ 商业授权
适用场景:
- 文档格式转换
- 文档生成
- 报表导出
# 💡 最佳实践
# 1. 推送频率控制
public class RateLimitedPushService
{
private readonly IJiguangService _jiguangService;
private readonly JPushConfig _jpushConfig;
private readonly IMemoryCache _cache;
public RateLimitedPushService(
IJiguangService jiguangService,
IOptions<JPushConfig> jpushConfig,
IMemoryCache cache)
{
_jiguangService = jiguangService;
_jpushConfig = jpushConfig.Value;
_cache = cache;
}
/// <summary>
/// 带频率限制的推送
/// </summary>
public MessageResult PushWithRateLimit(
string userAlias,
string message,
string type)
{
var rateLimitKey = $"push_rate_{userAlias}_{type}";
// 检查频率限制(同一类型消息 1 分钟内只能推送 1 次)
if (_cache.TryGetValue(rateLimitKey, out _))
{
throw new PushRateLimitException(
"推送过于频繁,请稍后再试");
}
var result = _jiguangService.Push(
_jpushConfig,
userAlias,
message,
"通知",
null);
if (result.IsResultOK())
{
// 设置频率限制(1 分钟)
_cache.Set(rateLimitKey, true, TimeSpan.FromMinutes(1));
}
return result;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 2. 推送日志记录
public class PushLogService
{
private readonly ILogger<PushLogService> _logger;
public PushLogService(ILogger<PushLogService> logger)
{
_logger = logger;
}
public void LogPushSent(
string type,
string target,
string message,
MessageResult result,
string businessType = null,
string businessId = null)
{
_logger.LogInformation(
"推送发送 - 类型:{Type}, 目标:{Target}, 业务类型:{BizType}, 业务 ID: {BizId}, 结果:{SendNo}, 消息:{Message}, MsgId: {MsgId}",
type,
target,
businessType,
businessId,
result.SendNo,
result.Message,
result.MsgId);
}
public void LogPushFailed(
string type,
string target,
string message,
Exception ex,
string businessType = null,
string businessId = null)
{
_logger.LogError(
ex,
"推送发送失败 - 类型:{Type}, 目标:{Target}, 业务类型:{BizType}, 业务 ID: {BizId}, 消息:{Message}",
type,
target,
businessType,
businessId,
message);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 3. 推送模板管理
public class PushTemplateService
{
private readonly Dictionary<string, PushTemplate> _templates;
public PushTemplateService()
{
_templates = new Dictionary<string, PushTemplate>
{
["ORDER_CREATED"] = new PushTemplate
{
Title = "订单通知",
Content = "您的订单${orderNo}已创建",
Link = "/order/${orderNo}"
},
["ORDER_SHIPPED"] = new PushTemplate
{
Title = "物流通知",
Content = "您的订单${orderNo}已发货",
Link = "/order/${orderNo}/tracking"
},
["PROMOTION"] = new PushTemplate
{
Title = "活动通知",
Content = "${activityName}正在进行中",
Link = "/activity/${activityId}"
}
};
}
public PushTemplate GetTemplate(string templateKey)
{
if (!_templates.ContainsKey(templateKey))
throw new TemplateNotFoundException(
$"模板不存在:{templateKey}");
return _templates[templateKey];
}
public string RenderContent(string templateKey, Dictionary<string, string> data)
{
var template = GetTemplate(templateKey);
var content = template.Content;
foreach (var kvp in data)
{
content = content.Replace($"${{{kvp.Key}}}", kvp.Value);
}
return content;
}
}
public class PushTemplate
{
public string Title { get; set; }
public string Content { get; set; }
public string Link { get; set; }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 🔍 常见问题
# Q1: 推送失败?
检查清单:
- ✅ 确认 AppId 和 AppSecret 正确
- ✅ 确认设备已注册到极光
- ✅ 确认推送目标(标签/别名)存在
- ✅ 查看错误信息和请求内容
- ✅ 确认账户余额充足
常见错误:
SendNo != "0"- 推送失败Invalid audience- 推送目标无效Missing appkey- 配置错误
# Q2: 如何选择推送方式?
选择建议:
| 场景 | 推荐方式 | 说明 |
|---|---|---|
| 系统公告 | PushAll | 推送给全部用户 |
| 活动通知 | PushByTag | 按客户类型定向 |
| 订单通知 | PushByAlias | 按用户别名推送 |
| 设备通知 | PushByRegistration | 按设备编号推送 |
# Q3: 如何处理推送回执?
解决方案:
// 极光推送回执需要通过极光后台查询
public class PushReceiptService
{
private readonly IJiguangService _jiguangService;
private readonly JPushConfig _jpushConfig;
public async Task<PushReceipt> GetReceiptAsync(string msgId)
{
var result = _jiguangService.GetMessageStatus(
_jpushConfig,
msgId);
return new PushReceipt
{
MsgId = msgId,
SendNo = result.SendNo,
IsSuccess = result.IsResultOK(),
Message = result.Message,
ReceivedAt = DateTime.Now
};
}
}
public class PushReceipt
{
public string MsgId { get; set; }
public string SendNo { get; set; }
public bool IsSuccess { get; set; }
public string Message { get; set; }
public DateTime ReceivedAt { get; set; }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 📚 相关文档
# 🔗 参考链接
- 源代码 (opens new window) -
src/Framework/Third - 极光推送文档 (opens new window)
- WPS Web Office 文档 (opens new window)
最后更新: 2024-09-20
← 短信 (21_SMS) 开发环境 →