            maud::html! {
                (maud::DOCTYPE)
                html {
                    head {
                        meta name="viewport" content="width=device-width, initial-scale=1";
                    }

                    body style="background-color: #ffffff; padding: 20px; font-family: Arial, Helvetica, Sans-Serif;" {
                        div id="loader1" class="lottie" style="height: 150px; display: block; position: relative; margin-top: 150px; margin-left: auto; margin-right: auto;" { "" }

                        (PreEscaped(r#"<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.4/lottie.min.js"></script>"#))

                        (PreEscaped(r#"
                            <script>
                            var anime = bodymovin.loadAnimation({
                                container: document.getElementById('loader1'),
                                renderer: 'svg',
                                loop: true,
                                autoplay: true,
                                name: 'hyperswitch loader',
                                animationData: {"v":"4.8.0","meta":{"g":"LottieFiles AE 3.1.1","a":"","k":"","d":"","tc":""},"fr":29.9700012207031,"ip":0,"op":31.0000012626559,"w":400,"h":250,"nm":"loader_shape","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.25,202.671,0],"ix":2},"a":{"a":0,"k":[23.72,23.72,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[12.935,0],[0,-12.936],[-12.935,0],[0,12.935]],"o":[[-12.952,0],[0,12.935],[12.935,0],[0,-12.936]],"v":[[0,-23.471],[-23.47,0.001],[0,23.471],[23.47,0.001]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.427451010311,0.976470648074,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":19.99,"s":[100]},{"t":29.9800012211104,"s":[10]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[23.72,23.721],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.0000019550801,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"square 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[196.25,201.271,0],"ix":2},"a":{"a":0,"k":[22.028,22.03,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.914,0],[0,0],[0,-1.914],[0,0],[-1.914,0],[0,0],[0,1.914],[0,0]],"o":[[0,0],[-1.914,0],[0,0],[0,1.914],[0,0],[1.914,0],[0,0],[0,-1.914]],"v":[[18.313,-21.779],[-18.312,-21.779],[-21.779,-18.313],[-21.779,18.314],[-18.312,21.779],[18.313,21.779],[21.779,18.314],[21.779,-18.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.427451010311,0.976470648074,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":14.99,"s":[100]},{"t":24.9800010174563,"s":[10]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[22.028,22.029],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":47.0000019143492,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Triangle 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[116.25,200.703,0],"ix":2},"a":{"a":0,"k":[27.11,21.243,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.558,-0.879],[0,0],[-1.133,0],[0,0],[0.609,0.947],[0,0]],"o":[[-0.558,-0.879],[0,0],[-0.609,0.947],[0,0],[1.133,0],[0,0],[0,0]],"v":[[1.209,-20.114],[-1.192,-20.114],[-26.251,18.795],[-25.051,20.993],[25.051,20.993],[26.251,18.795],[1.192,-20.114]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.427451010311,0.976470648074,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":9.99,"s":[100]},{"t":19.9800008138021,"s":[10]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[27.11,21.243],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.0000019550801,"st":0,"bm":0}],"markers":[]}
                            })
                            </script>
                            "#))

                        h3 style="text-align: center;" { "Please wait while we process your payment..." }
                    }
                    (PreEscaped(format!("<form id=\"PaReqForm\" method=\"POST\" action=\"{acs_url}\">
                        <input type=\"hidden\" name=\"creq\" value=\"{creq}\">
                        </form>")))
                    (PreEscaped(format!("<script>
                        {logging_template}
                        window.onload = function() {{
                        var paReqForm = document.querySelector('#PaReqForm'); if(paReqForm) paReqForm.submit();
                        }}
                    </script>")))
                }
            }
        }
        RedirectForm::Payme => {
            maud::html! {
                (maud::DOCTYPE)
                head {
                    (PreEscaped(r#"<script src="https://cdn.paymeservice.com/hf/v1/hostedfields.js"></script>"#))
                }
                (PreEscaped(format!("<script>
                    {logging_template}
                    var f = document.createElement('form');
                    f.action=window.location.pathname.replace(/payments\\/redirect\\/(\\w+)\\/(\\w+)\\/\\w+/, \"payments/$1/$2/redirect/complete/payme\");
                    f.method='POST';
                    PayMe.clientData()
                    .then((data) => {{
                        var i=document.createElement('input');
                        i.type='hidden';
                        i.name='meta_data';
                        i.value=data.hash;
                        f.appendChild(i);
                        document.body.appendChild(f);
                        f.submit();
                    }})
                    .catch((error) => {{
                        f.submit();
                    }});
            </script>
                ")))
            }
        }
        RedirectForm::Braintree {
            client_token,
            card_token,
            bin,
            acs_url,
        } => {
            maud::html! {
            (maud::DOCTYPE)
            html {
                head {
                    meta name="viewport" content="width=device-width, initial-scale=1";
                    (PreEscaped(r#"<script src="https://js.braintreegateway.com/web/3.97.1/js/three-d-secure.js"></script>"#))
                    // (PreEscaped(r#"<script src="https://js.braintreegateway.com/web/3.97.1/js/hosted-fields.js"></script>"#))

                }
                    body style="background-color: #ffffff; padding: 20px; font-family: Arial, Helvetica, Sans-Serif;" {

                        div id="loader1" class="lottie" style="height: 150px; display: block; position: relative; margin-top: 150px; margin-left: auto; margin-right: auto;" { "" }

                        (PreEscaped(r#"<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.4/lottie.min.js"></script>"#))

                        (PreEscaped(r#"
                            <script>
                            var anime = bodymovin.loadAnimation({
                                container: document.getElementById('loader1'),
                                renderer: 'svg',
                                loop: true,
                                autoplay: true,
                                name: 'hyperswitch loader',
                                animationData: {"v":"4.8.0","meta":{"g":"LottieFiles AE 3.1.1","a":"","k":"","d":"","tc":""},"fr":29.9700012207031,"ip":0,"op":31.0000012626559,"w":400,"h":250,"nm":"loader_shape","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[278.25,202.671,0],"ix":2},"a":{"a":0,"k":[23.72,23.72,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[12.935,0],[0,-12.936],[-12.935,0],[0,12.935]],"o":[[-12.952,0],[0,12.935],[12.935,0],[0,-12.936]],"v":[[0,-23.471],[-23.47,0.001],[0,23.471],[23.47,0.001]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.427451010311,0.976470648074,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":19.99,"s":[100]},{"t":29.9800012211104,"s":[10]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[23.72,23.721],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.0000019550801,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"square 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[196.25,201.271,0],"ix":2},"a":{"a":0,"k":[22.028,22.03,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.914,0],[0,0],[0,-1.914],[0,0],[-1.914,0],[0,0],[0,1.914],[0,0]],"o":[[0,0],[-1.914,0],[0,0],[0,1.914],[0,0],[1.914,0],[0,0],[0,-1.914]],"v":[[18.313,-21.779],[-18.312,-21.779],[-21.779,-18.313],[-21.779,18.314],[-18.312,21.779],[18.313,21.779],[21.779,18.314],[21.779,-18.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.427451010311,0.976470648074,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":14.99,"s":[100]},{"t":24.9800010174563,"s":[10]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[22.028,22.029],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":47.0000019143492,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Triangle 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[116.25,200.703,0],"ix":2},"a":{"a":0,"k":[27.11,21.243,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.558,-0.879],[0,0],[-1.133,0],[0,0],[0.609,0.947],[0,0]],"o":[[-0.558,-0.879],[0,0],[-0.609,0.947],[0,0],[1.133,0],[0,0],[0,0]],"v":[[1.209,-20.114],[-1.192,-20.114],[-26.251,18.795],[-25.051,20.993],[25.051,20.993],[26.251,18.795],[1.192,-20.114]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.427451010311,0.976470648074,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":9.99,"s":[100]},{"t":19.9800008138021,"s":[10]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[27.11,21.243],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":48.0000019550801,"st":0,"bm":0}],"markers":[]}
                            })
                            </script>
                            "#))

                        h3 style="text-align: center;" { "Please wait while we process your payment..." }
                    }

                (PreEscaped(format!("<script>
                                {logging_template}
                                var my3DSContainer;
                                var clientToken = \"{client_token}\";
                                braintree.threeDSecure.create({{
                                        authorization: clientToken,
                                        version: 2
                                    }}, function(err, threeDs) {{
                                        threeDs.verifyCard({{
                                            amount: \"{amount}\",
                                            nonce: \"{card_token}\",
                                            bin: \"{bin}\",
                                            addFrame: function(err, iframe) {{
                                                my3DSContainer = document.createElement('div');
                                                my3DSContainer.appendChild(iframe);
                                                document.body.appendChild(my3DSContainer);
                                            }},
                                            removeFrame: function() {{
                                                if(my3DSContainer && my3DSContainer.parentNode) {{
                                                    my3DSContainer.parentNode.removeChild(my3DSContainer);
                                                }}
                                            }},
                                            onLookupComplete: function(data, next) {{
                                                // console.log(\"onLookup Complete\", data);
                                                    next();
                                                }}
                                            }},
                                            function(err, payload) {{
                                                if(err) {{
                                                    console.error(err);
                                                    var f = document.createElement('form');
                                                    f.action=window.location.pathname.replace(/payments\\/redirect\\/(\\w+)\\/(\\w+)\\/\\w+/, \"payments/$1/$2/redirect/response/braintree\");
                                                    var i = document.createElement('input');
                                                    i.type = 'hidden';
                                                    f.method='POST';
                                                    i.name = 'authentication_response';
                                                    i.value = JSON.stringify(err);
                                                    f.appendChild(i);
                                                    f.body = JSON.stringify(err);
                                                    document.body.appendChild(f);
                                                    f.submit();
                                                }} else {{
                                                    // console.log(payload);
                                                    var f = document.createElement('form');
                                                    f.action=\"{acs_url}\";
                                                    var i = document.createElement('input');
                                                    i.type = 'hidden';
                                                    f.method='POST';
                                                    i.name = 'authentication_response';
                                                    i.value = JSON.stringify(payload);
                                                    f.appendChild(i);
                                                    f.body = JSON.stringify(payload);
                                                    document.body.appendChild(f);
                                                    f.submit();
                                                    }}
                                                }});
                                        }}); </script>"
                                    )))
                }}
        }
        RedirectForm::Nmi {
            amount,
            currency,
            public_key,
            customer_vault_id,
            order_id,
        } => {
            let public_key_val = public_key.peek();
            maud::html! {
                    (maud::DOCTYPE)
                    head {
                        (PreEscaped(r#"<script src="https://secure.networkmerchants.com/js/v1/Gateway.js"></script>"#))
                    }
                    body style="background-color: #ffffff; padding: 20px; font-family: Arial, Helvetica, Sans-Serif;" {

                        div id="loader-wrapper" {
                            div id="loader1" class="lottie" style="height: 150px; display: block; position: relative; margin-top: 150px; margin-left: auto; margin-right: auto;" { "" }

                        (PreEscaped(r#"<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.4/lottie.min.js"></script>"#))

                        (PreEscaped(r#"
                            <script>
                            var anime = bodymovin.loadAnimation({
                                container: document.getElementById('loader1'),
                                renderer: 'svg',
                                loop: true,
                                autoplay: true,
                                name: 'hyperswitch loader',


pub struct WalletRequest {
    flow: Flow,
    payment_method: PaymentMethod,
}


pub struct Memoization<V: ValueNode>(
    #[allow(clippy::type_complexity)]
    FxHashMap<(NodeId, Relation, Strength), Result<(), Arc<AnalysisTrace<V>>>>,
);


pub struct FiservAuthType {
    pub(super) api_key: Secret<String>,
    pub(super) merchant_account: Secret<String>,
    pub(super) api_secret: Secret<String>,
}


pub struct OrderFulfillmentTime(i64);


OpenAPI Block Path: components.schemas.GsmRetrieveRequest
{
  "type": "object",
  "required": [
    "connector",
    "flow",
    "sub_flow",
    "code",
    "message"
  ],
  "properties": {
    "connector": {
      "$ref": "#/components/schemas/Connector"
    },
    "flow": {
      "type": "string",
      "description": "The flow in which the code and message occurred for a connector"
    },
    "sub_flow": {
      "type": "string",
      "description": "The sub_flow in which the code and message occurred  for a connector"
    },
    "code": {
      "type": "string",
      "description": "code received from the connector"
    },
    "message": {
      "type": "string",
      "description": "message received from the connector"
    }
  }
}


pub fn generate_env_specific_merchant_id(value: String) -> UserResult<id_type::MerchantId> {
    if matches!(env::which(), env::Env::Production) {
        let raw_id = domain::MerchantId::new(value)?;
        Ok(id_type::MerchantId::try_from(raw_id)?)
    } else {
        Ok(id_type::MerchantId::new_from_unix_timestamp())
    }
}


pub struct Details {
    pub field: String,
    pub reason: String,
}


impl api::PaymentSync for Amazonpay {}


impl api::PaymentCapture for Billwerk {}

impl api::PaymentCapture for for Billwerk


File: crates/diesel_models/src/query/dashboard_metadata.rs
 Public functions: 6

use common_utils::id_type;
use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods};

use crate::{
    enums,
    query::generics,
    schema::dashboard_metadata::dsl,
    user::dashboard_metadata::{
        DashboardMetadata, DashboardMetadataNew, DashboardMetadataUpdate,
        DashboardMetadataUpdateInternal,
    },
    PgPooledConn, StorageResult,
};

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

impl DashboardMetadata {
    pub async fn update(
        conn: &PgPooledConn,
        user_id: Option<String>,
        merchant_id: id_type::MerchantId,
        org_id: id_type::OrganizationId,
        data_key: enums::DashboardMetadata,
        dashboard_metadata_update: DashboardMetadataUpdate,
    ) -> StorageResult<Self> {
        let predicate = dsl::merchant_id
            .eq(merchant_id.to_owned())
            .and(dsl::org_id.eq(org_id.to_owned()))
            .and(dsl::data_key.eq(data_key.to_owned()));

        if let Some(uid) = user_id {
            generics::generic_update_with_unique_predicate_get_result::<
                <Self as HasTable>::Table,
                _,
                _,
                _,
            >(
                conn,
                predicate.and(dsl::user_id.eq(uid)),
                DashboardMetadataUpdateInternal::from(dashboard_metadata_update),
            )
            .await
        } else {
            generics::generic_update_with_unique_predicate_get_result::<
                <Self as HasTable>::Table,
                _,
                _,
                _,
            >(
                conn,
                predicate.and(dsl::user_id.is_null()),
                DashboardMetadataUpdateInternal::from(dashboard_metadata_update),
            )
            .await
        }
    }

    pub async fn find_user_scoped_dashboard_metadata(
        conn: &PgPooledConn,
        user_id: String,
        merchant_id: id_type::MerchantId,
        org_id: id_type::OrganizationId,
        data_types: Vec<enums::DashboardMetadata>,
    ) -> StorageResult<Vec<Self>> {
        let predicate = dsl::user_id
            .eq(user_id)
            .and(dsl::merchant_id.eq(merchant_id))
            .and(dsl::org_id.eq(org_id))
            .and(dsl::data_key.eq_any(data_types));

        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            predicate,
            None,
            None,
            Some(dsl::last_modified_at.asc()),
        )
        .await
    }

    pub async fn find_merchant_scoped_dashboard_metadata(
        conn: &PgPooledConn,
        merchant_id: id_type::MerchantId,
        org_id: id_type::OrganizationId,
        data_types: Vec<enums::DashboardMetadata>,
    ) -> StorageResult<Vec<Self>> {
        let predicate = dsl::merchant_id
            .eq(merchant_id)
            .and(dsl::org_id.eq(org_id))
            .and(dsl::data_key.eq_any(data_types));

        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            predicate,
            None,
            None,
            Some(dsl::last_modified_at.asc()),
        )
        .await
    }

    pub async fn delete_all_user_scoped_dashboard_metadata_by_merchant_id(
        conn: &PgPooledConn,
        user_id: String,
        merchant_id: id_type::MerchantId,
    ) -> StorageResult<bool> {
        generics::generic_delete::<<Self as HasTable>::Table, _>(
            conn,
            dsl::user_id
                .eq(user_id)
                .and(dsl::merchant_id.eq(merchant_id)),
        )
        .await
    }

    pub async fn delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
        conn: &PgPooledConn,
        user_id: String,
        merchant_id: id_type::MerchantId,
        data_key: enums::DashboardMetadata,
    ) -> StorageResult<Self> {
        generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::user_id
                .eq(user_id)
                .and(dsl::merchant_id.eq(merchant_id))
                .and(dsl::data_key.eq(data_key)),
        )
        .await
    }
}


impl api::Refund for Cryptopay {}


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


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


pub struct PaymentMethodDeleteResponse {
    /// The unique identifier of the Payment method
    #[schema(value_type = String, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")]
    pub id: id_type::GlobalPaymentMethodId,
}


pub struct Netcetera;


impl api::PaymentSync for HyperswitchVault {}

impl api::PaymentSync for for HyperswitchVault


impl api::Payment for Xendit {}


pub struct DetailTax {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tax_included_in_total: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tax_amount: Option<MinorUnit>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub card_acceptor_tax_id: Option<Secret<String>>,
}


pub struct ApiKeyAuthWithMerchantIdFromRoute(pub id_type::MerchantId);


pub struct OrderAddress {
    first_name: Option<Secret<String>>,
    last_name: Option<Secret<String>>,
    address1: Option<Secret<String>>,
    country_code: Option<common_enums::CountryAlpha2>,
    city: Option<String>,
    province: Option<Secret<String>>,
    phone: Option<Secret<String>>,
    zip: Option<Secret<String>>,
}


OpenAPI Block Path: components.schemas.MandateResponse
{
  "type": "object",
  "required": [
    "mandate_id",
    "status",
    "payment_method_id",
    "payment_method"
  ],
  "properties": {
    "mandate_id": {
      "type": "string",
      "description": "The identifier for mandate"
    },
    "status": {
      "$ref": "#/components/schemas/MandateStatus"
    },
    "payment_method_id": {
      "type": "string",
      "description": "The identifier for payment method"
    },
    "payment_method": {
      "type": "string",
      "description": "The payment method"
    },
    "payment_method_type": {
      "type": "string",
      "description": "The payment method type",
      "nullable": true
    },
    "card": {
      "allOf": [
        {
          "$ref": "#/components/schemas/MandateCardDetails"
        }
      ],
      "nullable": true
    },
    "customer_acceptance": {
      "allOf": [
        {
          "$ref": "#/components/schemas/CustomerAcceptance"
        }
      ],
      "nullable": true
    }
  }
}


impl ConnectorCommon for Adyen {
    fn id(&self) -> &'static str {
        "adyen"
    }
    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Minor
    }
    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let auth = adyen::AdyenAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        Ok(vec![(
            headers::X_API_KEY.to_string(),
            auth.api_key.into_masked(),
        )])
    }
    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.adyen.base_url.as_ref()
    }

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

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

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.error_code,
            message: response.message.to_owned(),
            reason: Some(response.message),
            attempt_status: None,
            connector_transaction_id: response.psp_reference,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}


impl ApiEventMetric for CardInfoUpdateRequest {}

impl ApiEventMetric for for CardInfoUpdateRequest


OpenAPI Block Path: components.schemas.PaymentsCancelRequest
{
  "type": "object",
  "properties": {
    "cancellation_reason": {
      "type": "string",
      "description": "The reason for the payment cancel",
      "nullable": true
    },
    "merchant_connector_details": {
      "allOf": [
        {
          "$ref": "#/components/schemas/MerchantConnectorDetailsWrap"
        }
      ],
      "nullable": true
    }
  }
}


OpenAPI Block Path: paths."/customers/{customer_id}/payment_methods"
{
  "get": {
    "tags": [
      "Payment Methods"
    ],
    "summary": "List payment methods for a Customer",
    "description": "Lists all the applicable payment methods for a particular Customer ID.",
    "operationId": "List all Payment Methods for a Customer",
    "parameters": [
      {
        "name": "customer_id",
        "in": "path",
        "description": "The unique identifier for the customer account",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "client_secret",
        "in": "query",
        "description": "This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK",
        "required": false,
        "schema": {
          "type": "string",
          "nullable": true
        }
      },
      {
        "name": "accepted_countries",
        "in": "query",
        "description": "The two-letter ISO currency code",
        "required": false,
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/CountryAlpha2"
          },
          "nullable": true
        }
      },
      {
        "name": "accepted_currencies",
        "in": "query",
        "description": "The three-letter ISO currency code",
        "required": false,
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/Currency"
          },
          "nullable": true
        }
      },
      {
        "name": "amount",
        "in": "query",
        "description": "The amount accepted for processing by the particular payment method.",
        "required": false,
        "schema": {
          "type": "integer",
          "format": "int64",
          "nullable": true
        }
      },
      {
        "name": "recurring_enabled",
        "in": "query",
        "description": "Indicates whether the payment method is eligible for recurring payments",
        "required": false,
        "schema": {
          "type": "boolean",
          "nullable": true
        }
      },
      {
        "name": "installment_payment_enabled",
        "in": "query",
        "description": "Indicates whether the payment method is eligible for installment payments",
        "required": false,
        "schema": {
          "type": "boolean",
          "nullable": true
        }
      },
      {
        "name": "limit",
        "in": "query",
        "description": "Indicates the limit of last used payment methods",
        "required": false,
        "schema": {
          "type": "integer",
          "format": "int64",
          "nullable": true
        }
      },
      {
        "name": "card_networks",
        "in": "query",
        "description": "Indicates whether the payment method is eligible for card netwotks",
        "required": false,
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/CardNetwork"
          },
          "nullable": true
        }
      }
    ],
    "responses": {
      "200": {
        "description": "Payment Methods retrieved",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/CustomerPaymentMethodsListResponse"
            }
          }
        }
      },
      "400": {
        "description": "Invalid Data"
      },
      "404": {
        "description": "Payment Methods does not exist in records"
      }
    },
    "security": [
      {
        "api_key": []
      }
    ]
  }
}


pub async fn add_refund_sync_task(
    db: &dyn db::StorageInterface,
    refund: &diesel_refund::Refund,
    runner: storage::ProcessTrackerRunner,
) -> errors::RouterResult<storage::ProcessTracker> {
    let task = "SYNC_REFUND";
    let process_tracker_id = format!("{runner}_{task}_{}", refund.id.get_string_repr());
    let schedule_time = common_utils::date_time::now();
    let refund_workflow_tracking_data = refund_to_refund_core_workflow_model(refund);
    let tag = ["REFUND"];
    let process_tracker_entry = storage::ProcessTrackerNew::new(
        process_tracker_id,
        task,
        runner,
        tag,
        refund_workflow_tracking_data,
        None,
        schedule_time,
        common_types::consts::API_VERSION,
    )
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("Failed to construct refund sync process tracker task")?;

    let response = db
        .insert_process(process_tracker_entry)
        .await
        .to_duplicate_response(errors::ApiErrorResponse::DuplicateRefundRequest)
        .attach_printable_lazy(|| {
            format!(
                "Failed while inserting task in process_tracker: refund_id: {}",
                refund.id.get_string_repr()
            )
        })?;
    metrics::TASKS_ADDED_COUNT.add(1, router_env::metric_attributes!(("flow", "Refund")));

    Ok(response)
}


pub async fn filter_payment_methods(
    graph: &cgraph::ConstraintGraph<dir::DirValue>,
    mca_id: id_type::MerchantConnectorAccountId,
    payment_methods: &[Secret<serde_json::Value>],
    req: &mut api::PaymentMethodListRequest,
    resp: &mut Vec<ResponsePaymentMethodIntermediate>,
    payment_intent: Option<&storage::PaymentIntent>,
    payment_attempt: Option<&storage::PaymentAttempt>,
    address: Option<&domain::Address>,
    connector: String,
    configs: &settings::Settings<RawSecret>,
) -> errors::CustomResult<(), errors::ApiErrorResponse> {
    for payment_method in payment_methods.iter() {
        let parse_result = serde_json::from_value::<PaymentMethodsEnabled>(
            payment_method.clone().expose().clone(),
        );
        if let Ok(payment_methods_enabled) = parse_result {
            let payment_method = payment_methods_enabled.payment_method;

            let allowed_payment_method_types = payment_intent.and_then(|payment_intent| {
                payment_intent
                    .allowed_payment_method_types
                    .clone()
                    .map(|val| val.parse_value("Vec<PaymentMethodType>"))
                    .transpose()
                    .unwrap_or_else(|error| {
                        logger::error!(
                            ?error,
                            "Failed to deserialize PaymentIntent allowed_payment_method_types"
                        );
                        None
                    })
            });

            for payment_method_type_info in payment_methods_enabled
                .payment_method_types
                .unwrap_or_default()
            {
                if filter_recurring_based(&payment_method_type_info, req.recurring_enabled)
                    && filter_installment_based(
                        &payment_method_type_info,
                        req.installment_payment_enabled,
                    )
                    && filter_amount_based(&payment_method_type_info, req.amount)
                {
                    let payment_method_object = payment_method_type_info.clone();

                    let pm_dir_value: dir::DirValue =
                        (payment_method_type_info.payment_method_type, payment_method)
                            .into_dir_value()
                            .change_context(errors::ApiErrorResponse::InternalServerError)
                            .attach_printable("pm_value_node not created")?;

                    let connector_variant = api_enums::Connector::from_str(connector.as_str())
                        .change_context(errors::ConnectorError::InvalidConnectorName)
                        .change_context(errors::ApiErrorResponse::InvalidDataValue {
                            field_name: "connector",
                        })
                        .attach_printable_lazy(|| {
                            format!("unable to parse connector name {connector:?}")
                        })?;

                    let mut context_values: Vec<dir::DirValue> = Vec::new();
                    context_values.push(pm_dir_value.clone());

                    payment_intent.map(|intent| {
                        intent.currency.map(|currency| {
                            context_values.push(dir::DirValue::PaymentCurrency(currency))
                        })
                    });
                    address.map(|address| {
                        address.country.map(|country| {
                            context_values.push(dir::DirValue::BillingCountry(
                                common_enums::Country::from_alpha2(country),
                            ))
                        })
                    });

                    // Addition of Connector to context
                    if let Ok(connector) = api_enums::RoutableConnectors::from_str(
                        connector_variant.to_string().as_str(),
                    ) {
                        context_values.push(dir::DirValue::Connector(Box::new(
                            api_models::routing::ast::ConnectorChoice { connector },
                        )));
                    };

                    let filter_pm_based_on_allowed_types = filter_pm_based_on_allowed_types(
                        allowed_payment_method_types.as_ref(),
                        payment_method_object.payment_method_type,
                    );

                    // Filter logic for payment method types based on the below conditions
                    // Case 1: If the payment method type support Zero Mandate flow, filter only payment method type that support it
                    // Case 2: Whether the payment method type support Mandates or not, list all the payment method types
                    if payment_attempt
                        .and_then(|attempt| attempt.mandate_details.as_ref())
                        .is_some()
                        || payment_intent
                            .and_then(|intent| intent.setup_future_usage)
                            .map(|future_usage| {
                                future_usage == common_enums::FutureUsage::OffSession
                            })
                            .unwrap_or(false)
                    {
                        payment_intent.map(|intent| intent.amount).map(|amount| {
                            if amount == MinorUnit::zero() {
                                if configs
                                    .zero_mandates
                                    .supported_payment_methods
                                    .0
                                    .get(&payment_method)
                                    .and_then(|supported_pm_for_mandates| {
                                        supported_pm_for_mandates
                                            .0
                                            .get(&payment_method_type_info.payment_method_type)
                                            .map(|supported_connector_for_mandates| {
                                                supported_connector_for_mandates
                                                    .connector_list
                                                    .contains(&connector_variant)
                                            })
                                    })
                                    .unwrap_or(false)
                                {
                                    context_values.push(dir::DirValue::PaymentType(
                                        euclid::enums::PaymentType::SetupMandate,
                                    ));
                                }
                            } else if configs
                                .mandates
                                .supported_payment_methods
                                .0
                                .get(&payment_method)
                                .and_then(|supported_pm_for_mandates| {
                                    supported_pm_for_mandates
                                        .0
                                        .get(&payment_method_type_info.payment_method_type)
                                        .map(|supported_connector_for_mandates| {
                                            supported_connector_for_mandates
                                                .connector_list
                                                .contains(&connector_variant)
                                        })
                                })
                                .unwrap_or(false)
                            {
                                context_values.push(dir::DirValue::PaymentType(
                                    euclid::enums::PaymentType::NewMandate,
                                ));
                            } else {
                                context_values.push(dir::DirValue::PaymentType(
                                    euclid::enums::PaymentType::NonMandate,
                                ));
                            }
                        });
                    } else {
                        context_values.push(dir::DirValue::PaymentType(
                            euclid::enums::PaymentType::NonMandate,
                        ));
                    }

                    payment_attempt
                        .and_then(|attempt| attempt.mandate_data.as_ref())
                        .map(|mandate_detail| {
                            if mandate_detail.update_mandate_id.is_some() {
                                context_values.push(dir::DirValue::PaymentType(
                                    euclid::enums::PaymentType::UpdateMandate,
                                ));
                            }
                        });

                    payment_attempt
                        .and_then(|inner| inner.capture_method)
                        .map(|capture_method| {
                            context_values.push(dir::DirValue::CaptureMethod(capture_method));
                        });

                    let filter_pm_card_network_based = filter_pm_card_network_based(
                        payment_method_object.card_networks.as_ref(),
                        req.card_networks.as_ref(),
                        payment_method_object.payment_method_type,
                    );

                    let saved_payment_methods_filter = req
                        .client_secret
                        .as_ref()
                        .map(|cs| {
                            if cs.starts_with("pm_") {
                                configs
                                    .saved_payment_methods
                                    .sdk_eligible_payment_methods
                                    .contains(payment_method.to_string().as_str())
                            } else {
                                true
                            }
                        })
                        .unwrap_or(true);

                    let context = AnalysisContext::from_dir_values(context_values.clone());
                    logger::info!("Context created for List Payment method is {:?}", context);

                    let domain_ident: &[String] = &[mca_id.clone().get_string_repr().to_string()];
                    let result = graph.key_value_analysis(
                        pm_dir_value.clone(),
                        &context,
                        &mut cgraph::Memoization::new(),
                        &mut cgraph::CycleCheck::new(),
                        Some(domain_ident),
                    );
                    if let Err(ref e) = result {
                        logger::error!(
                            "Error while performing Constraint graph's key value analysis
                            for list payment methods {:?}",
                            e
                        );
                    } else if filter_pm_based_on_allowed_types
                        && filter_pm_card_network_based
                        && saved_payment_methods_filter
                        && matches!(result, Ok(()))
                    {
                        let response_pm_type = ResponsePaymentMethodIntermediate::new(
                            payment_method_object,
                            connector.clone(),
                            mca_id.get_string_repr().to_string(),
                            payment_method,
                        );
                        resp.push(response_pm_type);
                    } else {
                        logger::error!("Filtering Payment Methods Failed");
                    }
                }
            }
        }
    }
    Ok(())
}


File: crates/hyperswitch_domain_models/src/router_flow_types/unified_authentication_service.rs
 Public structs: 4

#[derive(Debug, Clone)]
pub struct PreAuthenticate;

#[derive(Debug, Clone)]
pub struct PostAuthenticate;

#[derive(Debug, Clone)]
pub struct AuthenticationConfirmation;

#[derive(Debug, Clone)]
pub struct Authenticate;


impl api::PaymentCapture for Redsys {}


pub struct TokenDetails {
    pub payment_token: cards::CardNumber,
    pub payment_account_reference: String,
    pub token_expiration_month: Secret<String>,
    pub token_expiration_year: Secret<String>,
}


pub struct PostProcessing;


pub async fn generate_recon_token(
    state: SessionState,
    user_with_role: authentication::UserFromTokenWithRoleInfo,
) -> RouterResponse<recon_api::ReconTokenResponse> {
    let user = user_with_role.user;
    let token = authentication::ReconToken::new_token(
        user.user_id.clone(),
        user.merchant_id.clone(),
        &state.conf,
        user.org_id.clone(),
        user.profile_id.clone(),
        user.tenant_id,
        user_with_role.role_info,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable_lazy(|| {
        format!(
            "Failed to create recon token for params [user_id, org_id, mid, pid] [{}, {:?}, {:?}, {:?}]",
            user.user_id, user.org_id, user.merchant_id, user.profile_id,
        )
    })?;

    Ok(service_api::ApplicationResponse::Json(
        recon_api::ReconTokenResponse {
            token: token.into(),
        },
    ))
}


pub async fn get_api_event<T>(
    merchant_id: &common_utils::id_type::MerchantId,
    query_param: ApiLogsRequest,
    pool: &T,
) -> FiltersResult<Vec<ApiLogsResult>>
where
    T: AnalyticsDataSource + ApiLogsFilterAnalytics,
    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("*").switch()?;

    query_builder
        .add_filter_clause("merchant_id", merchant_id)
        .switch()?;
    match query_param.query_param {
        QueryType::Payment { payment_id } => {
            query_builder
                .add_filter_clause("payment_id", &payment_id)
                .switch()?;
            query_builder
                .add_filter_in_range_clause(
                    "api_flow",
                    &[
                        Flow::PaymentsCancel,
                        Flow::PaymentsCapture,
                        Flow::PaymentsConfirm,
                        Flow::PaymentsCreate,
                        Flow::PaymentsStart,
                        Flow::PaymentsUpdate,
                        Flow::RefundsCreate,
                        Flow::RefundsUpdate,
                        Flow::DisputesEvidenceSubmit,
                        Flow::AttachDisputeEvidence,
                        Flow::RetrieveDisputeEvidence,
                        Flow::IncomingWebhookReceive,
                    ],
                )
                .switch()?;
        }
        QueryType::Refund {
            payment_id,
            refund_id,
        } => {
            query_builder
                .add_filter_clause("payment_id", &payment_id)
                .switch()?;
            query_builder
                .add_filter_clause("refund_id", refund_id)
                .switch()?;
            query_builder
                .add_filter_in_range_clause("api_flow", &[Flow::RefundsCreate, Flow::RefundsUpdate])
                .switch()?;
        }
        QueryType::Dispute {
            payment_id,
            dispute_id,
        } => {
            query_builder
                .add_filter_clause("payment_id", &payment_id)
                .switch()?;
            query_builder
                .add_filter_clause("dispute_id", dispute_id)
                .switch()?;
            query_builder
                .add_filter_in_range_clause(
                    "api_flow",
                    &[
                        Flow::DisputesEvidenceSubmit,
                        Flow::AttachDisputeEvidence,
                        Flow::RetrieveDisputeEvidence,
                    ],
                )
                .switch()?;
        }
    }
    //TODO!: update the execute_query function to return reports instead of plain errors...
    query_builder
        .execute_query::<ApiLogsResult, _>(pool)
        .await
        .change_context(FiltersError::QueryBuildingError)?
        .change_context(FiltersError::QueryExecutionFailure)
}


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

pub use diesel_models::unified_translations::{
    UnifiedTranslations, UnifiedTranslationsNew, UnifiedTranslationsUpdate,
    UnifiedTranslationsUpdateInternal,
};


impl webhooks::IncomingWebhook for Elavon {
    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))
    }
}

impl webhooks::IncomingWebhook for for Elavon


impl api::MandateSetup for Boku {}


File: crates/router/src/utils/connector_onboarding.rs
 Public functions: 5

use diesel_models::{ConfigNew, ConfigUpdate};
use error_stack::ResultExt;

use super::errors::StorageErrorExt;
use crate::{
    consts,
    core::errors::{ApiErrorResponse, NotImplementedMessage, RouterResult},
    routes::{app::settings, SessionState},
    types::{self, api::enums},
};

pub mod paypal;

pub fn get_connector_auth(
    connector: enums::Connector,
    connector_data: &settings::ConnectorOnboarding,
) -> RouterResult<types::ConnectorAuthType> {
    match connector {
        enums::Connector::Paypal => Ok(types::ConnectorAuthType::BodyKey {
            api_key: connector_data.paypal.client_secret.clone(),
            key1: connector_data.paypal.client_id.clone(),
        }),
        _ => Err(ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason(format!(
                "Onboarding is not implemented for {connector}",
            )),
        }
        .into()),
    }
}

pub fn is_enabled(
    connector: types::Connector,
    conf: &settings::ConnectorOnboarding,
) -> Option<bool> {
    match connector {
        enums::Connector::Paypal => Some(conf.paypal.enabled),
        _ => None,
    }
}

pub async fn check_if_connector_exists(
    state: &SessionState,
    connector_id: &common_utils::id_type::MerchantConnectorAccountId,
    merchant_id: &common_utils::id_type::MerchantId,
) -> RouterResult<()> {
    let key_manager_state = &state.into();
    let key_store = state
        .store
        .get_merchant_key_store_by_merchant_id(
            key_manager_state,
            merchant_id,
            &state.store.get_master_key().to_vec().into(),
        )
        .await
        .to_not_found_response(ApiErrorResponse::MerchantAccountNotFound)?;

    #[cfg(feature = "v1")]
    let _connector = state
        .store
        .find_by_merchant_connector_account_merchant_id_merchant_connector_id(
            key_manager_state,
            merchant_id,
            connector_id,
            &key_store,
        )
        .await
        .to_not_found_response(ApiErrorResponse::MerchantConnectorAccountNotFound {
            id: connector_id.get_string_repr().to_string(),
        })?;

    #[cfg(feature = "v2")]
    {
        let _ = connector_id;
        let _ = key_store;
        todo!()
    };

    Ok(())
}

pub async fn set_tracking_id_in_configs(
    state: &SessionState,
    connector_id: &common_utils::id_type::MerchantConnectorAccountId,
    connector: enums::Connector,
) -> RouterResult<()> {
    let timestamp = common_utils::date_time::now_unix_timestamp().to_string();
    let find_config = state
        .store
        .find_config_by_key(&build_key(connector_id, connector))
        .await;

    if find_config.is_ok() {
        state
            .store
            .update_config_by_key(
                &build_key(connector_id, connector),
                ConfigUpdate::Update {
                    config: Some(timestamp),
                },
            )
            .await
            .change_context(ApiErrorResponse::InternalServerError)
            .attach_printable("Error updating data in configs table")?;
    } else if find_config
        .as_ref()
        .map_err(|e| e.current_context().is_db_not_found())
        .err()
        .unwrap_or(false)
    {
        state
            .store
            .insert_config(ConfigNew {
                key: build_key(connector_id, connector),
                config: timestamp,
            })
            .await
            .change_context(ApiErrorResponse::InternalServerError)
            .attach_printable("Error inserting data in configs table")?;
    } else {
        find_config.change_context(ApiErrorResponse::InternalServerError)?;
    }

    Ok(())
}

pub async fn get_tracking_id_from_configs(
    state: &SessionState,
    connector_id: &common_utils::id_type::MerchantConnectorAccountId,
    connector: enums::Connector,
) -> RouterResult<String> {
    let timestamp = state
        .store
        .find_config_by_key_unwrap_or(
            &build_key(connector_id, connector),
            Some(common_utils::date_time::now_unix_timestamp().to_string()),
        )
        .await
        .change_context(ApiErrorResponse::InternalServerError)
        .attach_printable("Error getting data from configs table")?
        .config;

    Ok(format!("{}_{}", connector_id.get_string_repr(), timestamp))
}

fn build_key(
    connector_id: &common_utils::id_type::MerchantConnectorAccountId,
    connector: enums::Connector,
) -> String {
    format!(
        "{}_{}_{}",
        consts::CONNECTOR_ONBOARDING_CONFIG_PREFIX,
        connector,
        connector_id.get_string_repr(),
    )
}


pub fn new() -> Self {
        Self {
            method: Method::Get,
            url: String::with_capacity(1024),
            headers: std::collections::HashSet::new(),
            certificate: None,
            certificate_key: None,
            body: None,
            ca_certificate: None,
        }
    }


/// ConditionalConfigs
pub struct ConditionalConfigs {
    /// Override 3DS
    pub override_3ds: Option<common_enums::AuthenticationType>,
}


pub struct StripePaymentCancelRequest {
    cancellation_reason: Option<CancellationReason>,
}


pub async fn upload_file_to_user_theme_storage(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
    MultipartForm(payload)


impl DebitRoutingDecisionData {
    pub fn apply_debit_routing_decision<F, D>(&self, payment_data: &mut D)
    where
        F: Send + Clone,
        D: OperationSessionGetters<F> + OperationSessionSetters<F> + Send + Sync + Clone,
    {
        payment_data.set_card_network(self.card_network.clone());
        self.debit_routing_result
            .as_ref()
            .map(|data| payment_data.set_co_badged_card_data(data));
    }
}


pub async fn publish_revenue_recovery_event_to_kafka(
        state: &SessionState,
        recovery_payment_tuple: &Self,
        retry_count: Option<i32>,
    ) -> CustomResult<(), errors::RevenueRecoveryError> {
        let recovery_payment_intent = &recovery_payment_tuple.0;
        let recovery_payment_attempt = &recovery_payment_tuple.1;
        let revenue_recovery_feature_metadata = recovery_payment_intent
            .feature_metadata
            .as_ref()
            .and_then(|metadata| metadata.revenue_recovery.as_ref());

        let billing_city = recovery_payment_intent
            .billing_address
            .as_ref()
            .and_then(|billing_address| billing_address.address.as_ref())
            .and_then(|address| address.city.clone())
            .map(Secret::new);

        let billing_state = recovery_payment_intent
            .billing_address
            .as_ref()
            .and_then(|billing_address| billing_address.address.as_ref())
            .and_then(|address| address.state.clone());

        let billing_country = recovery_payment_intent
            .billing_address
            .as_ref()
            .and_then(|billing_address| billing_address.address.as_ref())
            .and_then(|address| address.country);

        let card_info = revenue_recovery_feature_metadata.and_then(|metadata| {
            metadata
                .billing_connector_payment_method_details
                .as_ref()
                .and_then(|details| details.get_billing_connector_card_info())
        });

        #[allow(clippy::as_conversions)]
        let retry_count = Some(retry_count.unwrap_or_else(|| {
            revenue_recovery_feature_metadata
                .map(|data| data.total_retry_count as i32)
                .unwrap_or(0)
        }));

        let event = kafka::revenue_recovery::RevenueRecovery {
            merchant_id: &recovery_payment_intent.merchant_id,
            invoice_amount: recovery_payment_intent.invoice_amount,
            invoice_currency: &recovery_payment_intent.invoice_currency,
            invoice_date: revenue_recovery_feature_metadata.and_then(|data| {
                data.invoice_billing_started_at_time
                    .map(|time| time.assume_utc())
            }),
            invoice_due_date: revenue_recovery_feature_metadata
                .and_then(|data| data.invoice_next_billing_time.map(|time| time.assume_utc())),
            billing_city,
            billing_country: billing_country.as_ref(),
            billing_state,
            attempt_amount: recovery_payment_attempt.amount,
            attempt_currency: &recovery_payment_intent.invoice_currency.clone(),
            attempt_status: &recovery_payment_attempt.attempt_status.clone(),
            pg_error_code: recovery_payment_attempt.error_code.clone(),
            network_advice_code: recovery_payment_attempt.network_advice_code.clone(),
            network_error_code: recovery_payment_attempt.network_decline_code.clone(),
            first_pg_error_code: revenue_recovery_feature_metadata
                .and_then(|data| data.first_payment_attempt_pg_error_code.clone()),
            first_network_advice_code: revenue_recovery_feature_metadata
                .and_then(|data| data.first_payment_attempt_network_advice_code.clone()),
            first_network_error_code: revenue_recovery_feature_metadata
                .and_then(|data| data.first_payment_attempt_network_decline_code.clone()),
            attempt_created_at: recovery_payment_attempt.created_at.assume_utc(),
            payment_method_type: revenue_recovery_feature_metadata
                .map(|data| &data.payment_method_type),
            payment_method_subtype: revenue_recovery_feature_metadata
                .map(|data| &data.payment_method_subtype),
            card_network: card_info
                .as_ref()
                .and_then(|info| info.card_network.as_ref()),
            card_issuer: card_info.and_then(|data| data.card_issuer.clone()),
            retry_count,
            payment_gateway: revenue_recovery_feature_metadata.map(|data| data.connector),
        };
        state.event_handler.log_event(&event);
        Ok(())
    }


pub(super) fn get_customer_details_from_request(
    request: &payouts::PayoutCreateRequest,
) -> CustomerDetails {
    let customer_id = request.get_customer_id().map(ToOwned::to_owned);

    let customer_name = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.name.clone())
        .or(request.name.clone());

    let customer_email = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.email.clone())
        .or(request.email.clone());

    let customer_phone = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.phone.clone())
        .or(request.phone.clone());

    let customer_phone_code = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.phone_country_code.clone())
        .or(request.phone_country_code.clone());

    let tax_registration_id = request
        .customer
        .as_ref()
        .and_then(|customer_details| customer_details.tax_registration_id.clone());

    CustomerDetails {
        customer_id,
        name: customer_name,
        email: customer_email,
        phone: customer_phone,
        phone_country_code: customer_phone_code,
        tax_registration_id,
    }
}


pub struct GlobalRefundId(super::GlobalId);


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


Documentation: api-reference/v2/payments/payments--create-intent.mdx
# Type: Doc File

---
openapi: post /v2/payments/create-intent
---


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


File: crates/common_utils/src/id_type.rs
 Public functions: 3

//! Common ID types
//! The id type can be used to create specific id types with custom behaviour

mod api_key;
mod authentication;
mod client_secret;
mod customer;
#[cfg(feature = "v2")]
mod global_id;
mod merchant;
mod merchant_connector_account;
mod organization;
mod payment;
mod payout;
mod profile;
mod profile_acquirer;
mod refunds;
mod relay;
mod routing;
mod tenant;

use std::{borrow::Cow, fmt::Debug};

use diesel::{
    backend::Backend,
    deserialize::FromSql,
    expression::AsExpression,
    serialize::{Output, ToSql},
    sql_types,
};
pub use payout::PayoutId;
use serde::{Deserialize, Serialize};
use thiserror::Error;

#[cfg(feature = "v2")]
pub use self::global_id::{
    customer::GlobalCustomerId,
    payment::{GlobalAttemptId, GlobalPaymentId},
    payment_methods::{GlobalPaymentMethodId, GlobalPaymentMethodSessionId},
    refunds::GlobalRefundId,
    token::GlobalTokenId,
    CellId,
};
pub use self::{
    api_key::ApiKeyId,
    authentication::AuthenticationId,
    client_secret::ClientSecretId,
    customer::CustomerId,
    merchant::MerchantId,
    merchant_connector_account::MerchantConnectorAccountId,
    organization::OrganizationId,
    payment::{PaymentId, PaymentReferenceId},
    profile::ProfileId,
    profile_acquirer::ProfileAcquirerId,
    refunds::RefundReferenceId,
    relay::RelayId,
    routing::RoutingId,
    tenant::TenantId,
};
use crate::{fp_utils::when, generate_id_with_default_len};

#[inline]
fn is_valid_id_character(input_char: char) -> bool {
    input_char.is_ascii_alphanumeric() || matches!(input_char, '_' | '-')
}

/// This functions checks for the input string to contain valid characters
/// Returns Some(char) if there are any invalid characters, else None
fn get_invalid_input_character(input_string: Cow<'static, str>) -> Option<char> {
    input_string
        .trim()
        .chars()
        .find(|&char| !is_valid_id_character(char))
}

#[derive(Debug, PartialEq, Hash, Serialize, Clone, Eq)]
/// A type for alphanumeric ids
pub(crate) struct AlphaNumericId(String);

#[derive(Debug, Deserialize, Hash, Serialize, Error, Eq, PartialEq)]
#[error("value `{0}` contains invalid character `{1}`")]
/// The error type for alphanumeric id
pub(crate) struct AlphaNumericIdError(String, char);

impl<'de> Deserialize<'de> for AlphaNumericId {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let deserialized_string = String::deserialize(deserializer)?;
        Self::from(deserialized_string.into()).map_err(serde::de::Error::custom)
    }
}

impl AlphaNumericId {
    /// Creates a new alphanumeric id from string by applying validation checks
    pub fn from(input_string: Cow<'static, str>) -> Result<Self, AlphaNumericIdError> {
        let invalid_character = get_invalid_input_character(input_string.clone());

        if let Some(invalid_character) = invalid_character {
            Err(AlphaNumericIdError(
                input_string.to_string(),
                invalid_character,
            ))?
        }

        Ok(Self(input_string.to_string()))
    }

    /// Create a new alphanumeric id without any validations
    pub(crate) fn new_unchecked(input_string: String) -> Self {
        Self(input_string)
    }

    /// Generate a new alphanumeric id of default length
    pub(crate) fn new(prefix: &str) -> Self {
        Self(generate_id_with_default_len(prefix))
    }
}

/// A common type of id that can be used for reference ids with length constraint
#[derive(Debug, Clone, Serialize, Hash, PartialEq, Eq, AsExpression)]
#[diesel(sql_type = sql_types::Text)]
pub(crate) struct LengthId<const MAX_LENGTH: u8, const MIN_LENGTH: u8>(AlphaNumericId);

/// Error generated from violation of constraints for MerchantReferenceId
#[derive(Debug, Error, PartialEq, Eq)]
pub(crate) enum LengthIdError {
    #[error("the maximum allowed length for this field is {0}")]
    /// Maximum length of string violated
    MaxLengthViolated(u8),

    #[error("the minimum required length for this field is {0}")]
    /// Minimum length of string violated
    MinLengthViolated(u8),

    #[error("{0}")]
    /// Input contains invalid characters
    AlphanumericIdError(AlphaNumericIdError),
}

impl From<AlphaNumericIdError> for LengthIdError {
    fn from(alphanumeric_id_error: AlphaNumericIdError) -> Self {
        Self::AlphanumericIdError(alphanumeric_id_error)
    }
}

impl<const MAX_LENGTH: u8, const MIN_LENGTH: u8> LengthId<MAX_LENGTH, MIN_LENGTH> {
    /// Generates new [MerchantReferenceId] from the given input string
    pub fn from(input_string: Cow<'static, str>) -> Result<Self, LengthIdError> {
        let trimmed_input_string = input_string.trim().to_string();
        let length_of_input_string = u8::try_from(trimmed_input_string.len())
            .map_err(|_| LengthIdError::MaxLengthViolated(MAX_LENGTH))?;

        when(length_of_input_string > MAX_LENGTH, || {
            Err(LengthIdError::MaxLengthViolated(MAX_LENGTH))
        })?;

        when(length_of_input_string < MIN_LENGTH, || {
            Err(LengthIdError::MinLengthViolated(MIN_LENGTH))
        })?;

        let alphanumeric_id = match AlphaNumericId::from(trimmed_input_string.into()) {
            Ok(valid_alphanumeric_id) => valid_alphanumeric_id,
            Err(error) => Err(LengthIdError::AlphanumericIdError(error))?,
        };

        Ok(Self(alphanumeric_id))
    }

    /// Generate a new MerchantRefId of default length with the given prefix
    pub fn new(prefix: &str) -> Self {
        Self(AlphaNumericId::new(prefix))
    }

    /// Use this function only if you are sure that the length is within the range
    pub(crate) fn new_unchecked(alphanumeric_id: AlphaNumericId) -> Self {
        Self(alphanumeric_id)
    }

    #[cfg(feature = "v2")]
    /// Create a new LengthId from aplhanumeric id
    pub(crate) fn from_alphanumeric_id(
        alphanumeric_id: AlphaNumericId,
    ) -> Result<Self, LengthIdError> {
        let length_of_input_string = alphanumeric_id.0.len();
        let length_of_input_string = u8::try_from(length_of_input_string)
            .map_err(|_| LengthIdError::MaxLengthViolated(MAX_LENGTH))?;

        when(length_of_input_string > MAX_LENGTH, || {
            Err(LengthIdError::MaxLengthViolated(MAX_LENGTH))
        })?;

        when(length_of_input_string < MIN_LENGTH, || {
            Err(LengthIdError::MinLengthViolated(MIN_LENGTH))
        })?;

        Ok(Self(alphanumeric_id))
    }
}

impl<'de, const MAX_LENGTH: u8, const MIN_LENGTH: u8> Deserialize<'de>
    for LengthId<MAX_LENGTH, MIN_LENGTH>
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let deserialized_string = String::deserialize(deserializer)?;
        Self::from(deserialized_string.into()).map_err(serde::de::Error::custom)
    }
}

impl<DB, const MAX_LENGTH: u8, const MIN_LENGTH: u8> ToSql<sql_types::Text, DB>
    for LengthId<MAX_LENGTH, MIN_LENGTH>
where
    DB: Backend,
    String: ToSql<sql_types::Text, DB>,
{
    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
        self.0 .0.to_sql(out)
    }
}

impl<DB, const MAX_LENGTH: u8, const MIN_LENGTH: u8> FromSql<sql_types::Text, DB>
    for LengthId<MAX_LENGTH, MIN_LENGTH>
where
    DB: Backend,
    String: FromSql<sql_types::Text, DB>,
{
    fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
        let string_val = String::from_sql(value)?;
        Ok(Self(AlphaNumericId::new_unchecked(string_val)))
    }
}

/// An interface to generate object identifiers.
pub trait GenerateId {
    /// Generates a random object identifier.
    fn generate() -> Self;
}

#[cfg(test)]
mod alphanumeric_id_tests {
    #![allow(clippy::unwrap_used)]
    use super::*;

    const VALID_UNDERSCORE_ID_JSON: &str = r#""cus_abcdefghijklmnopqrstuv""#;
    const EXPECTED_VALID_UNDERSCORE_ID: &str = "cus_abcdefghijklmnopqrstuv";

    const VALID_HYPHEN_ID_JSON: &str = r#""cus-abcdefghijklmnopqrstuv""#;
    const VALID_HYPHEN_ID_STRING: &str = "cus-abcdefghijklmnopqrstuv";

    const INVALID_ID_WITH_SPACES: &str = r#""cus abcdefghijklmnopqrstuv""#;
    const INVALID_ID_WITH_EMOJIS: &str = r#""cus_abc🦀""#;

    #[test]
    fn test_id_deserialize_underscore() {
        let parsed_alphanumeric_id =
            serde_json::from_str::<AlphaNumericId>(VALID_UNDERSCORE_ID_JSON);
        let alphanumeric_id = AlphaNumericId::from(EXPECTED_VALID_UNDERSCORE_ID.into()).unwrap();

        assert_eq!(parsed_alphanumeric_id.unwrap(), alphanumeric_id);
    }

    #[test]
    fn test_id_deserialize_hyphen() {
        let parsed_alphanumeric_id = serde_json::from_str::<AlphaNumericId>(VALID_HYPHEN_ID_JSON);
        let alphanumeric_id = AlphaNumericId::from(VALID_HYPHEN_ID_STRING.into()).unwrap();

        assert_eq!(parsed_alphanumeric_id.unwrap(), alphanumeric_id);
    }

    #[test]
    fn test_id_deserialize_with_spaces() {
        let parsed_alphanumeric_id = serde_json::from_str::<AlphaNumericId>(INVALID_ID_WITH_SPACES);

        assert!(parsed_alphanumeric_id.is_err());
    }

    #[test]
    fn test_id_deserialize_with_emojis() {
        let parsed_alphanumeric_id = serde_json::from_str::<AlphaNumericId>(INVALID_ID_WITH_EMOJIS);

        assert!(parsed_alphanumeric_id.is_err());
    }
}

#[cfg(test)]
mod merchant_reference_id_tests {
    use super::*;

    const VALID_REF_ID_JSON: &str = r#""cus_abcdefghijklmnopqrstuv""#;
    const MAX_LENGTH: u8 = 36;
    const MIN_LENGTH: u8 = 6;

    const INVALID_REF_ID_JSON: &str = r#""cus abcdefghijklmnopqrstuv""#;
    const INVALID_REF_ID_LENGTH: &str = r#""cus_abcdefghijklmnopqrstuvwxyzabcdefghij""#;

    #[test]
    fn test_valid_reference_id() {
        let parsed_merchant_reference_id =
            serde_json::from_str::<LengthId<MAX_LENGTH, MIN_LENGTH>>(VALID_REF_ID_JSON);

        dbg!(&parsed_merchant_reference_id);

        assert!(parsed_merchant_reference_id.is_ok());
    }

    #[test]
    fn test_invalid_ref_id() {
        let parsed_merchant_reference_id =
            serde_json::from_str::<LengthId<MAX_LENGTH, MIN_LENGTH>>(INVALID_REF_ID_JSON);

        assert!(parsed_merchant_reference_id.is_err());
    }

    #[test]
    fn test_invalid_ref_id_error_message() {
        let parsed_merchant_reference_id =
            serde_json::from_str::<LengthId<MAX_LENGTH, MIN_LENGTH>>(INVALID_REF_ID_JSON);

        let expected_error_message =
            r#"value `cus abcdefghijklmnopqrstuv` contains invalid character ` `"#.to_string();

        let error_message = parsed_merchant_reference_id
            .err()
            .map(|error| error.to_string());

        assert_eq!(error_message, Some(expected_error_message));
    }

    #[test]
    fn test_invalid_ref_id_length() {
        let parsed_merchant_reference_id =
            serde_json::from_str::<LengthId<MAX_LENGTH, MIN_LENGTH>>(INVALID_REF_ID_LENGTH);

        dbg!(&parsed_merchant_reference_id);

        let expected_error_message =
            format!("the maximum allowed length for this field is {MAX_LENGTH}");

        assert!(parsed_merchant_reference_id
            .is_err_and(|error_string| error_string.to_string().eq(&expected_error_message)));
    }

    #[test]
    fn test_invalid_ref_id_length_error_type() {
        let parsed_merchant_reference_id =
            LengthId::<MAX_LENGTH, MIN_LENGTH>::from(INVALID_REF_ID_LENGTH.into());

        dbg!(&parsed_merchant_reference_id);

        assert!(
            parsed_merchant_reference_id.is_err_and(|error_type| matches!(
                error_type,
                LengthIdError::MaxLengthViolated(MAX_LENGTH)
            ))
        );
    }
}


impl api::Payment for Worldpayvantiv {}

impl api::Payment for for Worldpayvantiv


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

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

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

impl ConnectorSpecifications for for Datatrans


pub async fn mock_delete_card_hs<'a>(
    db: &dyn db::StorageInterface,
    card_id: &'a str,
) -> errors::CustomResult<payment_methods::DeleteCardResp, errors::VaultError> {
    db.delete_locker_mock_up(card_id)
        .await
        .change_context(errors::VaultError::FetchCardFailed)?;
    Ok(payment_methods::DeleteCardResp {
        status: "Ok".to_string(),
        error_code: None,
        error_message: None,
    })
}


pub struct PaymentAuthRouterData<F, Request, Response> {
    pub flow: PhantomData<F>,
    pub merchant_id: Option<id_type::MerchantId>,
    pub connector: Option<String>,
    pub request: Request,
    pub response: Result<Response, ErrorResponse>,
    pub connector_auth_type: ConnectorAuthType,
    pub connector_http_status_code: Option<u16>,
}


File: crates/openapi/src/routes/blocklist.rs
 Public functions: 4

#[utoipa::path(
    post,
    path = "/blocklist/toggle",
    params (
        ("status" = bool, Query, description = "Boolean value to enable/disable blocklist"),
    ),
    responses(
        (status = 200, description = "Blocklist guard enabled/disabled", body = ToggleBlocklistResponse),
        (status = 400, description = "Invalid Data")
    ),
    tag = "Blocklist",
    operation_id = "Toggle blocklist guard for a particular merchant",
    security(("api_key" = []))
)]
pub async fn toggle_blocklist_guard() {}

