pub struct AmazonpayAuthType {
    pub(super) public_key: Secret<String>,
    pub(super) private_key: Secret<String>,
}


pub fn server(state: AppState) -> Scope {
        web::scope("/profile_acquirer")
            .app_data(web::Data::new(state))
            .service(
                web::resource("").route(web::post().to(profile_acquirer::create_profile_acquirer)),
            )
            .service(
                web::resource("/{profile_id}/{profile_acquirer_id}")
                    .route(web::post().to(profile_acquirer::profile_acquirer_update)),
            )
    }


pub fn get_masked_keys(&self) -> Self {
        match self {
            Self::TemporaryAuth => Self::TemporaryAuth,
            Self::NoKey => Self::NoKey,
            Self::HeaderKey { api_key } => Self::HeaderKey {
                api_key: self.mask_key(api_key.clone().expose()),
            },
            Self::BodyKey { api_key, key1 } => Self::BodyKey {
                api_key: self.mask_key(api_key.clone().expose()),
                key1: self.mask_key(key1.clone().expose()),
            },
            Self::SignatureKey {
                api_key,
                key1,
                api_secret,
            } => Self::SignatureKey {
                api_key: self.mask_key(api_key.clone().expose()),
                key1: self.mask_key(key1.clone().expose()),
                api_secret: self.mask_key(api_secret.clone().expose()),
            },
            Self::MultiAuthKey {
                api_key,
                key1,
                api_secret,
                key2,
            } => Self::MultiAuthKey {
                api_key: self.mask_key(api_key.clone().expose()),
                key1: self.mask_key(key1.clone().expose()),
                api_secret: self.mask_key(api_secret.clone().expose()),
                key2: self.mask_key(key2.clone().expose()),
            },
            Self::CurrencyAuthKey { auth_key_map } => Self::CurrencyAuthKey {
                auth_key_map: auth_key_map.clone(),
            },
            Self::CertificateAuth {
                certificate,
                private_key,
            } => Self::CertificateAuth {
                certificate: self.mask_key(certificate.clone().expose()),
                private_key: self.mask_key(private_key.clone().expose()),
            },
        }
    }


pub fn three_ds_decision_rule_execute() {}


pub struct SilverflowVoidRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub replacement_amount: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub reference: Option<String>,
}


pub struct RedirectionData {
    pub return_url: Option<String>,
}


File: crates/hyperswitch_constraint_graph/src/graph.rs
 Public functions: 5
 Public structs: 1

use std::sync::{Arc, Weak};

use rustc_hash::{FxHashMap, FxHashSet};

use crate::{
    builder,
    dense_map::DenseMap,
    error::{self, AnalysisTrace, GraphError},
    types::{
        CheckingContext, CycleCheck, DomainId, DomainIdentifier, DomainInfo, Edge, EdgeId,
        Memoization, Metadata, Node, NodeId, NodeType, NodeValue, Relation, RelationResolution,
        Strength, ValueNode,
    },
};

#[derive(Debug)]
struct CheckNodeContext<'a, V: ValueNode, C: CheckingContext<Value = V>> {
    ctx: &'a C,
    node: &'a Node<V>,
    node_id: NodeId,
    relation: Relation,
    strength: Strength,
    memo: &'a mut Memoization<V>,
    cycle_map: &'a mut CycleCheck,
    domains: Option<&'a [DomainId]>,
}

#[derive(Debug)]
pub struct ConstraintGraph<V: ValueNode> {
    pub domain: DenseMap<DomainId, DomainInfo>,
    pub domain_identifier_map: FxHashMap<DomainIdentifier, DomainId>,
    pub nodes: DenseMap<NodeId, Node<V>>,
    pub edges: DenseMap<EdgeId, Edge>,
    pub value_map: FxHashMap<NodeValue<V>, NodeId>,
    pub node_info: DenseMap<NodeId, Option<&'static str>>,
    pub node_metadata: DenseMap<NodeId, Option<Arc<dyn Metadata>>>,
}

