For the complete documentation index, see llms.txt. This page is also available as Markdown.

Financial address resolver

Design & Implementation

Part of writing a connector — for the end-to-end flow (implement the interface → extend the published Bridge Docker image → configure → deploy) see How to write your own connector.

Module Information

  • Module Name: openg2p-g2p-bridge-mapper-connectors

  • Location: /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.
        """
        pass

Data 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

  1. SPARMapperClient: HTTP async client for SPAR Mapper API communication

  2. Request Conversion: Maps bridge format to SPAR format

  3. Response Conversion: Maps SPAR format back to bridge format

  4. 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

  1. Async/Await Pattern: Uses async def and await for non-blocking I/O

  2. Format Translation: Converts between bridge and SPAR data formats

  3. Transaction IDs: Generates unique transaction and request IDs using timestamps

  4. Error Handling: Returns None on any exception (logs error details)

  5. Graceful Degradation: Exception returns None rather than raising

  6. 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

Parameter
Default Value
Purpose

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 keys

  • Headers: Content-Type application/json, optional Signature header

  • Error Handling: raise_for_status() converts 4xx/5xx to HTTPStatusError

  • Context 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

  1. HTTP Errors: SPARMapperClient raises BaseAppException with HTTP status code

  2. JSON Parsing Errors: SPARMapperClient raises BaseAppException with code "500"

  3. Request Conversion Errors: SPARMapper catches and logs, returns None

  4. Response Conversion Errors: SPARMapper catches and logs, returns None

  5. 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

  1. Async-Required: The resolve method is async; must be called with await and in async context

  2. Generator-Based IDs: Uses current timestamp for transaction and request IDs (not cryptographically unique)

  3. Scope Fixed to Details: Always requests ResolveScope.details; no parameter to change scope

  4. Empty FA on Request: Sends empty string for fa in request; SPAR fills this in response

  5. Locale Fixed to English: Always uses "en" locale; no parameter to change

  6. JWT Signing Optional: API signature only added if spar_mapper_api_sign_enabled is True

  7. Per-Request Client: Creates new httpx.AsyncClient for each request (avoids Celery fork worker issues)

  8. Crypto Helper: Uses cached_property to lazily initialize CryptoHelper component


Performance Considerations

  1. Async I/O: Non-blocking HTTP request allows concurrent execution of multiple mapper calls

  2. Single HTTP Request: All beneficiary IDs resolved in one POST request (not batched separately)

  3. Response Parsing: Uses Pydantic validation for type safety

  4. No Caching: Every resolve call hits the SPAR Mapper API (no local cache)

  5. Timeout: 30-second timeout prevents indefinite hangs


Limitations/Considerations

  1. Beneficiary IDs converted to strings; no validation of ID format

  2. No batch size limits; large lists of IDs sent in single request

  3. Scope and locale are hardcoded; no flexibility in request parameters

  4. Returns None on any error; caller cannot distinguish different failure modes

  5. No retry logic in mapper implementation; Celery task retries handle failures

  6. FA structure varies by provider; no validation or transformation applied

  7. Account provider info optional in response; name may be None

  8. No support for multiple locales despite locale parameter

  9. SPAR Mapper endpoint URL must be accessible; no fallback mechanisms

  10. JWT signing uses crypto helper component; requires proper configuration if enabled

Last updated

Was this helpful?