Skip to main content

r402_protocol/payment/
required.rs

1//! HTTP 402 `Payment Required` body.
2
3use compact_str::CompactString;
4use serde::{Deserialize, Serialize};
5
6use super::{Extensions, PaymentRequirements, ResourceInfo, V2, Version2};
7
8/// Body of an HTTP 402 Payment Required response.
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase", deny_unknown_fields)]
11#[non_exhaustive]
12pub struct PaymentRequired {
13    /// Protocol version (always `2`).
14    pub x402_version: Version2,
15    /// Optional error message describing why the request was rejected.
16    #[serde(default, skip_serializing_if = "Option::is_none")]
17    pub error: Option<CompactString>,
18    /// Resource metadata.
19    pub resource: ResourceInfo,
20    /// Accepted payment terms.
21    #[serde(default)]
22    pub accepts: Vec<PaymentRequirements>,
23    /// Optional extension block.
24    #[serde(default, skip_serializing_if = "Extensions::is_empty")]
25    pub extensions: Extensions,
26}
27
28impl PaymentRequired {
29    /// Constructs a 402 body with the resource and an empty `accepts` list.
30    #[must_use]
31    pub fn new(resource: ResourceInfo) -> Self {
32        Self {
33            x402_version: V2,
34            error: None,
35            resource,
36            accepts: Vec::new(),
37            extensions: Extensions::new(),
38        }
39    }
40
41    /// Replaces the accepted payment requirements list.
42    #[must_use]
43    pub fn with_accepts(mut self, accepts: Vec<PaymentRequirements>) -> Self {
44        self.accepts = accepts;
45        self
46    }
47
48    /// Appends a single payment requirement.
49    #[must_use]
50    pub fn add_accept(mut self, accept: PaymentRequirements) -> Self {
51        self.accepts.push(accept);
52        self
53    }
54
55    /// Attaches a human-readable error message.
56    #[must_use]
57    pub fn with_error(mut self, error: impl Into<CompactString>) -> Self {
58        self.error = Some(error.into());
59        self
60    }
61
62    /// Replaces the `extensions` block.
63    #[must_use]
64    pub fn with_extensions(mut self, extensions: Extensions) -> Self {
65        self.extensions = extensions;
66        self
67    }
68}