#[utoipa::path(
    post,
    path = "/blocklist",
    request_body = BlocklistRequest,
    responses(
        (status = 200, description = "Fingerprint Blocked", body = BlocklistResponse),
        (status = 400, description = "Invalid Data")
    ),
    tag = "Blocklist",
    operation_id = "Block a Fingerprint",
    security(("api_key" = []))
)]
pub async fn add_entry_to_blocklist() {}

#[utoipa::path(
    delete,
    path = "/blocklist",
    request_body = BlocklistRequest,
    responses(
        (status = 200, description = "Fingerprint Unblocked", body = BlocklistResponse),
        (status = 400, description = "Invalid Data")
    ),
    tag = "Blocklist",
    operation_id = "Unblock a Fingerprint",
    security(("api_key" = []))
)]
pub async fn remove_entry_from_blocklist() {}

#[utoipa::path(
    get,
    path = "/blocklist",
    params (
        ("data_kind" = BlocklistDataKind, Query, description = "Kind of the fingerprint list requested"),
    ),
    responses(
        (status = 200, description = "Blocked Fingerprints", body = BlocklistResponse),
        (status = 400, description = "Invalid Data")
    ),
    tag = "Blocklist",
    operation_id = "List Blocked fingerprints of a particular kind",
    security(("api_key" = []))
)]
pub async fn list_blocked_payment_methods() {}