impl<V> ConstraintGraph<V>
where
    V: ValueNode,
{
    fn get_predecessor_edges_by_domain(
        &self,
        node_id: NodeId,
        domains: Option<&[DomainId]>,
    ) -> Result<Vec<&Edge>, GraphError<V>> {
        let node = self.nodes.get(node_id).ok_or(GraphError::NodeNotFound)?;
        let mut final_list = Vec::new();
        for &pred in &node.preds {
            let edge = self.edges.get(pred).ok_or(GraphError::EdgeNotFound)?;
            if let Some((domain_id, domains)) = edge.domain.zip(domains) {
                if domains.contains(&domain_id) {
                    final_list.push(edge);
                }
            } else if edge.domain.is_none() {
                final_list.push(edge);
            }
        }

        Ok(final_list)
    }

    #[allow(clippy::too_many_arguments)]
    pub fn check_node<C>(
        &self,
        ctx: &C,
        node_id: NodeId,
        relation: Relation,
        strength: Strength,
        memo: &mut Memoization<V>,
        cycle_map: &mut CycleCheck,
        domains: Option<&[String]>,
    ) -> Result<(), GraphError<V>>
    where
        C: CheckingContext<Value = V>,
    {
        let domains = domains
            .map(|domain_idents| {
                domain_idents
                    .iter()
                    .map(|domain_ident| {
                        self.domain_identifier_map
                            .get(&DomainIdentifier::new(domain_ident.to_string()))
                            .copied()
                            .ok_or(GraphError::DomainNotFound)
                    })
                    .collect::<Result<Vec<_>, _>>()
            })
            .transpose()?;

        self.check_node_inner(
            ctx,
            node_id,
            relation,
            strength,
            memo,
            cycle_map,
            domains.as_deref(),
        )
    }

    #[allow(clippy::too_many_arguments)]
    pub fn check_node_inner<C>(
        &self,
        ctx: &C,
        node_id: NodeId,
        relation: Relation,
        strength: Strength,
        memo: &mut Memoization<V>,
        cycle_map: &mut CycleCheck,
        domains: Option<&[DomainId]>,
    ) -> Result<(), GraphError<V>>
    where
        C: CheckingContext<Value = V>,
    {
        let node = self.nodes.get(node_id).ok_or(GraphError::NodeNotFound)?;

        if let Some(already_memo) = memo.get(&(node_id, relation, strength)) {
            already_memo
                .clone()
                .map_err(|err| GraphError::AnalysisError(Arc::downgrade(&err)))
        } else if let Some((initial_strength, initial_relation)) = cycle_map.get(&node_id).copied()
        {
            let strength_relation = Strength::get_resolved_strength(initial_strength, strength);
            let relation_resolve =
                RelationResolution::get_resolved_relation(initial_relation, relation.into());
            cycle_map.entry(node_id).and_modify(|value| {
                value.0 = strength_relation;
                value.1 = relation_resolve
            });
            Ok(())
        } else {
            let check_node_context = CheckNodeContext {
                node,
                node_id,
                relation,
                strength,
                memo,
                cycle_map,
                ctx,
                domains,
            };

            match &node.node_type {
                NodeType::AllAggregator => self.validate_all_aggregator(check_node_context),

                NodeType::AnyAggregator => self.validate_any_aggregator(check_node_context),

                NodeType::InAggregator(expected) => {
                    self.validate_in_aggregator(check_node_context, expected)
                }
                NodeType::Value(val) => self.validate_value_node(check_node_context, val),
            }
        }
    }

    fn validate_all_aggregator<C>(
        &self,
        vald: CheckNodeContext<'_, V, C>,
    ) -> Result<(), GraphError<V>>
    where
        C: CheckingContext<Value = V>,
    {
        let mut unsatisfied = Vec::<Weak<AnalysisTrace<V>>>::new();

        for edge in self.get_predecessor_edges_by_domain(vald.node_id, vald.domains)? {
            vald.cycle_map
                .insert(vald.node_id, (vald.strength, vald.relation.into()));
            if let Err(e) = self.check_node_inner(
                vald.ctx,
                edge.pred,
                edge.relation,
                edge.strength,
                vald.memo,
                vald.cycle_map,
                vald.domains,
            ) {
                unsatisfied.push(e.get_analysis_trace()?);
            }
            if let Some((_resolved_strength, resolved_relation)) =
                vald.cycle_map.remove(&vald.node_id)
            {
                if resolved_relation == RelationResolution::Contradiction {
                    let err = Arc::new(AnalysisTrace::Contradiction {
                        relation: resolved_relation,
                    });
                    vald.memo.insert(
                        (vald.node_id, vald.relation, vald.strength),
                        Err(Arc::clone(&err)),
                    );
                    return Err(GraphError::AnalysisError(Arc::downgrade(&err)));
                }
            }
        }

        if !unsatisfied.is_empty() {
            let err = Arc::new(AnalysisTrace::AllAggregation {
                unsatisfied,
                info: self.node_info.get(vald.node_id).copied().flatten(),
                metadata: self.node_metadata.get(vald.node_id).cloned().flatten(),
            });

            vald.memo.insert(
                (vald.node_id, vald.relation, vald.strength),
                Err(Arc::clone(&err)),
            );
            Err(GraphError::AnalysisError(Arc::downgrade(&err)))
        } else {
            vald.memo
                .insert((vald.node_id, vald.relation, vald.strength), Ok(()));

            Ok(())
        }
    }

    fn validate_any_aggregator<C>(
        &self,
        vald: CheckNodeContext<'_, V, C>,
    ) -> Result<(), GraphError<V>>
    where
        C: CheckingContext<Value = V>,
    {
        let mut unsatisfied = Vec::<Weak<AnalysisTrace<V>>>::new();
        let mut matched_one = false;

        for edge in self.get_predecessor_edges_by_domain(vald.node_id, vald.domains)? {
            vald.cycle_map
                .insert(vald.node_id, (vald.strength, vald.relation.into()));
            if let Err(e) = self.check_node_inner(
                vald.ctx,
                edge.pred,
                edge.relation,
                edge.strength,
                vald.memo,
                vald.cycle_map,
                vald.domains,
            ) {
                unsatisfied.push(e.get_analysis_trace()?);
            } else {
                matched_one = true;
            }
            if let Some((_resolved_strength, resolved_relation)) =
                vald.cycle_map.remove(&vald.node_id)
            {
                if resolved_relation == RelationResolution::Contradiction {
                    let err = Arc::new(AnalysisTrace::Contradiction {
                        relation: resolved_relation,
                    });
                    vald.memo.insert(
                        (vald.node_id, vald.relation, vald.strength),
                        Err(Arc::clone(&err)),
                    );

                    return Err(GraphError::AnalysisError(Arc::downgrade(&err)));
                }
            }
        }

        if matched_one || vald.node.preds.is_empty() {
            vald.memo
                .insert((vald.node_id, vald.relation, vald.strength), Ok(()));
            Ok(())
        } else {
            let err = Arc::new(AnalysisTrace::AnyAggregation {
                unsatisfied: unsatisfied.clone(),
                info: self.node_info.get(vald.node_id).copied().flatten(),
                metadata: self.node_metadata.get(vald.node_id).cloned().flatten(),
            });

            vald.memo.insert(
                (vald.node_id, vald.relation, vald.strength),
                Err(Arc::clone(&err)),
            );
            Err(GraphError::AnalysisError(Arc::downgrade(&err)))
        }
    }

    fn validate_in_aggregator<C>(
        &self,
        vald: CheckNodeContext<'_, V, C>,
        expected: &FxHashSet<V>,
    ) -> Result<(), GraphError<V>>
    where
        C: CheckingContext<Value = V>,
    {
        let the_key = expected
            .iter()
            .next()
            .ok_or_else(|| GraphError::MalformedGraph {
                reason: "An OnlyIn aggregator node must have at least one expected value"
                    .to_string(),
            })?
            .get_key();

        let ctx_vals = if let Some(vals) = vald.ctx.get_values_by_key(&the_key) {
            vals
        } else {
            return if let Strength::Weak = vald.strength {
                vald.memo
                    .insert((vald.node_id, vald.relation, vald.strength), Ok(()));
                Ok(())
            } else {
                let err = Arc::new(AnalysisTrace::InAggregation {
                    expected: expected.iter().cloned().collect(),
                    found: None,
                    relation: vald.relation,
                    info: self.node_info.get(vald.node_id).copied().flatten(),
                    metadata: self.node_metadata.get(vald.node_id).cloned().flatten(),
                });

                vald.memo.insert(
                    (vald.node_id, vald.relation, vald.strength),
                    Err(Arc::clone(&err)),
                );
                Err(GraphError::AnalysisError(Arc::downgrade(&err)))
            };
        };

        let relation_bool: bool = vald.relation.into();
        for ctx_value in ctx_vals {
            if expected.contains(&ctx_value) != relation_bool {
                let err = Arc::new(AnalysisTrace::InAggregation {
                    expected: expected.iter().cloned().collect(),
                    found: Some(ctx_value.clone()),
                    relation: vald.relation,
                    info: self.node_info.get(vald.node_id).copied().flatten(),
                    metadata: self.node_metadata.get(vald.node_id).cloned().flatten(),
                });

                vald.memo.insert(
                    (vald.node_id, vald.relation, vald.strength),
                    Err(Arc::clone(&err)),
                );
                Err(GraphError::AnalysisError(Arc::downgrade(&err)))?;
            }
        }

        vald.memo
            .insert((vald.node_id, vald.relation, vald.strength), Ok(()));
        Ok(())
    }

    fn validate_value_node<C>(
        &self,
        vald: CheckNodeContext<'_, V, C>,
        val: &NodeValue<V>,
    ) -> Result<(), GraphError<V>>
    where
        C: CheckingContext<Value = V>,
    {
        let mut errors = Vec::<Weak<AnalysisTrace<V>>>::new();
        let mut matched_one = false;

        self.context_analysis(
            vald.node_id,
            vald.relation,
            vald.strength,
            vald.ctx,
            val,
            vald.memo,
        )?;

        for edge in self.get_predecessor_edges_by_domain(vald.node_id, vald.domains)? {
            vald.cycle_map
                .insert(vald.node_id, (vald.strength, vald.relation.into()));
            let result = self.check_node_inner(
                vald.ctx,
                edge.pred,
                edge.relation,
                edge.strength,
                vald.memo,
                vald.cycle_map,
                vald.domains,
            );

            if let Some((resolved_strength, resolved_relation)) =
                vald.cycle_map.remove(&vald.node_id)
            {
                if resolved_relation == RelationResolution::Contradiction {
                    let err = Arc::new(AnalysisTrace::Contradiction {
                        relation: resolved_relation,
                    });
                    vald.memo.insert(
                        (vald.node_id, vald.relation, vald.strength),
                        Err(Arc::clone(&err)),
                    );
                    return Err(GraphError::AnalysisError(Arc::downgrade(&err)));
                } else if resolved_strength != vald.strength {
                    self.context_analysis(
                        vald.node_id,
                        vald.relation,
                        resolved_strength,
                        vald.ctx,
                        val,
                        vald.memo,
                    )?
                }
            }
            match (edge.strength, result) {
                (Strength::Strong, Err(trace)) => {
                    let err = Arc::new(AnalysisTrace::Value {
                        value: val.clone(),
                        relation: vald.relation,
                        info: self.node_info.get(vald.node_id).copied().flatten(),
                        metadata: self.node_metadata.get(vald.node_id).cloned().flatten(),
                        predecessors: Some(error::ValueTracePredecessor::Mandatory(Box::new(
                            trace.get_analysis_trace()?,
                        ))),
                    });
                    vald.memo.insert(
                        (vald.node_id, vald.relation, vald.strength),
                        Err(Arc::clone(&err)),
                    );
                    Err(GraphError::AnalysisError(Arc::downgrade(&err)))?;
                }

                (Strength::Strong, Ok(_)) => {
                    matched_one = true;
                }

                (Strength::Normal | Strength::Weak, Err(trace)) => {
                    errors.push(trace.get_analysis_trace()?);
                }

                (Strength::Normal | Strength::Weak, Ok(_)) => {
                    matched_one = true;
                }
            }
        }

        if matched_one || vald.node.preds.is_empty() {
            vald.memo
                .insert((vald.node_id, vald.relation, vald.strength), Ok(()));
            Ok(())
        } else {
            let err = Arc::new(AnalysisTrace::Value {
                value: val.clone(),
                relation: vald.relation,
                info: self.node_info.get(vald.node_id).copied().flatten(),
                metadata: self.node_metadata.get(vald.node_id).cloned().flatten(),
                predecessors: Some(error::ValueTracePredecessor::OneOf(errors.clone())),
            });

            vald.memo.insert(
                (vald.node_id, vald.relation, vald.strength),
                Err(Arc::clone(&err)),
            );
            Err(GraphError::AnalysisError(Arc::downgrade(&err)))
        }
    }

    fn context_analysis<C>(
        &self,
        node_id: NodeId,
        relation: Relation,
        strength: Strength,
        ctx: &C,
        val: &NodeValue<V>,
        memo: &mut Memoization<V>,
    ) -> Result<(), GraphError<V>>
    where
        C: CheckingContext<Value = V>,
    {
        let in_context = ctx.check_presence(val, strength);
        let relation_bool: bool = relation.into();
        if in_context != relation_bool {
            let err = Arc::new(AnalysisTrace::Value {
                value: val.clone(),
                relation,
                predecessors: None,
                info: self.node_info.get(node_id).copied().flatten(),
                metadata: self.node_metadata.get(node_id).cloned().flatten(),
            });
            memo.insert((node_id, relation, strength), Err(Arc::clone(&err)));
            Err(GraphError::AnalysisError(Arc::downgrade(&err)))?;
        }
        if !relation_bool {
            memo.insert((node_id, relation, strength), Ok(()));
            return Ok(());
        }
        Ok(())
    }

    pub fn combine(g1: &Self, g2: &Self) -> Result<Self, GraphError<V>> {
        let mut node_builder = builder::ConstraintGraphBuilder::new();
        let mut g1_old2new_id = DenseMap::<NodeId, NodeId>::new();
        let mut g2_old2new_id = DenseMap::<NodeId, NodeId>::new();
        let mut g1_old2new_domain_id = DenseMap::<DomainId, DomainId>::new();
        let mut g2_old2new_domain_id = DenseMap::<DomainId, DomainId>::new();

        let add_domain = |node_builder: &mut builder::ConstraintGraphBuilder<V>,
                          domain: DomainInfo|
         -> Result<DomainId, GraphError<V>> {
            node_builder.make_domain(
                domain.domain_identifier.into_inner(),
                &domain.domain_description,
            )
        };

        let add_node = |node_builder: &mut builder::ConstraintGraphBuilder<V>,
                        node: &Node<V>|
         -> Result<NodeId, GraphError<V>> {
            match &node.node_type {
                NodeType::Value(node_value) => {
                    Ok(node_builder.make_value_node(node_value.clone(), None, None::<()>))
                }

                NodeType::AllAggregator => {
                    Ok(node_builder.make_all_aggregator(&[], None, None::<()>, None)?)
                }

                NodeType::AnyAggregator => {
                    Ok(node_builder.make_any_aggregator(&[], None, None::<()>, None)?)
                }

                NodeType::InAggregator(expected) => Ok(node_builder.make_in_aggregator(
                    expected.iter().cloned().collect(),
                    None,
                    None::<()>,
                )?),
            }
        };

        for (_old_domain_id, domain) in g1.domain.iter() {
            let new_domain_id = add_domain(&mut node_builder, domain.clone())?;
            g1_old2new_domain_id.push(new_domain_id);
        }

        for (_old_domain_id, domain) in g2.domain.iter() {
            let new_domain_id = add_domain(&mut node_builder, domain.clone())?;
            g2_old2new_domain_id.push(new_domain_id);
        }

        for (_old_node_id, node) in g1.nodes.iter() {
            let new_node_id = add_node(&mut node_builder, node)?;
            g1_old2new_id.push(new_node_id);
        }

        for (_old_node_id, node) in g2.nodes.iter() {
            let new_node_id = add_node(&mut node_builder, node)?;
            g2_old2new_id.push(new_node_id);
        }

        for edge in g1.edges.values() {
            let new_pred_id = g1_old2new_id
                .get(edge.pred)
                .ok_or(GraphError::NodeNotFound)?;
            let new_succ_id = g1_old2new_id
                .get(edge.succ)
                .ok_or(GraphError::NodeNotFound)?;
            let domain_ident = edge
                .domain
                .map(|domain_id| g1.domain.get(domain_id).ok_or(GraphError::DomainNotFound))
                .transpose()?
                .map(|domain| domain.domain_identifier.clone());

            node_builder.make_edge(
                *new_pred_id,
                *new_succ_id,
                edge.strength,
                edge.relation,
                domain_ident,
            )?;
        }

        for edge in g2.edges.values() {
            let new_pred_id = g2_old2new_id
                .get(edge.pred)
                .ok_or(GraphError::NodeNotFound)?;
            let new_succ_id = g2_old2new_id
                .get(edge.succ)
                .ok_or(GraphError::NodeNotFound)?;
            let domain_ident = edge
                .domain
                .map(|domain_id| g2.domain.get(domain_id).ok_or(GraphError::DomainNotFound))
                .transpose()?
                .map(|domain| domain.domain_identifier.clone());

            node_builder.make_edge(
                *new_pred_id,
                *new_succ_id,
                edge.strength,
                edge.relation,
                domain_ident,
            )?;
        }

        Ok(node_builder.build())
    }
}

