forked from Shared/esg
initial commit
This commit is contained in:
628
docs/API_DOCUMENTATION.md
Normal file
628
docs/API_DOCUMENTATION.md
Normal file
@@ -0,0 +1,628 @@
|
||||
# API Documentation
|
||||
|
||||
Complete API reference for the ESG Inquiry Gateway with request/response examples.
|
||||
|
||||
## Table of Contents
|
||||
- [Authentication](#authentication)
|
||||
- [Person Inquiry](#person-inquiry)
|
||||
- [Real Estate Inquiry](#real-estate-inquiry)
|
||||
- [Shahkar Inquiry](#shahkar-inquiry)
|
||||
- [Postal Code Inquiry](#postal-code-inquiry)
|
||||
- [Sheba Inquiry](#sheba-inquiry)
|
||||
- [Error Responses](#error-responses)
|
||||
|
||||
## Base URL
|
||||
|
||||
```
|
||||
Production: https://api.example.com
|
||||
Development: http://localhost:8085
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
All API requests require authentication using one of these methods:
|
||||
|
||||
### 1. API Key (Header)
|
||||
```http
|
||||
X-API-Key: your-api-key-here
|
||||
```
|
||||
|
||||
### 2. JWT Bearer Token
|
||||
```http
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
```
|
||||
|
||||
## Person Inquiry
|
||||
|
||||
Query person information using national code and birth date.
|
||||
|
||||
### Endpoint
|
||||
```
|
||||
POST /api/inquiry/person
|
||||
```
|
||||
|
||||
### Request Headers
|
||||
```http
|
||||
Content-Type: application/json
|
||||
X-API-Key: your-api-key-here
|
||||
```
|
||||
|
||||
### Request Body
|
||||
```json
|
||||
{
|
||||
"nationalCode": "0123456789",
|
||||
"birthDate": "1370/01/01"
|
||||
}
|
||||
```
|
||||
|
||||
### Request Parameters
|
||||
|
||||
| Field | Type | Required | Description | Example |
|
||||
|-------|------|----------|-------------|---------|
|
||||
| nationalCode | string | Yes | 10-digit national identification number | "0123456789" |
|
||||
| birthDate | string | Yes | Birth date in Persian calendar (YYYY/MM/DD) | "1370/01/01" |
|
||||
|
||||
### Success Response (200 OK)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"provider": "TEJARATNOU",
|
||||
"trackingCode": "a3e23be5-3128-4bb6-9424-9b62b41d6381",
|
||||
"message": "Person inquiry completed successfully",
|
||||
"data": {
|
||||
"nationalCode": "0123456789",
|
||||
"birthDate": "1370/01/01",
|
||||
"fullName": "علی احمدی",
|
||||
"raw": {
|
||||
"success": true,
|
||||
"data": {
|
||||
"fullName": "علی احمدی",
|
||||
"fatherName": "محمد",
|
||||
"birthPlace": "تهران"
|
||||
}
|
||||
}
|
||||
},
|
||||
"duration": 1250
|
||||
}
|
||||
```
|
||||
|
||||
### Response Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| success | boolean | Whether the inquiry was successful |
|
||||
| provider | string | Provider that handled the request (HAMTA, MOALLEM, TEJARATNOU) |
|
||||
| trackingCode | string | Unique tracking code for this request |
|
||||
| message | string | Human-readable status message |
|
||||
| data | object | Inquiry result data |
|
||||
| data.nationalCode | string | Queried national code |
|
||||
| data.birthDate | string | Queried birth date |
|
||||
| data.fullName | string | Person's full name (if found) |
|
||||
| data.raw | object | Raw response from provider |
|
||||
| duration | number | Request duration in milliseconds |
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.example.com/api/inquiry/person \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: your-api-key-here" \
|
||||
-d '{
|
||||
"nationalCode": "0123456789",
|
||||
"birthDate": "1370/01/01"
|
||||
}'
|
||||
```
|
||||
|
||||
### Swagger/OpenAPI Definition
|
||||
|
||||
```yaml
|
||||
/api/inquiry/person:
|
||||
post:
|
||||
summary: Person Inquiry
|
||||
description: Query person information using national code and birth date
|
||||
tags:
|
||||
- Inquiry
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
- BearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- nationalCode
|
||||
- birthDate
|
||||
properties:
|
||||
nationalCode:
|
||||
type: string
|
||||
pattern: '^\d{10}$'
|
||||
description: 10-digit national identification number
|
||||
example: "0123456789"
|
||||
birthDate:
|
||||
type: string
|
||||
pattern: '^\d{4}/\d{2}/\d{2}$'
|
||||
description: Birth date in Persian calendar (YYYY/MM/DD)
|
||||
example: "1370/01/01"
|
||||
responses:
|
||||
'200':
|
||||
description: Successful inquiry
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PersonInquiryResponse'
|
||||
'400':
|
||||
description: Invalid request
|
||||
'401':
|
||||
description: Unauthorized
|
||||
'500':
|
||||
description: Server error
|
||||
```
|
||||
|
||||
## Real Estate Inquiry
|
||||
|
||||
Query real estate/property information.
|
||||
|
||||
### Endpoint
|
||||
```
|
||||
POST /api/inquiry/real-estate
|
||||
```
|
||||
|
||||
### Request Body
|
||||
```json
|
||||
{
|
||||
"nationalId": "5098961130",
|
||||
"postalCode": "1349689554"
|
||||
}
|
||||
```
|
||||
|
||||
### Request Parameters
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| nationalId | string | Yes | National identification number |
|
||||
| postalCode | string | Yes | Property postal code |
|
||||
|
||||
### Success Response (200 OK)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"provider": "HAMTA",
|
||||
"trackingCode": "a3e23be5-3128-4bb6-9424-9b62b41d6381",
|
||||
"message": "Real estate inquiry completed successfully",
|
||||
"data": {
|
||||
"raw": {
|
||||
"Result": {
|
||||
"Result": false,
|
||||
"ErrorMessage": null,
|
||||
"ExternalServiceResponseDuration": 114.3783
|
||||
},
|
||||
"IsSucceed": true,
|
||||
"TrackingCode": "YTNlMjNiZTUtMzEyOC00YmI2LTk0MjQtOWI2MmI0MWQ2Mzgx"
|
||||
}
|
||||
},
|
||||
"duration": 1450
|
||||
}
|
||||
```
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.example.com/api/inquiry/real-estate \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: your-api-key-here" \
|
||||
-d '{
|
||||
"nationalId": "5098961130",
|
||||
"postalCode": "1349689554"
|
||||
}'
|
||||
```
|
||||
|
||||
## Shahkar Inquiry
|
||||
|
||||
Verify mobile number ownership.
|
||||
|
||||
### Endpoint
|
||||
```
|
||||
POST /api/inquiry/shahkar
|
||||
```
|
||||
|
||||
### Request Body
|
||||
```json
|
||||
{
|
||||
"nationalCode": "0123456789",
|
||||
"mobileNo": "09123456789"
|
||||
}
|
||||
```
|
||||
|
||||
### Request Parameters
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| nationalCode | string | Yes | 10-digit national identification number |
|
||||
| mobileNo | string | Yes | Mobile number (11 digits starting with 09) |
|
||||
|
||||
### Success Response (200 OK)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"provider": "MOALLEM",
|
||||
"trackingCode": "b4f34cf6-4239-5cc7-a535-ac73c52e7492",
|
||||
"message": "Shahkar inquiry completed successfully",
|
||||
"data": {
|
||||
"raw": {
|
||||
"nationalCode": "0123456789",
|
||||
"mobileNo": "09123456789",
|
||||
"result": "MATCH",
|
||||
"soap": "<?xml version=\"1.0\" encoding=\"utf-8\"?>..."
|
||||
}
|
||||
},
|
||||
"duration": 890
|
||||
}
|
||||
```
|
||||
|
||||
### Possible Results
|
||||
|
||||
| Result | Description |
|
||||
|--------|-------------|
|
||||
| MATCH | Mobile number belongs to the person |
|
||||
| MISMATCH | Mobile number does not belong to the person |
|
||||
| NOT_FOUND | No record found |
|
||||
| ERROR | Service error |
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.example.com/api/inquiry/shahkar \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: your-api-key-here" \
|
||||
-d '{
|
||||
"nationalCode": "0123456789",
|
||||
"mobileNo": "09123456789"
|
||||
}'
|
||||
```
|
||||
|
||||
## Postal Code Inquiry
|
||||
|
||||
Lookup address information by postal code.
|
||||
|
||||
### Endpoint
|
||||
```
|
||||
POST /api/inquiry/postal-code
|
||||
```
|
||||
|
||||
### Request Body
|
||||
```json
|
||||
{
|
||||
"postalCode": "1234567890"
|
||||
}
|
||||
```
|
||||
|
||||
### Request Parameters
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| postalCode | string | Yes | 10-digit postal code |
|
||||
|
||||
### Success Response (200 OK)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"provider": "MOALLEM",
|
||||
"trackingCode": "c5g45dg7-5340-6dd8-b646-bd84d63f8503",
|
||||
"message": "Postal code inquiry completed successfully",
|
||||
"data": {
|
||||
"raw": {
|
||||
"province": "تهران",
|
||||
"city": "تهران",
|
||||
"district": "منطقه 1",
|
||||
"street": "خیابان ولیعصر",
|
||||
"alley": "کوچه شماره 5",
|
||||
"plaque": "123"
|
||||
}
|
||||
},
|
||||
"duration": 650
|
||||
}
|
||||
```
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.example.com/api/inquiry/postal-code \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: your-api-key-here" \
|
||||
-d '{
|
||||
"postalCode": "1234567890"
|
||||
}'
|
||||
```
|
||||
|
||||
## Sheba Inquiry
|
||||
|
||||
Verify bank account (SHEBA/IBAN) information.
|
||||
|
||||
### Endpoint
|
||||
```
|
||||
POST /api/inquiry/sheba
|
||||
```
|
||||
|
||||
### Request Body
|
||||
```json
|
||||
{
|
||||
"accountOwnerType": "REAL",
|
||||
"nationalId": "0123456789",
|
||||
"shebaId": "IR123456789012345678901234"
|
||||
}
|
||||
```
|
||||
|
||||
### Request Parameters
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| accountOwnerType | string | Yes | Account owner type: "REAL" (person) or "LEGAL" (company) |
|
||||
| nationalId | string | Conditional | Required if accountOwnerType is "REAL" |
|
||||
| legalId | string | Conditional | Required if accountOwnerType is "LEGAL" |
|
||||
| shebaId | string | Yes | SHEBA/IBAN number (26 characters starting with IR) |
|
||||
|
||||
### Success Response (200 OK)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"provider": "MOALLEM",
|
||||
"trackingCode": "d6h56eh8-6451-7ee9-c757-ce95e74g9614",
|
||||
"message": "Sheba inquiry completed successfully",
|
||||
"data": {
|
||||
"raw": {
|
||||
"IsSucceed": true,
|
||||
"Result": {
|
||||
"accountOwner": "علی احمدی",
|
||||
"bankName": "بانک ملی ایران",
|
||||
"branchName": "شعبه مرکزی",
|
||||
"accountNumber": "1234567890",
|
||||
"isActive": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"duration": 1120
|
||||
}
|
||||
```
|
||||
|
||||
### cURL Example
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.example.com/api/inquiry/sheba \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: your-api-key-here" \
|
||||
-d '{
|
||||
"accountOwnerType": "REAL",
|
||||
"nationalId": "0123456789",
|
||||
"shebaId": "IR123456789012345678901234"
|
||||
}'
|
||||
```
|
||||
|
||||
## Error Responses
|
||||
|
||||
### 400 Bad Request - Invalid Input
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"provider": "GATEWAY",
|
||||
"trackingCode": "e7i67fi9-7562-8ff0-d868-df06f85h0725",
|
||||
"message": "Validation failed",
|
||||
"error": {
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "nationalCode must be a 10-digit string"
|
||||
},
|
||||
"duration": 5
|
||||
}
|
||||
```
|
||||
|
||||
### 401 Unauthorized - Missing/Invalid API Key
|
||||
|
||||
```json
|
||||
{
|
||||
"statusCode": 401,
|
||||
"message": "Unauthorized",
|
||||
"error": "Unauthorized"
|
||||
}
|
||||
```
|
||||
|
||||
### 404 Not Found - Invalid Endpoint
|
||||
|
||||
```json
|
||||
{
|
||||
"statusCode": 404,
|
||||
"message": "Cannot POST /api/inquiry/invalid",
|
||||
"error": "Not Found"
|
||||
}
|
||||
```
|
||||
|
||||
### 429 Too Many Requests - Rate Limit Exceeded
|
||||
|
||||
```json
|
||||
{
|
||||
"statusCode": 429,
|
||||
"message": "ThrottlerException: Too Many Requests"
|
||||
}
|
||||
```
|
||||
|
||||
### 500 Internal Server Error - No Providers Available
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"provider": "GATEWAY",
|
||||
"trackingCode": "f8j78gj0-8673-9gg1-e979-eg17g96i1836",
|
||||
"message": "No enabled providers configured for PERSON",
|
||||
"error": {
|
||||
"code": "NO_PROVIDERS",
|
||||
"message": "No enabled providers configured for PERSON"
|
||||
},
|
||||
"duration": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 500 Internal Server Error - Provider Service Unavailable
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"provider": "GATEWAY",
|
||||
"trackingCode": "g9k89hk1-9784-0hh2-f080-fh28h07j2947",
|
||||
"message": "TEJARATNOU service is not available",
|
||||
"error": {
|
||||
"code": "PROVIDER_SERVICE_NOT_AVAILABLE",
|
||||
"message": "TEJARATNOU service is not available",
|
||||
"providerMessage": "Connection timeout",
|
||||
"providerCode": "ETIMEDOUT"
|
||||
},
|
||||
"duration": 10500
|
||||
}
|
||||
```
|
||||
|
||||
### 500 Internal Server Error - All Providers Failed
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"provider": "GATEWAY",
|
||||
"trackingCode": "h0l90il2-0895-1ii3-g191-gi39i18k3058",
|
||||
"message": "TEJARATNOU failed: timeout; HAMTA failed: auth error; MOALLEM failed: network error",
|
||||
"error": {
|
||||
"code": "ALL_PROVIDERS_FAILED",
|
||||
"message": "TEJARATNOU failed: timeout; HAMTA failed: auth error; MOALLEM failed: network error",
|
||||
"providerMessage": "Connection timeout",
|
||||
"providerCode": "ETIMEDOUT"
|
||||
},
|
||||
"duration": 25000
|
||||
}
|
||||
```
|
||||
|
||||
## Error Codes Reference
|
||||
|
||||
| Code | Description | HTTP Status |
|
||||
|------|-------------|-------------|
|
||||
| VALIDATION_ERROR | Invalid request parameters | 400 |
|
||||
| NO_PROVIDERS | No providers configured for inquiry type | 500 |
|
||||
| PROVIDER_SERVICE_NOT_AVAILABLE | Single provider failed | 500 |
|
||||
| ALL_PROVIDERS_FAILED | All configured providers failed | 500 |
|
||||
| PROVIDER_ERROR | Generic provider error | 500 |
|
||||
| TIMEOUT | Request timeout | 500 |
|
||||
| NETWORK_ERROR | Network connectivity issue | 500 |
|
||||
| AUTH_ERROR | Authentication failed | 500 |
|
||||
| UNSUPPORTED_INQUIRY | Inquiry type not supported | 400 |
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
The API implements rate limiting to prevent abuse:
|
||||
|
||||
- **Default Limit**: 100 requests per minute per API key
|
||||
- **Window**: 60 seconds (sliding window)
|
||||
- **Response Header**: `X-RateLimit-Remaining` shows remaining requests
|
||||
|
||||
When rate limit is exceeded:
|
||||
```http
|
||||
HTTP/1.1 429 Too Many Requests
|
||||
X-RateLimit-Limit: 100
|
||||
X-RateLimit-Remaining: 0
|
||||
X-RateLimit-Reset: 1609459200
|
||||
```
|
||||
|
||||
## Response Time SLA
|
||||
|
||||
| Inquiry Type | Target Response Time | Timeout |
|
||||
|--------------|---------------------|---------|
|
||||
| Person | < 2 seconds | 10 seconds |
|
||||
| Real Estate | < 3 seconds | 10 seconds |
|
||||
| Shahkar | < 1.5 seconds | 10 seconds |
|
||||
| Postal Code | < 1 second | 10 seconds |
|
||||
| Sheba | < 2 seconds | 10 seconds |
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Always Include Tracking Code
|
||||
Store the `trackingCode` from responses for troubleshooting and support requests.
|
||||
|
||||
### 2. Handle Errors Gracefully
|
||||
Implement retry logic with exponential backoff for transient errors (5xx).
|
||||
|
||||
### 3. Validate Input Client-Side
|
||||
Validate national codes, postal codes, and mobile numbers before sending requests.
|
||||
|
||||
### 4. Use Appropriate Timeouts
|
||||
Set client-side timeouts slightly higher than API timeouts (e.g., 12 seconds).
|
||||
|
||||
### 5. Monitor Rate Limits
|
||||
Track `X-RateLimit-Remaining` header and implement client-side throttling.
|
||||
|
||||
### 6. Log All Requests
|
||||
Log request/response pairs with tracking codes for audit and debugging.
|
||||
|
||||
### 7. Secure API Keys
|
||||
- Never expose API keys in client-side code
|
||||
- Rotate keys regularly
|
||||
- Use environment variables
|
||||
- Implement key rotation without downtime
|
||||
|
||||
## Postman Collection
|
||||
|
||||
Import this collection to test all endpoints:
|
||||
|
||||
```json
|
||||
{
|
||||
"info": {
|
||||
"name": "ESG Inquiry Gateway",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||
},
|
||||
"item": [
|
||||
{
|
||||
"name": "Person Inquiry",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "X-API-Key",
|
||||
"value": "{{api_key}}"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"nationalCode\": \"0123456789\",\n \"birthDate\": \"1370/01/01\"\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{base_url}}/api/inquiry/person",
|
||||
"host": ["{{base_url}}"],
|
||||
"path": ["api", "inquiry", "person"]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"variable": [
|
||||
{
|
||||
"key": "base_url",
|
||||
"value": "http://localhost:8085"
|
||||
},
|
||||
{
|
||||
"key": "api_key",
|
||||
"value": "your-api-key-here"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
For API support:
|
||||
- **Documentation**: https://docs.example.com
|
||||
- **Status Page**: https://status.example.com
|
||||
- **Support Email**: support@example.com
|
||||
- **Emergency**: +98-21-1234-5678
|
||||
463
docs/ENVIRONMENT_CONFIGURATION.md
Normal file
463
docs/ENVIRONMENT_CONFIGURATION.md
Normal file
@@ -0,0 +1,463 @@
|
||||
# Environment Configuration Guide
|
||||
|
||||
This guide explains all environment variables used in the ESG Inquiry Gateway system.
|
||||
|
||||
## Table of Contents
|
||||
- [Application Settings](#application-settings)
|
||||
- [Database Configuration](#database-configuration)
|
||||
- [Authentication & Security](#authentication--security)
|
||||
- [Provider Configuration](#provider-configuration)
|
||||
- [Inquiry Routing](#inquiry-routing)
|
||||
- [Provider Behavior Examples](#provider-behavior-examples)
|
||||
|
||||
## Application Settings
|
||||
|
||||
### Basic Configuration
|
||||
```env
|
||||
PORT=8085 # HTTP server port
|
||||
NODE_ENV=development # Environment: development, production, test
|
||||
```
|
||||
|
||||
### OpenTelemetry (Optional)
|
||||
```env
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT=http://192.168.10.10:4318
|
||||
OTEL_SERVICE_NAME=esg
|
||||
OTEL_NODE_RESOURCE_DETECTORS=env,host,os
|
||||
```
|
||||
|
||||
## Database Configuration
|
||||
|
||||
### MongoDB
|
||||
```env
|
||||
MONGODB_URI=mongodb://localhost:27017/inquiry-gateway
|
||||
```
|
||||
|
||||
## Authentication & Security
|
||||
|
||||
### API Authentication
|
||||
```env
|
||||
API_KEY=your-secure-api-key-here # API key for external clients
|
||||
JWT_SECRET=change-me-use-long-random-string # JWT signing secret
|
||||
JWT_REFRESH_SECRET=change-me-refresh-secret # JWT refresh token secret
|
||||
JWT_ACCESS_EXPIRES_IN=15m # Access token lifetime
|
||||
JWT_REFRESH_EXPIRES_IN=7d # Refresh token lifetime
|
||||
JWT_ENABLED=true # Enable/disable JWT auth
|
||||
BCRYPT_SALT_ROUNDS=12 # Password hashing rounds
|
||||
```
|
||||
|
||||
### Rate Limiting
|
||||
```env
|
||||
THROTTLE_TTL=60 # Time window in seconds
|
||||
THROTTLE_LIMIT=100 # Max requests per window
|
||||
```
|
||||
|
||||
## Provider Configuration
|
||||
|
||||
### Understanding Provider Architecture
|
||||
|
||||
The system has **two types of components**:
|
||||
|
||||
1. **Providers** (Inquiry Handlers): HAMTA, MOALLEM, TEJARATNOU
|
||||
2. **Authentication Services**: AMITIS (used by HAMTA and MOALLEM)
|
||||
|
||||
### AMITIS Authentication Service
|
||||
|
||||
AMITIS is **not a provider** - it's an authentication service that provides tokens for HAMTA and MOALLEM.
|
||||
|
||||
```env
|
||||
# AMITIS Configuration
|
||||
AMITIS_BASE_URL=https://auth.services.centinsur.ir
|
||||
AMITIS_LOGIN_PATH=/api/security/login
|
||||
AMITIS_REFRESH_PATH=/api/security/RefreshToken
|
||||
AMITIS_TOKEN_TIME_ZONE=Asia/Tehran
|
||||
AMITIS_TIMEOUT=10000
|
||||
AMITIS_ENABLED=true
|
||||
```
|
||||
|
||||
**Token Management:**
|
||||
- Tokens refresh every 20 minutes
|
||||
- Tokens expire daily at 23:59:59 (Tehran time)
|
||||
- Automatic refresh with fallback to re-login
|
||||
|
||||
### Provider Structure
|
||||
|
||||
Each provider has:
|
||||
- **Global settings**: `ENABLED`, `TIMEOUT`, `MAX_RETRIES`
|
||||
- **Per-inquiry settings**: `URL`, `USERNAME`, `PASSWORD`, `AUTH_METHOD`
|
||||
|
||||
#### Format: `PROVIDER_INQUIRY_FIELD`
|
||||
|
||||
Example:
|
||||
```env
|
||||
HAMTA_REAL_ESTATE_URL=https://apigw.services.centinsur.ir/amlakeskanservice/amlakeskan/inquiry
|
||||
HAMTA_REAL_ESTATE_USERNAME=AmlakEskanHamta
|
||||
HAMTA_REAL_ESTATE_PASSWORD=r#Tk5!4bj
|
||||
HAMTA_REAL_ESTATE_AUTH_METHOD=AMITIS
|
||||
```
|
||||
|
||||
### Authentication Methods
|
||||
|
||||
Each inquiry can use different authentication:
|
||||
|
||||
- **`AMITIS`**: Token-based auth via AMITIS service
|
||||
- **`SOAP`**: Direct SOAP authentication (credentials in XML)
|
||||
- **`OAUTH2`**: OAuth2 flow (TejaratNou)
|
||||
- **`NONE`**: No authentication required
|
||||
|
||||
### HAMTA Provider
|
||||
|
||||
```env
|
||||
# Global Settings
|
||||
HAMTA_ENABLED=true
|
||||
HAMTA_TIMEOUT=10000
|
||||
HAMTA_MAX_RETRIES=3
|
||||
|
||||
# Person Inquiry (AMITIS auth)
|
||||
HAMTA_PERSON_URL=https://api.hamta.example.com/api/inquiry/person
|
||||
HAMTA_PERSON_USERNAME=pa6476
|
||||
HAMTA_PERSON_PASSWORD=ciiws@sabt92
|
||||
HAMTA_PERSON_AUTH_METHOD=AMITIS
|
||||
|
||||
# Real Estate Inquiry (AMITIS auth)
|
||||
HAMTA_REAL_ESTATE_URL=https://apigw.services.centinsur.ir/amlakeskanservice/amlakeskan/inquiry
|
||||
HAMTA_REAL_ESTATE_USERNAME=AmlakEskanHamta
|
||||
HAMTA_REAL_ESTATE_PASSWORD=r#Tk5!4bj
|
||||
HAMTA_REAL_ESTATE_AUTH_METHOD=AMITIS
|
||||
|
||||
# Shahkar Inquiry (SOAP auth - no AMITIS)
|
||||
HAMTA_SHAHKAR_URL=http://reinsure.centinsur.ir/shahkarinqOut
|
||||
HAMTA_SHAHKAR_USERNAME=Hamta.Shahkar
|
||||
HAMTA_SHAHKAR_PASSWORD=Y^WzP!8R5Tz
|
||||
HAMTA_SHAHKAR_AUTH_METHOD=SOAP
|
||||
|
||||
# Sheba/Sayah Inquiry (AMITIS auth)
|
||||
HAMTA_SHEBA_URL=https://api.hamta.example.com/api/inquiry/sheba
|
||||
HAMTA_SHEBA_USERNAME=Hamta.sayah
|
||||
HAMTA_SHEBA_PASSWORD=J$z07$bg
|
||||
HAMTA_SHEBA_AUTH_METHOD=AMITIS
|
||||
|
||||
# Postal Code Inquiry (AMITIS auth)
|
||||
HAMTA_POSTAL_CODE_URL=https://api.hamta.example.com/api/inquiry/postalCode
|
||||
HAMTA_POSTAL_CODE_USERNAME=
|
||||
HAMTA_POSTAL_CODE_PASSWORD=
|
||||
HAMTA_POSTAL_CODE_AUTH_METHOD=AMITIS
|
||||
|
||||
# Legal Person Inquiry (AMITIS auth)
|
||||
HAMTA_LEGAL_PERSON_URL=https://api.hamta.example.com/api/inquiry/legalPerson
|
||||
HAMTA_LEGAL_PERSON_USERNAME=SabtAsnadHamta
|
||||
HAMTA_LEGAL_PERSON_PASSWORD=HSY1f6?e@kSJ
|
||||
HAMTA_LEGAL_PERSON_AUTH_METHOD=AMITIS
|
||||
```
|
||||
|
||||
### MOALLEM Provider
|
||||
|
||||
```env
|
||||
# Global Settings
|
||||
MOALLEM_ENABLED=true
|
||||
MOALLEM_TIMEOUT=10000
|
||||
MOALLEM_MAX_RETRIES=2
|
||||
|
||||
# Person Inquiry (SOAP auth)
|
||||
MOALLEM_PERSON_URL=http://reinsure.centinsur.ir/SabtV3Out
|
||||
MOALLEM_PERSON_USERNAME=mo9635
|
||||
MOALLEM_PERSON_PASSWORD=ciiws@sabt92
|
||||
MOALLEM_PERSON_AUTH_METHOD=SOAP
|
||||
|
||||
# Postal Code Inquiry (AMITIS auth)
|
||||
MOALLEM_POSTAL_CODE_URL=https://postalcode.services.centinsur.ir/api/cisb
|
||||
MOALLEM_POSTAL_CODE_USERNAME=moallem.post
|
||||
MOALLEM_POSTAL_CODE_PASSWORD=tBUCLGfVJH
|
||||
MOALLEM_POSTAL_CODE_AUTH_METHOD=AMITIS
|
||||
|
||||
# Real Estate Inquiry (AMITIS auth)
|
||||
MOALLEM_REAL_ESTATE_URL=https://api.moallem.example.com/api/inquiry/realEstate
|
||||
MOALLEM_REAL_ESTATE_USERNAME=AmlakEskanMoalem
|
||||
MOALLEM_REAL_ESTATE_PASSWORD=AEM@123456
|
||||
MOALLEM_REAL_ESTATE_AUTH_METHOD=AMITIS
|
||||
|
||||
# Shahkar Inquiry (SOAP auth)
|
||||
MOALLEM_SHAHKAR_URL=http://reinsure.centinsur.ir/shahkarinqOut
|
||||
MOALLEM_SHAHKAR_USERNAME=ShkrMoalem1286
|
||||
MOALLEM_SHAHKAR_PASSWORD=cuYYELt9
|
||||
MOALLEM_SHAHKAR_AUTH_METHOD=SOAP
|
||||
|
||||
# Sheba/Sayah Inquiry (AMITIS auth)
|
||||
MOALLEM_SHEBA_URL=https://sayah.services.centinsur.ir/api/Cisb/TatbighServiceAsync
|
||||
MOALLEM_SHEBA_USERNAME=moallem.sayah
|
||||
MOALLEM_SHEBA_PASSWORD=BUCLGfVJH7
|
||||
MOALLEM_SHEBA_AUTH_METHOD=AMITIS
|
||||
|
||||
# Legal Person Inquiry (SOAP auth)
|
||||
MOALLEM_LEGAL_PERSON_URL=http://reinsure.centinsur.ir/SabtV3Out
|
||||
MOALLEM_LEGAL_PERSON_USERNAME=
|
||||
MOALLEM_LEGAL_PERSON_PASSWORD=
|
||||
MOALLEM_LEGAL_PERSON_AUTH_METHOD=SOAP
|
||||
```
|
||||
|
||||
### TEJARATNOU Provider
|
||||
|
||||
```env
|
||||
# Global Settings
|
||||
TEJARATNOU_ENABLED=true
|
||||
TEJARATNOU_TIMEOUT=15000
|
||||
TEJARATNOU_MAX_RETRIES=2
|
||||
|
||||
# OAuth2 Authentication
|
||||
TEJARATNOU_AUTH_URL=https://accounts.tejaratnoins.ir
|
||||
TEJARATNOU_CLIENT_ID=api-gateway
|
||||
TEJARATNOU_CLIENT_SECRET=hkld@ork123T
|
||||
TEJARATNOU_USERNAME=thirdparty-silcogroup
|
||||
TEJARATNOU_PASSWORD=FDHG87sdf787l764iuo
|
||||
|
||||
# Person Inquiry
|
||||
TEJARATNOU_PERSON_URL=https://gateway.tejaratnoins.ir/api/inquiry/person
|
||||
TEJARATNOU_PERSON_AUTH_METHOD=OAUTH2
|
||||
```
|
||||
|
||||
## Inquiry Routing
|
||||
|
||||
Routing determines which provider handles each inquiry type and whether to use fallbacks.
|
||||
|
||||
### Format
|
||||
```env
|
||||
{INQUIRY_TYPE}_DEFAULT_PROVIDER=PROVIDER_NAME
|
||||
{INQUIRY_TYPE}_FALLBACK_ENABLED=true|false
|
||||
{INQUIRY_TYPE}_FALLBACK_PROVIDERS=PROVIDER1,PROVIDER2
|
||||
```
|
||||
|
||||
### Available Inquiry Types
|
||||
- `PERSON` - Person/Civil registration inquiry
|
||||
- `REAL_ESTATE` - Real estate/property inquiry
|
||||
- `SHAHKAR` - Mobile number verification
|
||||
- `POSTAL_CODE` - Postal code lookup
|
||||
- `SHEBA` - Bank account verification
|
||||
- `LEGAL_PERSON` - Legal entity inquiry
|
||||
- `CAR_PLATE` - Vehicle plate inquiry
|
||||
|
||||
### Example Configurations
|
||||
|
||||
#### Person Inquiry (Single Provider)
|
||||
```env
|
||||
PERSON_DEFAULT_PROVIDER=TEJARATNOU
|
||||
PERSON_FALLBACK_ENABLED=false
|
||||
PERSON_FALLBACK_PROVIDERS=
|
||||
```
|
||||
**Behavior**: Only TEJARATNOU is used. If it fails, request fails.
|
||||
|
||||
#### Person Inquiry (With Fallback)
|
||||
```env
|
||||
PERSON_DEFAULT_PROVIDER=TEJARATNOU
|
||||
PERSON_FALLBACK_ENABLED=true
|
||||
PERSON_FALLBACK_PROVIDERS=HAMTA,MOALLEM
|
||||
```
|
||||
**Behavior**:
|
||||
1. Try TEJARATNOU first
|
||||
2. If fails, try HAMTA
|
||||
3. If fails, try MOALLEM
|
||||
4. If all fail, return error
|
||||
|
||||
#### Real Estate Inquiry
|
||||
```env
|
||||
REAL_ESTATE_DEFAULT_PROVIDER=HAMTA
|
||||
REAL_ESTATE_FALLBACK_ENABLED=false
|
||||
REAL_ESTATE_FALLBACK_PROVIDERS=
|
||||
```
|
||||
|
||||
#### Shahkar Inquiry
|
||||
```env
|
||||
SHAHKAR_DEFAULT_PROVIDER=MOALLEM
|
||||
SHAHKAR_FALLBACK_ENABLED=false
|
||||
SHAHKAR_FALLBACK_PROVIDERS=
|
||||
```
|
||||
|
||||
## Provider Behavior Examples
|
||||
|
||||
### Scenario 1: All Providers Enabled
|
||||
|
||||
```env
|
||||
HAMTA_ENABLED=true
|
||||
MOALLEM_ENABLED=true
|
||||
TEJARATNOU_ENABLED=true
|
||||
|
||||
PERSON_DEFAULT_PROVIDER=TEJARATNOU
|
||||
PERSON_FALLBACK_ENABLED=false
|
||||
```
|
||||
|
||||
**Result**: Only TEJARATNOU is used for person inquiries, even though others are enabled.
|
||||
|
||||
### Scenario 2: Default Provider Disabled
|
||||
|
||||
```env
|
||||
HAMTA_ENABLED=false
|
||||
MOALLEM_ENABLED=true
|
||||
TEJARATNOU_ENABLED=true
|
||||
|
||||
PERSON_DEFAULT_PROVIDER=HAMTA
|
||||
PERSON_FALLBACK_ENABLED=true
|
||||
PERSON_FALLBACK_PROVIDERS=TEJARATNOU,MOALLEM
|
||||
```
|
||||
|
||||
**Result**:
|
||||
- HAMTA is skipped (disabled)
|
||||
- TEJARATNOU is tried first (first enabled fallback)
|
||||
- MOALLEM is tried if TEJARATNOU fails
|
||||
|
||||
### Scenario 3: No Providers Available
|
||||
|
||||
```env
|
||||
HAMTA_ENABLED=false
|
||||
MOALLEM_ENABLED=false
|
||||
TEJARATNOU_ENABLED=false
|
||||
|
||||
PERSON_DEFAULT_PROVIDER=TEJARATNOU
|
||||
```
|
||||
|
||||
**Result**: API returns error:
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"provider": "GATEWAY",
|
||||
"message": "No enabled providers configured for PERSON",
|
||||
"error": {
|
||||
"code": "NO_PROVIDERS",
|
||||
"message": "No enabled providers configured for PERSON"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Scenario 4: All Providers Fail
|
||||
|
||||
```env
|
||||
HAMTA_ENABLED=true
|
||||
MOALLEM_ENABLED=true
|
||||
TEJARATNOU_ENABLED=true
|
||||
|
||||
PERSON_DEFAULT_PROVIDER=TEJARATNOU
|
||||
PERSON_FALLBACK_ENABLED=true
|
||||
PERSON_FALLBACK_PROVIDERS=HAMTA,MOALLEM
|
||||
```
|
||||
|
||||
**Result**: If all three providers fail, API returns:
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"provider": "GATEWAY",
|
||||
"message": "TEJARATNOU failed: timeout; HAMTA failed: auth error; MOALLEM failed: network error",
|
||||
"error": {
|
||||
"code": "ALL_PROVIDERS_FAILED",
|
||||
"message": "Combined error messages from all providers"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Production Recommendations
|
||||
|
||||
### High Availability Setup
|
||||
```env
|
||||
# Enable all providers
|
||||
HAMTA_ENABLED=true
|
||||
MOALLEM_ENABLED=true
|
||||
TEJARATNOU_ENABLED=true
|
||||
|
||||
# Use fallbacks for critical inquiries
|
||||
PERSON_DEFAULT_PROVIDER=TEJARATNOU
|
||||
PERSON_FALLBACK_ENABLED=true
|
||||
PERSON_FALLBACK_PROVIDERS=HAMTA,MOALLEM
|
||||
|
||||
REAL_ESTATE_DEFAULT_PROVIDER=HAMTA
|
||||
REAL_ESTATE_FALLBACK_ENABLED=true
|
||||
REAL_ESTATE_FALLBACK_PROVIDERS=MOALLEM
|
||||
```
|
||||
|
||||
### Performance-Optimized Setup
|
||||
```env
|
||||
# Enable only primary providers
|
||||
HAMTA_ENABLED=true
|
||||
MOALLEM_ENABLED=false
|
||||
TEJARATNOU_ENABLED=true
|
||||
|
||||
# No fallbacks for faster response
|
||||
PERSON_DEFAULT_PROVIDER=TEJARATNOU
|
||||
PERSON_FALLBACK_ENABLED=false
|
||||
|
||||
REAL_ESTATE_DEFAULT_PROVIDER=HAMTA
|
||||
REAL_ESTATE_FALLBACK_ENABLED=false
|
||||
```
|
||||
|
||||
### Cost-Optimized Setup
|
||||
```env
|
||||
# Enable only necessary providers
|
||||
HAMTA_ENABLED=true
|
||||
MOALLEM_ENABLED=false
|
||||
TEJARATNOU_ENABLED=false
|
||||
|
||||
# Single provider per inquiry type
|
||||
PERSON_DEFAULT_PROVIDER=HAMTA
|
||||
PERSON_FALLBACK_ENABLED=false
|
||||
|
||||
REAL_ESTATE_DEFAULT_PROVIDER=HAMTA
|
||||
REAL_ESTATE_FALLBACK_ENABLED=false
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Never commit `.env` to git** - Use `.env.example` as template
|
||||
2. **Rotate credentials regularly** - Update passwords every 90 days
|
||||
3. **Use strong secrets** - Generate random strings for JWT secrets
|
||||
4. **Limit API key distribution** - One key per client application
|
||||
5. **Enable rate limiting** - Protect against abuse
|
||||
6. **Monitor failed authentications** - Alert on repeated failures
|
||||
7. **Use HTTPS in production** - Never send credentials over HTTP
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Provider Not Working
|
||||
|
||||
1. Check if provider is enabled: `{PROVIDER}_ENABLED=true`
|
||||
2. Verify credentials are correct
|
||||
3. Check if inquiry type is configured for that provider
|
||||
4. Verify network connectivity to provider URL
|
||||
5. Check logs for authentication errors
|
||||
|
||||
### No Providers Available Error
|
||||
|
||||
1. Verify at least one provider is enabled
|
||||
2. Check `{INQUIRY}_DEFAULT_PROVIDER` is set correctly
|
||||
3. Ensure the default provider supports the inquiry type
|
||||
4. Verify provider credentials are configured
|
||||
|
||||
### Authentication Failures
|
||||
|
||||
1. Check AMITIS service is enabled and reachable
|
||||
2. Verify credentials in `{PROVIDER}_{INQUIRY}_USERNAME/PASSWORD`
|
||||
3. Check if tokens are expiring (should auto-refresh)
|
||||
4. Verify system time is correct (affects token expiration)
|
||||
|
||||
### Performance Issues
|
||||
|
||||
1. Reduce `MAX_RETRIES` for faster failures
|
||||
2. Decrease `TIMEOUT` values
|
||||
3. Disable fallbacks if not needed
|
||||
4. Enable only required providers
|
||||
5. Check network latency to provider services
|
||||
|
||||
## Migration from Old Format
|
||||
|
||||
### Old Format (Deprecated)
|
||||
```env
|
||||
AMITIS_HAMTA_PERSON_USERNAME=pa6476
|
||||
AMITIS_HAMTA_PERSON_PASSWORD=ciiws@sabt92
|
||||
```
|
||||
|
||||
### New Format (Current)
|
||||
```env
|
||||
HAMTA_PERSON_USERNAME=pa6476
|
||||
HAMTA_PERSON_PASSWORD=ciiws@sabt92
|
||||
HAMTA_PERSON_AUTH_METHOD=AMITIS
|
||||
```
|
||||
|
||||
**Key Changes:**
|
||||
- Removed `AMITIS_` prefix from provider credentials
|
||||
- Added `AUTH_METHOD` to specify authentication type
|
||||
- Added per-inquiry `URL` configuration
|
||||
- AMITIS is now a separate authentication service, not a provider
|
||||
Reference in New Issue
Block a user