openfare_lib/profile/
payment_methods.rs

1use anyhow::{format_err, Result};
2
3pub type Name = String;
4
5#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, serde::Serialize, serde::Deserialize)]
6pub enum Methods {
7    #[serde(rename = "paypal")]
8    PayPal,
9    #[serde(rename = "btc-lightning")]
10    BtcLightning,
11}
12
13pub trait MethodType {
14    fn type_method() -> Methods;
15}
16
17pub trait PaymentMethod {
18    fn method(&self) -> Methods;
19    fn to_serde_json_value(&self) -> Result<serde_json::Value>;
20}
21
22impl<'de, T> PaymentMethod for T
23where
24    T: MethodType + serde::de::DeserializeOwned + serde::Serialize,
25{
26    fn method(&self) -> Methods {
27        T::type_method()
28    }
29
30    fn to_serde_json_value(&self) -> Result<serde_json::Value> {
31        Ok(serde_json::to_value(&self)?)
32    }
33}
34
35#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
36pub struct PayPal {
37    /// PayPal ID.
38    #[serde(skip_serializing_if = "Option::is_none")]
39    id: Option<String>,
40
41    /// Payee email.
42    #[serde(skip_serializing_if = "Option::is_none")]
43    email: Option<String>,
44}
45
46impl PayPal {
47    pub fn new(id: &Option<String>, email: &Option<String>) -> Result<Self> {
48        if id.is_none() && email.is_none() {
49            return Err(format_err!("Both id and email fields can not be none."));
50        }
51        Ok(Self {
52            id: id.clone(),
53            email: email.clone(),
54        })
55    }
56}
57
58impl MethodType for PayPal {
59    fn type_method() -> Methods {
60        Methods::PayPal
61    }
62}
63
64pub type LnUrl = String;
65
66#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
67pub struct BtcLightning {
68    pub lnurl: LnUrl,
69    pub keysend: Option<String>,
70}
71
72impl BtcLightning {
73    pub fn new(lnurl: &str, keysend: &Option<String>) -> Result<Self> {
74        Ok(Self {
75            lnurl: lnurl.to_string(),
76            keysend: keysend.clone(),
77        })
78    }
79}
80
81impl MethodType for BtcLightning {
82    fn type_method() -> Methods {
83        Methods::BtcLightning
84    }
85}
86
87pub fn check(
88    payment_methods: &std::collections::BTreeMap<Methods, serde_json::Value>,
89) -> Result<()> {
90    for (method, json_value) in payment_methods {
91        let clean_json_value = match method {
92            Methods::PayPal => {
93                let method = serde_json::from_value::<PayPal>(json_value.clone())?;
94                serde_json::to_value(&method)?
95            }
96            Methods::BtcLightning => {
97                let method = serde_json::from_value::<BtcLightning>(json_value.clone())?;
98                serde_json::to_value(&method)?
99            }
100        };
101
102        if json_value != &clean_json_value {
103            return Err(anyhow::format_err!(
104                "Found unexpected field(s): {}",
105                json_value
106            ));
107        }
108    }
109    Ok(())
110}