#[cfg(feature = "viz")]
mod viz {
    use graphviz_rust::{
        dot_generator::*,
        dot_structures::*,
        printer::{DotPrinter, PrinterContext},
    };

    use crate::{dense_map::EntityId, types, ConstraintGraph, NodeViz, ValueNode};

    fn get_node_id(node_id: types::NodeId) -> String {
        format!("N{}", node_id.get_id())
    }

    impl<V> ConstraintGraph<V>
    where
        V: ValueNode + NodeViz,
        <V as ValueNode>::Key: NodeViz,
    {
        fn get_node_label(node: &types::Node<V>) -> String {
            let label = match &node.node_type {
                types::NodeType::Value(types::NodeValue::Key(key)) => format!("any {}", key.viz()),
                types::NodeType::Value(types::NodeValue::Value(val)) => {
                    format!("{} = {}", val.get_key().viz(), val.viz())
                }
                types::NodeType::AllAggregator => "&&".to_string(),
                types::NodeType::AnyAggregator => "| |".to_string(),
                types::NodeType::InAggregator(agg) => {
                    let key = if let Some(val) = agg.iter().next() {
                        val.get_key().viz()
                    } else {
                        return "empty in".to_string();
                    };

                    let nodes = agg.iter().map(NodeViz::viz).collect::<Vec<_>>();
                    format!("{key} in [{}]", nodes.join(", "))
                }
            };

            format!("\"{label}\"")
        }

        fn build_node(cg_node_id: types::NodeId, cg_node: &types::Node<V>) -> Node {
            let viz_node_id = get_node_id(cg_node_id);
            let viz_node_label = Self::get_node_label(cg_node);

            node!(viz_node_id; attr!("label", viz_node_label))
        }

        fn build_edge(cg_edge: &types::Edge) -> Edge {
            let pred_vertex = get_node_id(cg_edge.pred);
            let succ_vertex = get_node_id(cg_edge.succ);
            let arrowhead = match cg_edge.strength {
                types::Strength::Weak => "onormal",
                types::Strength::Normal => "normal",
                types::Strength::Strong => "normalnormal",
            };
            let color = match cg_edge.relation {
                types::Relation::Positive => "blue",
                types::Relation::Negative => "red",
            };

            edge!(
                node_id!(pred_vertex) => node_id!(succ_vertex);
                attr!("arrowhead", arrowhead),
                attr!("color", color)
            )
        }

        pub fn get_viz_digraph(&self) -> Graph {
            graph!(
                strict di id!("constraint_graph"),
                self.nodes
                    .iter()
                    .map(|(node_id, node)| Self::build_node(node_id, node))
                    .map(Stmt::Node)
                    .chain(self.edges.values().map(Self::build_edge).map(Stmt::Edge))
                    .collect::<Vec<_>>()
            )
        }

        pub fn get_viz_digraph_string(&self) -> String {
            let mut ctx = PrinterContext::default();
            let digraph = self.get_viz_digraph();
            digraph.print(&mut ctx)
        }
    }
}


File: crates/diesel_models/src/lib.rs
 Public functions: 2
 Public structs: 4

pub mod address;
pub mod api_keys;
pub mod blocklist_lookup;
pub mod business_profile;
pub mod capture;
pub mod cards_info;
pub mod configs;

pub mod authentication;
pub mod authorization;
pub mod blocklist;
pub mod blocklist_fingerprint;
pub mod callback_mapper;
pub mod customers;
pub mod dispute;
pub mod dynamic_routing_stats;
pub mod enums;
pub mod ephemeral_key;
pub mod errors;
pub mod events;
pub mod file;
#[allow(unused)]
pub mod fraud_check;
pub mod generic_link;
pub mod gsm;
#[cfg(feature = "kv_store")]
pub mod kv;
pub mod locker_mock_up;
pub mod mandate;
pub mod merchant_account;
pub mod merchant_connector_account;
pub mod merchant_key_store;
pub mod organization;
pub mod payment_attempt;
pub mod payment_intent;
pub mod payment_link;
pub mod payment_method;
pub mod payout_attempt;
pub mod payouts;
pub mod process_tracker;
pub mod query;
pub mod refund;
pub mod relay;
pub mod reverse_lookup;
pub mod role;
pub mod routing_algorithm;
pub mod subscription;
pub mod types;
pub mod unified_translations;

#[cfg(feature = "v2")]
pub mod payment_methods_session;

#[allow(unused_qualifications)]
pub mod schema;
#[allow(unused_qualifications)]
pub mod schema_v2;

pub mod user;
pub mod user_authentication_method;
pub mod user_key_store;
pub mod user_role;

use diesel_impl::{DieselArray, OptionalDieselArray};
#[cfg(feature = "v2")]
use diesel_impl::{RequiredFromNullable, RequiredFromNullableWithDefault};

pub type StorageResult<T> = error_stack::Result<T, errors::DatabaseError>;
pub type PgPooledConn = async_bb8_diesel::Connection<diesel::PgConnection>;
pub use self::{
    address::*, api_keys::*, callback_mapper::*, cards_info::*, configs::*, customers::*,
    dispute::*, ephemeral_key::*, events::*, file::*, generic_link::*, locker_mock_up::*,
    mandate::*, merchant_account::*, merchant_connector_account::*, payment_attempt::*,
    payment_intent::*, payment_method::*, payout_attempt::*, payouts::*, process_tracker::*,
    refund::*, reverse_lookup::*, user_authentication_method::*,
};
/// The types and implementations provided by this module are required for the schema generated by
/// `diesel_cli` 2.0 to work with the types defined in Rust code. This is because
/// [`diesel`][diesel] 2.0 [changed the nullability of array elements][diesel-2.0-array-nullability],
/// which causes [`diesel`][diesel] to deserialize arrays as `Vec<Option<T>>`. To prevent declaring
/// array elements as `Option<T>`, this module provides types and implementations to deserialize
/// arrays as `Vec<T>`, considering only non-null values (`Some(T)`) among the deserialized
/// `Option<T>` values.
///
/// [diesel-2.0-array-nullability]: https://diesel.rs/guides/migration_guide.html#2-0-0-nullability-of-array-elements
#[doc(hidden)]
pub(crate) mod diesel_impl {
    #[cfg(feature = "v2")]
    use common_utils::{id_type, types};
    use diesel::{
        deserialize::FromSql,
        pg::Pg,
        sql_types::{Array, Nullable},
        Queryable,
    };

    #[cfg(feature = "v2")]
    use crate::enums;

    pub struct DieselArray<T>(Vec<Option<T>>);

    impl<T> From<DieselArray<T>> for Vec<T> {
        fn from(array: DieselArray<T>) -> Self {
            array.0.into_iter().flatten().collect()
        }
    }