impl api::PaymentsCompleteAuthorize for Authorizedotnet {}

impl api::PaymentsCompleteAuthorize for for Authorizedotnet


pub struct WorldpayCompleteAuthorizationRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub collection_reference: Option<String>,
}


impl CurrentBlockThreshold {
    pub fn update(&mut self, new: Self) {
        if let Some(max_total_count) = new.max_total_count {
            self.max_total_count = Some(max_total_count)
        }
    }
}


pub struct BraintreeRefundInput {
    transaction_id: String,
    refund: RefundInputData,
}


pub async fn delete_theme(state: SessionState, theme_id: String) -> UserResponse<()> {
    state
        .store
        .delete_theme_by_theme_id(theme_id.clone())
        .await
        .to_not_found_response(UserErrors::ThemeNotFound)?;

    // TODO (#6717): Delete theme folder from the theme storage.
    // Currently there is no simple or easy way to delete a whole folder from S3.
    // So, we are not deleting the theme folder from the theme storage.

    Ok(ApplicationResponse::StatusOk)
}


pub async fn call_connector_payout(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    connector_data: &api::ConnectorData,
    payout_data: &mut PayoutData,
) -> RouterResult<()> {
    let payout_attempt = &payout_data.payout_attempt.to_owned();
    let payouts = &payout_data.payouts.to_owned();

    // fetch merchant connector account if not present
    if payout_data.merchant_connector_account.is_none()
        || payout_data.payout_attempt.merchant_connector_id.is_none()
    {
        let merchant_connector_account = get_mca_from_profile_id(
            state,
            merchant_context,
            &payout_data.profile_id,
            &connector_data.connector_name.to_string(),
            payout_attempt
                .merchant_connector_id
                .clone()
                .or(connector_data.merchant_connector_id.clone())
                .as_ref(),
        )
        .await?;
        payout_data.payout_attempt.merchant_connector_id = merchant_connector_account.get_mca_id();
        payout_data.merchant_connector_account = Some(merchant_connector_account);
    }

    // update connector_name
    if payout_data.payout_attempt.connector.is_none()
        || payout_data.payout_attempt.connector != Some(connector_data.connector_name.to_string())
    {
        payout_data.payout_attempt.connector = Some(connector_data.connector_name.to_string());
        let updated_payout_attempt = storage::PayoutAttemptUpdate::UpdateRouting {
            connector: connector_data.connector_name.to_string(),
            routing_info: payout_data.payout_attempt.routing_info.clone(),
            merchant_connector_id: payout_data.payout_attempt.merchant_connector_id.clone(),
        };
        let db = &*state.store;
        payout_data.payout_attempt = db
            .update_payout_attempt(
                &payout_data.payout_attempt,
                updated_payout_attempt,
                payouts,
                merchant_context.get_merchant_account().storage_scheme,
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Error updating routing info in payout_attempt")?;
    };

    // Fetch / store payout_method_data
    if payout_data.payout_method_data.is_none() || payout_attempt.payout_token.is_none() {
        helpers::fetch_payout_method_data(state, payout_data, connector_data, merchant_context)
            .await?;
    }
    // Eligibility flow
    Box::pin(complete_payout_eligibility(
        state,
        merchant_context,
        connector_data,
        payout_data,
    ))
    .await?;
    // Create customer flow
    Box::pin(complete_create_recipient(
        state,
        merchant_context,
        connector_data,
        payout_data,
    ))
    .await?;
    // Create customer's disbursement account flow
    Box::pin(complete_create_recipient_disburse_account(
        state,
        merchant_context,
        connector_data,
        payout_data,
    ))
    .await?;
    // Payout creation flow
    Box::pin(complete_create_payout(
        state,
        merchant_context,
        connector_data,
        payout_data,
    ))
    .await?;

    // Auto fulfillment flow
    let status = payout_data.payout_attempt.status;
    if payouts.auto_fulfill && status == storage_enums::PayoutStatus::RequiresFulfillment {
        Box::pin(fulfill_payout(
            state,
            merchant_context,
            connector_data,
            payout_data,
        ))
        .await
        .attach_printable("Payout fulfillment failed for given Payout request")?;
    }

    Ok(())
}


File: crates/diesel_models/src/payment_methods_session.rs
 Public functions: 1
 Public structs: 2

use common_utils::pii;

#[cfg(feature = "v2")]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct PaymentMethodSession {
    pub id: common_utils::id_type::GlobalPaymentMethodSessionId,
    pub customer_id: common_utils::id_type::GlobalCustomerId,
    pub billing: Option<common_utils::encryption::Encryption>,
    pub psp_tokenization: Option<common_types::payment_methods::PspTokenization>,
    pub network_tokenization: Option<common_types::payment_methods::NetworkTokenization>,
    pub tokenization_data: Option<pii::SecretSerdeValue>,
    pub return_url: Option<common_utils::types::Url>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub expires_at: time::PrimitiveDateTime,
    pub associated_payment_methods: Option<Vec<String>>,
    pub associated_payment: Option<common_utils::id_type::GlobalPaymentId>,
    pub associated_token_id: Option<common_utils::id_type::GlobalTokenId>,
}

