From b257d18c95dd2a39ea65a01db34d8728069b0a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Djk=C3=A1=C5=A5o?= Date: Wed, 10 Apr 2024 16:59:10 +0200 Subject: [PATCH] filter payment methods based on obtainment type --- rust-toolchain.toml | 3 +- simple-payment-gateway/src/app.rs | 4 +- .../src/queries/event_transactions.rs | 79 +++++++++++++++++-- simple-payment-gateway/src/routes/webhooks.rs | 42 +++++++++- 4 files changed, 116 insertions(+), 12 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8ac7a29..0c540fc 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,3 @@ [toolchain] -channel = "nightly" +channel = "nightly-2024-03-23" targets = ["x86_64-unknown-linux-gnu"] -components = ["clippy"] diff --git a/simple-payment-gateway/src/app.rs b/simple-payment-gateway/src/app.rs index 511b305..7347a2b 100644 --- a/simple-payment-gateway/src/app.rs +++ b/simple-payment-gateway/src/app.rs @@ -11,7 +11,7 @@ use tracing_subscriber::EnvFilter; use saleor_app_sdk::{config::Config, locales::LocaleCode, manifest::AppManifest, SaleorApp}; use serde::{Deserialize, Serialize}; // Make our own error that wraps `anyhow::Error`. -pub struct AppError(anyhow::Error); +pub struct AppError(pub anyhow::Error); // Tell axum how to convert `AppError` into a response. impl IntoResponse for AppError { @@ -49,7 +49,7 @@ pub fn trace_to_std(config: &Config) -> anyhow::Result<()> { Ok(()) } -#[derive(Debug, Clone, Sequence, Serialize, Deserialize)] +#[derive(Debug, Clone, Sequence, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "lowercase")] pub enum PaymentMethodType { Accreditation, diff --git a/simple-payment-gateway/src/queries/event_transactions.rs b/simple-payment-gateway/src/queries/event_transactions.rs index b5869c2..65043fe 100644 --- a/simple-payment-gateway/src/queries/event_transactions.rs +++ b/simple-payment-gateway/src/queries/event_transactions.rs @@ -2,6 +2,23 @@ use const_format::concatcp; #[cynic::schema("saleor")] mod schema {} +pub const fragment_checkout_details: &str = r#" +fragment CheckoutDetails on Checkout { + id + isShippingRequired + deliveryMethod { + ... on Warehouse { + name + id + } + ... on ShippingMethod { + id + name + } + } +} +"#; + pub const fragment_transaction_details: &str = r#" fragment TransactionDetails on TransactionItem { id @@ -48,6 +65,8 @@ fragment OrderDetails on Order { paymentStatus chargeStatus canFinalize + shippingMethodName + collectionPointName totalBalance { currency amount @@ -75,14 +94,20 @@ subscription PaymentGatewayInitializeSession { data amount sourceObject { - ...OrderDetails + ... on Checkout { + ...CheckoutDetails + } + ... on Order { + ...OrderDetails + } } amount } } } "#, - fragment_order_details + fragment_order_details, + fragment_checkout_details ); pub const sub_transaction_initialize_session: &str = concatcp!( @@ -92,7 +117,12 @@ subscription transactionInitializeSession { ... on TransactionInitializeSession { data sourceObject { - ...OrderDetails + ... on Checkout { + ...CheckoutDetails + } + ... on Order { + ...OrderDetails + } } transaction { ...TransactionDetails @@ -107,7 +137,8 @@ subscription transactionInitializeSession { } "#, fragment_order_details, - fragment_transaction_details + fragment_transaction_details, + fragment_checkout_details ); pub const sub_transaction_process_session: &str = concatcp!( @@ -120,7 +151,12 @@ subscription transactionProcessSession { actionType } sourceObject { - ...OrderDetails + ... on Checkout { + ...CheckoutDetails + } + ... on Order { + ...OrderDetails + } } transaction { ...TransactionDetails @@ -131,7 +167,8 @@ subscription transactionProcessSession { } "#, fragment_order_details, - fragment_transaction_details + fragment_transaction_details, + fragment_checkout_details, ); pub const sub_transaction_charge_requested: &str = concatcp!( @@ -191,6 +228,12 @@ subscription transactionCancelationRequested { fragment_transaction_details ); +#[derive(cynic::QueryFragment, Debug)] +pub struct Warehouse { + pub name: String, + pub id: cynic::Id, +} + #[derive(cynic::QueryFragment, Debug)] #[cynic(graphql_type = "TransactionRefundRequested")] pub struct TransactionRefundRequested2 { @@ -301,6 +344,12 @@ pub struct PaymentGatewayInitializeSession { pub event: Option, } +#[derive(cynic::QueryFragment, Debug)] +pub struct ShippingMethod { + pub id: cynic::Id, + pub name: String, +} + #[derive(cynic::QueryFragment, Debug)] #[cynic(graphql_type = "PaymentGatewayInitializeSession")] pub struct PaymentGatewayInitializeSession2 { @@ -318,6 +367,8 @@ pub struct Order { pub payment_status: PaymentChargeStatusEnum, pub charge_status: OrderChargeStatusEnum, pub can_finalize: bool, + pub shipping_method_name: Option, + pub collection_point_name: Option, pub total_balance: Money, } @@ -327,6 +378,13 @@ pub struct Money { pub amount: f64, } +#[derive(cynic::QueryFragment, Debug)] +pub struct Checkout { + pub id: cynic::Id, + pub is_shipping_required: bool, + pub delivery_method: Option, +} + #[derive(cynic::InlineFragments, Debug)] #[cynic(graphql_type = "Event")] pub enum Event6 { @@ -374,8 +432,17 @@ pub enum Event { Unknown, } +#[derive(cynic::InlineFragments, Debug)] +pub enum DeliveryMethod { + Warehouse(Warehouse), + ShippingMethod(ShippingMethod), + #[cynic(fallback)] + Unknown, +} + #[derive(cynic::InlineFragments, Debug)] pub enum OrderOrCheckout { + Checkout(Checkout), Order(Order), #[cynic(fallback)] Unknown, diff --git a/simple-payment-gateway/src/routes/webhooks.rs b/simple-payment-gateway/src/routes/webhooks.rs index aa9f321..63343fd 100644 --- a/simple-payment-gateway/src/routes/webhooks.rs +++ b/simple-payment-gateway/src/routes/webhooks.rs @@ -22,10 +22,12 @@ use tracing::{debug, error, info}; use crate::{ app::{ - AppError, AppState, PaymentGatewayInitializeSessionData, TransactionInitializeSessionData, + AppError, AppState, PaymentGatewayInitializeSessionData, PaymentMethodType, + TransactionInitializeSessionData, }, queries::{ event_transactions::{ + DeliveryMethod, OrderOrCheckout, PaymentGatewayInitializeSession2, TransactionCancelationRequested2, TransactionChargeRequested2, TransactionFlowStrategyEnum, TransactionInitializeSession2, TransactionProcessSession2, TransactionRefundRequested2, @@ -63,8 +65,44 @@ pub async fn webhooks( // Json::from(serde_json::to_value(PaymentListGatewaysResponse(gateways))?) // } SyncWebhookEventType::PaymentGatewayInitializeSession => { + let session_data = serde_json::from_str::(&body)?; + let mut filtered_payment_methods = state.active_payment_methods.clone(); + + //If obtainment method is via some sort of shipping, remove PaymentMethodType::Cash + //If obtainment method is collection in person at warehouse, remove PaymentMethodType::CODv + match session_data.source_object { + OrderOrCheckout::Order(o) => { + if o.shipping_method_name.is_some() { + filtered_payment_methods.retain(|p| p.typ != PaymentMethodType::Cash) + } else if o.collection_point_name.is_some() { + filtered_payment_methods.retain(|p| p.typ != PaymentMethodType::COD) + } else { + error!("Order has neither shipping_method_name or collection_point_name, how is it being payed for?"); + } + } + OrderOrCheckout::Checkout(c) => { + if let Some(d) = c.delivery_method { + match d { + DeliveryMethod::Warehouse(_) => { + filtered_payment_methods + .retain(|p| p.typ != PaymentMethodType::COD); + } + DeliveryMethod::ShippingMethod(_) => { + filtered_payment_methods + .retain(|p| p.typ != PaymentMethodType::Cash); + } + DeliveryMethod::Unknown => { + error!("DeliveryMethod is neither"); + } + } + } + } + OrderOrCheckout::Unknown => { + error!("OrderOrCheckout is neither"); + } + } let data = serde_json::to_value(PaymentGatewayInitializeSessionData { - payment_methods: state.active_payment_methods, + payment_methods: filtered_payment_methods, })?; Json::from(serde_json::to_value( PaymentGatewayInitializeSessionResponse:: { data: Some(data) },