feat(push): 新增设备推送和测试功能

- 新增基于设备令牌的推送通知接口
- 添加推送测试服务,支持应用启动时自动测试
- 新增推送测试文档说明
- 更新 APNS 配置和日志记录
- 迁移至 apns2 库的 PushType 枚举
- 替换订阅密钥文件
- 添加项目规则文档
This commit is contained in:
richarjiang
2025-10-15 19:09:51 +08:00
parent 38dd740c8c
commit cc83b84c80
20 changed files with 728 additions and 37 deletions

View File

@@ -5,7 +5,9 @@ import { RegisterDeviceTokenDto } from './dto/register-device-token.dto';
import { UpdateDeviceTokenDto } from './dto/update-device-token.dto';
import { SendPushNotificationDto } from './dto/send-push-notification.dto';
import { SendPushByTemplateDto } from './dto/send-push-by-template.dto';
import { SendPushToDevicesDto } from './dto/send-push-to-devices.dto';
import { PushResponseDto, BatchPushResponseDto, RegisterTokenResponseDto, UpdateTokenResponseDto, UnregisterTokenResponseDto } from './dto/push-response.dto';
import { DevicePushResponseDto, BatchDevicePushResponseDto } from './dto/device-push-response.dto';
import { CurrentUser } from '../common/decorators/current-user.decorator';
import { AccessTokenPayload } from '../users/services/apple-auth.service';
import { JwtAuthGuard } from '../common/guards/jwt-auth.guard';
@@ -25,7 +27,7 @@ export class PushNotificationsController {
@CurrentUser() user: AccessTokenPayload,
@Body() registerTokenDto: RegisterDeviceTokenDto,
): Promise<RegisterTokenResponseDto> {
return this.pushNotificationsService.registerToken(registerTokenDto, user.sub);
return this.pushNotificationsService.registerToken(registerTokenDto, user?.sub || '');
}
@Put('update-token')
@@ -37,7 +39,7 @@ export class PushNotificationsController {
@CurrentUser() user: AccessTokenPayload,
@Body() updateTokenDto: UpdateDeviceTokenDto,
): Promise<UpdateTokenResponseDto> {
return this.pushNotificationsService.updateToken(user.sub, updateTokenDto);
return this.pushNotificationsService.updateToken(user?.sub || '', updateTokenDto);
}
@Delete('unregister-token')
@@ -48,7 +50,7 @@ export class PushNotificationsController {
@CurrentUser() user: AccessTokenPayload,
@Body() body: { deviceToken: string },
): Promise<UnregisterTokenResponseDto> {
return this.pushNotificationsService.unregisterToken(user.sub, body.deviceToken);
return this.pushNotificationsService.unregisterToken(user?.sub || '', body.deviceToken);
}
@Post('send')
@@ -90,4 +92,24 @@ export class PushNotificationsController {
): Promise<PushResponseDto> {
return this.pushNotificationsService.sendSilentNotification(body.userId, body.payload);
}
@Post('send-to-devices')
@ApiOperation({ summary: '向指定设备发送推送通知' })
@UseGuards(JwtAuthGuard)
@ApiResponse({ status: 200, description: '发送成功', type: DevicePushResponseDto })
async sendNotificationToDevices(
@Body() sendToDevicesDto: SendPushToDevicesDto,
): Promise<DevicePushResponseDto> {
return this.pushNotificationsService.sendNotificationToDevices(sendToDevicesDto);
}
@Post('send-batch-to-devices')
@ApiOperation({ summary: '批量向指定设备发送推送通知' })
@UseGuards(JwtAuthGuard)
@ApiResponse({ status: 200, description: '发送成功', type: BatchDevicePushResponseDto })
async sendBatchNotificationToDevices(
@Body() sendBatchToDevicesDto: SendPushToDevicesDto,
): Promise<BatchDevicePushResponseDto> {
return this.pushNotificationsService.sendBatchNotificationToDevices(sendBatchToDevicesDto);
}
}