use crate::protocol::core::{PaymentCredential, Receipt};
use crate::protocol::intents::ChargeRequest;
use crate::protocol::traits::VerificationError;
use std::future::Future;
pub trait ChargeMethod: Clone + Send + Sync {
fn method(&self) -> &str;
fn prepare_request(
&self,
request: ChargeRequest,
_credential: Option<&PaymentCredential>,
) -> ChargeRequest {
request
}
fn verify(
&self,
credential: &PaymentCredential,
request: &ChargeRequest,
) -> impl Future<Output = Result<Receipt, VerificationError>> + Send;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::protocol::core::{ChallengeEcho, PaymentPayload};
#[derive(Clone)]
struct TestChargeMethod;
#[allow(clippy::manual_async_fn)]
impl ChargeMethod for TestChargeMethod {
fn method(&self) -> &str {
"test"
}
fn verify(
&self,
_credential: &PaymentCredential,
_request: &ChargeRequest,
) -> impl Future<Output = Result<Receipt, VerificationError>> + Send {
async { Ok(Receipt::success("test", "test_ref")) }
}
}
#[test]
fn test_charge_method_name() {
let method = TestChargeMethod;
assert_eq!(method.method(), "test");
}
#[tokio::test]
async fn test_charge_method_verify() {
let method = TestChargeMethod;
let echo = ChallengeEcho {
id: "test".into(),
realm: "test.com".into(),
method: "test".into(),
intent: "charge".into(),
request: crate::protocol::core::Base64UrlJson::from_raw("eyJ0ZXN0IjoidmFsdWUifQ"),
expires: None,
digest: None,
opaque: None,
};
let credential = PaymentCredential::new(echo, PaymentPayload::hash("0x123"));
let request = ChargeRequest {
amount: "1000".into(),
currency: "usd".into(),
..Default::default()
};
let result = method.verify(&credential, &request).await;
assert!(result.is_ok());
let receipt = result.unwrap();
assert_eq!(receipt.reference, "test_ref");
}
}