    impl<T, U> Queryable<Array<Nullable<U>>, Pg> for DieselArray<T>
    where
        T: FromSql<U, Pg>,
        Vec<Option<T>>: FromSql<Array<Nullable<U>>, Pg>,
    {
        type Row = Vec<Option<T>>;

        fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
            Ok(Self(row))
        }
    }

    pub struct OptionalDieselArray<T>(Option<Vec<Option<T>>>);

    impl<T> From<OptionalDieselArray<T>> for Option<Vec<T>> {
        fn from(option_array: OptionalDieselArray<T>) -> Self {
            option_array
                .0
                .map(|array| array.into_iter().flatten().collect())
        }
    }

    impl<T, U> Queryable<Nullable<Array<Nullable<U>>>, Pg> for OptionalDieselArray<T>
    where
        Option<Vec<Option<T>>>: FromSql<Nullable<Array<Nullable<U>>>, Pg>,
    {
        type Row = Option<Vec<Option<T>>>;

        fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
            Ok(Self(row))
        }
    }
    #[cfg(feature = "v2")]
    /// If the DB value is null, this wrapper will return an error when deserializing.
    ///
    /// This is useful when you want to ensure that a field is always present, even if the database
    /// value is NULL. If the database column contains a NULL value, an error will be returned.
    pub struct RequiredFromNullable<T>(T);

    #[cfg(feature = "v2")]
    impl<T> RequiredFromNullable<T> {
        /// Extracts the inner value from the wrapper
        pub fn into_inner(self) -> T {
            self.0
        }
    }

    #[cfg(feature = "v2")]
    impl<T, ST, DB> Queryable<Nullable<ST>, DB> for RequiredFromNullable<T>
    where
        DB: diesel::backend::Backend,
        T: Queryable<ST, DB>,
        Option<T::Row>: FromSql<Nullable<ST>, DB>,
        ST: diesel::sql_types::SingleValue,
    {
        type Row = Option<T::Row>;

        fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
            match row {
                Some(inner_row) => {
                    let value = T::build(inner_row)?;
                    Ok(Self(value))
                }
                None => Err("Cannot deserialize NULL value for required field. Check if the database column that should not be NULL contains a NULL value.".into()),
            }
        }
    }

    #[cfg(feature = "v2")]
    /// If the DB value is null, this wrapper will provide a default value for the type `T`.
    ///
    /// This is useful when you want to ensure that a field is always present, even if the database
    /// value is NULL. The default value is provided by the `Default` trait implementation of `T`.
    pub struct RequiredFromNullableWithDefault<T>(T);
    #[cfg(feature = "v2")]
    impl<T> RequiredFromNullableWithDefault<T> {
        /// Extracts the inner value from the wrapper
        pub fn into_inner(self) -> T {
            self.0
        }
    }
    #[cfg(feature = "v2")]
    impl<T, ST, DB> Queryable<Nullable<ST>, DB> for RequiredFromNullableWithDefault<T>
    where
        DB: diesel::backend::Backend,
        T: Queryable<ST, DB>,
        T: Default,
        Option<T::Row>: FromSql<Nullable<ST>, DB>,
        ST: diesel::sql_types::SingleValue,
    {
        type Row = Option<T::Row>;

        fn build(row: Self::Row) -> diesel::deserialize::Result<Self> {
            match row {
                Some(inner_row) => {
                    let value = T::build(inner_row)?;
                    Ok(Self(value))
                }
                None => Ok(Self(T::default())),
            }
        }
    }

    #[cfg(feature = "v2")]
    /// Macro to implement From trait for types wrapped in RequiredFromNullable
    #[macro_export]
    macro_rules! impl_from_required_from_nullable {
        ($($type:ty),* $(,)?) => {
            $(
                impl From<$crate::RequiredFromNullable<$type>> for $type {
                    fn from(wrapper: $crate::RequiredFromNullable<$type>) -> Self {
                        wrapper.into_inner()
                    }
                }
            )*
        };
    }

    #[cfg(feature = "v2")]
    /// Macro to implement From trait for types wrapped in RequiredFromNullableWithDefault
    #[macro_export]
    macro_rules! impl_from_required_from_nullable_with_default {
        ($($type:ty),* $(,)?) => {
            $(
                impl From<$crate::RequiredFromNullableWithDefault<$type>> for $type {
                    fn from(wrapper: $crate::RequiredFromNullableWithDefault<$type>) -> Self {
                        wrapper.into_inner()
                    }
                }
            )*
        };
    }
    #[cfg(feature = "v2")]
    crate::impl_from_required_from_nullable_with_default!(enums::DeleteStatus);

    #[cfg(feature = "v2")]
    crate::impl_from_required_from_nullable!(
        enums::AuthenticationType,
        types::MinorUnit,
        enums::PaymentMethod,
        enums::Currency,
        id_type::ProfileId,
        time::PrimitiveDateTime,
        id_type::RefundReferenceId,
    );
}

pub(crate) mod metrics {
    use router_env::{counter_metric, global_meter, histogram_metric_f64};

    global_meter!(GLOBAL_METER, "ROUTER_API");

    counter_metric!(DATABASE_CALLS_COUNT, GLOBAL_METER);
    histogram_metric_f64!(DATABASE_CALL_TIME, GLOBAL_METER);
}

#[cfg(feature = "tokenization_v2")]
pub mod tokenization;


pub struct ChargebeeInvoiceBody {
    pub content: ChargebeeInvoiceContent,
    pub event_type: ChargebeeEventType,
}


pub struct PaymentAccountCardInformation {
    #[serde(rename = "type")]
    card_type: Option<String>,
    hashed_number: Option<String>,
}


pub async fn find_optional_by_customer_id_merchant_id(
        conn: &PgPooledConn,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
    ) -> StorageResult<Option<Self>> {
        generics::generic_find_by_id_optional::<<Self as HasTable>::Table, _, _>(
            conn,
            (customer_id.to_owned(), merchant_id.to_owned()),
        )
        .await
    }


Documentation: api-reference/locker-api-reference/key-custodian/unlock-the-locker.mdx
# Type: Doc File

---
openapi: rust_locker_open_api_spec post /custodian/decrypt
---


File: crates/hyperswitch_connectors/src/connectors/amazonpay.rs
 Public functions: 2
 Public structs: 1

pub mod transformers;

use std::sync::LazyLock;

use base64::{engine::general_purpose::STANDARD, Engine};
use chrono::Utc;
use common_enums::enums;
use common_utils::{
    crypto::{RsaPssSha256, SignMessage},
    errors::CustomResult,
    ext_traits::BytesExt,
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, StringMajorUnit, StringMajorUnitForConnector},
};
use error_stack::{report, ResultExt};
use hex;
use hyperswitch_domain_models::{
    payment_method_data::{PaymentMethodData, WalletData as WalletDataPaymentMethod},
    router_data::{AccessToken, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks,
};
use masking::{ExposeInterface, Mask, Maskable, PeekInterface, Secret};
use sha2::{Digest, Sha256};
use transformers as amazonpay;

use crate::{
    constants::headers,
    types::ResponseRouterData,
    utils::{self, PaymentsSyncRequestData},
};

const SIGNING_ALGO: &str = "AMZN-PAY-RSASSA-PSS-V2";
const HEADER_ACCEPT: &str = "accept";
const HEADER_CONTENT_TYPE: &str = "content-type";
const HEADER_DATE: &str = "x-amz-pay-date";
const HEADER_HOST: &str = "x-amz-pay-host";
const HEADER_IDEMPOTENCY_KEY: &str = "x-amz-pay-idempotency-key";
const HEADER_REGION: &str = "x-amz-pay-region";
const FINALIZE_SEGMENT: &str = "finalize";
const AMAZON_PAY_API_BASE_URL: &str = "https://pay-api.amazon.com";
const AMAZON_PAY_HOST: &str = "pay-api.amazon.com";

#[derive(Clone)]
pub struct Amazonpay {
    amount_converter: &'static (dyn AmountConvertor<Output = StringMajorUnit> + Sync),
}

impl Amazonpay {
    pub fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMajorUnitForConnector,
        }
    }

    fn get_last_segment(canonical_uri: &str) -> String {
        canonical_uri
            .chars()
            .rev()
            .take_while(|&c| c != '/')
            .collect::<Vec<_>>()
            .into_iter()
            .rev()
            .collect()
    }

    pub fn create_authorization_header(
        &self,
        auth: amazonpay::AmazonpayAuthType,
        canonical_uri: &str,
        http_method: &Method,
        hashed_payload: &str,
        header: &[(String, Maskable<String>)],
    ) -> String {
        let amazonpay::AmazonpayAuthType {
            public_key,
            private_key,
        } = auth;

        let mut signed_headers =
            format!("{HEADER_ACCEPT};{HEADER_CONTENT_TYPE};{HEADER_DATE};{HEADER_HOST};",);
        if *http_method == Method::Post
            && Self::get_last_segment(canonical_uri) != *FINALIZE_SEGMENT.to_string()
        {
            signed_headers.push_str(HEADER_IDEMPOTENCY_KEY);
            signed_headers.push(';');
        }
        signed_headers.push_str(HEADER_REGION);

        format!(
            "{} PublicKeyId={}, SignedHeaders={}, Signature={}",
            SIGNING_ALGO,
            public_key.expose().clone(),
            signed_headers,
            Self::create_signature(
                &private_key,
                *http_method,
                canonical_uri,
                &signed_headers,
                hashed_payload,
                header
            )
            .unwrap_or_else(|_| "Invalid signature".to_string())
        )
    }

    fn create_signature(
        private_key: &Secret<String>,
        http_method: Method,
        canonical_uri: &str,
        signed_headers: &str,
        hashed_payload: &str,
        header: &[(String, Maskable<String>)],
    ) -> Result<String, String> {
        let mut canonical_request = http_method.to_string() + "\n" + canonical_uri + "\n\n";

        let mut lowercase_sorted_header_keys: Vec<String> =
            header.iter().map(|(key, _)| key.to_lowercase()).collect();

        lowercase_sorted_header_keys.sort();

        for key in lowercase_sorted_header_keys {
            if let Some((_, maskable_value)) = header.iter().find(|(k, _)| k.to_lowercase() == key)
            {
                let value: String = match maskable_value {
                    Maskable::Normal(v) => v.clone(),
                    Maskable::Masked(secret) => secret.clone().expose(),
                };
                canonical_request.push_str(&format!("{key}:{value}\n"));
            }
        }

        canonical_request.push_str(&("\n".to_owned() + signed_headers + "\n" + hashed_payload));

        let string_to_sign = format!(
            "{}\n{}",
            SIGNING_ALGO,
            hex::encode(Sha256::digest(canonical_request.as_bytes()))
        );

        Self::sign(private_key, &string_to_sign)
            .map_err(|e| format!("Failed to create signature: {e}"))
    }

    fn sign(
        private_key_pem_str: &Secret<String>,
        string_to_sign: &String,
    ) -> Result<String, String> {
        let rsa_pss_sha256_signer = RsaPssSha256;
        let signature_bytes = rsa_pss_sha256_signer
            .sign_message(
                private_key_pem_str.peek().as_bytes(),
                string_to_sign.as_bytes(),
            )
            .change_context(errors::ConnectorError::RequestEncodingFailed)
            .map_err(|e| format!("Crypto operation failed: {e:?}"))?;

        Ok(STANDARD.encode(signature_bytes))
    }
}

