Successfully implemented a comprehensive email and push notification service for payment receipts in the PayD application. The service integrates with email providers (Resend/SendGrid) and triggers notifications from a queue worker after on-chain transaction confirmation.
- Created migration
024_create_notifications.sqlwith:notificationstable for tracking email and push notificationsnotification_configstable for organization-specific settingspush_tokenstable for managing device push tokens- Added
localecolumn toemployeestable - Created indexes for query optimization
- Added triggers for
updated_atcolumns
- Extended
backend/src/config/queue.tswith:NOTIFICATION_QUEUE_NAMEconstantnotificationQueueConfigwith retry and backoff settings- Job retention policies (24h for completed, 7 days for failed)
- Created
IEmailProviderinterface with standard email operations - Implemented
ResendEmailProviderwith:- HTTPS API integration
- Error handling and logging
- Email redaction for privacy
- Implemented
SendGridEmailProviderwith:- HTTPS API integration
- Error handling and logging
- Email redaction for privacy
- Created
EmailProviderFactoryfor provider instantiation
- Implemented
TemplateRendererclass with:- HTML and plain text template rendering
- HTML escaping for XSS prevention
- Currency formatting with locale support
- Date/time formatting with locale support
- Fallback logic for rendering errors
- Locale-based template selection
- Created English email templates:
payment-notification.en.html(styled HTML)payment-notification.en.txt(plain text)
- Implemented
NotificationConfigServicewith:- Organization-specific configuration retrieval
- Configuration updates with validation
- Default configuration fallback
- Email provider validation
- Implemented
NotificationTrackingServicewith:- Email delivery tracking (sent/failed)
- Push notification tracking (sent/failed)
- Notification history queries with pagination
- Transaction-based notification lookup
- Comprehensive error logging
- Implemented
PushNotificationServicewith:- Stub send method (logs notification details)
- Token registration and removal
- Database operations for push_tokens table
- Ready for future integration with FCM/APNs
- Implemented
NotificationServicewith:- Payment notification orchestration
- Email and push notification sending
- Employee and organization data retrieval
- Email provider initialization
- Error handling with isolation (push failures don't fail email)
- Sensitive data redaction in logs
- Integration with all sub-services
- Implemented
NotificationQueueServicewith:- Job enqueuing with retry configuration
- Job status retrieval
- Queue connection management
- Error handling and logging
- Implemented
NotificationWorkerwith:- Job processing with retry logic
- Exponential backoff (3 attempts, 5s initial delay)
- Comprehensive error logging
- Integration with NotificationService
- Concurrency control (5 concurrent jobs)
- Registered worker in
backend/src/workers/index.ts
- Modified
backend/src/workers/payrollWorker.tsto:- Import NotificationQueueService
- Enqueue notification jobs after successful transactions
- Handle notification enqueuing errors gracefully
- Maintain payroll processing reliability
- Updated
backend/.env.examplewith:- Email provider configuration
- Resend and SendGrid API keys
- Email from address and name
- Notification queue settings
- Stellar explorer URL
- Updated
backend/src/config/env.tswith:- Environment variable schema validation
- Email provider enum validation
- Default values for all settings
- Created
NotificationControllerwith:getNotificationHistory- View notification historygetNotificationConfig- Get organization config (admin only)updateNotificationConfig- Update config (admin only)registerPushToken- Register device tokenremovePushToken- Remove device token- Authentication and authorization checks
- Input validation
- Created
notificationRoutes.tswith all API routes - Registered routes in
backend/src/app.tsat/api/notifications
Payment Transaction (Stellar)
↓
Payroll Worker (confirms transaction)
↓
Notification Queue (enqueues job)
↓
Notification Worker (processes job)
↓
Notification Service (orchestrates)
├→ Email Provider (Resend/SendGrid)
└→ Push Service (stub)
↓
Notification Tracking (records status)
- Asynchronous Processing: Queue-based architecture prevents blocking
- Provider Flexibility: Support for multiple email providers
- Resilience: Retry logic with exponential backoff
- Observability: Comprehensive tracking and logging
- Security: Sensitive data redaction, HTTPS transmission
- Localization: Multi-language template support
- Isolation: Push failures don't affect email delivery
backend/
├── src/
│ ├── config/
│ │ ├── queue.ts (extended)
│ │ └── env.ts (extended)
│ ├── controllers/
│ │ └── notificationController.ts (new)
│ ├── db/migrations/
│ │ └── 024_create_notifications.sql (new)
│ ├── routes/
│ │ └── notificationRoutes.ts (new)
│ ├── services/
│ │ ├── email/
│ │ │ ├── emailProvider.interface.ts (new)
│ │ │ ├── emailProviderFactory.ts (new)
│ │ │ ├── resendEmailProvider.ts (new)
│ │ │ └── sendgridEmailProvider.ts (new)
│ │ ├── notificationConfigService.ts (new)
│ │ ├── notificationQueueService.ts (new)
│ │ ├── notificationService.ts (new)
│ │ ├── notificationTrackingService.ts (new)
│ │ ├── pushNotificationService.ts (new)
│ │ └── templateRenderer.ts (new)
│ ├── templates/notifications/
│ │ ├── payment-notification.en.html (new)
│ │ └── payment-notification.en.txt (new)
│ └── workers/
│ ├── notificationWorker.ts (new)
│ ├── payrollWorker.ts (modified)
│ └── index.ts (modified)
└── .env.example (extended)
# Email Provider Configuration
EMAIL_PROVIDER=resend # or 'sendgrid'
EMAIL_FROM_ADDRESS=noreply@payd.example.com
EMAIL_FROM_NAME=PayD Payroll System
# Resend Configuration (if using Resend)
RESEND_API_KEY=re_xxxxxxxxxxxxx
# SendGrid Configuration (if using SendGrid)
SENDGRID_API_KEY=SG.xxxxxxxxxxxxx
# Stellar Explorer URL
STELLAR_EXPLORER_URL=https://stellar.expert/explorer/testnet/txGet notification history for an employee
- Query params:
employee_id,transaction_id,notification_type,status,page,limit - Auth: Required (JWT)
- Authorization: Users can view own history, admins can view all
Get organization notification configuration
- Auth: Required (JWT)
- Authorization: Admin only
Update organization notification configuration
- Body:
emailEnabled,pushEnabled,emailProvider,fromEmail,fromName,locale - Auth: Required (JWT)
- Authorization: Admin only
Register a push notification token
- Body:
token,platform(ios/android/web) - Auth: Required (JWT)
Remove a push notification token
- Body:
token - Auth: Required (JWT)
The following tasks are marked as optional in the spec and can be implemented for enhanced functionality:
- Unit Tests - Test individual services and components
- Property-Based Tests - Validate correctness properties
- Localization - Add Spanish and French templates
- Security Features - Transaction hash validation, rate limiting
- Error Handling - Circuit breaker pattern, retry wrappers
- Push Notification Enhancement - Integrate with FCM/APNs
- Integration Tests - End-to-end testing
- Monitoring - Metrics collection and structured logging
Before deploying to production:
- ✅ Run database migration
024_create_notifications.sql ⚠️ Set required environment variables (EMAIL_PROVIDER, API keys)⚠️ Configure email provider account (Resend or SendGrid)⚠️ Test email delivery with test account⚠️ Verify Redis connection for queue⚠️ Monitor notification worker logs⚠️ Set up alerts for failed notifications
-
Database Setup:
# Run migration psql -d payd_db -f backend/src/db/migrations/024_create_notifications.sql -
Environment Configuration:
# Copy and configure .env cp backend/.env.example backend/.env # Edit .env and add your email provider API key
-
Start Services:
cd backend npm install npm run dev -
Trigger a Payment:
- Process a payroll run through the existing PayD interface
- Check logs for notification job enqueuing
- Verify notification worker processes the job
- Check employee email for payment notification
-
Test API Endpoints:
# Get notification history curl -H "Authorization: Bearer YOUR_JWT" \ http://localhost:3000/api/notifications/history # Register push token curl -X POST -H "Authorization: Bearer YOUR_JWT" \ -H "Content-Type: application/json" \ -d '{"token":"test-token","platform":"web"}' \ http://localhost:3000/api/notifications/push-token
✅ Email provider integrated successfully (Resend and SendGrid) ✅ Queue-based notification trigger after transaction confirmation ✅ Branded email templates with payment details and transaction hash ✅ Push notification infrastructure (stub ready for enhancement) ✅ Comprehensive tracking and error handling ✅ API endpoints for configuration and history ✅ Security features (HTTPS, data redaction) ✅ Localization support (English templates, ready for more languages)
- The push notification service is implemented as a stub that logs notifications. To enable actual push delivery, integrate with Firebase Cloud Messaging (FCM) for Android, Apple Push Notification service (APNs) for iOS, and Web Push API for web notifications.
- Email templates are currently available in English only. Additional language templates can be added by creating
payment-notification.{locale}.htmlandpayment-notification.{locale}.txtfiles. - The notification worker processes up to 5 jobs concurrently. This can be adjusted in
backend/src/workers/notificationWorker.ts. - Failed notifications are retried 3 times with exponential backoff. This configuration is in
backend/src/config/queue.ts.