Financial address resolver
Design & Implementation
Module Information
Module Name:
openg2p-g2p-bridge-mapper-connectorsLocation:
/openg2p-g2p-bridge-mapper-connectors/Primary Implementation:
SPARMapper
Interface Definition
File: interface/mapper_interface.py
class MapperInterface(BaseService):
async def resolve(self, resolve_request: ResolveRequest) -> ResolveResponse | None:
"""
Resolve the given request from Mapper and return the Response.
"""
passData Models
File: schemas/resolve_schema.py
class ResolveRequest(BaseModel):
beneficiary_ids: List[str]
class ResolveResult(BaseModel):
id: Optional[str] = None
fa: Optional[dict] = None
name: Optional[str] = None
status: Optional[str] = None
status_reason_code: Optional[str] = None
class ResolveResponse(BaseModel):
results: List[ResolveResult]Method Parameters
resolve_request (ResolveRequest): Request object containing:
beneficiary_ids: List of strings - IDs of beneficiaries to resolve (typically disbursement IDs)
Return Value
ResolveResponse | None: Response containing list of ResolveResult objects, or None if request fails
Response Structure
Reference Implementation: SPARMapper
File: implementations/spar_mapper.py
Key Components
SPARMapperClient: HTTP async client for SPAR Mapper API communication
Request Conversion: Maps bridge format to SPAR format
Response Conversion: Maps SPAR format back to bridge format
Async Processing: Uses async/await for non-blocking I/O
Algorithm
Request Conversion Detail
The _convert_to_spar_request method transforms the bridge ResolveRequest into SPAR format:
Response Conversion Detail
The _convert_from_spar_response method transforms SPAR response back to bridge format:
Key Characteristics
Async/Await Pattern: Uses
async defandawaitfor non-blocking I/OFormat Translation: Converts between bridge and SPAR data formats
Transaction IDs: Generates unique transaction and request IDs using timestamps
Error Handling: Returns None on any exception (logs error details)
Graceful Degradation: Exception returns None rather than raising
Logging: Uses logger name "spar_mapper_impl"
INFO: Request received, SPAR conversion details, response received
DEBUG: Per-result conversion details
ERROR: Exception with full stack trace
SPARMapperClient
File: client/spar_mapper_client.py
Async HTTP Client
Algorithm
Configuration
File: config.py
Configuration uses Pydantic Settings with environment variable prefix g2p_bridge_mapper_connectors_:
Configuration Parameters
spar_mapper_url
http://localhost:8080/mapper/resolve
SPAR Mapper API endpoint URL
spar_mapper_api_sign_enabled
False
Enable JWT signature verification
spar_mapper_api_sign_crypto_helper_name
spar_mapper_crypto
Crypto helper component name for JWT
HTTP Client Details
Library:
httpx(async HTTP client)Timeout: 30 seconds
Method: POST
Serialization:
orjson.dumps()with sorted keysHeaders: Content-Type application/json, optional Signature header
Error Handling:
raise_for_status()converts 4xx/5xx to HTTPStatusErrorContext Manager: Uses
async with httpx.AsyncClient(...)for resource cleanup
Factory Pattern
File: factory/mapper_factory.py
SPAR Models Integration
The implementation uses models from openg2p_spar_models:
SPAR Request Structure
SparResolveRequest: Top-level request with request_header and request_body
G2PRequestHeader: Sender information and request metadata
ResolveRequestBody: Contains request payload
ResolveRequestPayload: Contains list of SingleResolveRequest
SingleResolveRequest: Individual beneficiary resolution request with id, fa, scope, locale
ResolveScope: Enum with values like
details
SPAR Response Structure
SparResolveResponse: Top-level response with response_header and response_body
ResolveResponsePayload: Contains list of SingleResolveResponse (results)
SingleResolveResponse: Individual result with id, fa, status, status_reason_code, account_provider_info
AccountProviderInfo: Contains name and other provider details
Data Flow Diagram
Logging
All logging uses logger name: spar_mapper_impl
INFO: Request received with count of IDs
INFO: Disbursement IDs being processed
INFO: SPAR request conversion details with transaction_id
INFO: Request completed successfully
INFO: Response status and transaction ID
INFO: Number of resolve results returned
DEBUG: Per-result conversion details (id, fa, name, status, status_reason)
ERROR: Exception with full stack trace
SPARMapperClient uses logger: spar_mapper_client
INFO: Request being sent to URL
DEBUG: Request payload
INFO: Response received with text
INFO: Response status and result count
EXCEPTION: HTTP and unknown errors
Integration Pattern
Error Handling
HTTP Errors: SPARMapperClient raises BaseAppException with HTTP status code
JSON Parsing Errors: SPARMapperClient raises BaseAppException with code "500"
Request Conversion Errors: SPARMapper catches and logs, returns None
Response Conversion Errors: SPARMapper catches and logs, returns None
Any Exception: SPARMapper returns None and logs full stack trace
No exceptions propagate from SPARMapper to caller; always check for None response.
Key Implementation Notes
Async-Required: The resolve method is async; must be called with
awaitand in async contextGenerator-Based IDs: Uses current timestamp for transaction and request IDs (not cryptographically unique)
Scope Fixed to Details: Always requests ResolveScope.details; no parameter to change scope
Empty FA on Request: Sends empty string for
fain request; SPAR fills this in responseLocale Fixed to English: Always uses "en" locale; no parameter to change
JWT Signing Optional: API signature only added if
spar_mapper_api_sign_enabledis TruePer-Request Client: Creates new httpx.AsyncClient for each request (avoids Celery fork worker issues)
Crypto Helper: Uses cached_property to lazily initialize CryptoHelper component
Performance Considerations
Async I/O: Non-blocking HTTP request allows concurrent execution of multiple mapper calls
Single HTTP Request: All beneficiary IDs resolved in one POST request (not batched separately)
Response Parsing: Uses Pydantic validation for type safety
No Caching: Every resolve call hits the SPAR Mapper API (no local cache)
Timeout: 30-second timeout prevents indefinite hangs
Limitations/Considerations
Beneficiary IDs converted to strings; no validation of ID format
No batch size limits; large lists of IDs sent in single request
Scope and locale are hardcoded; no flexibility in request parameters
Returns None on any error; caller cannot distinguish different failure modes
No retry logic in mapper implementation; Celery task retries handle failures
FA structure varies by provider; no validation or transformation applied
Account provider info optional in response; name may be None
No support for multiple locales despite locale parameter
SPAR Mapper endpoint URL must be accessible; no fallback mechanisms
JWT signing uses crypto helper component; requires proper configuration if enabled
Last updated
Was this helpful?