#[cfg(feature = "v2")]
impl PaymentMethodSession {
    pub fn apply_changeset(self, update_session: PaymentMethodsSessionUpdateInternal) -> Self {
        let Self {
            id,
            customer_id,
            billing,
            psp_tokenization,
            network_tokenization,
            tokenization_data,
            expires_at,
            return_url,
            associated_payment_methods,
            associated_payment,
            associated_token_id,
        } = self;

        Self {
            id,
            customer_id,
            billing: update_session.billing.or(billing),
            psp_tokenization: update_session.psp_tokenization.or(psp_tokenization),
            network_tokenization: update_session.network_tokenization.or(network_tokenization),
            tokenization_data: update_session.tokenzation_data.or(tokenization_data),
            expires_at,
            return_url,
            associated_payment_methods,
            associated_payment,
            associated_token_id,
        }
    }
}

#[cfg(feature = "v2")]
pub struct PaymentMethodsSessionUpdateInternal {
    pub billing: Option<common_utils::encryption::Encryption>,
    pub psp_tokenization: Option<common_types::payment_methods::PspTokenization>,
    pub network_tokenization: Option<common_types::payment_methods::NetworkTokenization>,
    pub tokenzation_data: Option<masking::Secret<serde_json::Value>>,
}


pub async fn revoke_api_key(
    state: &SessionState,
    api_key: Secret<String>,
) -> CustomResult<(), ApiClientError> {
    let decision_config = if let Some(config) = &state.conf.decision {
        config
    } else {
        return Ok(());
    };

    let rule = RuleDeleteRequest {
        tag: state.tenant.schema.clone(),
        variant: AuthType::ApiKey { api_key },
    };

    call_decision_service(state, decision_config, rule, RULE_DELETE_METHOD).await
}


