Implement dynamic payment session
This commit is contained in:
parent
30d0baebc1
commit
5801dbea2d
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4604,6 +4604,7 @@ name = "stripe_adapter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"derive_more",
|
||||
"fulfillment_adapter",
|
||||
"payment_adapter",
|
||||
"payup",
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
pub use config::PaymentProviderConfig;
|
||||
pub use model::v3::*;
|
||||
@ -32,14 +31,13 @@ pub struct UpdateRequests {
|
||||
pub customer_metadata: Option<CustomerMetadata>,
|
||||
}
|
||||
|
||||
pub struct PaymentSessionData {
|
||||
pub id: Option<String>,
|
||||
pub meta: HashMap<String, AnyData>,
|
||||
pub trait PaymentSessionData: Send + Sync {
|
||||
fn id(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
pub struct PaymentProcessorSessionResponse {
|
||||
pub update_requests: Option<UpdateRequests>,
|
||||
pub session_data: PaymentSessionData,
|
||||
pub session_data: Box<dyn PaymentSessionData>,
|
||||
}
|
||||
|
||||
pub struct PaymentProcessorContext {
|
||||
@ -50,7 +48,7 @@ pub struct PaymentProcessorContext {
|
||||
pub resource_id: String,
|
||||
pub customer: Option<Customer>,
|
||||
pub context: PaymentProcessCtx,
|
||||
pub payment_session_data: PaymentSessionData,
|
||||
pub payment_session_data: Box<dyn PaymentSessionData>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
@ -129,6 +127,8 @@ pub enum PError {
|
||||
ChargeNotExists(String),
|
||||
#[error("Failed capture charge with id {0:?}")]
|
||||
FailedCapture(String),
|
||||
#[error("Invalid charge for given payment adapter")]
|
||||
InvalidType,
|
||||
}
|
||||
|
||||
pub type PResult<T> = Result<T, PError>;
|
||||
@ -166,82 +166,68 @@ pub trait PaymentAdapter {
|
||||
*/
|
||||
async fn refund_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
refund_amount: Amount,
|
||||
) -> PResult<PaymentSessionData>;
|
||||
) -> PResult<()>;
|
||||
|
||||
/**
|
||||
* Authorize an existing session if it is not already authorized
|
||||
*/
|
||||
async fn authorize_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
data: PaymentProcessCtx,
|
||||
) -> PResult<(PaymentSessionStatus, PaymentSessionData)>;
|
||||
) -> PResult<(PaymentSessionStatus, ())>;
|
||||
|
||||
/**
|
||||
* Capture an existing session
|
||||
*/
|
||||
async fn capture_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
) -> PResult<PaymentSessionData>;
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<()>;
|
||||
|
||||
/**
|
||||
* Delete an existing session
|
||||
*/
|
||||
async fn delete_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
) -> PResult<PaymentSessionData>;
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<()>;
|
||||
|
||||
/**
|
||||
* Retrieve an existing session
|
||||
*/
|
||||
async fn retrieve_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
) -> PResult<PaymentSessionData>;
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<()>;
|
||||
|
||||
/**
|
||||
* Cancel an existing session
|
||||
*/
|
||||
async fn cancel_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
) -> PResult<PaymentSessionData>;
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<()>;
|
||||
|
||||
/**
|
||||
* Return the status of the session
|
||||
*/
|
||||
async fn payment_status(
|
||||
&mut self,
|
||||
payment_session_data: &PaymentSessionData,
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<PaymentSessionStatus>;
|
||||
}
|
||||
|
||||
// use traitcast::{Traitcast, TraitcastFrom};
|
||||
|
||||
pub trait APaymentSessionData: Any {
|
||||
fn id(&self) -> Option<String>;
|
||||
pub fn session_ref<T: PaymentSessionData + Any>(
|
||||
session: &Box<dyn PaymentSessionData>,
|
||||
) -> Option<&T> {
|
||||
<dyn Any>::downcast_ref(session)
|
||||
}
|
||||
|
||||
pub struct BPSD(Box<dyn APaymentSessionData>);
|
||||
|
||||
impl BPSD {
|
||||
pub fn as_mut_ref<T>(&mut self) -> Option<&mut T> {
|
||||
use std::boxed::Box;
|
||||
|
||||
let r = self.0.deref_mut();
|
||||
if <dyn Any>::is::<&T>(r) {
|
||||
Some(unsafe { r as &mut T })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn f(mut psd: &mut BPSD) {
|
||||
use std::boxed::Box;
|
||||
let c = psd.deref_mut();
|
||||
pub fn session_mut_ref<T: PaymentSessionData + Any>(
|
||||
session: &mut Box<dyn PaymentSessionData>,
|
||||
) -> Option<&mut T> {
|
||||
<dyn Any>::downcast_mut(session)
|
||||
}
|
||||
|
@ -17,3 +17,4 @@ payup = { version = "*", features = [] }
|
||||
tracing = { version = "0.1.37" }
|
||||
async-trait = { version = "0.1.68" }
|
||||
serde = { version = "1.0.162", features = ['derive'] }
|
||||
derive_more = { version = "0.99.17" }
|
||||
|
@ -1,9 +1,9 @@
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
use derive_more::DerefMut;
|
||||
use fulfillment_adapter::*;
|
||||
use payment_adapter::*;
|
||||
use payup::stripe;
|
||||
@ -105,7 +105,7 @@ impl PaymentAdapter for StripePrzelewy24 {
|
||||
captured: self.config.capture.clone(),
|
||||
currency: Some(currency_code.into()),
|
||||
description: desc,
|
||||
customer: customer.map(|c| c.id.0.to_string()),
|
||||
customer: customer.as_ref().map(|c| c.id.0.to_string()),
|
||||
receipt_email: Some(email.0),
|
||||
..stripe::Charge::new()
|
||||
}
|
||||
@ -113,11 +113,11 @@ impl PaymentAdapter for StripePrzelewy24 {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let update_requests = match customer {
|
||||
let update_requests = match customer.as_ref() {
|
||||
Some(c) if !c.has_stripe_id() => Some(UpdateRequests {
|
||||
customer_metadata: Some(CustomerMetadata(HashMap::from([(
|
||||
"id".to_string(),
|
||||
AnyData(change.customer.unwrap_or_default().into_bytes()),
|
||||
AnyData(change.customer.clone().unwrap_or_default().into_bytes()),
|
||||
)]))),
|
||||
}),
|
||||
_ => None,
|
||||
@ -125,7 +125,7 @@ impl PaymentAdapter for StripePrzelewy24 {
|
||||
|
||||
Ok(PaymentProcessorSessionResponse {
|
||||
update_requests,
|
||||
session_data: payment_session_data,
|
||||
session_data: Box::new(Charge(change)),
|
||||
})
|
||||
}
|
||||
|
||||
@ -138,30 +138,30 @@ impl PaymentAdapter for StripePrzelewy24 {
|
||||
|
||||
async fn refund_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
refund_amount: Amount,
|
||||
) -> PResult<PaymentSessionData> {
|
||||
) -> PResult<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn authorize_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
data: PaymentProcessCtx,
|
||||
) -> PResult<(PaymentSessionStatus, PaymentSessionData)> {
|
||||
self.payment_status(&payment_session_data)
|
||||
) -> PResult<(PaymentSessionStatus, ())> {
|
||||
self.payment_status(payment_session_data)
|
||||
.await
|
||||
.map(|status| (status, payment_session_data))
|
||||
.map(|status| (status, ()))
|
||||
}
|
||||
|
||||
async fn capture_payment(
|
||||
&mut self,
|
||||
mut payment_session_data: PaymentSessionData,
|
||||
) -> PResult<PaymentSessionData> {
|
||||
let id = payment_session_data
|
||||
.id
|
||||
.clone()
|
||||
.ok_or_else(|| PError::NoChargeId)?;
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<()> {
|
||||
let Some(session) = session_mut_ref::<Charge>(payment_session_data) else {
|
||||
return Err(PError::InvalidType);
|
||||
};
|
||||
let id = session.id().ok_or_else(|| PError::NoChargeId)?;
|
||||
let charge = stripe::Charge::async_get(self.stripe.clone(), id.clone())
|
||||
.await
|
||||
.map_err(|_| PError::ChargeNotExists(id.clone()))?;
|
||||
@ -172,38 +172,40 @@ impl PaymentAdapter for StripePrzelewy24 {
|
||||
tracing::warn!("{e}");
|
||||
PError::FailedCapture(id)
|
||||
})?;
|
||||
payment_session_data.id = charge.id;
|
||||
Ok(payment_session_data)
|
||||
session.0 = change;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
) -> PResult<PaymentSessionData> {
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn retrieve_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
) -> PResult<PaymentSessionData> {
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn cancel_payment(
|
||||
&mut self,
|
||||
payment_session_data: PaymentSessionData,
|
||||
) -> PResult<PaymentSessionData> {
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn payment_status(
|
||||
&mut self,
|
||||
payment_session_data: &PaymentSessionData,
|
||||
payment_session_data: &mut Box<dyn PaymentSessionData>,
|
||||
) -> PResult<PaymentSessionStatus> {
|
||||
payment_status(
|
||||
self.stripe.clone(),
|
||||
payment_session_data.id.clone().unwrap_or_default(),
|
||||
payment_session_data
|
||||
.id()
|
||||
.ok_or_else(|| PError::NoChargeId)?,
|
||||
)
|
||||
.await
|
||||
.map_err(|_| PError::HttpError)
|
||||
@ -240,3 +242,12 @@ impl StripeCustomerMetadata for Customer {
|
||||
.and_then(|v| String::from_utf8(v.clone()).ok())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, derive_more::Deref, derive_more::DerefMut)]
|
||||
struct Charge(stripe::Charge);
|
||||
|
||||
impl PaymentSessionData for Charge {
|
||||
fn id(&self) -> Option<String> {
|
||||
self.0.id.clone()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user