impl api::Payment for Amazonpay {}
impl api::PaymentSession for Amazonpay {}
impl api::ConnectorAccessToken for Amazonpay {}
impl api::MandateSetup for Amazonpay {}
impl api::PaymentAuthorize for Amazonpay {}
impl api::PaymentSync for Amazonpay {}
impl api::PaymentCapture for Amazonpay {}
impl api::PaymentVoid for Amazonpay {}
impl api::Refund for Amazonpay {}
impl api::RefundExecute for Amazonpay {}
impl api::RefundSync for Amazonpay {}
impl api::PaymentToken for Amazonpay {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Amazonpay
{
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Amazonpay
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let http_method = self.get_http_method();

        let canonical_uri: String =
            self.get_url(req, connectors)?
                .replacen(AMAZON_PAY_API_BASE_URL, "", 1);

        let mut header = vec![
            (
                headers::CONTENT_TYPE.to_string(),
                self.get_content_type().to_string().into(),
            ),
            (
                headers::ACCEPT.to_string(),
                "application/json".to_string().into(),
            ),
            (
                HEADER_DATE.to_string(),
                Utc::now()
                    .format("%Y-%m-%dT%H:%M:%SZ")
                    .to_string()
                    .into_masked(),
            ),
            (
                HEADER_HOST.to_string(),
                AMAZON_PAY_HOST.to_string().into_masked(),
            ),
            (HEADER_REGION.to_string(), "na".to_string().into_masked()),
        ];

        if http_method == Method::Post
            && Self::get_last_segment(&canonical_uri) != *FINALIZE_SEGMENT.to_string()
        {
            header.push((
                HEADER_IDEMPOTENCY_KEY.to_string(),
                req.connector_request_reference_id.clone().into_masked(),
            ));
        }

        let hashed_payload = if http_method == Method::Get {
            hex::encode(Sha256::digest("".as_bytes()))
        } else {
            hex::encode(Sha256::digest(
                self.get_request_body(req, connectors)?
                    .get_inner_value()
                    .expose()
                    .as_bytes(),
            ))
        };

        let authorization = self.create_authorization_header(
            amazonpay::AmazonpayAuthType::try_from(&req.connector_auth_type)?,
            &canonical_uri,
            &http_method,
            &hashed_payload,
            &header,
        );

        header.push((
            headers::AUTHORIZATION.to_string(),
            authorization.clone().into_masked(),
        ));

        Ok(header)
    }
}

impl ConnectorCommon for Amazonpay {
    fn id(&self) -> &'static str {
        "amazonpay"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Base
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.amazonpay.base_url.as_ref()
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: amazonpay::AmazonpayErrorResponse = res
            .response
            .parse_struct("AmazonpayErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.reason_code.clone(),
            message: response.message.clone(),
            attempt_status: None,
            connector_transaction_id: None,
            reason: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

impl ConnectorValidation for Amazonpay {}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Amazonpay {}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Amazonpay {}

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData>
    for Amazonpay
{
}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Amazonpay {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        match req.request.payment_method_data.clone() {
            PaymentMethodData::Wallet(ref wallet_data) => match wallet_data {
                WalletDataPaymentMethod::AmazonPay(ref req_wallet) => Ok(format!(
                    "{}/checkoutSessions/{}/finalize",
                    self.base_url(connectors),
                    req_wallet.checkout_session_id.clone()
                )),
                WalletDataPaymentMethod::AliPayQr(_)
                | WalletDataPaymentMethod::AliPayRedirect(_)
                | WalletDataPaymentMethod::AliPayHkRedirect(_)
                | WalletDataPaymentMethod::AmazonPayRedirect(_)
                | WalletDataPaymentMethod::MomoRedirect(_)
                | WalletDataPaymentMethod::KakaoPayRedirect(_)
                | WalletDataPaymentMethod::GoPayRedirect(_)
                | WalletDataPaymentMethod::GcashRedirect(_)
                | WalletDataPaymentMethod::ApplePay(_)
                | WalletDataPaymentMethod::ApplePayRedirect(_)
                | WalletDataPaymentMethod::ApplePayThirdPartySdk(_)
                | WalletDataPaymentMethod::DanaRedirect {}
                | WalletDataPaymentMethod::GooglePay(_)
                | WalletDataPaymentMethod::GooglePayRedirect(_)
                | WalletDataPaymentMethod::GooglePayThirdPartySdk(_)
                | WalletDataPaymentMethod::MbWayRedirect(_)
                | WalletDataPaymentMethod::MobilePayRedirect(_)
                | WalletDataPaymentMethod::PaypalRedirect(_)
                | WalletDataPaymentMethod::PaypalSdk(_)
                | WalletDataPaymentMethod::Paze(_)
                | WalletDataPaymentMethod::SamsungPay(_)
                | WalletDataPaymentMethod::TwintRedirect {}
                | WalletDataPaymentMethod::VippsRedirect {}
                | WalletDataPaymentMethod::BluecodeRedirect {}
                | WalletDataPaymentMethod::TouchNGoRedirect(_)
                | WalletDataPaymentMethod::WeChatPayRedirect(_)
                | WalletDataPaymentMethod::WeChatPayQr(_)
                | WalletDataPaymentMethod::CashappQr(_)
                | WalletDataPaymentMethod::SwishQr(_)
                | WalletDataPaymentMethod::RevolutPay(_)
                | WalletDataPaymentMethod::Paysera(_)
                | WalletDataPaymentMethod::Skrill(_)
                | WalletDataPaymentMethod::Mifinity(_) => {
                    Err(errors::ConnectorError::NotImplemented(
                        utils::get_unimplemented_payment_method_error_message("amazonpay"),
                    )
                    .into())
                }
            },
            _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()),
        }
    }

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.currency,
        )?;

        let connector_router_data = amazonpay::AmazonpayRouterData::from((amount, req));
        let connector_req = amazonpay::AmazonpayFinalizeRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsAuthorizeType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::PaymentsAuthorizeType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsAuthorizeType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
        let response: amazonpay::AmazonpayFinalizeResponse = res
            .response
            .parse_struct("Amazonpay PaymentsAuthorizeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Amazonpay {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}/charges/{}",
            self.base_url(connectors),
            req.request.get_connector_transaction_id()?
        ))
    }

    fn get_http_method(&self) -> Method {
        Method::Get
    }

    fn build_request(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: amazonpay::AmazonpayPaymentsResponse = res
            .response
            .parse_struct("Amazonpay PaymentsSyncResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Amazonpay {
    fn build_request(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("Capture".to_string()).into())
    }
}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Amazonpay {
    fn build_request(
        &self,
        _req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("Void".to_string()).into())
    }
}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Amazonpay {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}/refunds", self.base_url(connectors)))
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let refund_amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_refund_amount,
            req.request.currency,
        )?;

        let connector_router_data = amazonpay::AmazonpayRouterData::from((refund_amount, req));
        let connector_req = amazonpay::AmazonpayRefundRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(types::RefundExecuteType::get_headers(
                self, req, connectors,
            )?)
            .set_body(types::RefundExecuteType::get_request_body(
                self, req, connectors,
            )?)
            .build();
        Ok(Some(request))
    }

    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: amazonpay::RefundResponse = res
            .response
            .parse_struct("amazonpay RefundResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Amazonpay {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}/refunds/{}",
            self.base_url(connectors),
            req.request.connector_refund_id.clone().unwrap_or_default()
        ))
    }

    fn get_http_method(&self) -> Method {
        Method::Get
    }

    fn build_request(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
                .set_body(types::RefundSyncType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: amazonpay::RefundResponse = res
            .response
            .parse_struct("amazonpay RefundSyncResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[async_trait::async_trait]
impl webhooks::IncomingWebhook for Amazonpay {
    fn get_webhook_object_reference_id(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_resource_object(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }
}

static AMAZONPAY_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> =
    LazyLock::new(|| {
        let supported_capture_methods = vec![enums::CaptureMethod::Automatic];

        let mut amazonpay_supported_payment_methods = SupportedPaymentMethods::new();

        amazonpay_supported_payment_methods.add(
            enums::PaymentMethod::Wallet,
            enums::PaymentMethodType::AmazonPay,
            PaymentMethodDetails {
                mandates: enums::FeatureStatus::NotSupported,
                refunds: enums::FeatureStatus::Supported,
                supported_capture_methods: supported_capture_methods.clone(),
                specific_features: None,
            },
        );

        amazonpay_supported_payment_methods
    });

static AMAZONPAY_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Amazon Pay",
    description: "Amazon Pay is an Alternative Payment Method (APM) connector that allows merchants to accept payments using customers' stored Amazon account details, providing a seamless checkout experience.",
    connector_type: enums::HyperswitchConnectorCategory::AlternativePaymentMethod,
    integration_status: enums::ConnectorIntegrationStatus::Alpha,
};

static AMAZONPAY_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 0] = [];

impl ConnectorSpecifications for Amazonpay {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&AMAZONPAY_CONNECTOR_INFO)
    }

    fn get_supported_payment_methods(&self) -> Option<&'static SupportedPaymentMethods> {
        Some(&AMAZONPAY_SUPPORTED_PAYMENT_METHODS)
    }

    fn get_supported_webhook_flows(&self) -> Option<&'static [enums::EventClass]> {
        Some(&AMAZONPAY_SUPPORTED_WEBHOOK_FLOWS)
    }
}


pub fn add_default_headers(&mut self) {
        self.headers.extend(default_request_headers());
    }


pub struct CardDetail {
    pub card_number: cards::CardNumber,
    pub card_exp_month: Secret<String>,
    pub card_exp_year: Secret<String>,
    pub card_issuer: Option<String>,
    pub card_network: Option<api_enums::CardNetwork>,
    pub card_type: Option<String>,
    pub card_issuing_country: Option<String>,
    pub bank_code: Option<String>,
    pub nick_name: Option<Secret<String>>,
    pub card_holder_name: Option<Secret<String>>,
    pub co_badged_card_data: Option<payment_methods::CoBadgedCardData>,
}


