# iOS远程推送功能实施计划 ## 项目概述 本文档详细描述了在现有NestJS项目中实现iOS远程推送功能的完整实施计划。该功能将使用Apple官方APNs服务,通过@parse/node-apn库与Apple推送服务进行通信。 ## 技术选型 ### 核心技术栈 - **推送服务**: Apple官方APNs (Apple Push Notification service) - **Node.js库**: @parse/node-apn (Trust Score: 9.8,支持HTTP/2) - **认证方式**: Token-based authentication (推荐) - **数据库**: MySQL (与现有项目保持一致) ### 依赖包 ```json { "@parse/node-apn": "^5.0.0", "uuid": "^11.1.0" // 已存在 } ``` ## 实施阶段 ### 第一阶段:基础设施搭建 1. **创建推送模块结构** - 创建`src/push-notifications/`目录 - 设置模块、控制器、服务的基础结构 2. **数据库设计与实现** - 创建推送令牌表 (t_user_push_tokens) - 创建推送消息表 (t_push_messages) - 创建推送模板表 (t_push_templates) - 编写数据库迁移脚本 3. **APNs连接配置** - 配置APNs认证信息 - 实现APNs Provider服务 - 设置连接池和错误处理 ### 第二阶段:核心功能实现 1. **推送令牌管理** - 实现设备令牌注册/更新/注销 - 令牌有效性验证 - 无效令牌清理机制 2. **推送消息发送** - 实现单个推送发送 - 实现批量推送发送 - 实现静默推送发送 3. **推送模板系统** - 模板创建/更新/删除 - 模板渲染引擎 - 动态数据绑定 ### 第三阶段:API接口开发 1. **推送令牌管理API** - POST /api/push-notifications/register-token - PUT /api/push-notifications/update-token - DELETE /api/push-notifications/unregister-token 2. **推送消息发送API** - POST /api/push-notifications/send - POST /api/push-notifications/send-by-template - POST /api/push-notifications/send-batch 3. **推送模板管理API** - GET /api/push-notifications/templates - POST /api/push-notifications/templates - PUT /api/push-notifications/templates/:id - DELETE /api/push-notifications/templates/:id ### 第四阶段:优化与监控 1. **性能优化** - 连接池管理 - 批量处理优化 - 缓存策略实现 2. **错误处理与重试** - APNs错误分类处理 - 指数退避重试机制 - 无效令牌自动清理 3. **日志与监控** - 推送状态日志记录 - 性能指标监控 - 错误率统计 ## 文件结构 ``` src/push-notifications/ ├── push-notifications.module.ts ├── push-notifications.controller.ts ├── push-notifications.service.ts ├── apns.provider.ts ├── push-token.service.ts ├── push-template.service.ts ├── push-message.service.ts ├── models/ │ ├── user-push-token.model.ts │ ├── push-message.model.ts │ └── push-template.model.ts ├── dto/ │ ├── register-device-token.dto.ts │ ├── update-device-token.dto.ts │ ├── send-push-notification.dto.ts │ ├── send-push-by-template.dto.ts │ ├── create-push-template.dto.ts │ ├── update-push-template.dto.ts │ └── push-response.dto.ts ├── interfaces/ │ ├── push-notification.interface.ts │ ├── apns-config.interface.ts │ └── push-stats.interface.ts └── enums/ ├── device-type.enum.ts ├── push-type.enum.ts └── push-message-status.enum.ts ``` ## 环境配置 ### 环境变量 ```bash # APNs配置 APNS_KEY_ID=your_key_id APNS_TEAM_ID=your_team_id APNS_KEY_PATH=path/to/APNsAuthKey_XXXXXXXXXX.p8 APNS_BUNDLE_ID=com.yourcompany.yourapp APNS_ENVIRONMENT=production # or sandbox # 推送服务配置 PUSH_RETRY_LIMIT=3 PUSH_REQUEST_TIMEOUT=5000 PUSH_HEARTBEAT=60000 PUSH_BATCH_SIZE=100 ``` ### APNs认证文件 - 需要从Apple开发者账号下载.p8格式的私钥文件 - 将私钥文件安全地存储在服务器上 ## 数据库表结构 ### 推送令牌表 (t_user_push_tokens) ```sql CREATE TABLE t_user_push_tokens ( id VARCHAR(36) PRIMARY KEY DEFAULT (UUID()), user_id VARCHAR(255) NOT NULL, device_token VARCHAR(255) NOT NULL, device_type ENUM('IOS', 'ANDROID') NOT NULL DEFAULT 'IOS', app_version VARCHAR(50), os_version VARCHAR(50), device_name VARCHAR(255), is_active BOOLEAN DEFAULT TRUE, last_used_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_user_id (user_id), INDEX idx_device_token (device_token), INDEX idx_user_device (user_id, device_token), UNIQUE KEY uk_user_device_token (user_id, device_token) ); ``` ### 推送消息表 (t_push_messages) ```sql CREATE TABLE t_push_messages ( id VARCHAR(36) PRIMARY KEY DEFAULT (UUID()), user_id VARCHAR(255) NOT NULL, device_token VARCHAR(255) NOT NULL, message_type VARCHAR(50) NOT NULL, title VARCHAR(255), body TEXT, payload JSON, push_type ENUM('ALERT', 'BACKGROUND', 'VOIP', 'LIVEACTIVITY') DEFAULT 'ALERT', priority TINYINT DEFAULT 10, expiry DATETIME, collapse_id VARCHAR(64), status ENUM('PENDING', 'SENT', 'FAILED', 'EXPIRED') DEFAULT 'PENDING', apns_response JSON, error_message TEXT, sent_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_user_id (user_id), INDEX idx_status (status), INDEX idx_created_at (created_at), INDEX idx_message_type (message_type) ); ``` ### 推送模板表 (t_push_templates) ```sql CREATE TABLE t_push_templates ( id VARCHAR(36) PRIMARY KEY DEFAULT (UUID()), template_key VARCHAR(100) NOT NULL UNIQUE, title VARCHAR(255) NOT NULL, body TEXT NOT NULL, payload_template JSON, push_type ENUM('ALERT', 'BACKGROUND', 'VOIP', 'LIVEACTIVITY') DEFAULT 'ALERT', priority TINYINT DEFAULT 10, is_active BOOLEAN DEFAULT TRUE, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_template_key (template_key), INDEX idx_is_active (is_active) ); ``` ## 使用示例 ### 1. 注册设备令牌 ```typescript // iOS客户端获取设备令牌后,调用此API POST /api/push-notifications/register-token { "deviceToken": "a9d0ed10e9cfd022a61cb08753f49c5a0b0dfb383697bf9f9d750a1003da19c7", "deviceType": "IOS", "appVersion": "1.0.0", "osVersion": "iOS 15.0", "deviceName": "iPhone 13" } ``` ### 2. 发送推送通知 ```typescript // 在业务服务中调用推送服务 await this.pushNotificationsService.sendNotification({ userIds: ['user_123'], title: '训练提醒', body: '您今天的普拉提训练还未完成,快来打卡吧!', payload: { type: 'training_reminder', trainingId: 'training_123' } }); ``` ### 3. 使用模板发送推送 ```typescript // 使用预定义模板发送推送 await this.pushNotificationsService.sendNotificationByTemplate( 'user_123', 'training_reminder', { userName: '张三', trainingName: '核心力量训练' } ); ``` ## 预期收益 1. **用户体验提升**: 及时推送训练提醒、饮食记录等重要信息 2. **用户粘性增强**: 通过个性化推送提高用户活跃度 3. **业务目标达成**: 支持各种业务场景的推送需求 4. **技术架构完善**: 建立可扩展的推送服务架构 ## 风险评估 ### 技术风险 - **APNs连接稳定性**: 通过连接池和重试机制降低风险 - **推送令牌管理**: 实现自动清理和验证机制 - **性能瓶颈**: 通过批量处理和缓存优化解决 ### 业务风险 - **用户隐私**: 严格遵守数据保护法规 - **推送频率**: 实现推送频率限制避免骚扰用户 - **内容审核**: 建立推送内容审核机制 ## 后续扩展 1. **多平台支持**: 扩展Android推送功能 2. **推送策略**: 实现智能推送时机和内容优化 3. **数据分析**: 推送效果分析和用户行为追踪 4. **A/B测试**: 推送内容和策略的A/B测试功能 ## 总结 本实施计划提供了一个完整的iOS远程推送功能解决方案,包括技术选型、架构设计、实施步骤和使用示例。该方案具有良好的可扩展性和维护性,能够满足当前业务需求并为未来扩展留有空间。 实施完成后,您将拥有一个功能完整、性能优良的推送服务系统,可以通过简单的API调用来发送各种类型的推送通知,提升用户体验和业务指标。