self-serve-integration-service
v1.0.0
Published
Self-Serve Integration Service for managing multiple funder integrations including REST APIs, SOAP APIs, and UI automation
Downloads
13
Maintainers
Readme
Self-Serve Integration Service
A comprehensive integration service that provides a unified API for multiple vehicle finance funders including LEX, ALPHABET, and future funders.
🚀 Features
- Multi-Funder Support: Unified API for LEX, ALPHABET, and extensible for additional funders
- Environment Support: Both SANDBOX and LIVE environments for each funder
- Common Request Structure: Standardized request/response format across all funders
- 🔁 Dynamic Retry Mechanism: Configurable retry logic with exponential backoff for all funder API calls
- Comprehensive Logging: Full integration logging and monitoring
- Database Persistence: Complete quote and proposal data storage
- Customer Management: Automatic customer and vehicle data management
- Proposal Generation: Convert quotes to proposals with additional customer details
- JWT Authentication: Secure API access with RS256 token verification
🏗️ Architecture
Database Schema
The service uses a well-designed database schema that supports:
- Multiple Funders: Each funder has its own configuration and credentials
- Customer Management: Centralized customer data with flexible address/employment info
- Vehicle Management: Comprehensive vehicle data with funder-specific identifiers
- Quote Lifecycle: Complete quote generation, storage, and status tracking
- Proposal Management: Proposal generation and decision tracking
- Integration Logging: Full audit trail of all API interactions
Service Architecture
┌─────────────────────────────────────────────────────────────┐
│ Integration Service │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────┐ │
│ │ LEX Service │ │ Alphabet Service │ │ Future... │ │
│ │ (SANDBOX) │ │ (SANDBOX) │ │ │ │
│ │ (LIVE) │ │ (LIVE) │ │ │ │
│ └─────────────────┘ └─────────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Base Funder Service │
│ (Common functionality & logging) │
├─────────────────────────────────────────────────────────────┤
│ Database Layer (Prisma) │
│ (PostgreSQL with full schema) │
└─────────────────────────────────────────────────────────────┘📋 API Endpoints
Main Integration API
All endpoints are prefixed with /api/integration
Quote Generation
POST /api/integration/quotes/generateRequest Body:
{
"customerDetails": {
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]",
"phone": "+44 7700 900001",
"dateOfBirth": "1985-06-20",
"address": {
"line1": "123 Main Street",
"line2": "Apartment 4B",
"city": "London",
"postcode": "SW1A 1AA",
"country": "UK"
},
"employment": {
"employerName": "Tech Solutions Ltd",
"jobTitle": "Software Engineer",
"employmentType": "FULL_TIME",
"monthlyIncome": 4500
}
},
"vehicleDetails": {
"make": "BMW",
"model": "3 Series",
"variant": "320d M Sport",
"year": 2024,
"price": 38000,
"mileage": 0,
"fuelType": "DIESEL",
"transmission": "AUTOMATIC",
"capId": "12345",
"capCode": "BMW320DMS"
},
"contractDetails": {
"term": 36,
"deposit": 2500,
"annualMileage": 12000,
"quoteType": "PERSONAL_CONTRACT_HIRE",
"balloonPayment": 8000,
"maintenanceIncluded": true
},
"funderName": "LEX",
"environment": "SANDBOX",
"source": "SELF_SERVE_APP"
}Response:
{
"success": true,
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"funderName": "LEX",
"status": "GENERATED",
"monthlyPayment": 450.00,
"totalAmount": 16200.00,
"apr": 4.9,
"balloonPayment": 8000.00,
"externalQuoteId": "Q12345",
"externalReference": "LEX-2024-001",
"validUntil": "2024-12-31T23:59:59Z",
"createdAt": "2024-08-26T10:20:54.000Z",
"updatedAt": "2024-08-26T10:20:54.000Z"
},
"message": "Quote generated successfully with LEX"
}Quote Status
GET /api/integration/quotes/{quoteId}/statusProposal Generation
POST /api/integration/proposals/generateRequest Body:
{
"quoteId": "123e4567-e89b-12d3-a456-426614174000",
"additionalCustomerDetails": {
"address": {
"line1": "123 Main Street",
"city": "London",
"postcode": "SW1A 1AA"
},
"employment": {
"employerName": "Tech Solutions Ltd",
"jobTitle": "Software Engineer",
"employmentType": "FULL_TIME",
"monthlyIncome": 4500
}
},
"additionalDocuments": {
"drivingLicense": "base64-encoded-data",
"proofOfAddress": "base64-encoded-data"
}
}Proposal Status
GET /api/integration/proposals/{proposalId}/statusAvailable Funders
GET /api/integration/fundersTest Funder Connection
POST /api/integration/funders/{funderName}/testCustomer Quotes
GET /api/integration/customers/{email}/quotesCustomer Proposals
GET /api/integration/customers/{email}/proposals🔐 Authentication
The Integration Service uses JWT (JSON Web Token) authentication with RS256 algorithm for secure API access.
Authentication Flow
- Obtain JWT token from Auth Service
- Include token in Authorization header:
Authorization: Bearer <token> - Integration Service verifies token using public key
- User context is extracted and available in route handlers
Protected Routes
The following routes require authentication:
- All
/api/integration/*endpoints - All
/api/vehiclesendpoints - All
/api/customersendpoints - All
/api/quotesendpoints - All
/api/proposalsendpoints - All
/api/fundersendpoints
Public Routes
The following routes do NOT require authentication:
/health- Health check/webhooks/*- Webhook endpoints (validated via signatures)/api-docs- API documentation
Usage Example
# Get token from Auth Service (example)
TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
# Make authenticated request
curl -X POST http://localhost:3003/api/integration/quotes/generate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"customerDetails": {...},
"vehicleDetails": {...},
"contractDetails": {...}
}'JWT Configuration
Required environment variables:
# JWT Configuration (RS256 public key)
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"
JWT_ISSUER=self-serve-platform
JWT_AUDIENCE=self-serve-usersFor detailed authentication documentation, see JWT_AUTHENTICATION.md
🔁 Retry Mechanism
The Integration Service includes a robust retry mechanism for all funder API calls to handle transient failures automatically.
Features
- Exponential Backoff: Intelligent delay strategy to avoid overwhelming failing services
- Configurable: Fully customizable via environment variables
- Funder-Specific: Different retry settings per funder (LEX, Alphabet, etc.)
- Global Control: Enable/disable retries with a single flag
- Comprehensive Logging: All retry attempts tracked in IntegrationLog table
Configuration
# Global retry configuration
API_RETRY_ENABLED=true # Enable/disable retries
API_MAX_RETRIES=3 # Maximum retry attempts
API_RETRY_BASE_DELAY=1000 # Base delay in milliseconds
API_RETRY_MAX_DELAY=10000 # Maximum delay cap
API_RETRY_BACKOFF_MULTIPLIER=2 # Exponential multiplier
# Funder-specific overrides (optional)
LEX_MAX_RETRIES=3
LEX_RETRY_BASE_DELAY=1000
ALPHABET_MAX_RETRIES=5
ALPHABET_RETRY_BASE_DELAY=2000How It Works
Delay = min(BASE_DELAY × MULTIPLIER^(attempt-1), MAX_DELAY)Example with default settings (3 retries):
- Attempt 1: Immediate (0ms delay)
- Attempt 2: 1000ms delay
- Attempt 3: 2000ms delay
- Attempt 4: 4000ms delay
Total maximum time: ~7 seconds for 3 retries
Monitoring
All retry attempts are logged in the IntegrationLog table:
SELECT
operation,
status,
"retryCount",
"responseTime"
FROM "IntegrationLog"
WHERE status IN ('RETRY', 'FAILED')
ORDER BY "createdAt" DESC;For complete documentation, see:
- RETRY_MECHANISM.md - Complete guide
- RETRY_MECHANISM_SUMMARY.md - Quick reference
🔧 Configuration
Environment Variables
Copy env.example to .env and configure:
# Database
DATABASE_URL="postgresql://username:password@localhost:5432/self_serve_integration"
# LEX Configuration
LEX_APP_ID=6B7b5D1GnPG
LEX_SHARED_SECRET=5bxZBDwTQpYXIuKNzZKAZFGXQGRdtHRqOkf8Dg==
LEX_DEALER_ID_MAJOR=514244
LEX_DEALER_ID_MINOR=FLCSW7X4
LEX_JWT_EXPIRY_HOURS=24
# ALPHABET Configuration
ALPHABET_API_KEY=Egyml2M52BTKw72hB0
ALPHABET_SANDBOX_URL=https://demoservices.codeweavers.net
ALPHABET_LIVE_URL=https://services.codeweavers.netDatabase Setup
- Create Database:
createdb self_serve_integration- Run Migrations:
npx prisma migrate dev- Seed Database:
npx prisma db seed🚀 Getting Started
Prerequisites
- Node.js 18+
- PostgreSQL 13+
- npm or yarn
Installation
- Install Dependencies:
npm install- Setup Environment:
cp env.example .env
# Edit .env with your configuration- Setup Database:
npx prisma migrate dev
npx prisma db seed- Start Development Server:
npm run devThe service will be available at http://localhost:3003
Production Deployment
- Build Application:
npm run build- Run Production Server:
npm start🔌 Funder Integrations
LEX Integration
- Authentication: JWT tokens with HS256 algorithm
- Environments: SANDBOX and LIVE
- API Flow: Single API call for quote generation
- Features: Quote generation, proposal submission, status tracking
ALPHABET Integration
- Authentication: API Key (X-CW-ApiKey header)
- Environments: SANDBOX and LIVE
- API Flow: 3-step process (Vehicle Details → Finance Defaults → Calculate Quote)
- Features: Quote generation, proposal submission, status tracking
Adding New Funders
To add a new funder:
- Create Service Class:
export class NewFunderService extends BaseFunderService {
readonly funderName = 'NEW_FUNDER';
readonly supportedQuoteTypes = ['PERSONAL_CONTRACT_HIRE'];
readonly supportedProposalTypes = ['PERSONAL_CONTRACT_HIRE'];
async generateQuote(request: QuoteRequest): Promise<QuoteResponse> {
// Implementation
}
// ... other methods
}- Add to Integration Service:
// In integrationService.ts
const newFunderSandbox = new NewFunderService('SANDBOX');
const newFunderLive = new NewFunderService('LIVE');
this.funderServices.set('NEW_FUNDER_SANDBOX', newFunderSandbox);
this.funderServices.set('NEW_FUNDER_LIVE', newFunderLive);- Add Database Entry:
// In seed.ts
const newFunder = await prisma.funder.create({
data: {
name: 'NEW_FUNDER',
code: 'NEW_FUNDER',
displayName: 'New Funder',
// ... configuration
}
});📊 Monitoring & Logging
Integration Logs
All API interactions are logged to the IntegrationLog table with:
- Request/response data
- Performance metrics
- Error details
- Retry information
- Correlation IDs
Health Checks
GET /api/healthReturns service health status and funder connectivity.
Metrics
The service provides comprehensive metrics for:
- Quote generation success rates
- API response times
- Error rates by funder
- Retry statistics
🧪 Testing
Unit Tests
npm testIntegration Tests
npm run test:integrationTest Funder Connections
# Test LEX SANDBOX
curl -X POST http://localhost:3003/api/integration/funders/LEX/test \
-H "Content-Type: application/json" \
-d '{"environment": "SANDBOX"}'
# Test ALPHABET SANDBOX
curl -X POST http://localhost:3003/api/integration/funders/ALPHABET/test \
-H "Content-Type: application/json" \
-d '{"environment": "SANDBOX"}'🔒 Security
- No Credentials in Database: All credentials stored in environment variables
- JWT Token Management: Automatic token generation and refresh
- API Key Security: Secure API key handling
- Request Validation: Comprehensive input validation
- Error Handling: Secure error responses without sensitive data exposure
📈 Performance
- Retry Mechanism: Exponential backoff with configurable limits
- Connection Pooling: Efficient database connections
- Caching: Optional Redis integration for caching
- Rate Limiting: Built-in rate limiting per funder
- Monitoring: Real-time performance metrics
🤝 Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
📄 License
This project is licensed under the MIT License.
🆘 Support
For issues and questions:
- Check the logs in the
IntegrationLogtable - Review the health check endpoint
- Test individual funder connections
- Contact the development team
Built with ❤️ for the Self-Serve Application