pub async fn retrieve_disputes_list(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
    constraints: api_models::disputes::DisputeListGetConstraints,
) -> RouterResponse<Vec<api_models::disputes::DisputeResponse>> {
    let dispute_list_constraints = &(constraints.clone(), profile_id_list.clone()).try_into()?;
    let disputes = state
        .store
        .find_disputes_by_constraints(
            merchant_context.get_merchant_account().get_id(),
            dispute_list_constraints,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to retrieve disputes")?;
    let disputes_list = disputes
        .into_iter()
        .map(api_models::disputes::DisputeResponse::foreign_from)
        .collect();
    Ok(services::ApplicationResponse::Json(disputes_list))
}


OpenAPI Block Path: components.schemas.BHNGiftCardDetails
{
  "type": "object",
  "required": [
    "account_number",
    "pin",
    "cvv2",
    "expiration_date"
  ],
  "properties": {
    "account_number": {
      "type": "string",
      "description": "The gift card or account number"
    },
    "pin": {
      "type": "string",
      "description": "The security PIN for gift cards requiring it"
    },
    "cvv2": {
      "type": "string",
      "description": "The CVV2 code for Open Loop/VPLN products"
    },
    "expiration_date": {
      "type": "string",
      "description": "The expiration date in MMYYYY format for Open Loop/VPLN products"
    }
  }
}


impl api::PaymentSession for Mifinity {}

impl api::PaymentSession for for Mifinity


OpenAPI Block Path: components.schemas.PaymentProcessingDetailsAt
{
  "oneOf": [
    {
      "allOf": [
        {
          "$ref": "#/components/schemas/PaymentProcessingDetails"
        },
        {
          "type": "object",
          "required": [
            "payment_processing_details_at"
          ],
          "properties": {
            "payment_processing_details_at": {
              "type": "string",
              "enum": [
                "Hyperswitch"
              ]
            }
          }
        }
      ]
    },
    {
      "type": "object",
      "required": [
        "payment_processing_details_at"
      ],
      "properties": {
        "payment_processing_details_at": {
          "type": "string",
          "enum": [
            "Connector"
          ]
        }
      }
    }
  ],
  "discriminator": {
    "propertyName": "payment_processing_details_at"
  }
}


pub struct MandatePaymentInformation {
    payment_instrument: CybersoucrePaymentInstrument,
    tokenized_card: MandatePaymentTokenizedCard,
    card: Option<MandateCard>,
}


pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<Profile> {
        generics::generic_insert(conn, self).await
    }


impl api::ConnectorAccessToken for Globalpay {}

impl api::ConnectorAccessToken for for Globalpay


pub struct FrmFulfillmentRequest {
    ///unique payment_id for the transaction
    #[schema(max_length = 255, example = "pay_qiYfHcDou1ycIaxVXKHF")]
    pub payment_id: common_utils::id_type::PaymentId,
    ///unique order_id for the order_details in the transaction
    #[schema(max_length = 255, example = "pay_qiYfHcDou1ycIaxVXKHF")]
    pub order_id: String,
    ///denotes the status of the fulfillment... can be one of PARTIAL, COMPLETE, REPLACEMENT, CANCELED
    #[schema(value_type = Option<FulfillmentStatus>, example = "COMPLETE")]
    pub fulfillment_status: Option<FulfillmentStatus>,
    ///contains details of the fulfillment
    #[schema(value_type = Vec<Fulfillments>)]
    pub fulfillments: Vec<Fulfillments>,
    //name of the tracking Company
    #[schema(max_length = 255, example = "fedex")]
    pub tracking_company: Option<String>,
    //tracking ID of the product
    #[schema(example = r#"["track_8327446667", "track_8327446668"]"#)]
    pub tracking_numbers: Option<Vec<String>>,
    //tracking_url for tracking the product
    pub tracking_urls: Option<Vec<String>>,
    // The name of the Shipper.
    pub carrier: Option<String>,
    // Fulfillment method for the shipment.
    pub fulfillment_method: Option<String>,
    // Statuses to indicate shipment state.
    pub shipment_status: Option<String>,
    // The date and time items are ready to be shipped.
    pub shipped_at: Option<String>,
}


Documentation: api-reference/v1/merchant-account/merchant-account--delete.mdx
# Type: Doc File

---
openapi: delete /accounts/{account_id}
---


pub struct CancelTransactionData {
    reversal: CancelResponseTransactionBody,
}


pub async fn count_initial_attempts_by_constraints(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        profile_id: Option<common_utils::id_type::ProfileId>,
        created_after: time::PrimitiveDateTime,
        created_before: time::PrimitiveDateTime,
        event_types: HashSet<common_enums::EventType>,
        is_delivered: Option<bool>,
    ) -> StorageResult<i64> {
        use async_bb8_diesel::AsyncRunQueryDsl;
        use diesel::{debug_query, pg::Pg, QueryDsl};
        use error_stack::ResultExt;
        use router_env::logger;

        use super::generics::db_metrics::{track_database_call, DatabaseOperation};
        use crate::errors::DatabaseError;

        let mut query = Self::table()
            .count()
            .filter(
                dsl::event_id
                    .nullable()
                    .eq(dsl::initial_attempt_id) // Filter initial attempts only
                    .and(dsl::merchant_id.eq(merchant_id.to_owned())),
            )
            .into_boxed();

        query = Self::apply_filters(
            query,
            profile_id,
            (dsl::created_at, created_after, created_before),
            None,
            None,
            event_types,
            is_delivered,
        );

        logger::debug!(query = %debug_query::<Pg, _>(&query).to_string());

        track_database_call::<Self, _, _>(
            query.get_result_async::<i64>(conn),
            DatabaseOperation::Count,
        )
        .await
        .change_context(DatabaseError::Others)
        .attach_printable("Error counting events by constraints")
    }


pub struct WiseTransferDetails {
    transfer_purpose: Option<String>,
    source_of_funds: Option<String>,
    transfer_purpose_sub_transfer_purpose: Option<String>,
}


impl Responder {
        // safety: This shouldn't panic owing to the data type
        #[allow(clippy::expect_used)]
        let payload = json_payload
            .into_inner()
            .to_vec()
            .pop()
            .expect("Couldn't get GetPaymentMetricRequest");
        let flow = AnalyticsFlow::GetPaymentMetrics;
        Box::pin(api::server_wrap(
            flow,
            state,
            &req,
            payload,
            |state, auth: AuthenticationData, req, _| async move {
                let org_id = auth.merchant_account.get_org_id();
                let merchant_id = auth.merchant_account.get_id();
                let auth: AuthInfo = AuthInfo::MerchantLevel {
                    org_id: org_id.clone(),
                    merchant_ids: vec![merchant_id.clone()],
                };
                let validator_response = request_validator(
                    AnalyticsRequest {
                        payment_attempt: Some(req.clone()),
                        ..Default::default()
                    },
                    &state,
                )
                .await?;
                let ex_rates = validator_response;
                analytics::payments::get_metrics(&state.pool, &ex_rates, &auth, req)
                    .await
                    .map(ApplicationResponse::Json)
            },
            &auth::JWTAuth {
                permission: Permission::MerchantAnalyticsRead,
            },
            api_locking::LockAction::NotApplicable,
        ))
        .await
    }


impl Responder {
    let flow = Flow::CreateDynamicRoutingConfig;
    let wrapper = routing_types::CreateDynamicRoutingWrapper {
        feature_to_enable: query.into_inner().enable,
        profile_id: path.into_inner().profile_id,
        payload: api_models::routing::DynamicRoutingPayload::EliminationRoutingPayload(
            elimination_config.into_inner(),
        ),
    };
    Box::pin(oss_api::server_wrap(
        flow,
        state,
        &req,
        wrapper.clone(),
        |state,
         auth: auth::AuthenticationData,
         wrapper: routing_types::CreateDynamicRoutingWrapper,
         _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            routing::create_specific_dynamic_routing(
                state,
                merchant_context,
                wrapper.feature_to_enable,
                wrapper.profile_id,
                api_models::routing::DynamicRoutingType::EliminationRouting,
                wrapper.payload,
            )
        },
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            }),
            &auth::JWTAuthProfileFromRoute {
                profile_id: wrapper.profile_id,
                required_permission: Permission::ProfileRoutingWrite,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct SilverflowTokenizationRequest {
    pub reference: String,

    pub card_data: SilverflowCardData,
}


pub struct ZenItemObject {
    name: String,
    price: String,
    quantity: u16,
    line_amount_total: String,
}


pub async fn connector_update() {}


impl SdkEventMetricsBucketIdentifier {
    pub fn new(
        payment_method: Option<String>,
        platform: Option<String>,
        browser_name: Option<String>,
        source: Option<String>,
        component: Option<String>,
        payment_experience: Option<String>,
        time_bucket: Option<String>,
    ) -> Self {
        Self {
            payment_method,
            platform,
            browser_name,
            source,
            component,
            payment_experience,
            time_bucket,
        }
    }
}


impl Responder {
    let flow = Flow::PaymentsRedirect;
    let (payment_id, publishable_key, profile_id) = path.into_inner();
    let param_string = req.query_string();

    tracing::Span::current().record("payment_id", payment_id.get_string_repr());

    let payload = payments::PaymentsRedirectResponseData {
        payment_id,
        json_payload: json_payload.map(|payload| payload.0),
        query_params: param_string.to_string(),
    };

    let locking_action = payload.get_locking_input(flow.clone());

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, auth, req, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            <payments::PaymentRedirectSync as PaymentRedirectFlow>::handle_payments_redirect_response(
                &payments::PaymentRedirectSync {},
                state,
                req_state,
                merchant_context,
                auth.profile,
                req,
            )
        },
        &auth::PublishableKeyAndProfileIdAuth {
            publishable_key: publishable_key.clone(),
            profile_id: profile_id.clone(),
        },
        locking_action,
    ))
    .await
}


pub fn validate(&self) -> Result<(), ApplicationError> {
        common_utils::fp_utils::when(self.stream_name.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "drainer stream name must not be empty".into(),
            ))
        })
    }