pub struct OutgoingWebhookRetryProcessTrackerMapping {
    /// Default (fallback) retry configuration used when no merchant-specific retry configuration
    /// exists.
    pub default_mapping: RetryMapping,

    /// Merchant-specific retry configuration.
    pub custom_merchant_mapping: HashMap<common_utils::id_type::MerchantId, RetryMapping>,
}


pub fn build_form_from_struct<T: Serialize>(data: T) -> Result<Form, common_errors::ParsingError> {
    let mut form = Form::new();
    let serialized = serde_json::to_value(&data).map_err(|e| {
        router_env::logger::error!("Error serializing data to JSON value: {:?}", e);
        common_errors::ParsingError::EncodeError("json-value")
    })?;
    let serialized_object = serialized.as_object().ok_or_else(|| {
        router_env::logger::error!("Error: Expected JSON object but got something else");
        common_errors::ParsingError::EncodeError("Expected object")
    })?;
    for (key, values) in serialized_object {
        let value = match values {
            Value::String(s) => s.clone(),
            Value::Number(n) => n.to_string(),
            Value::Bool(b) => b.to_string(),
            Value::Null => "".to_string(),
            Value::Array(_) | Value::Object(_) => {
                router_env::logger::error!(serialization_error =? "Form Construction Failed.");
                "".to_string()
            }
        };
        form = form.text(key.clone(), value.clone());
    }
    Ok(form)
}


