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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! HTTP-level support for the x402 "upto" scheme.
//!
//! The upto scheme lets a buyer authorise a **maximum** payment and lets the
//! resource server decide the actual charge at request time (e.g. for
//! usage-based pricing). This module defines the
//! [`UptoActualAmount`] response extension that handlers use to communicate
//! the final charge back to the r402 middleware.
//!
//! # Flow
//!
//! ```text
//! client middleware handler
//! | | |
//! | POST + sig ---->| verify |
//! | | ok |
//! | |---- request ------>|
//! | | | (compute usage,
//! | | | set extension)
//! | |<--- response + ext |
//! | | read UptoActualAmount
//! | | → override
//! | | → settle(actual)
//! |<------- resp ---|
//! ```
//!
//! # Example
//!
//! ```ignore
//! use axum::response::IntoResponse;
//! use r402_http::server::UptoActualAmount;
//!
//! async fn handler() -> impl IntoResponse {
//! let mut response = "Hello".into_response();
//! response
//! .extensions_mut()
//! .insert(UptoActualAmount::new("125000")); // 0.125 USDC
//! response
//! }
//! ```
//!
//! # Compatibility
//!
//! Only [`SettlementMode::Sequential`](super::SettlementMode::Sequential)
//! honours this extension: concurrent and background modes spawn settlement
//! before the handler returns, so the override has nowhere to land. Mixing
//! upto with those modes silently charges the signed maximum.
use CompactString;
/// Response extension instructing the r402 middleware to settle the upto
/// payment for this specific amount (base units as a decimal string).
///
/// Inserted by application handlers into [`Response::extensions_mut`] so the
/// middleware can patch `paymentRequirements.amount` before forwarding the
/// settle request to the facilitator.
///
/// The value MUST be less than or equal to the authorised maximum from the
/// buyer's signed payload; otherwise the facilitator returns
/// [`ErrorReason::InvalidUptoEvmPayloadSettlementExceedsAmount`](r402_core::error_reason::ErrorReason::InvalidUptoEvmPayloadSettlementExceedsAmount).
///
/// [`Response::extensions_mut`]: axum_core::response::Response::extensions_mut
;