impl std::ops::DerefMut for PaymentsTokenReference {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl std::ops::DerefMut for for PaymentsTokenReference


pub struct PaymentMethodUpdateInternal {
    metadata: Option<serde_json::Value>,
    payment_method_data: Option<Encryption>,
    last_used_at: Option<PrimitiveDateTime>,
    network_transaction_id: Option<String>,
    status: Option<storage_enums::PaymentMethodStatus>,
    locker_id: Option<String>,
    network_token_requestor_reference_id: Option<String>,
    payment_method: Option<storage_enums::PaymentMethod>,
    connector_mandate_details: Option<serde_json::Value>,
    updated_by: Option<String>,
    payment_method_type: Option<storage_enums::PaymentMethodType>,
    payment_method_issuer: Option<String>,
    last_modified: PrimitiveDateTime,
    network_token_locker_id: Option<String>,
    network_token_payment_method_data: Option<Encryption>,
    scheme: Option<String>,
}


pub async fn generate_access_token(state: SessionState) -> RouterResult<types::AccessToken> {
    let connector = enums::Connector::Paypal;
    let boxed_connector =
        types::api::ConnectorData::convert_connector(connector.to_string().as_str())?;
    let connector_auth =
        super::get_connector_auth(connector, state.conf.connector_onboarding.get_inner())?;

    connector::Paypal::get_access_token(
        &state,
        verify_connector_types::VerifyConnectorData {
            connector: boxed_connector,
            connector_auth,
            card_details: verify_connector_utils::get_test_card_details(connector)?.ok_or(
                ApiErrorResponse::FlowNotSupported {
                    flow: "Connector onboarding".to_string(),
                    connector: connector.to_string(),
                },
            )?,
        },
    )
    .await?
    .ok_or(ApiErrorResponse::InternalServerError)
    .attach_printable("Error occurred while retrieving access token")
}


pub struct GenerateFingerprintRequest {
    pub card: Card,
    pub hash_key: StrongSecret<String>,
}


impl api::ConnectorAccessToken for Shift4 {}

impl api::ConnectorAccessToken for for Shift4


File: crates/router/src/types/storage/payment_link.rs

use async_bb8_diesel::AsyncRunQueryDsl;
use diesel::{associations::HasTable, ExpressionMethods, QueryDsl};
pub use diesel_models::{
    payment_link::{PaymentLink, PaymentLinkNew},
    schema::payment_link::dsl,
};
use error_stack::ResultExt;

use crate::{
    connection::PgPooledConn,
    core::errors::{self, CustomResult},
    logger,
};

#[async_trait::async_trait]
pub trait PaymentLinkDbExt: Sized {
    async fn filter_by_constraints(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_link_list_constraints: api_models::payments::PaymentLinkListConstraints,
    ) -> CustomResult<Vec<Self>, errors::DatabaseError>;
}

#[async_trait::async_trait]
impl PaymentLinkDbExt for PaymentLink {
    async fn filter_by_constraints(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_link_list_constraints: api_models::payments::PaymentLinkListConstraints,
    ) -> CustomResult<Vec<Self>, errors::DatabaseError> {
        let mut filter = <Self as HasTable>::table()
            .filter(dsl::merchant_id.eq(merchant_id.to_owned()))
            .order(dsl::created_at.desc())
            .into_boxed();

        if let Some(created_time) = payment_link_list_constraints.created {
            filter = filter.filter(dsl::created_at.eq(created_time));
        }
        if let Some(created_time_lt) = payment_link_list_constraints.created_lt {
            filter = filter.filter(dsl::created_at.lt(created_time_lt));
        }
        if let Some(created_time_gt) = payment_link_list_constraints.created_gt {
            filter = filter.filter(dsl::created_at.gt(created_time_gt));
        }
        if let Some(created_time_lte) = payment_link_list_constraints.created_lte {
            filter = filter.filter(dsl::created_at.le(created_time_lte));
        }
        if let Some(created_time_gte) = payment_link_list_constraints.created_gte {
            filter = filter.filter(dsl::created_at.ge(created_time_gte));
        }
        if let Some(limit) = payment_link_list_constraints.limit {
            filter = filter.limit(limit);
        }

        logger::debug!(query = %diesel::debug_query::<diesel::pg::Pg, _>(&filter).to_string());

        filter
            .get_results_async(conn)
            .await
            // The query built here returns an empty Vec when no records are found, and if any error does occur,
            // it would be an internal database error, due to which we are raising a DatabaseError::Unknown error
            .change_context(errors::DatabaseError::Others)
            .attach_printable("Error filtering payment link by specified constraints")
    }
}


pub async fn time_future<F, R>(future: F) -> (R, time::Duration)
where
    F: futures::Future<Output = R>,
{
    let start = time::Instant::now();
    let result = future.await;
    let time_spent = start.elapsed();
    (result, time_spent)
}


pub struct NetceteraErrorDetails {
    /// Universally unique identifier for the transaction assigned by the 3DS Server.
    #[serde(rename = "threeDSServerTransID")]
    pub three_ds_server_trans_id: Option<String>,

    /// Universally Unique identifier for the transaction assigned by the ACS.
    #[serde(rename = "acsTransID")]
    pub acs_trans_id: Option<String>,

    /// Universally unique identifier for the transaction assigned by the DS.
    #[serde(rename = "dsTransID")]
    pub ds_trans_id: Option<String>,

    /// Code indicating the type of problem identified.
    pub error_code: String,

    /// Code indicating the 3-D Secure component that identified the error.
    pub error_component: Option<String>,

    /// Text describing the problem identified.
    pub error_description: String,

    /// Additional detail regarding the problem identified.
    pub error_detail: Option<String>,

    /// Universally unique identifier for the transaction assigned by the 3DS SDK.
    #[serde(rename = "sdkTransID")]
    pub sdk_trans_id: Option<String>,

    /// The Message Type that was identified as erroneous.
    pub error_message_type: Option<String>,
}


pub async fn api_key_revoke(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::ApiKeyId>,
) -> impl Responder {
    let flow = Flow::ApiKeyRevoke;
    let key_id = path.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        &key_id,
        |state,
         auth::AuthenticationDataWithoutProfile {
             merchant_account, ..
         },
         key_id,
         _| api_keys::revoke_api_key(state, merchant_account.get_id().to_owned(), key_id),
        auth::auth_type(
            &auth::AdminApiAuthWithMerchantIdFromHeader,
            &auth::JWTAuthMerchantFromHeader {
                required_permission: Permission::MerchantApiKeyWrite,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub fn validate(&self) -> Result<(), ApplicationError> {
        use common_utils::{fp_utils::when, id_type};

        when(self == &Self::default(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "CellId cannot be set to a default".into(),
            ))
        })
    }


pub async fn call_surcharge_decision_management_for_saved_card(
    state: &routes::SessionState,
    merchant_context: &domain::MerchantContext,
    business_profile: &Profile,
    payment_attempt: &storage::PaymentAttempt,
    payment_intent: storage::PaymentIntent,
    customer_payment_method_response: &mut api::CustomerPaymentMethodsListResponse,
) -> errors::RouterResult<()> {
    #[cfg(feature = "v1")]
    let algorithm_ref: routing_types::RoutingAlgorithmRef = merchant_context
        .get_merchant_account()
        .routing_algorithm
        .clone()
        .map(|val| val.parse_value("routing algorithm"))
        .transpose()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Could not decode the routing algorithm")?
        .unwrap_or_default();
    #[cfg(feature = "v2")]
    let algorithm_ref: routing_types::RoutingAlgorithmRef = todo!();

    // TODO: Move to business profile surcharge column
    let surcharge_results = perform_surcharge_decision_management_for_saved_cards(
        state,
        algorithm_ref,
        payment_attempt,
        &payment_intent,
        &mut customer_payment_method_response.customer_payment_methods,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("error performing surcharge decision operation")?;
    if !surcharge_results.is_empty_result() {
        surcharge_results
            .persist_individual_surcharge_details_in_redis(state, business_profile)
            .await?;
        let _ = state
            .store
            .update_payment_intent(
                &state.into(),
                payment_intent,
                storage::PaymentIntentUpdate::SurchargeApplicableUpdate {
                    surcharge_applicable: true,
                    updated_by: merchant_context
                        .get_merchant_account()
                        .storage_scheme
                        .to_string(),
                },
                merchant_context.get_merchant_key_store(),
                merchant_context.get_merchant_account().storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
            .attach_printable("Failed to update surcharge_applicable in Payment Intent");
    }
    Ok(())
}


pub fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMinorUnitForConnector,
        }
    }


OpenAPI Block Path: components.schemas.EliminationRoutingConfig
{
  "type": "object",
  "required": [
    "decision_engine_configs"
  ],
  "properties": {
    "params": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/DynamicRoutingConfigParams"
      },
      "nullable": true
    },
    "elimination_analyser_config": {
      "allOf": [
        {
          "$ref": "#/components/schemas/EliminationAnalyserConfig"
        }
      ],
      "nullable": true
    },
    "decision_engine_configs": {
      "$ref": "#/components/schemas/DecisionEngineEliminationData"
    }
  },
  "additionalProperties": false
}


pub async fn find_by_capture_id(conn: &PgPooledConn, capture_id: &str) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::capture_id.eq(capture_id.to_owned()),
        )
        .await
    }


OpenAPI Block Path: components.schemas.TokenDataType
{
  "type": "string",
  "description": "The type of token data to fetch for get-token endpoint",
  "enum": [
    "single_use_token",
    "multi_use_token",
    "network_token"
  ]
}


pub struct Nexinets;