impl Settings<SecuredSecret> {
    pub fn new() -> Result<Self, errors::DrainerError> {
        Self::with_config_path(None)
    }

    pub fn with_config_path(config_path: Option<PathBuf>) -> Result<Self, errors::DrainerError> {
        // Configuration values are picked up in the following priority order (1 being least
        // priority):
        // 1. Defaults from the implementation of the `Default` trait.
        // 2. Values from config file. The config file accessed depends on the environment
        //    specified by the `RUN_ENV` environment variable. `RUN_ENV` can be one of
        //    `development`, `sandbox` or `production`. If nothing is specified for `RUN_ENV`,
        //    `/config/development.toml` file is read.
        // 3. Environment variables prefixed with `DRAINER` and each level separated by double
        //    underscores.
        //
        // Values in config file override the defaults in `Default` trait, and the values set using
        // environment variables override both the defaults and the config file values.

        let environment = env::which();
        let config_path = router_env::Config::config_path(&environment.to_string(), config_path);

        let config = router_env::Config::builder(&environment.to_string())?
            .add_source(File::from(config_path).required(false))
            .add_source(
                Environment::with_prefix("DRAINER")
                    .try_parsing(true)
                    .separator("__")
                    .list_separator(",")
                    .with_list_parse_key("redis.cluster_urls"),
            )
            .build()?;

        // The logger may not yet be initialized when constructing the application configuration
        #[allow(clippy::print_stderr)]
        serde_path_to_error::deserialize(config).map_err(|error| {
            logger::error!(%error, "Unable to deserialize application configuration");
            eprintln!("Unable to deserialize application configuration: {error}");
            errors::DrainerError::from(error.into_inner())
        })
    }

