1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Local entity cache for Payrix data.
//!
//! This module provides a local database cache that mirrors Payrix entities,
//! reducing API calls and enabling faster queries.
//!
//! # Feature Gate
//!
//! This module requires the `cache` feature to be enabled:
//!
//! ```toml
//! [dependencies]
//! payrix = { version = "0.1", features = ["cache"] }
//! ```
//!
//! # Architecture
//!
//! ```text
//! ┌─────────────────┐ webhook ┌──────────────────┐
//! │ Payrix API │ ───────────────> │ WebhookServer │
//! └────────┬────────┘ └────────┬─────────┘
//! │ │
//! │ ▼
//! │ ┌────────────────────┐
//! │ │ EntityCache │
//! │ │ (PostgreSQL) │
//! │ └────────┬───────────┘
//! │ │
//! │ ▼
//! │ ┌────────────────────┐
//! │ initial sync │ Your App │
//! └──────────────────────────>│ (queries cache) │
//! └────────────────────┘
//! ```
//!
//! # Benefits
//!
//! - **Reduce API calls** - Query local database instead of Payrix API
//! - **Faster queries** - Local database is much faster than API calls
//! - **Complex queries** - SQL JOINs, aggregations not possible via API
//! - **Offline resilience** - App continues working if Payrix is temporarily unavailable
//!
//! # Example
//!
//! ```no_run
//! use payrix::{PayrixClient, Environment};
//! use payrix::cache::{EntityCache, CacheConfig};
//!
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
//! let client = PayrixClient::new("api-key", Environment::Test)?;
//!
//! // Connect to cache database
//! let cache = EntityCache::new(
//! "postgresql://user:pass@localhost/payrix_cache",
//! client,
//! ).await?;
//!
//! // Initial sync from Payrix API
//! let stats = cache.initial_sync().await?;
//! println!("Synced {} chargebacks", stats.chargebacks);
//!
//! // Query from the local cache (fast!)
//! let chargeback = cache.get_chargeback("t1_chb_123").await?;
//!
//! // Or fall back to API if not in cache
//! let chargeback = cache.get_or_fetch_chargeback("t1_chb_456").await?;
//! # Ok(())
//! # }
//! ```
//!
//! # Webhook Integration
//!
//! The cache can be kept in sync via webhooks:
//!
//! ```no_run
//! use payrix::cache::EntityCache;
//! use payrix::webhooks::{WebhookServer, WebhookEvent};
//!
//! # async fn example(cache: EntityCache, mut events: tokio::sync::mpsc::Receiver<WebhookEvent>) {
//! while let Some(event) = events.recv().await {
//! // Update cache from webhook event
//! if let Err(e) = cache.process_webhook(&event).await {
//! tracing::error!("Failed to update cache: {}", e);
//! }
//! }
//! # }
//! ```
//!
//! # PCI DSS Considerations
//!
//! The cache stores tokenized data only - no raw card numbers:
//!
//! - **Safe to cache**: Transactions, Chargebacks, Merchants, Customers, Tokens
//! - **Payrix handles PCI**: Card numbers are tokenized before storage
//! - **No raw PAN data**: Webhooks contain the same tokenized data
pub use ;
pub use ensure_schema;