pub async fn list_payment_attempts(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    path: web::Path<common_utils::id_type::GlobalPaymentId>,
) -> impl Responder {
    let flow = Flow::PaymentAttemptsList;
    let payment_intent_id = path.into_inner();

    let payload = api_models::payments::PaymentAttemptListRequest {
        payment_intent_id: payment_intent_id.clone(),
    };

    let header_payload = match HeaderPayload::foreign_try_from(req.headers()) {
        Ok(headers) => headers,
        Err(err) => {
            return api::log_and_return_error_response(err);
        }
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload.clone(),
        |session_state, auth, req_payload, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));

            payments::payments_list_attempts_using_payment_intent_id::<
                payments::operations::PaymentGetListAttempts,
                api_models::payments::PaymentAttemptListResponse,
                api_models::payments::PaymentAttemptListRequest,
                payments::operations::payment_attempt_list::PaymentGetListAttempts,
                hyperswitch_domain_models::payments::PaymentAttemptListData<
                    payments::operations::PaymentGetListAttempts,
                >,
            >(
                session_state,
                req_state,
                merchant_context,
                auth.profile,
                payments::operations::PaymentGetListAttempts,
                payload.clone(),
                req_payload.payment_intent_id,
                header_payload.clone(),
            )
        },
        auth::auth_type(
            &auth::V2ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            },
            &auth::JWTAuth {
                permission: Permission::ProfilePaymentRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


impl api::RefundSync for Dwolla {}


pub fn setter(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input = syn::parse_macro_input!(input as syn::DeriveInput);
    let ident = &input.ident;
    // All the fields in the parent struct
    let fields = if let syn::Data::Struct(syn::DataStruct {
        fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }),
        ..
    }) = input.data
    {
        named
    } else {
        // FIXME: Use `compile_error!()` instead
        panic!("You can't use this proc-macro on structs without fields");
    };

    // Methods in the build struct like if the struct is
    // Struct i {n: u32}
    // this will be
    // pub fn set_n(&mut self,n: u32)
    let build_methods = fields.iter().map(|f| {
        let name = f.ident.as_ref().unwrap();
        let method_name = format!("set_{name}");
        let method_ident = syn::Ident::new(&method_name, name.span());
        let ty = &f.ty;
        if check_if_auth_based_attr_is_present(f, "auth_based") {
            quote::quote! {
                pub fn #method_ident(&mut self, val:#ty, is_merchant_flow: bool)->&mut Self{
                    if is_merchant_flow {
                        self.#name = val;
                    }
                    self
                }
            }
        } else {
            quote::quote! {
                pub fn #method_ident(&mut self, val:#ty)->&mut Self{
                    self.#name = val;
                    self
                }
            }
        }
    });
    let output = quote::quote! {
    #[automatically_derived]
    impl #ident {
            #(#build_methods)*
        }

    };
    output.into()
}


pub async fn get_filters(
    pool: &AnalyticsProvider,
    req: GetAuthEventFilterRequest,
    auth: &AuthInfo,
) -> AnalyticsResult<AuthEventFiltersResponse> {
    let mut res = AuthEventFiltersResponse::default();
    for dim in req.group_by_names {
        let values = match pool {
                        AnalyticsProvider::Sqlx(_pool) => {
                            Err(report!(AnalyticsError::UnknownError))
            }
                        AnalyticsProvider::Clickhouse(pool) => {
                get_auth_events_filter_for_dimension(dim, auth, &req.time_range, pool)
                    .await
                    .map_err(|e| e.change_context(AnalyticsError::UnknownError))
            }
                    AnalyticsProvider::CombinedCkh(sqlx_pool, ckh_pool) | AnalyticsProvider::CombinedSqlx(sqlx_pool, ckh_pool) => {
                let ckh_result = get_auth_events_filter_for_dimension(
                    dim,
                    auth,
                    &req.time_range,
                    ckh_pool,
                )
                .await
                .map_err(|e| e.change_context(AnalyticsError::UnknownError));
                let sqlx_result = get_auth_events_filter_for_dimension(
                    dim,
                    auth,
                    &req.time_range,
                    sqlx_pool,
                )
                .await
                .map_err(|e| e.change_context(AnalyticsError::UnknownError));
                match (&sqlx_result, &ckh_result) {
                    (Ok(ref sqlx_res), Ok(ref ckh_res)) if sqlx_res != ckh_res => {
                        router_env::logger::error!(clickhouse_result=?ckh_res, postgres_result=?sqlx_res, "Mismatch between clickhouse & postgres refunds analytics filters")
                    },
                    _ => {}
                };
                ckh_result
            }
        }
        .change_context(AnalyticsError::UnknownError)?
        .into_iter()
        .filter_map(|fil: AuthEventFilterRow| match dim {
            AuthEventDimensions::AuthenticationStatus => fil.authentication_status.map(|i| i.as_ref().to_string()),
            AuthEventDimensions::TransactionStatus => fil.trans_status.map(|i| i.as_ref().to_string()),
            AuthEventDimensions::AuthenticationType => fil.authentication_type.map(|i| i.as_ref().to_string()),
            AuthEventDimensions::ErrorMessage => fil.error_message,
            AuthEventDimensions::AuthenticationConnector => fil.authentication_connector.map(|i| i.as_ref().to_string()),
            AuthEventDimensions::MessageVersion => fil.message_version,
            AuthEventDimensions::AcsReferenceNumber => fil.acs_reference_number,
            AuthEventDimensions::Platform => fil.platform,
            AuthEventDimensions::Mcc => fil.mcc,
           AuthEventDimensions::Currency => fil.currency.map(|i| i.as_ref().to_string()),
            AuthEventDimensions::MerchantCountry => fil.merchant_country,
            AuthEventDimensions::BillingCountry => fil.billing_country,
            AuthEventDimensions::ShippingCountry => fil.shipping_country,
            AuthEventDimensions::IssuerCountry => fil.issuer_country,
            AuthEventDimensions::EarliestSupportedVersion => fil.earliest_supported_version,
            AuthEventDimensions::LatestSupportedVersion => fil.latest_supported_version,
            AuthEventDimensions::WhitelistDecision => fil.whitelist_decision.map(|i| i.to_string()),
            AuthEventDimensions::DeviceManufacturer => fil.device_manufacturer,
            AuthEventDimensions::DeviceType => fil.device_type,
            AuthEventDimensions::DeviceBrand => fil.device_brand,
            AuthEventDimensions::DeviceOs => fil.device_os,
            AuthEventDimensions::DeviceDisplay => fil.device_display,
            AuthEventDimensions::BrowserName => fil.browser_name,
            AuthEventDimensions::BrowserVersion => fil.browser_version,
            AuthEventDimensions::IssuerId => fil.issuer_id,
            AuthEventDimensions::SchemeName => fil.scheme_name,
            AuthEventDimensions::ExemptionRequested => fil.exemption_requested.map(|i| i.to_string()),
            AuthEventDimensions::ExemptionAccepted => fil.exemption_accepted.map(|i| i.to_string()),
        })
        .collect::<Vec<String>>();
        res.query_data.push(AuthEventFilterValue {
            dimension: dim,
            values,
        })
    }
    Ok(res)
}


pub fn is_payout_initiated(status: api_enums::PayoutStatus) -> bool {
    !matches!(
        status,
        api_enums::PayoutStatus::RequiresCreation
            | api_enums::PayoutStatus::RequiresConfirmation
            | api_enums::PayoutStatus::RequiresPayoutMethodData
            | api_enums::PayoutStatus::RequiresVendorAccountCreation
            | api_enums::PayoutStatus::Initiated
    )
}


impl common_utils::events::ApiEventMetric for SchedulerHealthCheckResponse {}

impl common_utils::events::ApiEventMetric for for SchedulerHealthCheckResponse


pub struct InputData {
    credit_card: CreditCardData,
}


pub struct RefundResponse {
    pub gateway_response: GatewayResponse,
    pub payment_receipt: PaymentReceipt,
}


pub struct BluesnapRedirectionResponse {
    pub authentication_response: String,
}


impl api::Refund for Paybox {}


pub struct BillTo {
    first_name: Option<Secret<String>>,
    last_name: Option<Secret<String>>,
    address1: Option<Secret<String>>,
    locality: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    administrative_area: Option<Secret<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    postal_code: Option<Secret<String>>,
    country: Option<enums::CountryAlpha2>,
    email: pii::Email,
}


pub struct ReconStatus {
    pub is_order_data_set: bool,
    pub is_processor_data_set: bool,
}


Documentation: api-reference/v1/merchant-connector-account/merchant-connector--delete.mdx
# Type: Doc File

---
openapi: delete /accounts/{account_id}/connectors/{connector_id}
---


File: crates/analytics/src/api_event/filters.rs
 Public functions: 1
 Public structs: 1

use api_models::analytics::{api_event::ApiEventDimensions, Granularity, TimeRange};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use crate::{
    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql, Window},
    types::{AnalyticsCollection, AnalyticsDataSource, FiltersError, FiltersResult, LoadRow},
};

pub trait ApiEventFilterAnalytics: LoadRow<ApiEventFilter> {}

pub async fn get_api_event_filter_for_dimension<T>(
    dimension: ApiEventDimensions,
    merchant_id: &common_utils::id_type::MerchantId,
    time_range: &TimeRange,
    pool: &T,
) -> FiltersResult<Vec<ApiEventFilter>>
where
    T: AnalyticsDataSource + ApiEventFilterAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::ApiEvents);

    query_builder.add_select_column(dimension).switch()?;
    time_range
        .set_filter_clause(&mut query_builder)
        .attach_printable("Error filtering time range")
        .switch()?;

    query_builder
        .add_filter_clause("merchant_id", merchant_id)
        .switch()?;

    query_builder.set_distinct();

    query_builder
        .execute_query::<ApiEventFilter, _>(pool)
        .await
        .change_context(FiltersError::QueryBuildingError)?
        .change_context(FiltersError::QueryExecutionFailure)
}

#[derive(Debug, serde::Serialize, Eq, PartialEq, serde::Deserialize)]
pub struct ApiEventFilter {
    pub status_code: Option<i32>,
    pub flow_type: Option<String>,
    pub api_flow: Option<String>,
}


pub fn get_order_fulfillment_time(&self) -> Option<i64> {
        self.intent_fulfillment_time
    }