    pub fn validate(&self) -> Result<(), errors::DrainerError> {
        self.server.validate()?;
        self.master_database.get_inner().validate()?;

        // The logger may not yet be initialized when validating the application configuration
        #[allow(clippy::print_stderr)]
        self.redis.validate().map_err(|error| {
            eprintln!("{error}");
            errors::DrainerError::ConfigParsingError("invalid Redis configuration".into())
        })?;
        self.drainer.validate()?;

        // The logger may not yet be initialized when validating the application configuration
        #[allow(clippy::print_stderr)]
        self.secrets_management.validate().map_err(|error| {
            eprintln!("{error}");
            errors::DrainerError::ConfigParsingError(
                "invalid secrets management configuration".into(),
            )
        })?;

        // The logger may not yet be initialized when validating the application configuration
        #[allow(clippy::print_stderr)]
        self.encryption_management.validate().map_err(|error| {
            eprintln!("{error}");
            errors::DrainerError::ConfigParsingError(
                "invalid encryption management configuration".into(),
            )
        })?;

        Ok(())
    }
}


pub struct ErrorData {
    pub message: String,
}


impl DisputeSync for Worldpayvantiv {}


pub struct ResultData {
    pub redirect_url: Option<Secret<url::Url>>,
    pub status: NovalnetAPIStatus,
    pub status_code: u64,
    pub status_text: String,
    pub additional_message: Option<String>,
}


