9.9 KiB
9.9 KiB
Webhook Integration Architecture
Overview
This document outlines the architecture for adding webhook handling capabilities to the Circle WebSocket Server. The integration adds HTTP webhook endpoints alongside the existing WebSocket functionality without disrupting the current system.
Architecture Diagram
graph TB
subgraph "External Services"
A[Stripe Webhooks]
B[iDenfy Webhooks]
end
subgraph "Circle Server"
C[HTTP Router]
D[WebSocket Handler]
E[Webhook Handler]
F[Stripe Verifier]
G[iDenfy Verifier]
H[Script Dispatcher]
I[RhaiDispatcherBuilder]
end
subgraph "Configuration"
J[.env File]
K[Environment Variables]
end
subgraph "Backend"
L[Redis]
M[Rhai Worker]
end
A --> |POST /webhooks/stripe/{circle_pk}| E
B --> |POST /webhooks/idenfy/{circle_pk}| E
C --> D
C --> E
E --> F
E --> G
F --> H
G --> H
H --> I
I --> L
L --> M
J --> K
K --> F
K --> G
D --> I
URL Structure
Webhook Endpoints
- Stripe:
POST /webhooks/stripe/{circle_pk}
- iDenfy:
POST /webhooks/idenfy/{circle_pk}
Existing WebSocket Endpoints (Unchanged)
- WebSocket:
GET /{circle_pk}
(upgrades to WebSocket)
Configuration
Environment Variables (.env file)
# Webhook secrets for signature verification
STRIPE_WEBHOOK_SECRET=whsec_...
IDENFY_WEBHOOK_SECRET=your_idenfy_secret
# Existing configuration
REDIS_URL=redis://127.0.0.1/
Server Configuration Updates
pub struct ServerConfig {
// ... existing fields
pub stripe_webhook_secret: Option<String>,
pub idenfy_webhook_secret: Option<String>,
}
Webhook Processing Flow
1. Request Reception
sequenceDiagram
participant WS as Webhook Service
participant CS as Circle Server
participant WV as Webhook Verifier
participant SD as Script Dispatcher
participant RC as RhaiDispatcher
participant RW as Rhai Worker
WS->>CS: POST /webhooks/stripe/{circle_pk}
CS->>CS: Extract circle_pk from URL
CS->>CS: Read request body and headers
CS->>WV: Verify webhook signature
alt Stripe Webhook
WV->>WV: Verify Stripe signature using STRIPE_WEBHOOK_SECRET
WV->>WV: Deserialize to Stripe webhook payload
else iDenfy Webhook
WV->>WV: Verify iDenfy signature using IDENFY_WEBHOOK_SECRET
WV->>WV: Deserialize to iDenfy webhook payload
end
WV->>CS: Return verification result + parsed payload
alt Verification Success
CS->>SD: Dispatch appropriate script
SD->>RC: Create RhaiDispatcherBuilder
RC->>RC: Set caller_id="stripe" or "idenfy"
RC->>RC: Set recipient_id=circle_pk
RC->>RC: Set script="stripe_webhook_received" or "idenfy_webhook_received"
RC->>RW: Execute via Redis
RW->>RC: Return result
RC->>CS: Script execution result
CS->>WS: HTTP 200 OK
else Verification Failed
CS->>WS: HTTP 401 Unauthorized
end
2. Signature Verification
Stripe Verification
- Uses
Stripe-Signature
header - HMAC-SHA256 verification with
STRIPE_WEBHOOK_SECRET
- Follows Stripe's webhook signature verification protocol
iDenfy Verification
- Uses appropriate iDenfy signature header
- HMAC verification with
IDENFY_WEBHOOK_SECRET
- Follows iDenfy's webhook signature verification protocol
3. Payload Deserialization
Type Definitions in Heromodels Library
Webhook payload types are now defined in the heromodels
library for better code organization and reusability:
- Stripe Types: Located in
heromodels::models::payment::stripe
- iDenfy Types: Located in
heromodels::models::identity::kyc
Stripe Payload Structure
// From heromodels::models::payment::StripeWebhookEvent
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct StripeWebhookEvent {
pub id: String,
pub object: String,
pub api_version: Option<String>,
pub created: i64,
pub data: StripeEventData,
pub livemode: bool,
pub pending_webhooks: i32,
pub request: Option<StripeEventRequest>,
#[serde(rename = "type")]
pub event_type: String,
}
iDenfy Payload Structure
// From heromodels::models::identity::IdenfyWebhookEvent
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct IdenfyWebhookEvent {
#[serde(rename = "clientId")]
pub client_id: String,
#[serde(rename = "scanRef")]
pub scan_ref: String,
pub status: String,
pub platform: String,
#[serde(rename = "startedAt")]
pub started_at: String,
#[serde(rename = "finishedAt")]
pub finished_at: Option<String>,
pub data: Option<IdenfyVerificationData>,
// ... additional fields
}
4. Script Execution
Script Names
- Stripe:
stripe_webhook_received
- iDenfy:
idenfy_webhook_received
Script Context
The Rhai scripts will receive structured data:
// For Stripe webhooks
let webhook_data = {
"caller_id": "stripe",
"circle_id": "circle_public_key",
"event_type": "payment_intent.succeeded",
"event_id": "evt_...",
"created": 1234567890,
"livemode": false,
"data": { /* Stripe event data */ }
};
// For iDenfy webhooks
let webhook_data = {
"caller_id": "idenfy",
"circle_id": "circle_public_key",
"final_decision": "APPROVED",
"platform": "PC",
"status": { /* iDenfy status data */ },
"data": { /* iDenfy verification data */ }
};
Implementation Structure
Current File Structure
src/server/src/
├── webhook/
│ ├── mod.rs # Main webhook module with route configuration
│ ├── handlers/
│ │ ├── mod.rs # Handler module exports
│ │ ├── common.rs # Common utilities and app state
│ │ ├── stripe.rs # Stripe webhook handler
│ │ └── idenfy.rs # iDenfy webhook handler
│ ├── verifiers.rs # Signature verification for all providers
│ └── types.rs # Local webhook types (config, errors, etc.)
└── .env # Environment configuration
Heromodels Library Structure
heromodels/src/models/
├── payment/
│ ├── mod.rs # Payment module exports
│ └── stripe.rs # Stripe webhook event types
└── identity/
├── mod.rs # Identity module exports
└── kyc.rs # iDenfy KYC webhook event types
Key Architectural Changes
- Type Organization: Webhook payload types moved to
heromodels
library for reusability - Modular Handlers: Separate handler files for each webhook provider
- Simplified Architecture: Removed unnecessary dispatcher complexity
- Direct Script Execution: Handlers directly use
RhaiDispatcher
for script execution
Modified Files
src/lib.rs
- Add webhook routes and module importsCargo.toml
- Add heromodels dependency and webhook-related dependenciescmd/main.rs
- Load .env file and configure webhook secrets
Dependencies
[dependencies]
# Existing dependencies...
# Heromodels library for shared types
heromodels = { path = "../../../db/heromodels" }
# For webhook signature verification
hmac = "0.12"
sha2 = "0.10"
hex = { workspace = true }
# For environment variable loading
dotenv = "0.15"
# For HTTP request handling
bytes = "1.0"
thiserror = { workspace = true }
Security Considerations
Signature Verification
- Mandatory: All webhook requests must have valid signatures
- Timing Attack Protection: Use constant-time comparison for signatures
- Secret Management: Webhook secrets loaded from environment variables only
Error Handling
- No Information Leakage: Generic error responses for invalid webhooks
- Logging: Detailed logging for debugging (same as existing WebSocket errors)
- Graceful Degradation: Webhook failures don't affect WebSocket functionality
Request Validation
- Content-Type: Verify appropriate content types
- Payload Size: No explicit limits initially (as requested)
- Rate Limiting: Consider future implementation
Backward Compatibility
WebSocket Functionality
- Zero Impact: Existing WebSocket routes and functionality unchanged
- Authentication: WebSocket authentication system remains independent
- Performance: No performance impact on WebSocket connections
Configuration
- Optional: Webhook functionality only enabled when secrets are configured
- Graceful Fallback: Server starts normally even without webhook configuration
Testing Strategy
Unit Tests
- Webhook signature verification for both providers
- Payload deserialization
- Error handling scenarios
Integration Tests
- End-to-end webhook processing
- Script dispatch verification
- Configuration loading
Mock Testing
- Simulated Stripe webhook calls
- Simulated iDenfy webhook calls
- Invalid signature scenarios
Deployment Considerations
Environment Setup
# .env file in src/server/
STRIPE_WEBHOOK_SECRET=whsec_1234567890abcdef...
IDENFY_WEBHOOK_SECRET=your_idenfy_webhook_secret
REDIS_URL=redis://127.0.0.1/
Server Startup
- Load .env file before server initialization
- Validate webhook secrets if webhook endpoints are to be enabled
- Log webhook endpoint availability
Monitoring
- Log webhook reception and processing
- Track script execution success/failure rates
- Monitor webhook signature verification failures
Future Enhancements
Potential Additions
- Additional webhook providers
- Webhook retry mechanisms
- Webhook event filtering
- Rate limiting implementation
- Webhook event queuing for high-volume scenarios
Scalability Considerations
- Webhook processing can be made asynchronous if needed
- Multiple server instances can handle webhooks independently
- Redis-based script execution provides natural load distribution