ABDM OPD Queue (today): - New EAtriaBridgeConnector: opdQueueFetch/opdTokenCreate/opdTokenUpdateStatus + patch() helper - New AbdmOpdQueue controller: index/list/fetchQueue/createToken/updateTokenStatus/processScannedToken - fetchQueue syncs gateway tokens into abdm_opd_tokens (local DB) and enriches with HMS patient data - processScannedToken auto-finds/creates patient_master record from ABHA scan data, marks token CALLED - New migration: abdm_opd_tokens table (gateway_token_id, source, status, patient_id, opd_id, processed_at) - New view: abdm/opd_queue.php - reception screen with auto-refresh 30s, HMS Patient column (green row when OPD registered) - Sidebar: ABDM OPD Queue nav link added - Routes: AbdmOpdQueue with abdmPermFilter ABHA Register tab (earlier this session): - New Abha controller: initiate/verifyOtp/communication/verifyCommOtp/validateAbha/card + autoCreateOrFindPatient - New views: abha/card.php, partials/abha_create_panel.php, partials/abha_otp_modal.php - Patient_V.php: ABHA Register tab with 4-method wizard (ABHA number, QR scan, facility QR, mobile OTP) Patient ABHA search fix: - Patient::search() now detects ABHA column (abha_id/abha_no/abha/abha_address) and searches by it ABDM Bridge infrastructure: - EAtriaBridgeConnector: new connector for e-atria.in ABDM bridge gateway - AbdmConnectorFactory/Interface updated - AbdmGatewaySettings controller + view - SNOMED/CSNOTK terminology service skeleton - Finance payout OPD consult views - Migration: AddAbdmPushFieldsToOpdAndPatient, CreateSnomedCoreTables - Docs: abdm/ API specs, architecture, gateway guides
9.6 KiB
9.6 KiB
Dual-Bridge Architecture Configuration Guide
Architecture Overview
HMS CI4 Queues Events
↓ Routes by event_type prefix
├─→ snomed.* events
│ ↓ POST to BRIDGE_SYNC_URL
│ https://csnotk.e-atria.in/api/bridge
│ (CSNOtk Bridge: Codes diagnosis → FHIR)
│
└─→ abdm.* events
↓ POST to ABDM_BRIDGE_URL
https://abdm-bridge.e-atria.in/api/v1/bridge
(ABDM Bridge: Routes to ABDM M1 server)
Event Type Routing Table
| Event Type | Destination | Purpose |
|---|---|---|
snomed.diagnosis.validate |
CSNOtk /api/bridge |
Validate & code diagnosis with SNOMED CT |
snomed.medication.validate |
CSNOtk /api/bridge |
Validate & code medication with SNOMED CT |
abdm.abha.validate |
ABDM Bridge /api/v1/bridge |
Validate ABHA number with ABDM M1 |
abdm.scan_share.lookup |
ABDM Bridge /api/v1/bridge |
QR code lookup for health records |
abdm.fhir.share.requested |
ABDM Bridge /api/v1/bridge |
Push FHIR bundle to ABDM M1 |
abdm.opd.prescription.share.requested |
ABDM Bridge /api/v1/bridge |
Push OPD prescription bundle |
abdm.ipd.discharge.share.requested |
ABDM Bridge /api/v1/bridge |
Push IPD discharge bundle |
abdm.diagnosis.report.share.requested |
ABDM Bridge /api/v1/bridge |
Push diagnosis report bundle |
abdm.consent.requested |
ABDM Bridge /api/v1/bridge |
Request patient consent for data access |
HMS .env Configuration Required
Step 1: Dual Bridge URLs
Replace the current BRIDGE configuration with this:
# ==================== CSNOtk Bridge (SNOMED CT Terminology) ====================
# Purpose: Receive diagnosis/medication events, validate with SNOMED CT, return FHIR-coded data
# Endpoint: POST /api/bridge
# Used by: BridgeSyncService when routing snomed.* events
BRIDGE_SYNC_URL = https://csnotk.e-atria.in/api/bridge
BRIDGE_SYNC_TOKEN =
BRIDGE_SYNC_TIMEOUT = 20
# ==================== ABDM Bridge (ABDM M1 Communication) ====================
# Purpose: Receive ABDM events, route to ABDM Live/Sandbox M1 server
# Endpoint: POST /api/v1/bridge
# Used by: BridgeSyncService when routing abdm.* events
# Architecture: Multiple HMS instances → Single ABDM Bridge → ABDM M1 Server
ABDM_BRIDGE_URL = https://abdm-bridge.e-atria.in/api/v1/bridge
ABDM_BRIDGE_TOKEN =
# ==================== Bridge Configuration ====================
BRIDGE_SOURCE_CODE = SBXID_033661
BRIDGE_SYNC_PROVIDER = bridge
# ==================== SNOMED CT Terminology Service (Direct REST API) ====================
# Purpose: Direct access to CSNOtk REST API for autocomplete (OPD diagnosis search)
# Endpoints: /rest/search/suggest, /rest/search/lookup, /rest/search/validate/id
# Used by: CsnotkTerminologyService in OPD_Prescription controller
snomed.csnotk.baseUrl = https://csnotk.e-atria.in/csnoserv
snomed.csnotk.enabled = true
snomed.csnotk.timeoutSec = 10
Step 2: Generate Bearer Tokens
Generate TWO random tokens (one for each bridge):
# Token 1 for CSNOtk Bridge
openssl rand -hex 32
# Example: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
# Token 2 for ABDM Bridge
openssl rand -hex 32
# Example: f2e1d0c9b8a7z6y5x4w3v2u1t0s9r8q7p6o5n4m3l2k1j0i9h8g7f6e5d4c3b2a1
Step 3: Update .env Tokens
BRIDGE_SYNC_TOKEN = a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
ABDM_BRIDGE_TOKEN = f2e1d0c9b8a7z6y5x4w3v2u1t0s9r8q7p6o5n4m3l2k1j0i9h8g7f6e5d4c3b2a1
BridgeSyncService Routing Logic (To Be Implemented)
Update app/Libraries/BridgeSyncService.php buildBridgeDispatchContext() to route based on event prefix:
Pseudocode Logic
private function buildBridgeDispatchContext(array $row, array $payload): array
{
$eventType = (string) ($row['event_type'] ?? '');
// Route snomed.* events to CSNOtk
if (str_starts_with($eventType, 'snomed.')) {
return [
'ok' => true,
'channel' => 'csnotk',
'endpoint' => $this->readSetting('BRIDGE_SYNC_URL'), // CSNOtk bridge
'method' => 'POST',
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $this->readSetting('BRIDGE_SYNC_TOKEN'),
],
'body' => [
'queue_id' => (int) ($row['id'] ?? 0),
'source' => $source,
'event_type' => $eventType,
'payload' => $payload,
'occurred_at' => (string) ($row['created_at'] ?? ''),
],
];
}
// Route abdm.* events to ABDM Bridge
if (str_starts_with($eventType, 'abdm.')) {
return [
'ok' => true,
'channel' => 'abdm',
'endpoint' => $this->readSetting('ABDM_BRIDGE_URL'), // ABDM bridge
'method' => 'POST',
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $this->readSetting('ABDM_BRIDGE_TOKEN'),
],
'body' => [
'queue_id' => (int) ($row['id'] ?? 0),
'source' => $source,
'event_type' => $eventType,
'payload' => $payload,
'occurred_at' => (string) ($row['created_at'] ?? ''),
],
];
}
// Unknown event type
return ['ok' => false, 'error' => 'Unsupported event_type prefix'];
}
CSNOtk Bridge /api/bridge Contract
Request Format
{
"queue_id": 12345,
"source": "SBXID_033661",
"event_type": "snomed.diagnosis.validate",
"payload": {
"diagnosis_text": "fever",
"return_limit": 10
},
"occurred_at": "2024-05-13T10:30:00+05:30"
}
Response Format (Expected)
{
"ok": 1,
"event_type": "snomed.diagnosis.validate",
"data": [
{
"concept_id": "25064002",
"term": "Headache",
"hierarchy": "disorder",
"is_preferred": 1,
"concept_fsn": "Headache (disorder)"
}
],
"request_id": "REQ-abc123"
}
ABDM Bridge /api/v1/bridge Contract
(See gateway-php-ci4/README.md for full API contract)
Request Format
{
"queue_id": 12345,
"source": "SBXID_033661",
"event_type": "abdm.abha.validate",
"payload": {
"abha_id": "00-0000-0000-0000"
},
"occurred_at": "2024-05-13T10:30:00+05:30"
}
Response Format (Expected)
{
"ok": 1,
"event_type": "abdm.abha.validate",
"request_id": "REQ-abc123",
"data": {
"abha": "00-0000-0000-0000",
"status": "VALID"
}
}
Implementation Checklist
Phase 1: Configuration
- Update HMS
.envwith bothBRIDGE_SYNC_URL(CSNOtk) andABDM_BRIDGE_URL(ABDM) - Generate two separate bearer tokens
- Set
BRIDGE_SYNC_TOKENandABDM_BRIDGE_TOKENin .env - Document tokens in secure location (password manager)
Phase 2: Code Changes
- Update
BridgeSyncService::buildBridgeDispatchContext()with routing logic - Update
BridgeSyncService::buildDispatchContext()to handle snomed.* routing - Update
BridgeSyncService::readSetting()to supportABDM_BRIDGE_URLandABDM_BRIDGE_TOKEN - Add logging to distinguish between CSNOtk and ABDM bridge calls in
abdm_api_logstable
Phase 3: Testing
- Queue a
snomed.diagnosis.validateevent and verify it goes to CSNOtk - Queue an
abdm.abha.validateevent and verify it goes to ABDM Bridge - Check
abdm_api_logsfor successful routing - Verify CSNOtk returns SNOMED-coded data
- Verify ABDM Bridge routes to ABDM M1 correctly
Phase 4: Deployment
- Deploy PHP gateway to https://abdm-bridge.e-atria.in (if not already live)
- Configure gateway
.envwithGATEWAY_BEARER_TOKENmatching HMSABDM_BRIDGE_TOKEN - Run
php spark bridge:sync --limit 10to test both bridge types - Monitor logs for any routing or authentication errors
Database Logging
The abdm_api_logs table will now record:
channel= 'csnotk' or 'abdm' (for routing differentiation)event_type= snomed.* or abdm.*endpoint= CSNOtk or ABDM bridge URL usedstatus= 'success' or 'error'error_message= 403 Unauthorized, 404 Not Found, etc.
Troubleshooting
Problem: 403 Unauthorized on CSNOtk
- Check: BRIDGE_SYNC_TOKEN matches CSNOtk Bridge expectation
- Verify: Request to
https://csnotk.e-atria.in/api/bridgeincludes bearer token
Problem: 403 Unauthorized on ABDM Bridge
- Check: ABDM_BRIDGE_TOKEN matches PHP gateway
GATEWAY_BEARER_TOKEN - Verify: PHP gateway
.envhas the same token as HMSABDM_BRIDGE_TOKEN
Problem: Events stuck in pending status
- Check: Routing logic correctly identifies event prefix (snomed.* vs abdm.*)
- Query:
SELECT * FROM bridge_sync_queue WHERE status='pending' ORDER BY created_at DESC - Debug: Add logging to see which endpoint was called
Problem: CSNOtk returns 404 on /api/bridge
- Cause:
/api/bridgeendpoint may not be exposed on the CSNOtk public server - Fallback: Check if CSNOtk only exposes
/rest/search/*endpoints (direct API calls only) - Action: If needed, create intermediate queue processor for CSNOtk terminology service
References
- CSNOtk REST API Reference:
docs/CSNOTK_API_REFERENCE.md - CSNOtk Database:
SnomedCT_InternationalRF2_PRODUCTION_20260501T120000Z/ - ABDM PHP Gateway:
gateway-php-ci4/(deployment guide:ABDM_GATEWAY_PHP_DEPLOYMENT.md) - Current CSNOtk Direct API Integration:
app/Libraries/CsnotkTerminologyService.php - Bridge Service:
app/Libraries/BridgeSyncService.php