pub trait NetworkTokenWebhookResponseExt {
    fn decrypt_payment_method_data(
        &self,
        payment_method: &domain::PaymentMethod,
    ) -> CustomResult<api::payment_methods::CardDetailFromLocker, errors::ApiErrorResponse>;

    async fn update_payment_method(
        &self,
        state: &SessionState,
        payment_method: &domain::PaymentMethod,
        merchant_context: &domain::MerchantContext,
    ) -> CustomResult<WebhookResponseTracker, errors::ApiErrorResponse>;
}


pub async fn signal_handler(_sig: DummySignal, _sender: mpsc::Sender<()


File: crates/router/src/core/payment_methods/validator.rs
 Public functions: 2

use api_models::{admin, payment_methods::PaymentMethodCollectLinkRequest};
use common_utils::link_utils;
use diesel_models::generic_link::PaymentMethodCollectLinkData;
use error_stack::ResultExt;
use masking::Secret;

use crate::{
    consts,
    core::{
        errors::{self, RouterResult},
        utils as core_utils,
    },
    routes::{app::StorageInterface, SessionState},
    types::domain,
    utils,
};

#[cfg(feature = "v2")]
pub async fn validate_request_and_initiate_payment_method_collect_link(
    _state: &SessionState,
    _merchant_context: &domain::MerchantContext,
    _req: &PaymentMethodCollectLinkRequest,
) -> RouterResult<PaymentMethodCollectLinkData> {
    todo!()
}

#[cfg(feature = "v1")]
pub async fn validate_request_and_initiate_payment_method_collect_link(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    req: &PaymentMethodCollectLinkRequest,
) -> RouterResult<PaymentMethodCollectLinkData> {
    // Validate customer_id
    let db: &dyn StorageInterface = &*state.store;
    let customer_id = req.customer_id.clone();
    let merchant_id = merchant_context.get_merchant_account().get_id().clone();
    #[cfg(feature = "v1")]
    match db
        .find_customer_by_customer_id_merchant_id(
            &state.into(),
            &customer_id,
            &merchant_id,
            merchant_context.get_merchant_key_store(),
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
    {
        Ok(_) => Ok(()),
        Err(err) => {
            if err.current_context().is_db_not_found() {
                Err(err).change_context(errors::ApiErrorResponse::InvalidRequestData {
                    message: format!(
                        "customer [{}] not found for merchant [{:?}]",
                        customer_id.get_string_repr(),
                        merchant_id
                    ),
                })
            } else {
                Err(err)
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("database error while finding customer")
            }
        }
    }?;

    // Create payment method collect link ID
    let pm_collect_link_id = core_utils::get_or_generate_id(
        "pm_collect_link_id",
        &req.pm_collect_link_id,
        "pm_collect_link",
    )?;

    // Fetch all configs
    let default_config = &state.conf.generic_link.payment_method_collect;

    #[cfg(feature = "v1")]
    let merchant_config = merchant_context
        .get_merchant_account()
        .pm_collect_link_config
        .as_ref()
        .map(|config| {
            common_utils::ext_traits::ValueExt::parse_value::<admin::BusinessCollectLinkConfig>(
                config.clone(),
                "BusinessCollectLinkConfig",
            )
        })
        .transpose()
        .change_context(errors::ApiErrorResponse::InvalidDataValue {
            field_name: "pm_collect_link_config in merchant_account",
        })?;

    #[cfg(feature = "v2")]
    let merchant_config = Option::<admin::BusinessCollectLinkConfig>::None;

    let merchant_ui_config = merchant_config.as_ref().map(|c| c.config.ui_config.clone());
    let ui_config = req
        .ui_config
        .as_ref()
        .or(merchant_ui_config.as_ref())
        .cloned();

    // Form data to be injected in the link
    let (logo, merchant_name, theme) = match ui_config {
        Some(config) => (config.logo, config.merchant_name, config.theme),
        _ => (None, None, None),
    };
    let pm_collect_link_config = link_utils::GenericLinkUiConfig {
        logo,
        merchant_name,
        theme,
    };
    let client_secret = utils::generate_id(consts::ID_LENGTH, "pm_collect_link_secret");
    let domain = merchant_config
        .clone()
        .and_then(|c| c.config.domain_name)
        .map(|domain| format!("https://{domain}"))
        .unwrap_or(state.base_url.clone());
    let session_expiry = match req.session_expiry {
        Some(expiry) => expiry,
        None => default_config.expiry,
    };
    let link = Secret::new(format!(
        "{domain}/payment_methods/collect/{}/{pm_collect_link_id}",
        merchant_id.get_string_repr()
    ));
    let enabled_payment_methods = match (&req.enabled_payment_methods, &merchant_config) {
        (Some(enabled_payment_methods), _) => enabled_payment_methods.clone(),
        (None, Some(config)) => config.enabled_payment_methods.clone(),
        _ => {
            let mut default_enabled_payout_methods: Vec<link_utils::EnabledPaymentMethod> = vec![];
            for (payment_method, payment_method_types) in
                default_config.enabled_payment_methods.clone().into_iter()
            {
                let enabled_payment_method = link_utils::EnabledPaymentMethod {
                    payment_method,
                    payment_method_types: payment_method_types.into_iter().collect(),
                };
                default_enabled_payout_methods.push(enabled_payment_method);
            }

            default_enabled_payout_methods
        }
    };

    Ok(PaymentMethodCollectLinkData {
        pm_collect_link_id: pm_collect_link_id.clone(),
        customer_id,
        link,
        client_secret: Secret::new(client_secret),
        session_expiry,
        ui_config: pm_collect_link_config,
        enabled_payment_methods: Some(enabled_payment_methods),
    })
}


impl api::PaymentAuthorize for Trustpayments {}

impl api::PaymentAuthorize for for Trustpayments


pub struct CancelResponseData {
    reverse_transaction: CancelTransactionData,
}


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