From f4d9e5dea93c08eacde335f9d922811d43ba7eda Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Tue, 26 Nov 2024 19:41:27 +0530 Subject: [PATCH 01/12] feat(connector): [JPMORGAN] add Payment flows for cards --- api-reference-v2/openapi_spec.json | 2 + api-reference/openapi_spec.json | 2 + config/config.example.toml | 1 + config/deployments/integration_test.toml | 1 + config/deployments/production.toml | 1 + config/deployments/sandbox.toml | 1 + config/development.toml | 1 + config/docker_compose.toml | 1 + crates/api_models/src/connector_enums.rs | 5 +- crates/common_enums/src/connector_enums.rs | 2 +- crates/connector_configs/src/connector.rs | 2 + .../connector_configs/toml/development.toml | 40 + crates/connector_configs/toml/production.toml | 40 + crates/connector_configs/toml/sandbox.toml | 40 + .../src/connectors/jpmorgan.rs | 388 +++++- .../src/connectors/jpmorgan/transformers.rs | 1180 +++++++++++++++-- crates/router/src/core/admin.rs | 4 + crates/router/src/core/payments/flows.rs | 1 + crates/router/src/types/api.rs | 4 +- crates/router/src/types/transformers.rs | 2 +- .../router/tests/connectors/sample_auth.toml | 3 +- crates/test_utils/src/connector_auth.rs | 2 +- .../cypress/e2e/PaymentUtils/Jpmorgan.js | 141 ++ .../cypress/e2e/PaymentUtils/Utils.js | 2 + loadtest/config/development.toml | 1 + 25 files changed, 1726 insertions(+), 141 deletions(-) create mode 100644 cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 778e89ab30b..1312ed0b09b 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -6250,6 +6250,7 @@ "helcim", "iatapay", "itaubank", + "jpmorgan", "klarna", "mifinity", "mollie", @@ -18682,6 +18683,7 @@ "helcim", "iatapay", "itaubank", + "jpmorgan", "klarna", "mifinity", "mollie", diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 3f3ffc17a18..e1342ae2c08 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -8754,6 +8754,7 @@ "helcim", "iatapay", "itaubank", + "jpmorgan", "klarna", "mifinity", "mollie", @@ -22889,6 +22890,7 @@ "helcim", "iatapay", "itaubank", + "jpmorgan", "klarna", "mifinity", "mollie", diff --git a/config/config.example.toml b/config/config.example.toml index 54a3ab3827b..17430426602 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -223,6 +223,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" +jpmorgan.secondary_base_url= "https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index fbf80ced5f1..0ad7a99cc50 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -65,6 +65,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/deployments/production.toml b/config/deployments/production.toml index befd70795d7..b062db4c8c5 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -69,6 +69,7 @@ iatapay.base_url = "https://iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://secure.api.itau/" jpmorgan.base_url = "https://api-ms.payments.jpmorgan.com/api/v2" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" klarna.base_url = "https://api{{klarna_region}}.klarna.com/" mifinity.base_url = "https://secure.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 2defc5729cf..4479b2f49cc 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -69,6 +69,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/development.toml b/config/development.toml index 4e3a9b09993..e3a3019c1a5 100644 --- a/config/development.toml +++ b/config/development.toml @@ -240,6 +240,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" +jpmorgan.secondary_base_url= "https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/docker_compose.toml b/config/docker_compose.toml index f38da4183b1..7ee0de7e593 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -154,6 +154,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/crates/api_models/src/connector_enums.rs b/crates/api_models/src/connector_enums.rs index 294666f35f8..e84adb66751 100644 --- a/crates/api_models/src/connector_enums.rs +++ b/crates/api_models/src/connector_enums.rs @@ -87,7 +87,7 @@ pub enum Connector { // Inespay, Iatapay, Itaubank, - //Jpmorgan, + Jpmorgan, Klarna, Mifinity, Mollie, @@ -173,6 +173,7 @@ impl Connector { (Self::Airwallex, _) | (Self::Deutschebank, _) | (Self::Globalpay, _) + | (Self::Jpmorgan, _) | (Self::Paypal, _) | (Self::Payu, _) | (Self::Trustpay, PaymentMethod::BankRedirect) @@ -232,7 +233,7 @@ impl Connector { | Self::Iatapay // | Self::Inespay | Self::Itaubank - //| Self::Jpmorgan + | Self::Jpmorgan | Self::Klarna | Self::Mifinity | Self::Mollie diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs index 421a51205de..fda89956852 100644 --- a/crates/common_enums/src/connector_enums.rs +++ b/crates/common_enums/src/connector_enums.rs @@ -83,7 +83,7 @@ pub enum RoutableConnectors { Iatapay, // Inespay, Itaubank, - //Jpmorgan, + Jpmorgan, Klarna, Mifinity, Mollie, diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs index c1f7cfc366c..f7d2cd78ccd 100644 --- a/crates/connector_configs/src/connector.rs +++ b/crates/connector_configs/src/connector.rs @@ -193,6 +193,7 @@ pub struct ConnectorConfig { pub gpayments: Option, pub helcim: Option, // pub inespay: Option, + pub jpmorgan: Option, pub klarna: Option, pub mifinity: Option, pub mollie: Option, @@ -359,6 +360,7 @@ impl ConnectorConfig { Connector::Gpayments => Ok(connector_data.gpayments), Connector::Helcim => Ok(connector_data.helcim), // Connector::Inespay => Ok(connector_data.inespay), + Connector::Jpmorgan => Ok(connector_data.jpmorgan), Connector::Klarna => Ok(connector_data.klarna), Connector::Mifinity => Ok(connector_data.mifinity), Connector::Mollie => Ok(connector_data.mollie), diff --git a/crates/connector_configs/toml/development.toml b/crates/connector_configs/toml/development.toml index 1f2062cdea3..52aee1f20f9 100644 --- a/crates/connector_configs/toml/development.toml +++ b/crates/connector_configs/toml/development.toml @@ -1731,6 +1731,46 @@ api_key="Client Secret" api_secret="Certificates" key2="Certificate Key" +[jpmorgan] +[[jpmorgan.credit]] + payment_method_type = "American Express" +[[jpmorgan.credit]] + payment_method_type = "ChaseNet" +[[jpmorgan.credit]] + payment_method_type = "Diners Club" +[[jpmorgan.credit]] + payment_method_type = "Discover" +[[jpmorgan.credit]] + payment_method_type = "JCB" +[[jpmorgan.credit]] + payment_method_type = "Mastercard" +[[jpmorgan.credit]] + payment_method_type = "Discover" +[[jpmorgan.credit]] + payment_method_type = "UnionPay" +[[jpmorgan.credit]] + payment_method_type = "Visa" + [[jpmorgan.debit]] + payment_method_type = "American Express" +[[jpmorgan.debit]] + payment_method_type = "ChaseNet" +[[jpmorgan.debit]] + payment_method_type = "Diners Club" +[[jpmorgan.debit]] + payment_method_type = "Discover" +[[jpmorgan.debit]] + payment_method_type = "JCB" +[[jpmorgan.debit]] + payment_method_type = "Mastercard" +[[jpmorgan.debit]] + payment_method_type = "Discover" +[[jpmorgan.debit]] + payment_method_type = "UnionPay" +[[jpmorgan.debit]] + payment_method_type = "Visa" +[jpmorgan.connector_auth.BodyKey] +api_key="Access Token" + [klarna] [[klarna.pay_later]] payment_method_type = "klarna" diff --git a/crates/connector_configs/toml/production.toml b/crates/connector_configs/toml/production.toml index 443d3fd72ac..7216d4f7890 100644 --- a/crates/connector_configs/toml/production.toml +++ b/crates/connector_configs/toml/production.toml @@ -1443,6 +1443,46 @@ api_key="Client Secret" api_secret="Certificates" key2="Certificate Key" +[jpmorgan] +[[jpmorgan.credit]] + payment_method_type = "American Express" +[[jpmorgan.credit]] + payment_method_type = "ChaseNet" +[[jpmorgan.credit]] + payment_method_type = "Diners Club" +[[jpmorgan.credit]] + payment_method_type = "Discover" +[[jpmorgan.credit]] + payment_method_type = "JCB" +[[jpmorgan.credit]] + payment_method_type = "Mastercard" +[[jpmorgan.credit]] + payment_method_type = "Discover" +[[jpmorgan.credit]] + payment_method_type = "UnionPay" +[[jpmorgan.credit]] + payment_method_type = "Visa" + [[jpmorgan.debit]] + payment_method_type = "American Express" +[[jpmorgan.debit]] + payment_method_type = "ChaseNet" +[[jpmorgan.debit]] + payment_method_type = "Diners Club" +[[jpmorgan.debit]] + payment_method_type = "Discover" +[[jpmorgan.debit]] + payment_method_type = "JCB" +[[jpmorgan.debit]] + payment_method_type = "Mastercard" +[[jpmorgan.debit]] + payment_method_type = "Discover" +[[jpmorgan.debit]] + payment_method_type = "UnionPay" +[[jpmorgan.debit]] + payment_method_type = "Visa" +[jpmorgan.connector_auth.BodyKey] +api_key="Access Token" + [klarna] [[klarna.pay_later]] payment_method_type = "klarna" diff --git a/crates/connector_configs/toml/sandbox.toml b/crates/connector_configs/toml/sandbox.toml index 1e9d274780b..f162707b286 100644 --- a/crates/connector_configs/toml/sandbox.toml +++ b/crates/connector_configs/toml/sandbox.toml @@ -1681,6 +1681,46 @@ api_key="Client Secret" api_secret="Certificates" key2="Certificate Key" +[jpmorgan] +[[jpmorgan.credit]] + payment_method_type = "American Express" +[[jpmorgan.credit]] + payment_method_type = "ChaseNet" +[[jpmorgan.credit]] + payment_method_type = "Diners Club" +[[jpmorgan.credit]] + payment_method_type = "Discover" +[[jpmorgan.credit]] + payment_method_type = "JCB" +[[jpmorgan.credit]] + payment_method_type = "Mastercard" +[[jpmorgan.credit]] + payment_method_type = "Discover" +[[jpmorgan.credit]] + payment_method_type = "UnionPay" +[[jpmorgan.credit]] + payment_method_type = "Visa" + [[jpmorgan.debit]] + payment_method_type = "American Express" +[[jpmorgan.debit]] + payment_method_type = "ChaseNet" +[[jpmorgan.debit]] + payment_method_type = "Diners Club" +[[jpmorgan.debit]] + payment_method_type = "Discover" +[[jpmorgan.debit]] + payment_method_type = "JCB" +[[jpmorgan.debit]] + payment_method_type = "Mastercard" +[[jpmorgan.debit]] + payment_method_type = "Discover" +[[jpmorgan.debit]] + payment_method_type = "UnionPay" +[[jpmorgan.debit]] + payment_method_type = "Visa" +[jpmorgan.connector_auth.BodyKey] +api_key="Access Token" + [klarna] [[klarna.pay_later]] payment_method_type = "klarna" diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index 6095a53ad00..f39b103225c 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -1,10 +1,13 @@ pub mod transformers; +use std::convert::TryFrom; +use base64::Engine; +use common_enums::enums; use common_utils::{ errors::CustomResult, ext_traits::BytesExt, request::{Method, Request, RequestBuilder, RequestContent}, - types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, + types::{AmountConvertor, MinorUnit, MinorUnitForConnector}, }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ @@ -21,33 +24,36 @@ use hyperswitch_domain_models::{ }, router_response_types::{PaymentsResponseData, RefundsResponseData}, types::{ - PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, - RefundSyncRouterData, RefundsRouterData, + PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData, + PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, }, }; -// use hyperswitch_interfaces::{ api::{self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorValidation}, configs::Connectors, - errors, + consts, errors, events::connector_api_logs::ConnectorEvent, - types::{self, Response}, + types::{self, RefreshTokenType, Response}, webhooks, }; -use masking::{ExposeInterface, Mask}; -use transformers as jpmorgan; +use masking::{Mask, PeekInterface}; +use transformers::{self as jpmorgan, JpmorganErrorResponse}; -use crate::{constants::headers, types::ResponseRouterData, utils}; +use crate::{ + constants::headers, + types::{RefreshTokenRouterData, ResponseRouterData}, + utils, +}; #[derive(Clone)] pub struct Jpmorgan { - amount_converter: &'static (dyn AmountConvertor + Sync), + amount_converter: &'static (dyn AmountConvertor + Sync), } impl Jpmorgan { pub fn new() -> &'static Self { &Self { - amount_converter: &StringMinorUnitForConnector, + amount_converter: &MinorUnitForConnector, } } } @@ -80,13 +86,21 @@ where req: &RouterData, _connectors: &Connectors, ) -> CustomResult)>, errors::ConnectorError> { - let mut header = vec![( + let mut headers = vec![( headers::CONTENT_TYPE.to_string(), self.get_content_type().to_string().into(), )]; - let mut api_key = self.get_auth_header(&req.connector_auth_type)?; - header.append(&mut api_key); - Ok(header) + let access_token = req + .access_token + .clone() + .ok_or(errors::ConnectorError::FailedToObtainAuthType)?; + let auth_header = ( + headers::AUTHORIZATION.to_string(), + format!("Bearer {}", access_token.token.peek()).into_masked(), + ); + + headers.push(auth_header); + Ok(headers) } } @@ -96,7 +110,7 @@ impl ConnectorCommon for Jpmorgan { } fn get_currency_unit(&self) -> api::CurrencyUnit { - api::CurrencyUnit::Base + api::CurrencyUnit::Minor //todo!() // TODO! Check connector documentation, on which unit they are processing the currency. // If the connector accepts amount in lower unit ( i.e cents for USD) then return api::CurrencyUnit::Minor, @@ -119,7 +133,7 @@ impl ConnectorCommon for Jpmorgan { .change_context(errors::ConnectorError::FailedToObtainAuthType)?; Ok(vec![( headers::AUTHORIZATION.to_string(), - auth.api_key.expose().into_masked(), + auth.api_key.into_masked(), )]) } @@ -128,19 +142,24 @@ impl ConnectorCommon for Jpmorgan { res: Response, event_builder: Option<&mut ConnectorEvent>, ) -> CustomResult { - let response: jpmorgan::JpmorganErrorResponse = res + let response: JpmorganErrorResponse = res .response .parse_struct("JpmorganErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); + event_builder.map(|i| i.set_response_body(&response)); + + let response_message = response + .response_message + .as_ref() + .map_or_else(|| consts::NO_ERROR_MESSAGE.to_string(), ToString::to_string); Ok(ErrorResponse { status_code: res.status_code, - code: response.code, - message: response.message, - reason: response.reason, + code: response.response_code, + message: response_message.clone(), + reason: Some(response_message), attempt_status: None, connector_transaction_id: None, }) @@ -149,13 +168,154 @@ impl ConnectorCommon for Jpmorgan { impl ConnectorValidation for Jpmorgan { //TODO: implement functions when support enabled + fn validate_capture_method( + &self, + capture_method: Option, + _pmt: Option, + ) -> CustomResult<(), errors::ConnectorError> { + let capture_method = capture_method.unwrap_or_default(); + match capture_method { + enums::CaptureMethod::Automatic | enums::CaptureMethod::Manual => Ok(()), + //enums::CaptureMethod::ManualMultiple | + enums::CaptureMethod::Scheduled => Err(utils::construct_not_implemented_error_report( + capture_method, + self.id(), + )), + enums::CaptureMethod::ManualMultiple => Err(errors::ConnectorError::NotImplemented( + //ManualMultiple unimplemented + utils::get_unimplemented_payment_method_error_message("Jpmorgan"), + ))?, + } + } + + fn validate_psync_reference_id( + &self, + data: &PaymentsSyncData, + _is_three_ds: bool, + _status: enums::AttemptStatus, + _connector_meta_data: Option, + ) -> CustomResult<(), errors::ConnectorError> { + if data.encoded_data.is_some() + || data + .connector_transaction_id + .get_connector_transaction_id() + .is_ok() + { + return Ok(()); + } + Err(errors::ConnectorError::MissingConnectorTransactionID.into()) + } } impl ConnectorIntegration for Jpmorgan { //TODO: implement sessions flow } -impl ConnectorIntegration for Jpmorgan {} +// use masking::Secret; + +impl ConnectorIntegration for Jpmorgan { + fn get_url( + &self, + _req: &RefreshTokenRouterData, + connectors: &Connectors, + ) -> CustomResult { + let access_token_url = connectors + .jpmorgan + .secondary_base_url + .as_ref() + .ok_or(errors::ConnectorError::FailedToObtainIntegrationUrl)?; + Ok(access_token_url.to_string()) + } + + fn get_content_type(&self) -> &'static str { + "application/x-www-form-urlencoded" + } + + fn get_headers( + &self, + req: &RefreshTokenRouterData, + _connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + let client_id = req.request.app_id.clone(); + + let client_secret = req.request.id.clone(); + + let creds = format!( + "{}:{}", + client_id.peek(), + client_secret.unwrap_or_default().peek() + ); + // let creds = format!("{}:{}", client_id.peek(), client_secret.unwrap_or_default().peek()); + let encoded_creds = common_utils::consts::BASE64_ENGINE.encode(creds); + + let auth_string = format!("Basic {}", encoded_creds); + Ok(vec![ + ( + headers::CONTENT_TYPE.to_string(), + RefreshTokenType::get_content_type(self).to_string().into(), + ), + ( + headers::AUTHORIZATION.to_string(), + auth_string.into_masked(), + ), + ]) + } + + fn get_request_body( + &self, + req: &RefreshTokenRouterData, + _connectors: &Connectors, + ) -> CustomResult { + let connector_req = jpmorgan::JpmorganAuthUpdateRequest::try_from(req)?; + Ok(RequestContent::FormUrlEncoded(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &RefreshTokenRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + let req = Some( + RequestBuilder::new() + .method(Method::Post) + .attach_default_headers() + .headers(RefreshTokenType::get_headers(self, req, connectors)?) + .url(&RefreshTokenType::get_url(self, req, connectors)?) + .set_body(RefreshTokenType::get_request_body(self, req, connectors)?) + .build(), + ); + Ok(req) + } + + fn handle_response( + &self, + data: &RefreshTokenRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: jpmorgan::JpmorganAuthUpdateResponse = res + .response + .parse_struct("jpmorgan JpmorganAuthUpdateResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + .change_context(errors::ConnectorError::ResponseHandlingFailed) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} impl ConnectorIntegration for Jpmorgan @@ -178,9 +338,10 @@ impl ConnectorIntegration CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + let endpoint = self.base_url(connectors); + Ok(format!("{}/payments", endpoint)) } fn get_request_body( @@ -188,7 +349,7 @@ impl ConnectorIntegration CustomResult { - let amount = utils::convert_amount( + let amount: MinorUnit = utils::convert_amount( self.amount_converter, req.request.minor_amount, req.request.currency, @@ -196,6 +357,9 @@ impl ConnectorIntegration for Jpmorgan { + fn get_headers( + &self, + req: &PaymentsCaptureRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + req: &PaymentsCaptureRouterData, + connectors: &Connectors, + ) -> CustomResult { + let endpoint = self.base_url(connectors); + let tid = req.request.connector_transaction_id.clone(); + Ok(format!("{}/payments/{}/captures", endpoint, tid)) + // Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn get_request_body( + &self, + req: &PaymentsCaptureRouterData, + _connectors: &Connectors, + ) -> CustomResult { + let amount: MinorUnit = utils::convert_amount( + self.amount_converter, + req.request.minor_amount_to_capture, + req.request.currency, + )?; + + let connector_router_data = jpmorgan::JpmorganRouterData::from((amount, req)); + let connector_req = jpmorgan::JpmorganCaptureRequest::try_from(&connector_router_data)?; + let _printrequest = + common_utils::ext_traits::Encode::encode_to_string_of_json(&connector_req) + .change_context(errors::ConnectorError::RequestEncodingFailed)?; + Ok(RequestContent::Json(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &PaymentsCaptureRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Post) + .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::PaymentsCaptureType::get_headers( + self, req, connectors, + )?) + .set_body(types::PaymentsCaptureType::get_request_body( + self, req, connectors, + )?) + .build(), + )) + } + + fn handle_response( + &self, + data: &PaymentsCaptureRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: jpmorgan::JpmorganPaymentsResponse = res + .response + .parse_struct("Jpmorgan PaymentsCaptureResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + impl ConnectorIntegration for Jpmorgan { fn get_headers( &self, @@ -264,10 +519,16 @@ impl ConnectorIntegration for Jpm fn get_url( &self, - _req: &PaymentsSyncRouterData, - _connectors: &Connectors, + req: &PaymentsSyncRouterData, + connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + let tid = req + .request + .connector_transaction_id + .get_connector_transaction_id() + .change_context(errors::ConnectorError::MissingConnectorTransactionID)?; + let endpoint = self.base_url(connectors); + Ok(format!("{}/payments/{}", endpoint, tid)) } fn build_request( @@ -297,6 +558,7 @@ impl ConnectorIntegration for Jpm .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { response, data: data.clone(), @@ -313,10 +575,10 @@ impl ConnectorIntegration for Jpm } } -impl ConnectorIntegration for Jpmorgan { +impl ConnectorIntegration for Jpmorgan { fn get_headers( &self, - req: &PaymentsCaptureRouterData, + req: &PaymentsCancelRouterData, connectors: &Connectors, ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) @@ -328,34 +590,42 @@ impl ConnectorIntegration fo fn get_url( &self, - _req: &PaymentsCaptureRouterData, - _connectors: &Connectors, + req: &PaymentsCancelRouterData, + connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + let endpoint = self.base_url(connectors); + let tid = req.request.connector_transaction_id.clone(); + Ok(format!("{}/payments/{}", endpoint, tid)) } fn get_request_body( &self, - _req: &PaymentsCaptureRouterData, + req: &PaymentsCancelRouterData, _connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into()) + let amount: MinorUnit = utils::convert_amount( + self.amount_converter, + req.request.minor_amount.unwrap_or_default(), + req.request.currency.unwrap_or_default(), + )?; + + let connector_router_data = jpmorgan::JpmorganRouterData::from((amount, req)); + let connector_req = jpmorgan::JpmorganCancelRequest::try_from(connector_router_data)?; + Ok(RequestContent::Json(Box::new(connector_req))) } fn build_request( &self, - req: &PaymentsCaptureRouterData, + req: &PaymentsCancelRouterData, connectors: &Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( RequestBuilder::new() - .method(Method::Post) - .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?) + .method(Method::Patch) + .url(&types::PaymentsVoidType::get_url(self, req, connectors)?) .attach_default_headers() - .headers(types::PaymentsCaptureType::get_headers( - self, req, connectors, - )?) - .set_body(types::PaymentsCaptureType::get_request_body( + .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?) + .set_body(types::PaymentsVoidType::get_request_body( self, req, connectors, )?) .build(), @@ -364,14 +634,15 @@ impl ConnectorIntegration fo fn handle_response( &self, - data: &PaymentsCaptureRouterData, + data: &PaymentsCancelRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { - let response: jpmorgan::JpmorganPaymentsResponse = res + ) -> CustomResult { + let response: jpmorgan::JpmorganCancelResponse = res .response - .parse_struct("Jpmorgan PaymentsCaptureResponse") + .parse_struct("JpmrorganPaymentsVoidResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); RouterData::try_from(ResponseRouterData { @@ -390,8 +661,6 @@ impl ConnectorIntegration fo } } -impl ConnectorIntegration for Jpmorgan {} - impl ConnectorIntegration for Jpmorgan { fn get_headers( &self, @@ -408,9 +677,10 @@ impl ConnectorIntegration for Jpmorga fn get_url( &self, _req: &RefundsRouterData, - _connectors: &Connectors, + connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + let endpoint = self.base_url(connectors); + Ok(format!("{}/refunds", endpoint)) } fn get_request_body( @@ -454,9 +724,9 @@ impl ConnectorIntegration for Jpmorga event_builder: Option<&mut ConnectorEvent>, res: Response, ) -> CustomResult, errors::ConnectorError> { - let response: jpmorgan::RefundResponse = res + let response: jpmorgan::JpmorganRefundResponse = res .response - .parse_struct("jpmorgan RefundResponse") + .parse_struct("JpmorganRefundResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); @@ -488,15 +758,15 @@ impl ConnectorIntegration for Jpmorgan fn get_content_type(&self) -> &'static str { self.common_get_content_type() } - fn get_url( &self, - _req: &RefundSyncRouterData, - _connectors: &Connectors, + req: &RefundSyncRouterData, + connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + let endpoint = self.base_url(connectors); + let tid = req.request.connector_transaction_id.clone(); + Ok(format!("{}/refunds/{}", endpoint, tid)) } - fn build_request( &self, req: &RefundSyncRouterData, @@ -521,7 +791,7 @@ impl ConnectorIntegration for Jpmorgan event_builder: Option<&mut ConnectorEvent>, res: Response, ) -> CustomResult { - let response: jpmorgan::RefundResponse = res + let response: jpmorgan::JpmorganRefundSyncResponse = res .response .parse_struct("jpmorgan RefundSyncResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index 90b05869705..fad8e7201df 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -1,30 +1,32 @@ use common_enums::enums; -use common_utils::types::StringMinorUnit; +use common_utils::types::MinorUnit; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, - router_data::{ConnectorAuthType, RouterData}, + router_data::{AccessToken, ConnectorAuthType, RouterData}, router_flow_types::refunds::{Execute, RSync}, - router_request_types::ResponseId, + router_request_types::{PaymentsCancelData, ResponseId}, router_response_types::{PaymentsResponseData, RefundsResponseData}, - types::{PaymentsAuthorizeRouterData, RefundsRouterData}, + types::{ + PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData, + RefreshTokenRouterData, RefundsRouterData, + }, }; use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; +use strum::Display; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, utils::PaymentsAuthorizeRequestData, }; - -//TODO: Fill the struct with respective fields pub struct JpmorganRouterData { - pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. + pub amount: MinorUnit, pub router_data: T, } -impl From<(StringMinorUnit, T)> for JpmorganRouterData { - fn from((amount, item): (StringMinorUnit, T)) -> Self { +impl From<(MinorUnit, T)> for JpmorganRouterData { + fn from((amount, item): (MinorUnit, T)) -> Self { //Todo : use utils to convert the amount to the type of amount that a connector accepts Self { amount, @@ -33,20 +35,99 @@ impl From<(StringMinorUnit, T)> for JpmorganRouterData { } } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Serialize, PartialEq)] +#[derive(Debug, Clone, Serialize)] +pub struct JpmorganAuthUpdateRequest { + pub grant_type: String, + pub scope: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct JpmorganAuthUpdateResponse { + pub access_token: Secret, + pub scope: String, + pub token_type: String, + pub expires_in: i64, +} + +impl TryFrom<&RefreshTokenRouterData> for JpmorganAuthUpdateRequest { + type Error = error_stack::Report; + fn try_from(_item: &RefreshTokenRouterData) -> Result { + Ok(Self { + grant_type: String::from("client_credentials"), + scope: String::from("jpm:payments:sandbox"), //for prod testing, needs to be added differently + //docs : https://developer.payments.jpmorgan.com/contact/sales?post_auth=true + }) + } +} + +impl TryFrom> + for RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData, + ) -> Result { + let token = item.response.access_token; + let expires = item.response.expires_in; + Ok(Self { + response: Ok(AccessToken { token, expires }), + ..item.data + }) + } +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct JpmorganPaymentsRequest { - amount: StringMinorUnit, - card: JpmorganCard, + capture_method: String, + amount: MinorUnit, + currency: String, + merchant: JpmorganMerchant, + payment_method_type: JpmorganPaymentMethodType, } -#[derive(Default, Debug, Serialize, Eq, PartialEq)] +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct JpmorganCard { - number: cards::CardNumber, - expiry_month: Secret, - expiry_year: Secret, - cvc: Secret, - complete: bool, + account_number: Secret, + expiry: Expiry, + is_bill_payment: bool, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganPaymentMethodType { + card: JpmorganCard, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Expiry { + month: Secret, + year: Secret, +} + +#[derive(Serialize, Debug, Default, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganMerchantSoftware { + company_name: String, + product_name: String, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganMerchant { + merchant_software: JpmorganMerchantSoftware, +} + +fn map_capture_method(capture_method: enums::CaptureMethod) -> String { + match capture_method { + enums::CaptureMethod::Automatic => String::from("NOW"), + enums::CaptureMethod::Manual | enums::CaptureMethod::ManualMultiple => { + String::from("MANUAL") + } + enums::CaptureMethod::Scheduled => String::from("DELAYED"), + } } impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaymentsRequest { @@ -56,84 +137,793 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym ) -> Result { match item.router_data.request.payment_method_data.clone() { PaymentMethodData::Card(req_card) => { + let capture_method = if let Some(method) = item.router_data.request.capture_method { + map_capture_method(method) + } else { + String::from("AUTOMATIC") + }; + + let currency = item.router_data.request.currency.to_string(); + + let merchant_software = JpmorganMerchantSoftware { + company_name: String::from("JPMC"), + product_name: String::from("Hyperswitch"), //could be Amazon or something else, subject to change + }; + //hardcoded as of now + + let merchant = JpmorganMerchant { merchant_software }; + + let expiry: Expiry = Expiry { + month: req_card.card_exp_month, + year: req_card.card_exp_year, + }; + + let account_number = Secret::new(req_card.card_number.to_string()); + let card = JpmorganCard { - number: req_card.card_number, - expiry_month: req_card.card_exp_month, - expiry_year: req_card.card_exp_year, - cvc: req_card.card_cvc, - complete: item.router_data.request.is_auto_capture()?, + account_number, + expiry, + is_bill_payment: item.router_data.request.is_auto_capture()?, }; + + let payment_method_type = JpmorganPaymentMethodType { card }; + Ok(Self { - amount: item.amount.clone(), - card, + capture_method, + currency, + amount: item.amount, + merchant, + payment_method_type, }) } - _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), + _ => Err(errors::ConnectorError::NotImplemented( + "Selected payment method through jpmorgan".to_string(), + ) + .into()), } } } -//TODO: Fill the struct with respective fields -// Auth Struct +//in jpm, we get a client id and secret and using these two, we have a curl, we make an api call and we get a access token in res with an expiry time as well +#[derive(Debug)] pub struct JpmorganAuthType { pub(super) api_key: Secret, + #[allow(dead_code)] + pub(super) key1: Secret, } impl TryFrom<&ConnectorAuthType> for JpmorganAuthType { type Error = error_stack::Report; fn try_from(auth_type: &ConnectorAuthType) -> Result { match auth_type { - ConnectorAuthType::HeaderKey { api_key } => Ok(Self { + ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self { api_key: api_key.to_owned(), + key1: key1.to_owned(), }), _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), } } } + // PaymentsResponse //TODO: Append the remaining status flags -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] -#[serde(rename_all = "lowercase")] -pub enum JpmorganPaymentStatus { - Succeeded, - Failed, +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "UPPERCASE")] +pub enum JpmorganTransactionStatus { + Success, + Denied, + Error, +} + +#[derive(Default, Debug, Display, Serialize, Deserialize, Clone)] +#[serde(rename_all = "UPPERCASE")] +pub enum JpmorganTransactionState { + Closed, + Authorized, + Voided, #[default] - Processing, + Pending, + Declined, + Error, } -impl From for common_enums::AttemptStatus { - fn from(item: JpmorganPaymentStatus) -> Self { - match item { - JpmorganPaymentStatus::Succeeded => Self::Charged, - JpmorganPaymentStatus::Failed => Self::Failure, - JpmorganPaymentStatus::Processing => Self::Authorizing, +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganPaymentsResponse { + transaction_id: String, + request_id: Option, + transaction_state: JpmorganTransactionState, + response_status: String, + response_code: String, + response_message: Option, + payment_method_type: Option, + capture_method: Option, + is_capture: Option, + initiator_type: Option, + account_on_file: Option, + transaction_date: Option, + approval_code: Option, + host_message: Option, + amount: Option, + currency: Option, + remaining_refundable_amount: Option, + remaining_auth_amount: Option, + host_reference_id: Option, + merchant: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Merchant { + merchant_id: Option, + merchant_software: MerchantSoftware, + merchant_category_code: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MerchantSoftware { + company_name: String, + product_name: String, + version: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PaymentMethodType { + card: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Card { + expiry: Option, + card_type: Option, + card_type_name: Option, + is_bill_payment: Option, + masked_account_number: Option, + card_type_indicators: Option, + network_response: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct NetworkResponse { + address_verification_result: Option, + address_verification_result_code: Option, + card_verification_result_code: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExpiryResponse { + month: Option, + year: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CardTypeIndicators { + issuance_country_code: Option, + is_durbin_regulated: Option, + card_product_types: Vec, +} + +pub trait FromTransactionState { + fn from_transaction_state(transaction_state: String) -> Self; +} + +impl FromTransactionState for common_enums::AttemptStatus { + fn from_transaction_state(transaction_state: String) -> Self { + match transaction_state.as_str() { + "Authorized" => Self::Authorized, + "Closed" => Self::Charged, + "Declined" | "Error" => Self::Failure, + "Pending" => Self::Pending, + "Voided" => Self::Voided, //subject to change, when doing void/cancel flow + _ => Self::Failure, // Default case } } } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] -pub struct JpmorganPaymentsResponse { - status: JpmorganPaymentStatus, - id: String, +pub trait FromResponseStatus { + fn from_response_status(transaction_state: String) -> Self; +} + +impl FromResponseStatus for common_enums::AttemptStatus { + fn from_response_status(transaction_state: String) -> Self { + match transaction_state.as_str() { + "Success" => Self::Voided, //subject to change, when doing void/cancel flow + _ => Self::Failure, // Default case + } + } +} + +impl From for common_enums::AttemptStatus { + fn from(item: JpmorganTransactionStatus) -> Self { + match item { + JpmorganTransactionStatus::Success => Self::Charged, + //JpmorganTransactionStatus::Pending => Self::Pending, + JpmorganTransactionStatus::Denied | JpmorganTransactionStatus::Error => Self::Failure, + } + } } impl TryFrom> for RouterData { type Error = error_stack::Report; + fn try_from( item: ResponseRouterData, ) -> Result { + let mut transaction_state = item.response.transaction_state.to_string(); + + if transaction_state == "Closed" { + let cm = item.response.capture_method.clone(); + if cm == Some("NOW".to_string()) { + transaction_state = String::from("Closed"); + } else if cm == Some("MANUAL".to_string()) { + transaction_state = String::from("Authorized"); + } + } + let status = common_enums::AttemptStatus::from_transaction_state(transaction_state); + + let connector_response_reference_id = Some(item.response.transaction_id.clone()); + + let resource_id = ResponseId::ConnectorTransactionId(item.response.transaction_id.clone()); + + Ok(Self { + status, + response: Ok(PaymentsResponseData::TransactionResponse { + resource_id, + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id, + incremental_authorization_allowed: None, + charge_id: None, + }), + ..item.data + }) + } +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganCaptureRequest { + capture_method: Option, + merchant: Option, + recurring: Option, + installment: Option, + payment_method_type: Option, + ship_to: Option, + initiator_type: Option, + account_on_file: Option, + original_transaction_id: Option, + is_amount_final: Option, + amount: MinorUnit, + currency: Option, + merchant_order_number: Option, + risk: Option, + retail_addenda: Option, + account_holder: Option, + statement_descriptor: Option, + partial_authorization_support: Option, + payment_request_id: Option, + multi_capture: Option, + sub_merchant_supplemental_data: Option, +} + +//sub merchant supplemental data starting here + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SubMerchantSupplementalData { + pub custom_data: Option, + pub service_address: Option, + pub business_information: Option, + pub partner_service: Option, + pub shipping_info: Option, + pub recurring_billing: Option, + pub merchant_reported_revenue: Option, + pub order_information: Option, + pub consumer_device: Option, + pub merchant_identification: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CustomData { + pub external_transaction_reference_number: Option, + pub external_transaction_type: Option, + pub external_merchant_id: Option, + pub merchant_order_reference_id: Option, + pub external_batch_id: Option, + pub merchant_expected_deposit_date: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ServiceAddress { + pub line1: Option, + pub line2: Option, + pub city: Option, + pub state: Option, + pub postal_code: Option, + pub country_code: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BusinessInformation { + pub organization_legal_name: Option, + pub client_business_description_text: Option, + pub organization_d_b_a_name: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PartnerService { + pub external_vendor_product_name: Option, + pub currency: Option, + pub external_monthly_service_fee_amount: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShippingInfo { + pub shipping_carrier_name: Option, + pub expected_merchant_product_delivery_date: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RecurringBilling { + pub billing_schedule_update_timestamp: Option, + pub payment_frequency_code: Option, + pub billing_cycle_sequence_number: Option, + pub initiator_type: Option, + pub billing_cycles_total_count: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MerchantReportedRevenue { + pub amount: Option, + pub start_date: Option, + pub end_date: Option, + pub currency: Option, + pub amount_type: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OrderInformation { + pub order_items: Option>, + pub receipt_url: Option, + pub payment_notes: Option, + pub merchant_url: Option, + pub terms_url: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OrderItem { + pub merchant_product_identifier: Option, + pub line_item_description_text: Option, + pub unit_price_amount: Option, + pub line_item_unit_quantity: Option, + pub item_comodity_code: Option, + pub chosen_shipping_option: Option, + pub merchant_campaign_name: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ConsumerDevice { + pub session_id: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MerchantIdentification { + pub sub_merchant_id: Option, + pub service_entitlement_number: Option, + pub seller_identifier: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MultiCapture { + multi_capture_sequence_number: Option, + multi_capture_record_count: Option, + is_final_capture: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct AccountHolderCapReq { + reference_id: Option, + consumer_id_creation_date: String, + full_name: Option, + email: Option, + mobile: Option, + phone: Option, + i_p_address: Option, + billing_address: Option, + national_id: Option, + first_name: Option, + last_name: Option, + middle_name: Option, + consumer_profile_info: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct PhoneNumber { + country_code: Option, + phone_number: String, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BillingAddress { + line1: Option, + line2: Option, + city: Option, + state: Option, + postal_code: Option, + country_code: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct ConsumerProfileInfo { + consumer_profile_request_type: Option, + legacy_consumer_profile_id: Option, + external_consumer_profile_identifier: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RetailAddendaCapReq { + purchase_order_number: Option, + order_date: Option, + tax_amount: Option, + is_taxable: Option, + level3: Option, + gratuity_amount: Option, + surcharge_amount: Option, + health_care_data: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct HealthCareDataCapReq { + total_healthcare_amount: Option, + total_vision_amount: Option, + total_clinic_amount: Option, + total_dental_amount: Option, + total_prescription_amount: Option, + is_i_i_a_s: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Level3 { + total_shipping_amount: Option, + duty_amount: Option, + ship_to_address_postal_code: Option, + ship_to_address_country_code: Option, + ship_from_address_postal_code: Option, + total_transaction_discount_amount: Option, + value_added_tax_amount: Option, + value_added_tax_percent: Option, + shipping_value_added_tax_percent: Option, + order_discount_treatment_code: Option, + value_added_tax_invoice_reference_number: Option, + shipping_value_added_tax_amount: Option, + party_tax_government_issued_identifier: Option, + alternate_tax_amount: Option, + line_items: Option, + tax_treatment_code: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct LineItemsCapReq { + line_item_description_text: Option, + merchant_product_identifier: Option, + item_commodity_code: Option, + line_item_unit_quantity: Option, + line_item_unit_of_measure_code: Option, + unit_price_amount: Option, + tax_inclusive_line_item_total_amount: Option, + transaction_discount_amount: Option, + purchase_transaction_discount_percent: Option, + line_item_discount_treatment_code: Option, + line_item_detail_code: Option, + line_item_tax_indicator: Option, + line_item_discount_indicator: Option, + line_item_taxes: Option>, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct LineItemTaxesCapReq { + tax_type_code: Option, + line_item_tax_amount: Option, + tax_percent: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RiskCapReq { + request_fraud_score: Option, + transaction_risk_score: Option, + token_risk_score: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShipToCapReq { + shipping_description: Option, + shipping_address: Option, + full_name: Option, + email: Option, + mobile: Option, + phone: Option, + first_name: Option, + last_name: Option, + middle_name: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PhoneCapReq { + country_code: Option, + phone_number: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MobileCapReq { + country_code: Option, + phone_number: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShippingAddressCapReq { + line1: Option, + line2: Option, + city: Option, + state: Option, + postal_code: Option, + country_code: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PaymentMethodTypeCapReq { + card: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CardCapReq { + account_number_type: Option, + account_number: String, + expiry: Option, + wallet_provider: Option, + cvv: Option, + original_network_transaction_id: Option, + is_bill_payment: Option, + account_updater: Option, + authentication: Option, + encryption_integrity_check: Option, + preferred_payment_network_name_list: Vec, + merchant_sales_channel_name: Option, + merchant_preferred_routing: Option, + card_type_funding: Option, + pie_key_id: Option, + pie_phase_id: Option, + //payment_authentication_request : Option, //requires 3ds, do it later + encrypted_payload: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PaymentAuthenticationCapReq {} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AuthenticationCapReq { + authentication_id: Option, + //three_d_s //do it later + electronic_commerce_indicator: Option, + token_authentication_value: Option, + s_c_a_exemption_reason: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AccountUpdaterCapReq { + request_account_updater: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExpiryCapReq { + month: i32, + year: i32, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstallmentCapReq { + installment_count: Option, + total_installments: Option, + number_of_deferrals: Option, + plan_id: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct RecurringCapReq { + recurring_sequence: Option, + agreement_id: Option, + payment_agreement_expiry_date: Option, //this will be string, just recheck again + is_variable_amount: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MerchantCapReq { + merchant_software: MerchantSoftwareCapReq, + merchant_category_code: Option, + merchant_logo_url: Option, + soft_merchant: SoftMerchantCapReq, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MerchantSoftwareCapReq { + company_name: Option, + product_name: Option, + version: Option, + software_id: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SoftMerchantCapReq { + name: Option, + phone: Option, + email: Option, + url: Option, + merchant_purchase_description: Option, + visa_merchant_verification_value_id: Option, + master_card_merchant_verification_value_id: Option, + merchant_incorporation_status: Option, + foreign_merchant_indicator: Option, +} + +#[derive(Debug, Default, Copy, Serialize, Deserialize, Clone)] +#[serde(rename_all = "UPPERCASE")] +pub enum CaptureMethod { + #[default] + Now, + Delayed, + Manual, +} + +impl TryFrom<&JpmorganRouterData<&PaymentsCaptureRouterData>> for JpmorganCaptureRequest { + type Error = error_stack::Report; + fn try_from( + item: &JpmorganRouterData<&PaymentsCaptureRouterData>, + ) -> Result { + let capture_method = item + .router_data + .request + .capture_method + .as_ref() + .map(|cm| cm.to_string()); + + let currency = Some(item.router_data.request.currency.to_string()); + + let amount = item.amount; Ok(Self { - status: common_enums::AttemptStatus::from(item.response.status), + capture_method, + merchant: None, + recurring: None, + installment: None, + payment_method_type: None, + ship_to: None, + initiator_type: None, + account_on_file: None, + original_transaction_id: None, + is_amount_final: None, + amount, + currency, + merchant_order_number: None, + risk: None, + retail_addenda: None, + account_holder: None, + statement_descriptor: None, + partial_authorization_support: None, + payment_request_id: None, + multi_capture: None, + sub_merchant_supplemental_data: None, + }) + } +} + +//made changes here in JpmorganTransactionState +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganCaptureResponse { + pub transaction_id: String, + pub request_id: String, + pub transaction_state: JpmorganTransactionState, + pub response_status: JpmorganTransactionStatus, + pub response_code: String, + pub response_message: String, + pub payment_method_type: PaymentMethodTypeCapRes, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PaymentMethodTypeCapRes { + pub card: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CardCapRes { + pub card_type: Option, + pub card_type_name: Option, + unmasked_account_number: Option, +} + +impl From for common_enums::AttemptStatus { + fn from(item: JpmorganTransactionState) -> Self { + match item { + JpmorganTransactionState::Authorized => Self::Authorized, + JpmorganTransactionState::Closed => Self::Charged, + JpmorganTransactionState::Declined | JpmorganTransactionState::Error => Self::Failure, + JpmorganTransactionState::Pending => Self::Pending, + JpmorganTransactionState::Voided => Self::Voided, + } + } +} + +impl TryFrom> + for RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData, + ) -> Result { + let transaction_state = item.response.transaction_state.to_string(); + let status = common_enums::AttemptStatus::from_transaction_state(transaction_state); + + let transaction_id = item.response.transaction_id.clone(); + let connector_response_reference_id = Some(transaction_id.clone()); + + let resource_id = ResponseId::ConnectorTransactionId(transaction_id.clone()); + + Ok(Self { + status, response: Ok(PaymentsResponseData::TransactionResponse { - resource_id: ResponseId::ConnectorTransactionId(item.response.id), + resource_id, redirection_data: Box::new(None), mandate_reference: Box::new(None), connector_metadata: None, network_txn_id: None, - connector_response_reference_id: None, + connector_response_reference_id, incremental_authorization_allowed: None, charge_id: None, }), @@ -142,24 +932,115 @@ impl TryFrom + TryFrom> + for RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData, + ) -> Result { + let transaction_state = item.response.transaction_state.to_string(); + let status = common_enums::AttemptStatus::from_transaction_state(transaction_state); + + let transaction_id = item.response.transaction_id.clone(); + let connector_response_reference_id = Some(transaction_id.clone()); + + let resource_id = ResponseId::ConnectorTransactionId(transaction_id.clone()); + + Ok(Self { + status, + response: Ok(PaymentsResponseData::TransactionResponse { + resource_id, + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id, + incremental_authorization_allowed: None, + charge_id: None, + }), + ..item.data + }) + } +} + +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct TransactionData { + payment_type: Option, + status_code: i32, + txn_secret: Option, + tid: Option>, + test_mode: Option, + status: Option, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct JpmorganRefundRequest { - pub amount: StringMinorUnit, + pub merchant: MerchantRefundReq, + pub amount: MinorUnit, +} + +#[derive(Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct MerchantRefundReq { + pub merchant_software: MerchantSoftware, } impl TryFrom<&JpmorganRouterData<&RefundsRouterData>> for JpmorganRefundRequest { type Error = error_stack::Report; fn try_from(item: &JpmorganRouterData<&RefundsRouterData>) -> Result { - Ok(Self { - amount: item.amount.to_owned(), - }) + let merchant_software = MerchantSoftware { + company_name: String::from("JPMC"), //According to documentation, it should be the company name of software integrated to this API. If merchant is directly integrated, send "JPMC." + product_name: String::from("Hyperswitch"), //According to documentation, it should be the name of the product used for marketing purposes from a customer perspective. I. e. what the customer would recognize. + //https://developer.payments.jpmorgan.com/api/commerce/online-payments/online-payments#/operations/V2PaymentPost + version: Some(String::from("1.235")), //recheck, seek guidance + }; + + let merchant = MerchantRefundReq { merchant_software }; + + let amount = item.amount; + + Ok(Self { merchant, amount }) } } -// Type definition for Refund Response +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganRefundResponse { + pub transaction_id: Option, + pub request_id: String, + pub transaction_state: JpmorganTransactionState, + pub amount: MinorUnit, + pub currency: String, + pub response_status: JpmorganResponseStatus, + pub response_code: String, + pub response_message: String, + pub transaction_reference_id: Option, + pub remaining_refundable_amount: Option, +} #[allow(dead_code)] #[derive(Debug, Serialize, Default, Deserialize, Clone)] @@ -176,53 +1057,202 @@ impl From for enums::RefundStatus { RefundStatus::Succeeded => Self::Success, RefundStatus::Failed => Self::Failure, RefundStatus::Processing => Self::Pending, - //TODO: Review mapping } } } -//TODO: Fill the struct with respective fields #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct RefundResponse { id: String, status: RefundStatus, } -impl TryFrom> for RefundsRouterData { +pub trait FromRefundState { + fn from_transaction_state(transaction_state: String) -> Self; +} + +impl FromRefundState for common_enums::RefundStatus { + fn from_transaction_state(transaction_state: String) -> Self { + match transaction_state.as_str() { + "Closed" | "Authorized" => Self::Success, + "Declined" | "Error" => Self::Failure, + "Pending" => Self::Pending, + _ => Self::Failure, + } + } +} + +impl TryFrom> + for RefundsRouterData +{ type Error = error_stack::Report; fn try_from( - item: RefundsResponseRouterData, + item: RefundsResponseRouterData, ) -> Result { + let refund_id = item + .response + .transaction_id + .clone() + .ok_or(errors::ConnectorError::ResponseHandlingFailed)?; + + let transaction_state = item.response.transaction_state.to_string(); + let refund_status = common_enums::RefundStatus::from_transaction_state(transaction_state); + Ok(Self { response: Ok(RefundsResponseData { - connector_refund_id: item.response.id.to_string(), - refund_status: enums::RefundStatus::from(item.response.status), + connector_refund_id: refund_id, + refund_status, }), ..item.data }) } } -impl TryFrom> for RefundsRouterData { +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganRefundSyncResponse { + transaction_id: String, + request_id: String, + transaction_state: JpmorganTransactionState, + amount: MinorUnit, + currency: String, + response_status: JpmorganResponseStatus, + response_code: String, +} + +impl TryFrom> + for RefundsRouterData +{ type Error = error_stack::Report; fn try_from( - item: RefundsResponseRouterData, + item: RefundsResponseRouterData, ) -> Result { + let refund_id = item.response.transaction_id.clone(); + let transaction_state = item.response.transaction_state.to_string(); + let status = common_enums::RefundStatus::from_transaction_state(transaction_state); Ok(Self { response: Ok(RefundsResponseData { - connector_refund_id: item.response.id.to_string(), - refund_status: enums::RefundStatus::from(item.response.status), + connector_refund_id: refund_id, + refund_status: status, + }), + ..item.data + }) + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganCancelRequest { + //is_capture: Option, + //capture_method : Option, + pub amount: Option, + pub is_void: Option, + pub reversal_reason: Option, +} + +impl TryFrom> for JpmorganCancelRequest { + type Error = error_stack::Report; + fn try_from(item: JpmorganRouterData<&PaymentsCancelRouterData>) -> Result { + let is_void = Some(true); + let amount = item.router_data.request.amount; + let reversal_reason = item.router_data.request.cancellation_reason.clone(); + Ok(Self { + amount, + is_void, + reversal_reason, + }) + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganCancelResponse { + transaction_id: String, + request_id: String, + response_status: JpmorganResponseStatus, + response_code: String, + response_message: String, + payment_method_type: JpmorganPaymentMethodTypeCancelResponse, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganPaymentMethodTypeCancelResponse { + pub card: CardCancelResponse, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CardCancelResponse { + pub card_type: String, + pub card_type_name: String, +} + +impl + TryFrom> + for RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData< + F, + JpmorganCancelResponse, + PaymentsCancelData, + PaymentsResponseData, + >, + ) -> Result { + let response_status = match item.response.response_status { + JpmorganResponseStatus::Success => String::from("Success"), + JpmorganResponseStatus::Denied => String::from("Denied"), + JpmorganResponseStatus::Error => String::from("Error"), + }; + + let status = common_enums::AttemptStatus::from_response_status(response_status); + + let transaction_id = item.response.transaction_id.clone(); + + let resource_id = ResponseId::ConnectorTransactionId(transaction_id.clone()); + + let connector_response_reference_id = Some(transaction_id.clone()); + + Ok(Self { + status, + response: Ok(PaymentsResponseData::TransactionResponse { + resource_id, + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id, + incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) } } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganValidationErrors { + pub code: Option, + pub message: Option, + pub entity: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct JpmorganErrorInformation { + pub code: Option, + pub message: Option, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] pub struct JpmorganErrorResponse { - pub status_code: u16, - pub code: String, - pub message: String, - pub reason: Option, + pub response_status: JpmorganTransactionStatus, + pub response_code: String, + pub response_message: Option, + // pub validation_errors : Option>, + // pub information : JpmorganErrorInformation, } diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 40ed4e75521..d7c09062a09 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1401,6 +1401,10 @@ impl ConnectorAuthTypeAndMetadataValidation<'_> { itaubank::transformers::ItaubankAuthType::try_from(self.auth_type)?; Ok(()) } + api_enums::Connector::Jpmorgan => { + jpmorgan::transformers::JpmorganAuthType::try_from(self.auth_type)?; + Ok(()) + } api_enums::Connector::Klarna => { klarna::transformers::KlarnaAuthType::try_from(self.auth_type)?; klarna::transformers::KlarnaConnectorMetadataObject::try_from( diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index cf349ef6e05..a042a3979e1 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -949,6 +949,7 @@ default_imp_for_payouts!( connector::Gpayments, connector::Iatapay, connector::Itaubank, + //connector::Jpmorgan, connector::Klarna, connector::Mifinity, connector::Netcetera, diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 763d408d174..b477acb6d05 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -438,9 +438,11 @@ impl ConnectorData { // Ok(ConnectorEnum::Old(Box::new(connector::Inespay::new()))) // } enums::Connector::Itaubank => { - //enums::Connector::Jpmorgan => Ok(ConnectorEnum::Old(Box::new(connector::Jpmorgan))), Ok(ConnectorEnum::Old(Box::new(connector::Itaubank::new()))) } + enums::Connector::Jpmorgan => { + Ok(ConnectorEnum::Old(Box::new(connector::Jpmorgan::new()))) + } enums::Connector::Klarna => { Ok(ConnectorEnum::Old(Box::new(connector::Klarna::new()))) } diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 55a523b528e..829c8b1dbd3 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -251,7 +251,7 @@ impl ForeignTryFrom for common_enums::RoutableConnectors { api_enums::Connector::Iatapay => Self::Iatapay, // api_enums::Connector::Inespay => Self::Inespay, api_enums::Connector::Itaubank => Self::Itaubank, - //api_enums::Connector::Jpmorgan => Self::Jpmorgan, + api_enums::Connector::Jpmorgan => Self::Jpmorgan, api_enums::Connector::Klarna => Self::Klarna, api_enums::Connector::Mifinity => Self::Mifinity, api_enums::Connector::Mollie => Self::Mollie, diff --git a/crates/router/tests/connectors/sample_auth.toml b/crates/router/tests/connectors/sample_auth.toml index d099c16254b..bfa54691b7c 100644 --- a/crates/router/tests/connectors/sample_auth.toml +++ b/crates/router/tests/connectors/sample_auth.toml @@ -294,7 +294,8 @@ api_key="API Key" api_key="API Key" [jpmorgan] -api_key="API Key" +api_key="Client ID" +key1 ="Client Secret" [elavon] api_key="API Key" diff --git a/crates/test_utils/src/connector_auth.rs b/crates/test_utils/src/connector_auth.rs index 3fab02e64d1..b08dced47c9 100644 --- a/crates/test_utils/src/connector_auth.rs +++ b/crates/test_utils/src/connector_auth.rs @@ -51,7 +51,7 @@ pub struct ConnectorAuthentication { pub iatapay: Option, pub inespay: Option, pub itaubank: Option, - pub jpmorgan: Option, + pub jpmorgan: Option, pub mifinity: Option, pub mollie: Option, pub multisafepay: Option, diff --git a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js new file mode 100644 index 00000000000..00a1ca26eab --- /dev/null +++ b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js @@ -0,0 +1,141 @@ +const successfulNo3DSCardDetails = { + card_number : "6011016011016011", + card_exp_month : "10", + card_exp_year : "2027", + card_holder_name : "John Doe", + card_cvc : "123", +}; + +export const connectorDetails = { + card_pm : { + PaymentIntent : { + Request : { + currency : "USD", + customer_acceptance : null, + setup_future_usage : "on_session", + }, + Response : { + status : 200, + body : { + status : + "requires_payment_method", + }, + }, + }, + No3DSManualCapture: { + Request: { + currency: "USD", + payment_method: "card", + billing: { + address: { + line1: "1467", + line2: "CA", + line3: "CA", + city: "Musterhausen", + state: "California", + zip: "12345", + country: "US", + first_name: "John", + last_name: "Doe", + }, + email: "test@jpmorgan.us", + phone: { + number: "9123456789", + country_code: "+91", + }, + }, + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + setup_future_usage: "on_session", + }, + Response: { + status: 200, + body: { + status: "requires_capture", + }, + }, + }, + No3DSAutoCapture: { + Request: { + currency: "USD", + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + setup_future_usage: "on_session", + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, + }, + }, + Capture: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + body: { + status: "succeeded", + amount: 6500, + amount_capturable: 0, + amount_received: 6500, + }, + }, + }, + Refund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, + }, + }, + PartialRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, + }, + }, + SyncRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, + }, + }, + } +} \ No newline at end of file diff --git a/cypress-tests/cypress/e2e/PaymentUtils/Utils.js b/cypress-tests/cypress/e2e/PaymentUtils/Utils.js index e432c37717b..6e494039beb 100644 --- a/cypress-tests/cypress/e2e/PaymentUtils/Utils.js +++ b/cypress-tests/cypress/e2e/PaymentUtils/Utils.js @@ -15,6 +15,7 @@ import { connectorDetails as fiservemeaConnectorDetails } from "./Fiservemea.js" import { connectorDetails as fiuuConnectorDetails } from "./Fiuu.js"; import { connectorDetails as iatapayConnectorDetails } from "./Iatapay.js"; import { connectorDetails as itaubankConnectorDetails } from "./ItauBank.js"; +import { connectorDetails as jpmorganConnectorDetails} from "./Jpmorgan.js"; import { connectorDetails as nexixpayConnectorDetails } from "./Nexixpay.js"; import { connectorDetails as nmiConnectorDetails } from "./Nmi.js"; import { connectorDetails as noonConnectorDetails } from "./Noon.js"; @@ -36,6 +37,7 @@ const connectorDetails = { fiservemea: fiservemeaConnectorDetails, iatapay: iatapayConnectorDetails, itaubank: itaubankConnectorDetails, + jpmorgan : jpmorganConnectorDetails, nexixpay: nexixpayConnectorDetails, nmi: nmiConnectorDetails, novalnet: novalnetConnectorDetails, diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index 81bcf01fddc..25a391b70d2 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -120,6 +120,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" From 60317e388651b5d6e0931462732c2a672a32054d Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Thu, 28 Nov 2024 18:35:57 +0530 Subject: [PATCH 02/12] fix: Handle default cases --- config/development.toml | 1 + .../src/connectors/jpmorgan.rs | 21 +- .../src/connectors/jpmorgan/transformers.rs | 18 +- .../hyperswitch_connectors/src/constants.rs | 2 + .../cypress/e2e/PaymentUtils/Jpmorgan.js | 374 +++++++++++------- 5 files changed, 274 insertions(+), 142 deletions(-) diff --git a/config/development.toml b/config/development.toml index e3a3019c1a5..4e2be24dda7 100644 --- a/config/development.toml +++ b/config/development.toml @@ -56,6 +56,7 @@ max_feed_count = 200 [server] # HTTP Request body limit. Defaults to 32kB request_body_limit = 32768 +port=8082 [secrets] admin_api_key = "test_admin" diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index f39b103225c..eaf36ee7fb7 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -77,6 +77,8 @@ impl ConnectorIntegration ConnectorCommonExt for Jpmorgan where Self: ConnectorIntegration, @@ -85,7 +87,8 @@ where &self, req: &RouterData, _connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { + println!("Entered build headers of ConnectorCommonExt impl"); let mut headers = vec![( headers::CONTENT_TYPE.to_string(), self.get_content_type().to_string().into(), @@ -98,8 +101,20 @@ where headers::AUTHORIZATION.to_string(), format!("Bearer {}", access_token.token.peek()).into_masked(), ); - + let request_id = ( + headers::REQUEST_ID.to_string(), + req.connector_request_reference_id.clone().to_string().into_masked() + ); + let merchant_id = ( + headers::MERCHANTID.to_string(), + req.merchant_id.get_string_repr().to_string().into_masked() + ); + println!("Auth Header {:?}", auth_header); + println!("Request Id {:?}", request_id); + println!("Merchant Id {:?}", merchant_id); headers.push(auth_header); + headers.push(request_id); + headers.push(merchant_id); Ok(headers) } } @@ -129,6 +144,7 @@ impl ConnectorCommon for Jpmorgan { &self, auth_type: &ConnectorAuthType, ) -> CustomResult)>, errors::ConnectorError> { + println!("Entering get_auth_header"); let auth = jpmorgan::JpmorganAuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; Ok(vec![( @@ -328,6 +344,7 @@ impl ConnectorIntegration CustomResult)>, errors::ConnectorError> { + println!("in get_headers of authorize {:?}", self.build_headers(req, connectors)); self.build_headers(req, connectors) } diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index fad8e7201df..404ad616f74 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -343,7 +343,6 @@ impl From for common_enums::AttemptStatus { fn from(item: JpmorganTransactionStatus) -> Self { match item { JpmorganTransactionStatus::Success => Self::Charged, - //JpmorganTransactionStatus::Pending => Self::Pending, JpmorganTransactionStatus::Denied | JpmorganTransactionStatus::Error => Self::Failure, } } @@ -371,7 +370,7 @@ impl TryFrom> for JpmorganCaptur let currency = Some(item.router_data.request.currency.to_string()); + // let company_name : Option = Some(String::from("JPMC")); + // let product_name : Option = Some(String::from("Hyperswitch")); + // let version : Option = Some(String::from("1.235")); + // let software_id : Option = None; + + // let merchant_software = MerchantSoftwareCapReq{ + // company_name, + // product_name, + // version, + // software_id, + // }; + + // let merchant_category_code : Option = item.router_data.address; let amount = item.amount; Ok(Self { capture_method, @@ -1040,6 +1052,7 @@ pub struct JpmorganRefundResponse { pub response_message: String, pub transaction_reference_id: Option, pub remaining_refundable_amount: Option, + //pub payment_request_id : Option, } #[allow(dead_code)] @@ -1097,7 +1110,6 @@ impl TryFrom> let transaction_state = item.response.transaction_state.to_string(); let refund_status = common_enums::RefundStatus::from_transaction_state(transaction_state); - Ok(Self { response: Ok(RefundsResponseData { connector_refund_id: refund_id, diff --git a/crates/hyperswitch_connectors/src/constants.rs b/crates/hyperswitch_connectors/src/constants.rs index 48a32c18047..38cfd5f4795 100644 --- a/crates/hyperswitch_connectors/src/constants.rs +++ b/crates/hyperswitch_connectors/src/constants.rs @@ -10,6 +10,8 @@ pub(crate) mod headers { pub(crate) const IDEMPOTENCY_KEY: &str = "Idempotency-Key"; pub(crate) const MESSAGE_SIGNATURE: &str = "Message-Signature"; pub(crate) const MERCHANT_ID: &str = "Merchant-ID"; + pub(crate) const MERCHANTID: &str = "merchant-id"; + pub(crate) const REQUEST_ID: &str = "request-id"; pub(crate) const NONCE: &str = "nonce"; pub(crate) const TIMESTAMP: &str = "Timestamp"; pub(crate) const TOKEN: &str = "token"; diff --git a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js index 00a1ca26eab..86e7e53c793 100644 --- a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js +++ b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js @@ -1,141 +1,241 @@ const successfulNo3DSCardDetails = { - card_number : "6011016011016011", - card_exp_month : "10", - card_exp_year : "2027", - card_holder_name : "John Doe", - card_cvc : "123", + card_number: "6011016011016011", + card_exp_month: "10", + card_exp_year: "2027", + card_holder_name: "John Doe", + card_cvc: "123", }; export const connectorDetails = { - card_pm : { - PaymentIntent : { - Request : { - currency : "USD", - customer_acceptance : null, - setup_future_usage : "on_session", - }, - Response : { - status : 200, - body : { - status : - "requires_payment_method", - }, - }, - }, - No3DSManualCapture: { - Request: { - currency: "USD", - payment_method: "card", - billing: { - address: { - line1: "1467", - line2: "CA", - line3: "CA", - city: "Musterhausen", - state: "California", - zip: "12345", - country: "US", - first_name: "John", - last_name: "Doe", - }, - email: "test@jpmorgan.us", - phone: { - number: "9123456789", - country_code: "+91", - }, - }, - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - setup_future_usage: "on_session", - }, - Response: { - status: 200, - body: { - status: "requires_capture", - }, - }, - }, - No3DSAutoCapture: { - Request: { - currency: "USD", - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - setup_future_usage: "on_session", - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, - Capture: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - body: { - status: "succeeded", - amount: 6500, - amount_capturable: 0, - amount_received: 6500, - }, - }, - }, - Refund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, - PartialRefund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, - SyncRefund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, - } -} \ No newline at end of file + card_pm: { + PaymentIntent: { + Request: { + currency: "USD", + customer_acceptance: null, + setup_future_usage: "on_session", + }, + Response: { + status: 200, + body: { + status: "requires_payment_method", + }, + }, + }, + "3DSManualCapture": { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + currency: "USD", + customer_acceptance: null, + setup_future_usage: "on_session", + }, + Response: { + status: 200, + trigger_skip: true, + body: { + // status: "requires_customer_action", + status: "succeeded" + // setup_future_usage: "on_session", + // payment_method_data: payment_method_data_3ds, + }, + }, + }, + + "3DSAutoCapture": { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + currency: "USD", + customer_acceptance: null, + setup_future_usage: "on_session", + }, + Response: { + status: 200, + trigger_skip: true, + body: { + //status: "requires_customer_action", + status: "succeeded" + // setup_future_usage: "on_session", + // payment_method_data: payment_method_data_3ds, + }, + }, + }, + No3DSManualCapture: { + Request: { + currency: "USD", + payment_method: "card", + billing: { + address: { + line1: "1467", + line2: "CA", + line3: "CA", + city: "Musterhausen", + state: "California", + zip: "12345", + country: "US", + first_name: "John", + last_name: "Doe", + }, + email: "test@jpmorgan.us", + phone: { + number: "9123456789", + country_code: "+91", + }, + }, + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + setup_future_usage: "on_session", + }, + Response: { + status: 200, + body: { + status: "requires_capture", + }, + }, + }, + No3DSAutoCapture: { + Request: { + currency: "USD", + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + setup_future_usage: "on_session", + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, + }, + }, + Capture: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + body: { + status: "succeeded", + amount: 6500, + amount_capturable: 0, + amount_received: 6500, + }, + }, + }, + PartialCapture: { + Request: {}, + Response: { + status: 200, + body: { + status: "partially_captured", + amount: 6500, + amount_capturable: 0, + amount_received: 100, + }, + }, + }, + Refund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + //trigger_skip: true, + body: { + status: "succeeded", + }, + }, + }, + manualPaymentRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + //trigger_skip: true, + body: { + status: "succeeded", + }, + }, + // Response: { + // status: 400, + // //trigger_skip: true, + // body: { + // error: { + // type : "invalid_request", + // message : "This Payment could not be refund because it has a status of processing. The expected state is succeeded, partially_captured", + // code : "IR_14", + // } + // }, + // }, + }, + manualPaymentPartialRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + //currency: "USD", + customer_acceptance: null, + }, + Response: { + status: 200, + //trigger_skip: true, + body: { + status: "succeeded", + }, + }, + }, + PartialRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + //trigger_skip: true, + body: { + status: "succeeded", + }, + }, + }, + SyncRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 200, + body: { + status: "succeeded", + }, + }, + }, + }, +}; From 1c4984e38e45cf322dbb6e149431bfc882d62788 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Fri, 29 Nov 2024 16:23:32 +0530 Subject: [PATCH 03/12] fix: Handle default cases --- config/development.toml | 1 - .../src/connectors/jpmorgan.rs | 22 ++++------ .../src/connectors/jpmorgan/transformers.rs | 9 ++++- .../cypress/e2e/PaymentUtils/Jpmorgan.js | 40 ++++++------------- 4 files changed, 28 insertions(+), 44 deletions(-) diff --git a/config/development.toml b/config/development.toml index 4e2be24dda7..e3a3019c1a5 100644 --- a/config/development.toml +++ b/config/development.toml @@ -56,7 +56,6 @@ max_feed_count = 200 [server] # HTTP Request body limit. Defaults to 32kB request_body_limit = 32768 -port=8082 [secrets] admin_api_key = "test_admin" diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index eaf36ee7fb7..b761c71b0d1 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -88,7 +88,6 @@ where req: &RouterData, _connectors: &Connectors, ) -> CustomResult)>, errors::ConnectorError> { - println!("Entered build headers of ConnectorCommonExt impl"); let mut headers = vec![( headers::CONTENT_TYPE.to_string(), self.get_content_type().to_string().into(), @@ -109,9 +108,6 @@ where headers::MERCHANTID.to_string(), req.merchant_id.get_string_repr().to_string().into_masked() ); - println!("Auth Header {:?}", auth_header); - println!("Request Id {:?}", request_id); - println!("Merchant Id {:?}", merchant_id); headers.push(auth_header); headers.push(request_id); headers.push(merchant_id); @@ -143,8 +139,7 @@ impl ConnectorCommon for Jpmorgan { fn get_auth_header( &self, auth_type: &ConnectorAuthType, - ) -> CustomResult)>, errors::ConnectorError> { - println!("Entering get_auth_header"); + ) -> CustomResult)>, errors::ConnectorError> { let auth = jpmorgan::JpmorganAuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; Ok(vec![( @@ -251,7 +246,7 @@ impl ConnectorIntegration &self, req: &RefreshTokenRouterData, _connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { let client_id = req.request.app_id.clone(); let client_secret = req.request.id.clone(); @@ -343,8 +338,7 @@ impl ConnectorIntegration CustomResult)>, errors::ConnectorError> { - println!("in get_headers of authorize {:?}", self.build_headers(req, connectors)); + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -435,7 +429,7 @@ impl ConnectorIntegration fo &self, req: &PaymentsCaptureRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -526,7 +520,7 @@ impl ConnectorIntegration for Jpm &self, req: &PaymentsSyncRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -597,7 +591,7 @@ impl ConnectorIntegration for Jp &self, req: &PaymentsCancelRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -683,7 +677,7 @@ impl ConnectorIntegration for Jpmorga &self, req: &RefundsRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -768,7 +762,7 @@ impl ConnectorIntegration for Jpmorgan &self, req: &RefundSyncRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index 404ad616f74..da4c10bb0a2 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -18,7 +18,7 @@ use strum::Display; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::PaymentsAuthorizeRequestData, + utils::{PaymentsAuthorizeRequestData, RouterData as OtherRouterData}, }; pub struct JpmorganRouterData { pub amount: MinorUnit, @@ -137,6 +137,13 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym ) -> Result { match item.router_data.request.payment_method_data.clone() { PaymentMethodData::Card(req_card) => { + if item.router_data.is_three_ds(){ + return Err(errors::ConnectorError::NotSupported{ + message : "Three_ds payments".to_string(), + connector : "Jpmorgan" + } + .into()); + } let capture_method = if let Some(method) = item.router_data.request.capture_method { map_capture_method(method) } else { diff --git a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js index 86e7e53c793..debd18401fa 100644 --- a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js +++ b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js @@ -32,13 +32,13 @@ export const connectorDetails = { setup_future_usage: "on_session", }, Response: { - status: 200, - trigger_skip: true, + status: 501, body: { - // status: "requires_customer_action", - status: "succeeded" - // setup_future_usage: "on_session", - // payment_method_data: payment_method_data_3ds, + error: { + type: "invalid_request", + message: "Three_ds payments is not supported by Jpmorgan", + code: "IR_00", + }, }, }, }, @@ -54,13 +54,13 @@ export const connectorDetails = { setup_future_usage: "on_session", }, Response: { - status: 200, - trigger_skip: true, + status: 501, body: { - //status: "requires_customer_action", - status: "succeeded" - // setup_future_usage: "on_session", - // payment_method_data: payment_method_data_3ds, + error: { + type: "invalid_request", + message: "Three_ds payments is not supported by Jpmorgan", + code: "IR_00", + }, }, }, }, @@ -156,7 +156,6 @@ export const connectorDetails = { }, Response: { status: 200, - //trigger_skip: true, body: { status: "succeeded", }, @@ -172,22 +171,10 @@ export const connectorDetails = { }, Response: { status: 200, - //trigger_skip: true, body: { status: "succeeded", }, }, - // Response: { - // status: 400, - // //trigger_skip: true, - // body: { - // error: { - // type : "invalid_request", - // message : "This Payment could not be refund because it has a status of processing. The expected state is succeeded, partially_captured", - // code : "IR_14", - // } - // }, - // }, }, manualPaymentPartialRefund: { Request: { @@ -195,12 +182,10 @@ export const connectorDetails = { payment_method_data: { card: successfulNo3DSCardDetails, }, - //currency: "USD", customer_acceptance: null, }, Response: { status: 200, - //trigger_skip: true, body: { status: "succeeded", }, @@ -216,7 +201,6 @@ export const connectorDetails = { }, Response: { status: 200, - //trigger_skip: true, body: { status: "succeeded", }, From ef344f92313794e1bcf45e92b00052cda8c41e96 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Thu, 5 Dec 2024 14:30:01 +0530 Subject: [PATCH 04/12] fix: Handle default cases --- config/development.toml | 1 + .../src/connectors/jpmorgan/transformers.rs | 12 +- .../cypress/e2e/PaymentUtils/Jpmorgan.js | 93 +- cypress-tests/package-lock.json | 17 +- cypress-tests/package.json | 3 + package-lock.json | 997 ++++++++++++------ package.json | 3 + 7 files changed, 784 insertions(+), 342 deletions(-) diff --git a/config/development.toml b/config/development.toml index e3a3019c1a5..4e2be24dda7 100644 --- a/config/development.toml +++ b/config/development.toml @@ -56,6 +56,7 @@ max_feed_count = 200 [server] # HTTP Request body limit. Defaults to 32kB request_body_limit = 32768 +port=8082 [secrets] admin_api_key = "test_admin" diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index da4c10bb0a2..1f973a202e9 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -377,7 +377,8 @@ impl TryFrom TryFrom<&JpmorganRouterData<&RefundsRouterData>> for JpmorganRefundRequest { +/*impl TryFrom<&JpmorganRouterData<&RefundsRouterData>> for JpmorganRefundRequest { type Error = error_stack::Report; fn try_from(item: &JpmorganRouterData<&RefundsRouterData>) -> Result { let merchant_software = MerchantSoftware { @@ -1044,6 +1045,13 @@ impl TryFrom<&JpmorganRouterData<&RefundsRouterData>> for JpmorganRefundRe Ok(Self { merchant, amount }) } +}*/ + +impl TryFrom<&JpmorganRouterData<&RefundsRouterData>> for JpmorganRefundRequest { + type Error = error_stack::Report; + fn try_from(_item: &JpmorganRouterData<&RefundsRouterData>) -> Result { + Err(errors::ConnectorError::NotImplemented("Refunds".to_string()).into()) + } } #[derive(Debug, Serialize, Deserialize)] diff --git a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js index debd18401fa..ca7feefde51 100644 --- a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js +++ b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js @@ -146,7 +146,7 @@ export const connectorDetails = { }, }, }, - Refund: { + /*Refund: { Request: { payment_method: "card", payment_method_data: { @@ -205,8 +205,77 @@ export const connectorDetails = { status: "succeeded", }, }, + },*/ + Refund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 501, + body: { + // status: "succeeded", + type: "invalid_request", + message: "Refunds is not implemented", + code: "IR_00" + }, + }, }, - SyncRefund: { + manualPaymentRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 501, + body: { + type: "invalid_request", + message: "Refunds is not implemented", + code: "IR_00" + }, + }, + }, + manualPaymentPartialRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 501, + body: { + type: "invalid_request", + message: "Refunds is not implemented", + code: "IR_00" + }, + }, + }, + PartialRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 501, + body: { + type: "invalid_request", + message: "Refunds is not implemented", + code: "IR_00" + }, + }, + }, + /*SyncRefund: { Request: { payment_method: "card", payment_method_data: { @@ -216,10 +285,28 @@ export const connectorDetails = { }, Response: { status: 200, + trigger_skip: true, body: { status: "succeeded", }, }, - }, + }*/ + SyncRefund: { + Request: { + payment_method: "card", + payment_method_data: { + card: successfulNo3DSCardDetails, + }, + customer_acceptance: null, + }, + Response: { + status: 404, + body: { + type: "undefined", + message: "Refund does not exist in our records.", + code: "HE_02" + }, + }, + } }, }; diff --git a/cypress-tests/package-lock.json b/cypress-tests/package-lock.json index a2c2c4b8fb2..4038f0866c0 100644 --- a/cypress-tests/package-lock.json +++ b/cypress-tests/package-lock.json @@ -8,6 +8,9 @@ "name": "test", "version": "1.0.0", "license": "ISC", + "dependencies": { + "ci": "^2.3.0" + }, "devDependencies": { "@eslint/js": "^9.16.0", "cypress": "^13.16.0", @@ -830,20 +833,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/ci-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", diff --git a/cypress-tests/package.json b/cypress-tests/package.json index ff168f61eff..a2eb034d692 100644 --- a/cypress-tests/package.json +++ b/cypress-tests/package.json @@ -29,5 +29,8 @@ "globals": "^15.13.0", "jsqr": "^1.4.0", "prettier": "^3.4.1" + }, + "dependencies": { + "ci": "^2.3.0" } } diff --git a/package-lock.json b/package-lock.json index 19a2d2fb02e..115ab0f9cee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,662 +1,870 @@ { "name": "hyperswitch", "version": "0.0.0", - "lockfileVersion": 1, + "lockfileVersion": 3, "requires": true, - "dependencies": { - "@colors/colors": { + "packages": { + "": { + "name": "hyperswitch", + "version": "0.0.0", + "dependencies": { + "ci": "^2.3.0" + }, + "devDependencies": { + "newman": "git+ssh://git@github.com:knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8" + } + }, + "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, - "optional": true + "optional": true, + "engines": { + "node": ">=0.1.90" + } }, - "@faker-js/faker": { + "node_modules/@faker-js/faker": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz", "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==", + "deprecated": "Please update to a newer version.", "dev": true }, - "@postman/form-data": { + "node_modules/@postman/form-data": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@postman/form-data/-/form-data-3.1.1.tgz", "integrity": "sha512-vjh8Q2a8S6UCm/KKs31XFJqEEgmbjBmpPNVV2eVav6905wyFAwaUOBGA1NPBI4ERH9MMZc6w0umFgM6WbEPMdg==", "dev": true, - "requires": { + "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, - "@postman/tough-cookie": { + "node_modules/@postman/tough-cookie": { "version": "4.1.3-postman.1", "resolved": "https://registry.npmjs.org/@postman/tough-cookie/-/tough-cookie-4.1.3-postman.1.tgz", "integrity": "sha512-txpgUqZOnWYnUHZpHjkfb0IwVH4qJmyq77pPnJLlfhMtdCLMFTEeQHlzQiK906aaNCe4NEB5fGJHo9uzGbFMeA==", "dev": true, - "requires": { + "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" } }, - "@postman/tunnel-agent": { + "node_modules/@postman/tunnel-agent": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.4.tgz", "integrity": "sha512-CJJlq8V7rNKhAw4sBfjixKpJW00SHqebqNUQKxMoepgeWZIbdPcD+rguRcivGhS4N12PymDcKgUgSD4rVC+RjQ==", "dev": true, - "requires": { + "dependencies": { "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" } }, - "ajv": { + "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "requires": { + "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "ansi-regex": { + "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "ansi-styles": { + "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "requires": { + "dependencies": { "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "array-back": { + "node_modules/array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "asn1": { + "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, - "requires": { + "dependencies": { "safer-buffer": "~2.1.0" } }, - "assert-plus": { + "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8" + } }, - "async": { + "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, - "asynckit": { + "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, - "aws-sign2": { + "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "aws4": { + "node_modules/aws4": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", "dev": true }, - "base64-js": { + "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "bcrypt-pbkdf": { + "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, - "requires": { + "dependencies": { "tweetnacl": "^0.14.3" } }, - "bluebird": { + "node_modules/bluebird": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==", "dev": true }, - "brotli": { + "node_modules/brotli": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", "dev": true, - "requires": { + "dependencies": { "base64-js": "^1.1.2" } }, - "caseless": { + "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, - "chalk": { + "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "requires": { + "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "chardet": { + "node_modules/chardet": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.6.0.tgz", "integrity": "sha512-+QOTw3otC4+FxdjK9RopGpNOglADbr4WPFi0SonkO99JbpkTPbMxmdm4NenhF5Zs+4gPXLI1+y2uazws5TMe8w==", "dev": true }, - "charset": { + "node_modules/charset": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/ci": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ci/-/ci-2.3.0.tgz", + "integrity": "sha512-0MGXkzJKkwV3enG7RUxjJKdiAkbaZ7visCjitfpCN2BQjv02KGRMxCHLv4RPokkjJ4xR33FLMAXweS+aQ0pFSQ==", + "bin": { + "ci": "dist/cli.js" + }, + "funding": { + "url": "https://github.com/privatenumber/ci?sponsor=1" + } }, - "cli-progress": { + "node_modules/cli-progress": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", "dev": true, - "requires": { + "dependencies": { "string-width": "^4.2.3" + }, + "engines": { + "node": ">=4" } }, - "cli-table3": { + "node_modules/cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dev": true, - "requires": { - "@colors/colors": "1.5.0", + "dependencies": { "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "color-convert": { + "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "requires": { + "dependencies": { "color-name": "1.1.3" } }, - "color-name": { + "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "colors": { + "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.1.90" + } }, - "combined-stream": { + "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "requires": { + "dependencies": { "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "command-line-args": { + "node_modules/command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, - "requires": { + "dependencies": { "array-back": "^3.1.0", "find-replace": "^3.0.0", "lodash.camelcase": "^4.3.0", "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" } }, - "command-line-usage": { + "node_modules/command-line-usage": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", "dev": true, - "requires": { + "dependencies": { "array-back": "^4.0.2", "chalk": "^2.4.2", "table-layout": "^1.0.2", "typical": "^5.2.0" }, - "dependencies": { - "array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true - }, - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true - } + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "engines": { + "node": ">=8" } }, - "commander": { + "node_modules/commander": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=16" + } }, - "core-util-is": { + "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, - "csv-parse": { + "node_modules/csv-parse": { "version": "4.16.3", "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz", "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==", "dev": true }, - "dashdash": { + "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "deep-extend": { + "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.0.0" + } }, - "delayed-stream": { + "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "des.js": { + "node_modules/des.js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", "dev": true, - "requires": { + "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, - "directory-tree": { + "node_modules/directory-tree": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/directory-tree/-/directory-tree-3.5.1.tgz", "integrity": "sha512-HqjZ49fDzUnKYUhHxVw9eKBqbQ+lL0v4kSBInlDlaktmLtGoV9tC54a6A0ZfYeIrkMHWTE6MwwmUXP477+UEKQ==", "dev": true, - "requires": { + "dependencies": { "command-line-args": "^5.2.0", "command-line-usage": "^6.1.1" + }, + "bin": { + "directory-tree": "bin/index.js" + }, + "engines": { + "node": ">=10.0" } }, - "ecc-jsbn": { + "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, - "requires": { + "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "emoji-regex": { + "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "eventemitter3": { + "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, - "extend": { + "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "extsprintf": { + "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true + "dev": true, + "engines": [ + "node >=0.6.0" + ] }, - "fast-deep-equal": { + "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "fast-json-stable-stringify": { + "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "file-type": { + "node_modules/file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "filesize": { + "node_modules/filesize": { "version": "10.0.12", "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.0.12.tgz", "integrity": "sha512-6RS9gDchbn+qWmtV2uSjo5vmKizgfCQeb5jKmqx8HyzA3MoLqqyQxN+QcjkGBJt7FjJ9qFce67Auyya5rRRbpw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 10.4.0" + } }, - "find-replace": { + "node_modules/find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, - "requires": { + "dependencies": { "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" } }, - "flatted": { + "node_modules/flatted": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", "dev": true }, - "forever-agent": { + "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "getpass": { + "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0" } }, - "handlebars": { + "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, - "requires": { + "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", - "uglify-js": "^3.1.4", "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "har-schema": { + "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "har-validator": { + "node_modules/har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", "dev": true, - "requires": { + "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "has-flag": { + "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "http-reasons": { + "node_modules/http-reasons": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==", "dev": true }, - "http-signature": { + "node_modules/http-signature": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", "dev": true, - "requires": { + "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^2.0.2", "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" } }, - "httpntlm": { + "node_modules/httpntlm": { "version": "1.8.13", "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.8.13.tgz", "integrity": "sha512-2F2FDPiWT4rewPzNMg3uPhNkP3NExENlUGADRUDPQvuftuUTGW98nLZtGemCIW3G40VhWZYgkIDcQFAwZ3mf2Q==", "dev": true, - "requires": { + "funding": [ + { + "type": "paypal", + "url": "https://www.paypal.com/donate/?hosted_button_id=2CKNJLZJBW8ZC" + }, + { + "type": "buymeacoffee", + "url": "https://www.buymeacoffee.com/samdecrock" + } + ], + "dependencies": { "des.js": "^1.0.1", "httpreq": ">=0.4.22", "js-md4": "^0.3.2", "underscore": "~1.12.1" + }, + "engines": { + "node": ">=10.4.0" } }, - "httpreq": { + "node_modules/httpreq": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-1.1.1.tgz", "integrity": "sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw==", - "dev": true + "dev": true, + "engines": { + "node": ">= 6.15.1" + } }, - "iconv-lite": { + "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, - "requires": { + "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "is-fullwidth-code-point": { + "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "is-typedarray": { + "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, - "isstream": { + "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, - "jose": { + "node_modules/jose": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", - "dev": true + "dev": true, + "funding": { + "url": "https://github.com/sponsors/panva" + } }, - "js-md4": { + "node_modules/js-md4": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz", "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==", "dev": true }, - "js-sha512": { + "node_modules/js-sha512": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==", "dev": true }, - "jsbn": { + "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, - "json-schema": { + "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, - "json-schema-traverse": { + "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "json-stringify-safe": { + "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, - "jsprim": { + "node_modules/jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", "dev": true, - "requires": { + "engines": [ + "node >=0.6.0" + ], + "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" } }, - "liquid-json": { + "node_modules/liquid-json": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "lodash": { + "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "lodash.camelcase": { + "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, - "lru-cache": { + "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "requires": { + "dependencies": { "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "mime-db": { + "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "mime-format": { + "node_modules/mime-format": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.1.tgz", "integrity": "sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==", "dev": true, - "requires": { + "dependencies": { "charset": "^1.0.0" } }, - "mime-types": { + "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, - "requires": { + "dependencies": { "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" } }, - "minimalistic-assert": { + "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, - "minimist": { + "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "mkdirp": { + "node_modules/mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true + "dev": true, + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "neo-async": { + "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "newman": { - "version": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", - "from": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", + "node_modules/newman": { + "version": "6.0.0", + "resolved": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", + "integrity": "sha512-koxHs8uW2R0BLl9dZ9FH5CmJGv1y8Ilur7oIZC89iUOlxW8ID40HuCyKhdgh1ewVTcArGGNET6U1Iv5dbFiqrw==", "dev": true, - "requires": { + "license": "Apache-2.0", + "dependencies": { "@postman/tough-cookie": "4.1.3-postman.1", "async": "3.2.4", "chardet": "1.6.0", @@ -680,44 +888,59 @@ "serialised-error": "1.1.3", "word-wrap": "1.2.5", "xmlbuilder": "15.1.1" + }, + "bin": { + "newman": "bin/newman.js" + }, + "engines": { + "node": ">=16" } }, - "node-oauth1": { + "node_modules/node-oauth1": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", "integrity": "sha512-0yggixNfrA1KcBwvh/Hy2xAS1Wfs9dcg6TdFf2zN7gilcAigMdrtZ4ybrBSXBgLvGDw9V1p2MRnGBMq7XjTWLg==", "dev": true }, - "oauth-sign": { + "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "object-hash": { + "node_modules/object-hash": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", - "dev": true + "dev": true, + "engines": { + "node": ">= 0.10.0" + } }, - "parse-ms": { + "node_modules/parse-ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "performance-now": { + "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true }, - "postman-collection": { + "node_modules/postman-collection": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.1.tgz", "integrity": "sha512-DFLt3/yu8+ldtOTIzmBUctoupKJBOVK4NZO0t68K2lIir9smQg7OdQTBjOXYy+PDh7u0pSDvD66tm93eBHEPHA==", "dev": true, - "requires": { + "dependencies": { "@faker-js/faker": "5.5.3", "file-type": "3.9.0", "http-reasons": "0.1.0", @@ -729,35 +952,45 @@ "postman-url-encoder": "3.0.5", "semver": "7.5.4", "uuid": "8.3.2" + }, + "engines": { + "node": ">=10" } }, - "postman-collection-transformer": { + "node_modules/postman-collection-transformer": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/postman-collection-transformer/-/postman-collection-transformer-4.1.7.tgz", "integrity": "sha512-SxJkm/LnlFZs2splUBnS4jQFicgBptghpm4voHtNnaum3Ad64E2MHLV4fJhv58dVUmFwdSwdQUN3m2q0iLecnQ==", "dev": true, - "requires": { + "dependencies": { "commander": "8.3.0", "inherits": "2.0.4", "lodash": "4.17.21", "semver": "7.5.4", "strip-json-comments": "3.1.1" }, - "dependencies": { - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true - } + "bin": { + "postman-collection-transformer": "bin/transform-collection.js" + }, + "engines": { + "node": ">=10" } }, - "postman-request": { + "node_modules/postman-collection-transformer/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/postman-request": { "version": "2.88.1-postman.33", "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.33.tgz", "integrity": "sha512-uL9sCML4gPH6Z4hreDWbeinKU0p0Ke261nU7OvII95NU22HN6Dk7T/SaVPaj6T4TsQqGKIFw6/woLZnH7ugFNA==", "dev": true, - "requires": { + "dependencies": { "@postman/form-data": "~3.1.1", "@postman/tough-cookie": "~4.1.3-postman.1", "@postman/tunnel-agent": "^0.6.3", @@ -780,14 +1013,17 @@ "safe-buffer": "^5.1.2", "stream-length": "^1.0.2", "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" } }, - "postman-runtime": { + "node_modules/postman-runtime": { "version": "7.33.0", "resolved": "https://registry.npmjs.org/postman-runtime/-/postman-runtime-7.33.0.tgz", "integrity": "sha512-cYCb+5Y12FwZU/T3gOj2SKiOz38pisVLc0tdppb+ZlG7iqn5aLgxghJwhjG62pZCV6uixKiQX1hNdLSk9a9Xtw==", "dev": true, - "requires": { + "dependencies": { "@postman/tough-cookie": "4.1.3-postman.1", "async": "3.2.4", "aws4": "1.12.0", @@ -807,173 +1043,224 @@ "strip-json-comments": "3.1.1", "uuid": "8.3.2" }, + "engines": { + "node": ">=12" + } + }, + "node_modules/postman-runtime/node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true + }, + "node_modules/postman-runtime/node_modules/postman-collection": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", + "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", + "dev": true, "dependencies": { - "aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, - "postman-collection": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", - "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", - "dev": true, - "requires": { - "@faker-js/faker": "5.5.3", - "file-type": "3.9.0", - "http-reasons": "0.1.0", - "iconv-lite": "0.6.3", - "liquid-json": "0.3.1", - "lodash": "4.17.21", - "mime-format": "2.0.1", - "mime-types": "2.1.35", - "postman-url-encoder": "3.0.5", - "semver": "7.5.4", - "uuid": "8.3.2" - } - } + "@faker-js/faker": "5.5.3", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.35", + "postman-url-encoder": "3.0.5", + "semver": "7.5.4", + "uuid": "8.3.2" + }, + "engines": { + "node": ">=10" } }, - "postman-sandbox": { + "node_modules/postman-sandbox": { "version": "4.2.7", "resolved": "https://registry.npmjs.org/postman-sandbox/-/postman-sandbox-4.2.7.tgz", "integrity": "sha512-/EcCrKnb/o+9iLS4u+H76E0kBomJFjPptVjoDiq1uZ7Es/4aTv0MAX+0aoDxdDO+0h9sl8vy65uKQwyjN7AOaw==", "dev": true, - "requires": { + "dependencies": { "lodash": "4.17.21", "postman-collection": "4.2.0", "teleport-javascript": "1.0.0", "uvm": "2.1.1" }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postman-sandbox/node_modules/postman-collection": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", + "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", + "dev": true, "dependencies": { - "postman-collection": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", - "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", - "dev": true, - "requires": { - "@faker-js/faker": "5.5.3", - "file-type": "3.9.0", - "http-reasons": "0.1.0", - "iconv-lite": "0.6.3", - "liquid-json": "0.3.1", - "lodash": "4.17.21", - "mime-format": "2.0.1", - "mime-types": "2.1.35", - "postman-url-encoder": "3.0.5", - "semver": "7.5.4", - "uuid": "8.3.2" - } - } + "@faker-js/faker": "5.5.3", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.35", + "postman-url-encoder": "3.0.5", + "semver": "7.5.4", + "uuid": "8.3.2" + }, + "engines": { + "node": ">=10" } }, - "postman-url-encoder": { + "node_modules/postman-url-encoder": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.5.tgz", "integrity": "sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==", "dev": true, - "requires": { + "dependencies": { "punycode": "^2.1.1" + }, + "engines": { + "node": ">=10" } }, - "pretty-ms": { + "node_modules/pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", "dev": true, - "requires": { + "dependencies": { "parse-ms": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "psl": { + "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, - "punycode": { + "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "qs": { + "node_modules/qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.6" + } }, - "querystringify": { + "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, - "reduce-flatten": { + "node_modules/reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "requires-port": { + "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, - "safe-buffer": { + "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "safer-buffer": { + "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "semver": { + "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "requires": { + "dependencies": { "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "serialised-error": { + "node_modules/serialised-error": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/serialised-error/-/serialised-error-1.1.3.tgz", "integrity": "sha512-vybp3GItaR1ZtO2nxZZo8eOo7fnVaNtP3XE2vJKgzkKR2bagCkdJ1EpYYhEMd3qu/80DwQk9KjsNSxE3fXWq0g==", "dev": true, - "requires": { + "dependencies": { "object-hash": "^1.1.2", "stack-trace": "0.0.9", "uuid": "^3.0.0" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } } }, - "source-map": { + "node_modules/serialised-error/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "sshpk": { + "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, - "requires": { + "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", @@ -983,203 +1270,267 @@ "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" } }, - "stack-trace": { + "node_modules/stack-trace": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", "integrity": "sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "stream-length": { + "node_modules/stream-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", "integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==", "dev": true, - "requires": { + "dependencies": { "bluebird": "^2.6.2" } }, - "string-width": { + "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "requires": { + "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "strip-ansi": { + "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "strip-json-comments": { + "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "supports-color": { + "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "requires": { + "dependencies": { "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "table-layout": { + "node_modules/table-layout": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", "dev": true, - "requires": { + "dependencies": { "array-back": "^4.0.1", "deep-extend": "~0.6.0", "typical": "^5.2.0", "wordwrapjs": "^4.0.0" }, - "dependencies": { - "array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true - }, - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true - } + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "engines": { + "node": ">=8" } }, - "teleport-javascript": { + "node_modules/table-layout/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/teleport-javascript": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/teleport-javascript/-/teleport-javascript-1.0.0.tgz", "integrity": "sha512-j1llvWVFyEn/6XIFDfX5LAU43DXe0GCt3NfXDwJ8XpRRMkS+i50SAkonAONBy+vxwPFBd50MFU8a2uj8R/ccLg==", "dev": true }, - "tweetnacl": { + "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, - "typical": { + "node_modules/typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "uglify-js": { + "node_modules/uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, - "optional": true + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } }, - "underscore": { + "node_modules/underscore": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", "dev": true }, - "universalify": { + "node_modules/universalify": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 4.0.0" + } }, - "uri-js": { + "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "requires": { + "dependencies": { "punycode": "^2.1.0" } }, - "url-parse": { + "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, - "requires": { + "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, - "uuid": { + "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } }, - "uvm": { + "node_modules/uvm": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/uvm/-/uvm-2.1.1.tgz", "integrity": "sha512-BZ5w8adTpNNr+zczOBRpaX/hH8UPKAf7fmCnidrcsqt3bn8KT9bDIfuS7hgRU9RXgiN01su2pwysBONY6w8W5w==", "dev": true, - "requires": { + "dependencies": { "flatted": "3.2.6" + }, + "engines": { + "node": ">=10" } }, - "verror": { + "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "dev": true, - "requires": { + "engines": [ + "node >=0.6.0" + ], + "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "word-wrap": { + "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "wordwrap": { + "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, - "wordwrapjs": { + "node_modules/wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", "dev": true, - "requires": { + "dependencies": { "reduce-flatten": "^2.0.0", "typical": "^5.2.0" }, - "dependencies": { - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true - } + "engines": { + "node": ">=8.0.0" } }, - "xmlbuilder": { + "node_modules/wordwrapjs/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true + "dev": true, + "engines": { + "node": ">=8.0" + } }, - "yallist": { + "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", diff --git a/package.json b/package.json index 0766efdcc17..586a95cd141 100644 --- a/package.json +++ b/package.json @@ -5,5 +5,8 @@ "description": "This is just to run automated newman tests for this service", "devDependencies": { "newman": "git+ssh://git@github.com:knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8" + }, + "dependencies": { + "ci": "^2.3.0" } } From 5bde1cb4d198df9c490c7d8662e97d945d5943b4 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Thu, 5 Dec 2024 16:29:57 +0530 Subject: [PATCH 05/12] fix: Handle default cases --- config/development.toml | 1 - .../src/connectors/jpmorgan.rs | 7 ++- .../src/connectors/jpmorgan/transformers.rs | 12 ++-- .../cypress/e2e/PaymentUtils/Jpmorgan.js | 61 ++++++++----------- .../cypress/e2e/PaymentUtils/Utils.js | 4 +- cypress-tests/package-lock.json | 24 ++++++++ 6 files changed, 62 insertions(+), 47 deletions(-) diff --git a/config/development.toml b/config/development.toml index 4e2be24dda7..e3a3019c1a5 100644 --- a/config/development.toml +++ b/config/development.toml @@ -56,7 +56,6 @@ max_feed_count = 200 [server] # HTTP Request body limit. Defaults to 32kB request_body_limit = 32768 -port=8082 [secrets] admin_api_key = "test_admin" diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index b761c71b0d1..831e46f6c0e 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -102,11 +102,14 @@ where ); let request_id = ( headers::REQUEST_ID.to_string(), - req.connector_request_reference_id.clone().to_string().into_masked() + req.connector_request_reference_id + .clone() + .to_string() + .into_masked(), ); let merchant_id = ( headers::MERCHANTID.to_string(), - req.merchant_id.get_string_repr().to_string().into_masked() + req.merchant_id.get_string_repr().to_string().into_masked(), ); headers.push(auth_header); headers.push(request_id); diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index 1f973a202e9..b8b257f0e69 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -137,11 +137,11 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym ) -> Result { match item.router_data.request.payment_method_data.clone() { PaymentMethodData::Card(req_card) => { - if item.router_data.is_three_ds(){ - return Err(errors::ConnectorError::NotSupported{ - message : "Three_ds payments".to_string(), - connector : "Jpmorgan" - } + if item.router_data.is_three_ds() { + return Err(errors::ConnectorError::NotSupported { + message: "Three_ds payments".to_string(), + connector: "Jpmorgan", + } .into()); } let capture_method = if let Some(method) = item.router_data.request.capture_method { @@ -1049,7 +1049,7 @@ pub struct MerchantRefundReq { impl TryFrom<&JpmorganRouterData<&RefundsRouterData>> for JpmorganRefundRequest { type Error = error_stack::Report; - fn try_from(_item: &JpmorganRouterData<&RefundsRouterData>) -> Result { + fn try_from(_item: &JpmorganRouterData<&RefundsRouterData>) -> Result { Err(errors::ConnectorError::NotImplemented("Refunds".to_string()).into()) } } diff --git a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js index ca7feefde51..6d74f9a3da3 100644 --- a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js +++ b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js @@ -68,24 +68,6 @@ export const connectorDetails = { Request: { currency: "USD", payment_method: "card", - billing: { - address: { - line1: "1467", - line2: "CA", - line3: "CA", - city: "Musterhausen", - state: "California", - zip: "12345", - country: "US", - first_name: "John", - last_name: "Doe", - }, - email: "test@jpmorgan.us", - phone: { - number: "9123456789", - country_code: "+91", - }, - }, payment_method_data: { card: successfulNo3DSCardDetails, }, @@ -207,6 +189,9 @@ export const connectorDetails = { }, },*/ Refund: { + Configs: { + TRIGGER_SKIP: true, + }, Request: { payment_method: "card", payment_method_data: { @@ -217,14 +202,16 @@ export const connectorDetails = { Response: { status: 501, body: { - // status: "succeeded", type: "invalid_request", - message: "Refunds is not implemented", - code: "IR_00" + message: "Refunds is not implemented", + code: "IR_00", }, }, }, manualPaymentRefund: { + Configs: { + TRIGGER_SKIP: true, + }, Request: { payment_method: "card", payment_method_data: { @@ -236,12 +223,15 @@ export const connectorDetails = { status: 501, body: { type: "invalid_request", - message: "Refunds is not implemented", - code: "IR_00" + message: "Refunds is not implemented", + code: "IR_00", }, }, }, manualPaymentPartialRefund: { + Configs: { + TRIGGER_SKIP: true, + }, Request: { payment_method: "card", payment_method_data: { @@ -253,12 +243,15 @@ export const connectorDetails = { status: 501, body: { type: "invalid_request", - message: "Refunds is not implemented", - code: "IR_00" + message: "Refunds is not implemented", + code: "IR_00", }, }, }, PartialRefund: { + Configs: { + TRIGGER_SKIP: true, + }, Request: { payment_method: "card", payment_method_data: { @@ -270,8 +263,8 @@ export const connectorDetails = { status: 501, body: { type: "invalid_request", - message: "Refunds is not implemented", - code: "IR_00" + message: "Refunds is not implemented", + code: "IR_00", }, }, }, @@ -292,21 +285,17 @@ export const connectorDetails = { }, }*/ SyncRefund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, + Configs: { + TRIGGER_SKIP: true, }, Response: { status: 404, body: { - type: "undefined", + type: "invalid_request", message: "Refund does not exist in our records.", - code: "HE_02" + code: "HE_02", }, }, - } + }, }, }; diff --git a/cypress-tests/cypress/e2e/PaymentUtils/Utils.js b/cypress-tests/cypress/e2e/PaymentUtils/Utils.js index 6e494039beb..3b4c9e5decf 100644 --- a/cypress-tests/cypress/e2e/PaymentUtils/Utils.js +++ b/cypress-tests/cypress/e2e/PaymentUtils/Utils.js @@ -15,7 +15,7 @@ import { connectorDetails as fiservemeaConnectorDetails } from "./Fiservemea.js" import { connectorDetails as fiuuConnectorDetails } from "./Fiuu.js"; import { connectorDetails as iatapayConnectorDetails } from "./Iatapay.js"; import { connectorDetails as itaubankConnectorDetails } from "./ItauBank.js"; -import { connectorDetails as jpmorganConnectorDetails} from "./Jpmorgan.js"; +import { connectorDetails as jpmorganConnectorDetails } from "./Jpmorgan.js"; import { connectorDetails as nexixpayConnectorDetails } from "./Nexixpay.js"; import { connectorDetails as nmiConnectorDetails } from "./Nmi.js"; import { connectorDetails as noonConnectorDetails } from "./Noon.js"; @@ -37,7 +37,7 @@ const connectorDetails = { fiservemea: fiservemeaConnectorDetails, iatapay: iatapayConnectorDetails, itaubank: itaubankConnectorDetails, - jpmorgan : jpmorganConnectorDetails, + jpmorgan: jpmorganConnectorDetails, nexixpay: nexixpayConnectorDetails, nmi: nmiConnectorDetails, novalnet: novalnetConnectorDetails, diff --git a/cypress-tests/package-lock.json b/cypress-tests/package-lock.json index 4038f0866c0..252ab36ae9c 100644 --- a/cypress-tests/package-lock.json +++ b/cypress-tests/package-lock.json @@ -833,6 +833,30 @@ "fsevents": "~2.3.2" } }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "peer": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ci": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ci/-/ci-2.3.0.tgz", + "integrity": "sha512-0MGXkzJKkwV3enG7RUxjJKdiAkbaZ7visCjitfpCN2BQjv02KGRMxCHLv4RPokkjJ4xR33FLMAXweS+aQ0pFSQ==", + "bin": { + "ci": "dist/cli.js" + }, + "funding": { + "url": "https://github.com/privatenumber/ci?sponsor=1" + } + }, "node_modules/ci-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", From 6edeb7d0824ab8e35c019d2d8a00a205d290d570 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Fri, 6 Dec 2024 13:12:50 +0530 Subject: [PATCH 06/12] fix: Handle default cases --- config/deployments/production.toml | 4 + .../src/connectors/jpmorgan.rs | 9 +- .../src/connectors/jpmorgan/transformers.rs | 4 +- .../hyperswitch_connectors/src/constants.rs | 1 - crates/router/src/core/payments/flows.rs | 1 - cypress-tests/package-lock.json | 15 +- cypress-tests/package.json | 3 - package-lock.json | 997 ++++++------------ package.json | 3 - 9 files changed, 335 insertions(+), 702 deletions(-) diff --git a/config/deployments/production.toml b/config/deployments/production.toml index b062db4c8c5..b05dbf308c4 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -321,6 +321,10 @@ debit.currency = "USD" ali_pay.currency = "GBP,CNY" we_chat_pay.currency = "GBP,CNY" +[pm.filters.jpmorgan] +debit = { country = "CA, EU, UK, US", currency = "AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, ISK, JMD, JPY, KES, KHR, KMF, KRW, KYD, KZT, LAK, LBP, LKR, LRD, LSL, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RWF, SAR, SBD, SCR, SEK, SGD, SHP, SLL, SOS, SRD, STN, SZL, THB, TJS, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, UYU, UZS, VND, VUV, WST, XAF, XCD, XOF, XPF, YER, ZAR, ZMW" } +credit = { country = "CA, EU, UK, US", currency = "AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, ISK, JMD, JPY, KES, KHR, KMF, KRW, KYD, KZT, LAK, LBP, LKR, LRD, LSL, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RWF, SAR, SBD, SCR, SEK, SGD, SHP, SLL, SOS, SRD, STN, SZL, THB, TJS, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, UYU, UZS, VND, VUV, WST, XAF, XCD, XOF, XPF, YER, ZAR, ZMW" } + [pm_filters.klarna] klarna = { country = "AU,AT,BE,CA,CZ,DK,FI,FR,DE,GR,IE,IT,NL,NZ,NO,PL,PT,ES,SE,CH,GB,US", currency = "CHF,DKK,EUR,GBP,NOK,PLN,SEK,USD,AUD,NZD,CAD" } diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index 831e46f6c0e..54f68d784ba 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -108,7 +108,7 @@ where .into_masked(), ); let merchant_id = ( - headers::MERCHANTID.to_string(), + headers::MERCHANT_ID.to_string(), req.merchant_id.get_string_repr().to_string().into_masked(), ); headers.push(auth_header); @@ -191,10 +191,9 @@ impl ConnectorValidation for Jpmorgan { match capture_method { enums::CaptureMethod::Automatic | enums::CaptureMethod::Manual => Ok(()), //enums::CaptureMethod::ManualMultiple | - enums::CaptureMethod::Scheduled => Err(utils::construct_not_implemented_error_report( - capture_method, - self.id(), - )), + enums::CaptureMethod::Scheduled | enums::CaptureMethod::SequentialAutomatic => Err( + utils::construct_not_implemented_error_report(capture_method, self.id()), + ), enums::CaptureMethod::ManualMultiple => Err(errors::ConnectorError::NotImplemented( //ManualMultiple unimplemented utils::get_unimplemented_payment_method_error_message("Jpmorgan"), diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index b8b257f0e69..5731e4f19db 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -126,7 +126,9 @@ fn map_capture_method(capture_method: enums::CaptureMethod) -> String { enums::CaptureMethod::Manual | enums::CaptureMethod::ManualMultiple => { String::from("MANUAL") } - enums::CaptureMethod::Scheduled => String::from("DELAYED"), + enums::CaptureMethod::Scheduled | enums::CaptureMethod::SequentialAutomatic => { + String::from("DELAYED") + } } } diff --git a/crates/hyperswitch_connectors/src/constants.rs b/crates/hyperswitch_connectors/src/constants.rs index 38cfd5f4795..b43a5fcc7cb 100644 --- a/crates/hyperswitch_connectors/src/constants.rs +++ b/crates/hyperswitch_connectors/src/constants.rs @@ -10,7 +10,6 @@ pub(crate) mod headers { pub(crate) const IDEMPOTENCY_KEY: &str = "Idempotency-Key"; pub(crate) const MESSAGE_SIGNATURE: &str = "Message-Signature"; pub(crate) const MERCHANT_ID: &str = "Merchant-ID"; - pub(crate) const MERCHANTID: &str = "merchant-id"; pub(crate) const REQUEST_ID: &str = "request-id"; pub(crate) const NONCE: &str = "nonce"; pub(crate) const TIMESTAMP: &str = "Timestamp"; diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index a042a3979e1..cf349ef6e05 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -949,7 +949,6 @@ default_imp_for_payouts!( connector::Gpayments, connector::Iatapay, connector::Itaubank, - //connector::Jpmorgan, connector::Klarna, connector::Mifinity, connector::Netcetera, diff --git a/cypress-tests/package-lock.json b/cypress-tests/package-lock.json index 252ab36ae9c..a2c2c4b8fb2 100644 --- a/cypress-tests/package-lock.json +++ b/cypress-tests/package-lock.json @@ -8,9 +8,6 @@ "name": "test", "version": "1.0.0", "license": "ISC", - "dependencies": { - "ci": "^2.3.0" - }, "devDependencies": { "@eslint/js": "^9.16.0", "cypress": "^13.16.0", @@ -838,6 +835,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.1" @@ -846,17 +844,6 @@ "node": ">= 6" } }, - "node_modules/ci": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ci/-/ci-2.3.0.tgz", - "integrity": "sha512-0MGXkzJKkwV3enG7RUxjJKdiAkbaZ7visCjitfpCN2BQjv02KGRMxCHLv4RPokkjJ4xR33FLMAXweS+aQ0pFSQ==", - "bin": { - "ci": "dist/cli.js" - }, - "funding": { - "url": "https://github.com/privatenumber/ci?sponsor=1" - } - }, "node_modules/ci-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", diff --git a/cypress-tests/package.json b/cypress-tests/package.json index a2eb034d692..ff168f61eff 100644 --- a/cypress-tests/package.json +++ b/cypress-tests/package.json @@ -29,8 +29,5 @@ "globals": "^15.13.0", "jsqr": "^1.4.0", "prettier": "^3.4.1" - }, - "dependencies": { - "ci": "^2.3.0" } } diff --git a/package-lock.json b/package-lock.json index 115ab0f9cee..19a2d2fb02e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,870 +1,662 @@ { "name": "hyperswitch", "version": "0.0.0", - "lockfileVersion": 3, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "hyperswitch", - "version": "0.0.0", - "dependencies": { - "ci": "^2.3.0" - }, - "devDependencies": { - "newman": "git+ssh://git@github.com:knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8" - } - }, - "node_modules/@colors/colors": { + "dependencies": { + "@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } + "optional": true }, - "node_modules/@faker-js/faker": { + "@faker-js/faker": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz", "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==", - "deprecated": "Please update to a newer version.", "dev": true }, - "node_modules/@postman/form-data": { + "@postman/form-data": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@postman/form-data/-/form-data-3.1.1.tgz", "integrity": "sha512-vjh8Q2a8S6UCm/KKs31XFJqEEgmbjBmpPNVV2eVav6905wyFAwaUOBGA1NPBI4ERH9MMZc6w0umFgM6WbEPMdg==", "dev": true, - "dependencies": { + "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" } }, - "node_modules/@postman/tough-cookie": { + "@postman/tough-cookie": { "version": "4.1.3-postman.1", "resolved": "https://registry.npmjs.org/@postman/tough-cookie/-/tough-cookie-4.1.3-postman.1.tgz", "integrity": "sha512-txpgUqZOnWYnUHZpHjkfb0IwVH4qJmyq77pPnJLlfhMtdCLMFTEeQHlzQiK906aaNCe4NEB5fGJHo9uzGbFMeA==", "dev": true, - "dependencies": { + "requires": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" } }, - "node_modules/@postman/tunnel-agent": { + "@postman/tunnel-agent": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.4.tgz", "integrity": "sha512-CJJlq8V7rNKhAw4sBfjixKpJW00SHqebqNUQKxMoepgeWZIbdPcD+rguRcivGhS4N12PymDcKgUgSD4rVC+RjQ==", "dev": true, - "dependencies": { + "requires": { "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" } }, - "node_modules/ajv": { + "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "dependencies": { + "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { + "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/ansi-styles": { + "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "dependencies": { + "requires": { "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" } }, - "node_modules/array-back": { + "array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/asn1": { + "asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, - "dependencies": { + "requires": { "safer-buffer": "~2.1.0" } }, - "node_modules/assert-plus": { + "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "engines": { - "node": ">=0.8" - } + "dev": true }, - "node_modules/async": { + "async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, - "node_modules/asynckit": { + "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, - "node_modules/aws-sign2": { + "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "engines": { - "node": "*" - } + "dev": true }, - "node_modules/aws4": { + "aws4": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", "dev": true }, - "node_modules/base64-js": { + "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dev": true }, - "node_modules/bcrypt-pbkdf": { + "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, - "dependencies": { + "requires": { "tweetnacl": "^0.14.3" } }, - "node_modules/bluebird": { + "bluebird": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==", "dev": true }, - "node_modules/brotli": { + "brotli": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", "dev": true, - "dependencies": { + "requires": { "base64-js": "^1.1.2" } }, - "node_modules/caseless": { + "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, - "node_modules/chalk": { + "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "dependencies": { + "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" } }, - "node_modules/chardet": { + "chardet": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.6.0.tgz", "integrity": "sha512-+QOTw3otC4+FxdjK9RopGpNOglADbr4WPFi0SonkO99JbpkTPbMxmdm4NenhF5Zs+4gPXLI1+y2uazws5TMe8w==", "dev": true }, - "node_modules/charset": { + "charset": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/ci": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ci/-/ci-2.3.0.tgz", - "integrity": "sha512-0MGXkzJKkwV3enG7RUxjJKdiAkbaZ7visCjitfpCN2BQjv02KGRMxCHLv4RPokkjJ4xR33FLMAXweS+aQ0pFSQ==", - "bin": { - "ci": "dist/cli.js" - }, - "funding": { - "url": "https://github.com/privatenumber/ci?sponsor=1" - } + "dev": true }, - "node_modules/cli-progress": { + "cli-progress": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", "dev": true, - "dependencies": { + "requires": { "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" } }, - "node_modules/cli-table3": { + "cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dev": true, - "dependencies": { + "requires": { + "@colors/colors": "1.5.0", "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" } }, - "node_modules/color-convert": { + "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "dependencies": { + "requires": { "color-name": "1.1.3" } }, - "node_modules/color-name": { + "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "node_modules/colors": { + "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } + "dev": true }, - "node_modules/combined-stream": { + "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "dependencies": { + "requires": { "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" } }, - "node_modules/command-line-args": { + "command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, - "dependencies": { + "requires": { "array-back": "^3.1.0", "find-replace": "^3.0.0", "lodash.camelcase": "^4.3.0", "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" } }, - "node_modules/command-line-usage": { + "command-line-usage": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", "dev": true, - "dependencies": { + "requires": { "array-back": "^4.0.2", "chalk": "^2.4.2", "table-layout": "^1.0.2", "typical": "^5.2.0" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } } }, - "node_modules/commander": { + "commander": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", - "dev": true, - "engines": { - "node": ">=16" - } + "dev": true }, - "node_modules/core-util-is": { + "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, - "node_modules/csv-parse": { + "csv-parse": { "version": "4.16.3", "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz", "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==", "dev": true }, - "node_modules/dashdash": { + "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, - "dependencies": { + "requires": { "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" } }, - "node_modules/deep-extend": { + "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } + "dev": true }, - "node_modules/delayed-stream": { + "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } + "dev": true }, - "node_modules/des.js": { + "des.js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", "dev": true, - "dependencies": { + "requires": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, - "node_modules/directory-tree": { + "directory-tree": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/directory-tree/-/directory-tree-3.5.1.tgz", "integrity": "sha512-HqjZ49fDzUnKYUhHxVw9eKBqbQ+lL0v4kSBInlDlaktmLtGoV9tC54a6A0ZfYeIrkMHWTE6MwwmUXP477+UEKQ==", "dev": true, - "dependencies": { + "requires": { "command-line-args": "^5.2.0", "command-line-usage": "^6.1.1" - }, - "bin": { - "directory-tree": "bin/index.js" - }, - "engines": { - "node": ">=10.0" } }, - "node_modules/ecc-jsbn": { + "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, - "dependencies": { + "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "node_modules/emoji-regex": { + "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/escape-string-regexp": { + "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "dev": true }, - "node_modules/eventemitter3": { + "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, - "node_modules/extend": { + "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "node_modules/extsprintf": { + "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] + "dev": true }, - "node_modules/fast-deep-equal": { + "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-json-stable-stringify": { + "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/file-type": { + "file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/filesize": { + "filesize": { "version": "10.0.12", "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.0.12.tgz", "integrity": "sha512-6RS9gDchbn+qWmtV2uSjo5vmKizgfCQeb5jKmqx8HyzA3MoLqqyQxN+QcjkGBJt7FjJ9qFce67Auyya5rRRbpw==", - "dev": true, - "engines": { - "node": ">= 10.4.0" - } + "dev": true }, - "node_modules/find-replace": { + "find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, - "dependencies": { + "requires": { "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" } }, - "node_modules/flatted": { + "flatted": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", "dev": true }, - "node_modules/forever-agent": { + "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } + "dev": true }, - "node_modules/getpass": { + "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, - "dependencies": { + "requires": { "assert-plus": "^1.0.0" } }, - "node_modules/handlebars": { + "handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, - "dependencies": { + "requires": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", + "uglify-js": "^3.1.4", "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" } }, - "node_modules/har-schema": { + "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, - "engines": { - "node": ">=4" - } + "dev": true }, - "node_modules/har-validator": { + "har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", "dev": true, - "dependencies": { + "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" } }, - "node_modules/has-flag": { + "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } + "dev": true }, - "node_modules/http-reasons": { + "http-reasons": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==", "dev": true }, - "node_modules/http-signature": { + "http-signature": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", "dev": true, - "dependencies": { + "requires": { "assert-plus": "^1.0.0", "jsprim": "^2.0.2", "sshpk": "^1.14.1" - }, - "engines": { - "node": ">=0.10" } }, - "node_modules/httpntlm": { + "httpntlm": { "version": "1.8.13", "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.8.13.tgz", "integrity": "sha512-2F2FDPiWT4rewPzNMg3uPhNkP3NExENlUGADRUDPQvuftuUTGW98nLZtGemCIW3G40VhWZYgkIDcQFAwZ3mf2Q==", "dev": true, - "funding": [ - { - "type": "paypal", - "url": "https://www.paypal.com/donate/?hosted_button_id=2CKNJLZJBW8ZC" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/samdecrock" - } - ], - "dependencies": { + "requires": { "des.js": "^1.0.1", "httpreq": ">=0.4.22", "js-md4": "^0.3.2", "underscore": "~1.12.1" - }, - "engines": { - "node": ">=10.4.0" } }, - "node_modules/httpreq": { + "httpreq": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-1.1.1.tgz", "integrity": "sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw==", - "dev": true, - "engines": { - "node": ">= 6.15.1" - } + "dev": true }, - "node_modules/iconv-lite": { + "iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, - "dependencies": { + "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" } }, - "node_modules/inherits": { + "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/is-fullwidth-code-point": { + "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/is-typedarray": { + "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, - "node_modules/isstream": { + "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, - "node_modules/jose": { + "jose": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/panva" - } + "dev": true }, - "node_modules/js-md4": { + "js-md4": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz", "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==", "dev": true }, - "node_modules/js-sha512": { + "js-sha512": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==", "dev": true }, - "node_modules/jsbn": { + "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, - "node_modules/json-schema": { + "json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, - "node_modules/json-schema-traverse": { + "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/json-stringify-safe": { + "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, - "node_modules/jsprim": { + "jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { + "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" } }, - "node_modules/liquid-json": { + "liquid-json": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", - "dev": true, - "engines": { - "node": ">=4" - } + "dev": true }, - "node_modules/lodash": { + "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/lodash.camelcase": { + "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, - "node_modules/lru-cache": { + "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "dependencies": { + "requires": { "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" } }, - "node_modules/mime-db": { + "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } + "dev": true }, - "node_modules/mime-format": { + "mime-format": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.1.tgz", "integrity": "sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==", "dev": true, - "dependencies": { + "requires": { "charset": "^1.0.0" } }, - "node_modules/mime-types": { + "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, - "dependencies": { + "requires": { "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" } }, - "node_modules/minimalistic-assert": { + "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, - "node_modules/minimist": { + "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/mkdirp": { + "mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "dev": true }, - "node_modules/neo-async": { + "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/newman": { - "version": "6.0.0", - "resolved": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", - "integrity": "sha512-koxHs8uW2R0BLl9dZ9FH5CmJGv1y8Ilur7oIZC89iUOlxW8ID40HuCyKhdgh1ewVTcArGGNET6U1Iv5dbFiqrw==", + "newman": { + "version": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", + "from": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", "dev": true, - "license": "Apache-2.0", - "dependencies": { + "requires": { "@postman/tough-cookie": "4.1.3-postman.1", "async": "3.2.4", "chardet": "1.6.0", @@ -888,59 +680,44 @@ "serialised-error": "1.1.3", "word-wrap": "1.2.5", "xmlbuilder": "15.1.1" - }, - "bin": { - "newman": "bin/newman.js" - }, - "engines": { - "node": ">=16" } }, - "node_modules/node-oauth1": { + "node-oauth1": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", "integrity": "sha512-0yggixNfrA1KcBwvh/Hy2xAS1Wfs9dcg6TdFf2zN7gilcAigMdrtZ4ybrBSXBgLvGDw9V1p2MRnGBMq7XjTWLg==", "dev": true }, - "node_modules/oauth-sign": { + "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } + "dev": true }, - "node_modules/object-hash": { + "object-hash": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } + "dev": true }, - "node_modules/parse-ms": { + "parse-ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/performance-now": { + "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true }, - "node_modules/postman-collection": { + "postman-collection": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.1.tgz", "integrity": "sha512-DFLt3/yu8+ldtOTIzmBUctoupKJBOVK4NZO0t68K2lIir9smQg7OdQTBjOXYy+PDh7u0pSDvD66tm93eBHEPHA==", "dev": true, - "dependencies": { + "requires": { "@faker-js/faker": "5.5.3", "file-type": "3.9.0", "http-reasons": "0.1.0", @@ -952,45 +729,35 @@ "postman-url-encoder": "3.0.5", "semver": "7.5.4", "uuid": "8.3.2" - }, - "engines": { - "node": ">=10" } }, - "node_modules/postman-collection-transformer": { + "postman-collection-transformer": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/postman-collection-transformer/-/postman-collection-transformer-4.1.7.tgz", "integrity": "sha512-SxJkm/LnlFZs2splUBnS4jQFicgBptghpm4voHtNnaum3Ad64E2MHLV4fJhv58dVUmFwdSwdQUN3m2q0iLecnQ==", "dev": true, - "dependencies": { + "requires": { "commander": "8.3.0", "inherits": "2.0.4", "lodash": "4.17.21", "semver": "7.5.4", "strip-json-comments": "3.1.1" }, - "bin": { - "postman-collection-transformer": "bin/transform-collection.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postman-collection-transformer/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + } } }, - "node_modules/postman-request": { + "postman-request": { "version": "2.88.1-postman.33", "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.33.tgz", "integrity": "sha512-uL9sCML4gPH6Z4hreDWbeinKU0p0Ke261nU7OvII95NU22HN6Dk7T/SaVPaj6T4TsQqGKIFw6/woLZnH7ugFNA==", "dev": true, - "dependencies": { + "requires": { "@postman/form-data": "~3.1.1", "@postman/tough-cookie": "~4.1.3-postman.1", "@postman/tunnel-agent": "^0.6.3", @@ -1013,17 +780,14 @@ "safe-buffer": "^5.1.2", "stream-length": "^1.0.2", "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" } }, - "node_modules/postman-runtime": { + "postman-runtime": { "version": "7.33.0", "resolved": "https://registry.npmjs.org/postman-runtime/-/postman-runtime-7.33.0.tgz", "integrity": "sha512-cYCb+5Y12FwZU/T3gOj2SKiOz38pisVLc0tdppb+ZlG7iqn5aLgxghJwhjG62pZCV6uixKiQX1hNdLSk9a9Xtw==", "dev": true, - "dependencies": { + "requires": { "@postman/tough-cookie": "4.1.3-postman.1", "async": "3.2.4", "aws4": "1.12.0", @@ -1043,224 +807,173 @@ "strip-json-comments": "3.1.1", "uuid": "8.3.2" }, - "engines": { - "node": ">=12" - } - }, - "node_modules/postman-runtime/node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, - "node_modules/postman-runtime/node_modules/postman-collection": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", - "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", - "dev": true, "dependencies": { - "@faker-js/faker": "5.5.3", - "file-type": "3.9.0", - "http-reasons": "0.1.0", - "iconv-lite": "0.6.3", - "liquid-json": "0.3.1", - "lodash": "4.17.21", - "mime-format": "2.0.1", - "mime-types": "2.1.35", - "postman-url-encoder": "3.0.5", - "semver": "7.5.4", - "uuid": "8.3.2" - }, - "engines": { - "node": ">=10" + "aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true + }, + "postman-collection": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", + "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", + "dev": true, + "requires": { + "@faker-js/faker": "5.5.3", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.35", + "postman-url-encoder": "3.0.5", + "semver": "7.5.4", + "uuid": "8.3.2" + } + } } }, - "node_modules/postman-sandbox": { + "postman-sandbox": { "version": "4.2.7", "resolved": "https://registry.npmjs.org/postman-sandbox/-/postman-sandbox-4.2.7.tgz", "integrity": "sha512-/EcCrKnb/o+9iLS4u+H76E0kBomJFjPptVjoDiq1uZ7Es/4aTv0MAX+0aoDxdDO+0h9sl8vy65uKQwyjN7AOaw==", "dev": true, - "dependencies": { + "requires": { "lodash": "4.17.21", "postman-collection": "4.2.0", "teleport-javascript": "1.0.0", "uvm": "2.1.1" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postman-sandbox/node_modules/postman-collection": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", - "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", - "dev": true, "dependencies": { - "@faker-js/faker": "5.5.3", - "file-type": "3.9.0", - "http-reasons": "0.1.0", - "iconv-lite": "0.6.3", - "liquid-json": "0.3.1", - "lodash": "4.17.21", - "mime-format": "2.0.1", - "mime-types": "2.1.35", - "postman-url-encoder": "3.0.5", - "semver": "7.5.4", - "uuid": "8.3.2" - }, - "engines": { - "node": ">=10" + "postman-collection": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", + "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", + "dev": true, + "requires": { + "@faker-js/faker": "5.5.3", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.35", + "postman-url-encoder": "3.0.5", + "semver": "7.5.4", + "uuid": "8.3.2" + } + } } }, - "node_modules/postman-url-encoder": { + "postman-url-encoder": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.5.tgz", "integrity": "sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==", "dev": true, - "dependencies": { + "requires": { "punycode": "^2.1.1" - }, - "engines": { - "node": ">=10" } }, - "node_modules/pretty-ms": { + "pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", "dev": true, - "dependencies": { + "requires": { "parse-ms": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/psl": { + "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, - "node_modules/punycode": { + "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/qs": { + "qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } + "dev": true }, - "node_modules/querystringify": { + "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, - "node_modules/reduce-flatten": { + "reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/requires-port": { + "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, - "node_modules/safe-buffer": { + "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dev": true }, - "node_modules/safer-buffer": { + "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "node_modules/semver": { + "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "dependencies": { + "requires": { "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, - "node_modules/serialised-error": { + "serialised-error": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/serialised-error/-/serialised-error-1.1.3.tgz", "integrity": "sha512-vybp3GItaR1ZtO2nxZZo8eOo7fnVaNtP3XE2vJKgzkKR2bagCkdJ1EpYYhEMd3qu/80DwQk9KjsNSxE3fXWq0g==", "dev": true, - "dependencies": { + "requires": { "object-hash": "^1.1.2", "stack-trace": "0.0.9", "uuid": "^3.0.0" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, - "node_modules/serialised-error/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/source-map": { + "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/sshpk": { + "sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, - "dependencies": { + "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", @@ -1270,267 +983,203 @@ "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" } }, - "node_modules/stack-trace": { + "stack-trace": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", "integrity": "sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ==", - "dev": true, - "engines": { - "node": "*" - } + "dev": true }, - "node_modules/stream-length": { + "stream-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", "integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==", "dev": true, - "dependencies": { + "requires": { "bluebird": "^2.6.2" } }, - "node_modules/string-width": { + "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "dependencies": { + "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" } }, - "node_modules/strip-ansi": { + "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "dependencies": { + "requires": { "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" } }, - "node_modules/strip-json-comments": { + "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "dev": true }, - "node_modules/supports-color": { + "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "dependencies": { + "requires": { "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" } }, - "node_modules/table-layout": { + "table-layout": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", "dev": true, - "dependencies": { + "requires": { "array-back": "^4.0.1", "deep-extend": "~0.6.0", "typical": "^5.2.0", "wordwrapjs": "^4.0.0" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/table-layout/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } } }, - "node_modules/teleport-javascript": { + "teleport-javascript": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/teleport-javascript/-/teleport-javascript-1.0.0.tgz", "integrity": "sha512-j1llvWVFyEn/6XIFDfX5LAU43DXe0GCt3NfXDwJ8XpRRMkS+i50SAkonAONBy+vxwPFBd50MFU8a2uj8R/ccLg==", "dev": true }, - "node_modules/tweetnacl": { + "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, - "node_modules/typical": { + "typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/uglify-js": { + "uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } + "optional": true }, - "node_modules/underscore": { + "underscore": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", "dev": true }, - "node_modules/universalify": { + "universalify": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } + "dev": true }, - "node_modules/uri-js": { + "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "dependencies": { + "requires": { "punycode": "^2.1.0" } }, - "node_modules/url-parse": { + "url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, - "dependencies": { + "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, - "node_modules/uuid": { + "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } + "dev": true }, - "node_modules/uvm": { + "uvm": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/uvm/-/uvm-2.1.1.tgz", "integrity": "sha512-BZ5w8adTpNNr+zczOBRpaX/hH8UPKAf7fmCnidrcsqt3bn8KT9bDIfuS7hgRU9RXgiN01su2pwysBONY6w8W5w==", "dev": true, - "dependencies": { + "requires": { "flatted": "3.2.6" - }, - "engines": { - "node": ">=10" } }, - "node_modules/verror": { + "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { + "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "node_modules/word-wrap": { + "word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/wordwrap": { + "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, - "node_modules/wordwrapjs": { + "wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", "dev": true, - "dependencies": { + "requires": { "reduce-flatten": "^2.0.0", "typical": "^5.2.0" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/wordwrapjs/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } } }, - "node_modules/xmlbuilder": { + "xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true, - "engines": { - "node": ">=8.0" - } + "dev": true }, - "node_modules/yallist": { + "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", diff --git a/package.json b/package.json index 586a95cd141..0766efdcc17 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,5 @@ "description": "This is just to run automated newman tests for this service", "devDependencies": { "newman": "git+ssh://git@github.com:knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8" - }, - "dependencies": { - "ci": "^2.3.0" } } From 0478f185c83e083b99c4ca3bc950a068b9891ea7 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Mon, 9 Dec 2024 20:29:57 +0530 Subject: [PATCH 07/12] chore: Resolve PR Comments --- .../connector_configs/toml/development.toml | 3 +- .../src/connectors/jpmorgan.rs | 103 +++++---------- .../src/connectors/jpmorgan/transformers.rs | 120 ++++++++---------- .../cypress/e2e/PaymentUtils/Jpmorgan.js | 78 +----------- 4 files changed, 91 insertions(+), 213 deletions(-) diff --git a/crates/connector_configs/toml/development.toml b/crates/connector_configs/toml/development.toml index 52aee1f20f9..3238f576442 100644 --- a/crates/connector_configs/toml/development.toml +++ b/crates/connector_configs/toml/development.toml @@ -1769,7 +1769,8 @@ key2="Certificate Key" [[jpmorgan.debit]] payment_method_type = "Visa" [jpmorgan.connector_auth.BodyKey] -api_key="Access Token" +api_key="Client ID" +key1="Client Secret" [klarna] [[klarna.pay_later]] diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index 54f68d784ba..dfb7fe95bbd 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -1,6 +1,4 @@ pub mod transformers; -use std::convert::TryFrom; - use base64::Engine; use common_enums::enums; use common_utils::{ @@ -11,7 +9,7 @@ use common_utils::{ }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ - router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, + router_data::{AccessToken, ErrorResponse, RouterData}, router_flow_types::{ access_token_auth::AccessTokenAuth, payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void}, @@ -125,10 +123,6 @@ impl ConnectorCommon for Jpmorgan { fn get_currency_unit(&self) -> api::CurrencyUnit { api::CurrencyUnit::Minor - //todo!() - // TODO! Check connector documentation, on which unit they are processing the currency. - // If the connector accepts amount in lower unit ( i.e cents for USD) then return api::CurrencyUnit::Minor, - // if connector accepts amount in base unit (i.e dollars for USD) then return api::CurrencyUnit::Base } fn common_get_content_type(&self) -> &'static str { @@ -139,18 +133,6 @@ impl ConnectorCommon for Jpmorgan { connectors.jpmorgan.base_url.as_ref() } - fn get_auth_header( - &self, - auth_type: &ConnectorAuthType, - ) -> CustomResult)>, errors::ConnectorError> { - let auth = jpmorgan::JpmorganAuthType::try_from(auth_type) - .change_context(errors::ConnectorError::FailedToObtainAuthType)?; - Ok(vec![( - headers::AUTHORIZATION.to_string(), - auth.api_key.into_masked(), - )]) - } - fn build_error_response( &self, res: Response, @@ -181,7 +163,6 @@ impl ConnectorCommon for Jpmorgan { } impl ConnectorValidation for Jpmorgan { - //TODO: implement functions when support enabled fn validate_capture_method( &self, capture_method: Option, @@ -190,14 +171,13 @@ impl ConnectorValidation for Jpmorgan { let capture_method = capture_method.unwrap_or_default(); match capture_method { enums::CaptureMethod::Automatic | enums::CaptureMethod::Manual => Ok(()), - //enums::CaptureMethod::ManualMultiple | - enums::CaptureMethod::Scheduled | enums::CaptureMethod::SequentialAutomatic => Err( - utils::construct_not_implemented_error_report(capture_method, self.id()), - ), - enums::CaptureMethod::ManualMultiple => Err(errors::ConnectorError::NotImplemented( - //ManualMultiple unimplemented - utils::get_unimplemented_payment_method_error_message("Jpmorgan"), - ))?, + enums::CaptureMethod::ManualMultiple + | enums::CaptureMethod::Scheduled + | enums::CaptureMethod::SequentialAutomatic => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("Jpmorgan"), + ))? + } } } @@ -224,26 +204,7 @@ impl ConnectorIntegration fo //TODO: implement sessions flow } -// use masking::Secret; - impl ConnectorIntegration for Jpmorgan { - fn get_url( - &self, - _req: &RefreshTokenRouterData, - connectors: &Connectors, - ) -> CustomResult { - let access_token_url = connectors - .jpmorgan - .secondary_base_url - .as_ref() - .ok_or(errors::ConnectorError::FailedToObtainIntegrationUrl)?; - Ok(access_token_url.to_string()) - } - - fn get_content_type(&self) -> &'static str { - "application/x-www-form-urlencoded" - } - fn get_headers( &self, req: &RefreshTokenRouterData, @@ -258,7 +219,6 @@ impl ConnectorIntegration client_id.peek(), client_secret.unwrap_or_default().peek() ); - // let creds = format!("{}:{}", client_id.peek(), client_secret.unwrap_or_default().peek()); let encoded_creds = common_utils::consts::BASE64_ENGINE.encode(creds); let auth_string = format!("Basic {}", encoded_creds); @@ -274,6 +234,23 @@ impl ConnectorIntegration ]) } + fn get_content_type(&self) -> &'static str { + "application/x-www-form-urlencoded" + } + + fn get_url( + &self, + _req: &RefreshTokenRouterData, + connectors: &Connectors, + ) -> CustomResult { + let access_token_url = connectors + .jpmorgan + .secondary_base_url + .as_ref() + .ok_or(errors::ConnectorError::FailedToObtainIntegrationUrl)?; + Ok(access_token_url.to_string()) + } + fn get_request_body( &self, req: &RefreshTokenRouterData, @@ -353,8 +330,7 @@ impl ConnectorIntegration CustomResult { - let endpoint = self.base_url(connectors); - Ok(format!("{}/payments", endpoint)) + Ok(format!("{}/payments", self.base_url(connectors))) } fn get_request_body( @@ -370,9 +346,6 @@ impl ConnectorIntegration fo req: &PaymentsCaptureRouterData, connectors: &Connectors, ) -> CustomResult { - let endpoint = self.base_url(connectors); let tid = req.request.connector_transaction_id.clone(); - Ok(format!("{}/payments/{}/captures", endpoint, tid)) - // Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + Ok(format!( + "{}/payments/{}/captures", + self.base_url(connectors), + tid + )) } fn get_request_body( @@ -463,9 +438,6 @@ impl ConnectorIntegration fo let connector_router_data = jpmorgan::JpmorganRouterData::from((amount, req)); let connector_req = jpmorgan::JpmorganCaptureRequest::try_from(&connector_router_data)?; - let _printrequest = - common_utils::ext_traits::Encode::encode_to_string_of_json(&connector_req) - .change_context(errors::ConnectorError::RequestEncodingFailed)?; Ok(RequestContent::Json(Box::new(connector_req))) } @@ -540,8 +512,7 @@ impl ConnectorIntegration for Jpm .connector_transaction_id .get_connector_transaction_id() .change_context(errors::ConnectorError::MissingConnectorTransactionID)?; - let endpoint = self.base_url(connectors); - Ok(format!("{}/payments/{}", endpoint, tid)) + Ok(format!("{}/payments/{}", self.base_url(connectors), tid)) } fn build_request( @@ -571,7 +542,6 @@ impl ConnectorIntegration for Jpm .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); - RouterData::try_from(ResponseRouterData { response, data: data.clone(), @@ -606,9 +576,8 @@ impl ConnectorIntegration for Jp req: &PaymentsCancelRouterData, connectors: &Connectors, ) -> CustomResult { - let endpoint = self.base_url(connectors); let tid = req.request.connector_transaction_id.clone(); - Ok(format!("{}/payments/{}", endpoint, tid)) + Ok(format!("{}/payments/{}", self.base_url(connectors), tid)) } fn get_request_body( @@ -692,8 +661,7 @@ impl ConnectorIntegration for Jpmorga _req: &RefundsRouterData, connectors: &Connectors, ) -> CustomResult { - let endpoint = self.base_url(connectors); - Ok(format!("{}/refunds", endpoint)) + Ok(format!("{}/refunds", self.base_url(connectors))) } fn get_request_body( @@ -776,9 +744,8 @@ impl ConnectorIntegration for Jpmorgan req: &RefundSyncRouterData, connectors: &Connectors, ) -> CustomResult { - let endpoint = self.base_url(connectors); let tid = req.request.connector_transaction_id.clone(); - Ok(format!("{}/refunds/{}", endpoint, tid)) + Ok(format!("{}/refunds/{}", self.base_url(connectors), tid)) } fn build_request( &self, diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index 5731e4f19db..388819eba47 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -1,4 +1,4 @@ -use common_enums::enums; +use common_enums::enums::CaptureMethod; use common_utils::types::MinorUnit; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, @@ -18,7 +18,10 @@ use strum::Display; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::{PaymentsAuthorizeRequestData, RouterData as OtherRouterData}, + utils::{ + get_unimplemented_payment_method_error_message, PaymentsAuthorizeRequestData, + RouterData as OtherRouterData, + }, }; pub struct JpmorganRouterData { pub amount: MinorUnit, @@ -27,7 +30,6 @@ pub struct JpmorganRouterData { impl From<(MinorUnit, T)> for JpmorganRouterData { fn from((amount, item): (MinorUnit, T)) -> Self { - //Todo : use utils to convert the amount to the type of amount that a connector accepts Self { amount, router_data: item, @@ -54,8 +56,7 @@ impl TryFrom<&RefreshTokenRouterData> for JpmorganAuthUpdateRequest { fn try_from(_item: &RefreshTokenRouterData) -> Result { Ok(Self { grant_type: String::from("client_credentials"), - scope: String::from("jpm:payments:sandbox"), //for prod testing, needs to be added differently - //docs : https://developer.payments.jpmorgan.com/contact/sales?post_auth=true + scope: String::from("jpm:payments:sandbox"), }) } } @@ -67,10 +68,11 @@ impl TryFrom, ) -> Result { - let token = item.response.access_token; - let expires = item.response.expires_in; Ok(Self { - response: Ok(AccessToken { token, expires }), + response: Ok(AccessToken { + token: item.response.access_token, + expires: item.response.expires_in, + }), ..item.data }) } @@ -79,7 +81,7 @@ impl TryFrom String { +fn map_capture_method(capture_method: CaptureMethod) -> CapMethod { match capture_method { - enums::CaptureMethod::Automatic => String::from("NOW"), - enums::CaptureMethod::Manual | enums::CaptureMethod::ManualMultiple => { - String::from("MANUAL") - } - enums::CaptureMethod::Scheduled | enums::CaptureMethod::SequentialAutomatic => { - String::from("DELAYED") - } + CaptureMethod::Automatic => CapMethod::Now, + CaptureMethod::Manual | CaptureMethod::ManualMultiple => CapMethod::Manual, + CaptureMethod::Scheduled | CaptureMethod::SequentialAutomatic => CapMethod::Delayed, } } @@ -141,24 +139,21 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym PaymentMethodData::Card(req_card) => { if item.router_data.is_three_ds() { return Err(errors::ConnectorError::NotSupported { - message: "Three_ds payments".to_string(), + message: "3DS payments".to_string(), connector: "Jpmorgan", } .into()); } - let capture_method = if let Some(method) = item.router_data.request.capture_method { - map_capture_method(method) - } else { - String::from("AUTOMATIC") - }; + + let capture_method = + map_capture_method(item.router_data.request.capture_method.unwrap_or_default()); let currency = item.router_data.request.currency.to_string(); let merchant_software = JpmorganMerchantSoftware { company_name: String::from("JPMC"), - product_name: String::from("Hyperswitch"), //could be Amazon or something else, subject to change + product_name: String::from("Hyperswitch"), }; - //hardcoded as of now let merchant = JpmorganMerchant { merchant_software }; @@ -185,17 +180,33 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym payment_method_type, }) } - _ => Err(errors::ConnectorError::NotImplemented( - "Selected payment method through jpmorgan".to_string(), + PaymentMethodData::CardDetailsForNetworkTransactionId(_) + | PaymentMethodData::CardRedirect(_) + | PaymentMethodData::Wallet(_) + | PaymentMethodData::PayLater(_) + | PaymentMethodData::BankRedirect(_) + | PaymentMethodData::BankDebit(_) + | PaymentMethodData::BankTransfer(_) + | PaymentMethodData::Crypto(_) + | PaymentMethodData::MandatePayment + | PaymentMethodData::Reward + | PaymentMethodData::RealTimePayment(_) + | PaymentMethodData::MobilePayment(_) + | PaymentMethodData::Upi(_) + | PaymentMethodData::Voucher(_) + | PaymentMethodData::GiftCard(_) + | PaymentMethodData::OpenBanking(_) + | PaymentMethodData::CardToken(_) + | PaymentMethodData::NetworkToken(_) => Err(errors::ConnectorError::NotImplemented( + get_unimplemented_payment_method_error_message("jpmorgan"), ) .into()), } } } - -//in jpm, we get a client id and secret and using these two, we have a curl, we make an api call and we get a access token in res with an expiry time as well #[derive(Debug)] pub struct JpmorganAuthType { + #[allow(dead_code)] pub(super) api_key: Secret, #[allow(dead_code)] pub(super) key1: Secret, @@ -214,9 +225,7 @@ impl TryFrom<&ConnectorAuthType> for JpmorganAuthType { } } -// PaymentsResponse -//TODO: Append the remaining status flags -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "UPPERCASE")] pub enum JpmorganTransactionStatus { Success, @@ -224,7 +233,7 @@ pub enum JpmorganTransactionStatus { Error, } -#[derive(Default, Debug, Display, Serialize, Deserialize, Clone)] +#[derive(Default, Display, Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "UPPERCASE")] pub enum JpmorganTransactionState { Closed, @@ -329,8 +338,8 @@ impl FromTransactionState for common_enums::AttemptStatus { "Closed" => Self::Charged, "Declined" | "Error" => Self::Failure, "Pending" => Self::Pending, - "Voided" => Self::Voided, //subject to change, when doing void/cancel flow - _ => Self::Failure, // Default case + "Voided" => Self::Voided, + _ => Self::Failure, } } } @@ -342,8 +351,8 @@ pub trait FromResponseStatus { impl FromResponseStatus for common_enums::AttemptStatus { fn from_response_status(transaction_state: String) -> Self { match transaction_state.as_str() { - "Success" => Self::Voided, //subject to change, when doing void/cancel flow - _ => Self::Failure, // Default case + "Success" => Self::Voided, + _ => Self::Failure, } } } @@ -368,19 +377,19 @@ impl TryFrom, } -//sub merchant supplemental data starting here - #[derive(Default, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SubMerchantSupplementalData { @@ -739,7 +746,6 @@ pub struct CardCapReq { card_type_funding: Option, pie_key_id: Option, pie_phase_id: Option, - //payment_authentication_request : Option, //requires 3ds, do it later encrypted_payload: Option, } @@ -751,7 +757,6 @@ pub struct PaymentAuthenticationCapReq {} #[serde(rename_all = "camelCase")] pub struct AuthenticationCapReq { authentication_id: Option, - //three_d_s //do it later electronic_commerce_indicator: Option, token_authentication_value: Option, s_c_a_exemption_reason: Option, @@ -784,7 +789,7 @@ pub struct InstallmentCapReq { pub struct RecurringCapReq { recurring_sequence: Option, agreement_id: Option, - payment_agreement_expiry_date: Option, //this will be string, just recheck again + payment_agreement_expiry_date: Option, is_variable_amount: Option, } @@ -822,7 +827,7 @@ pub struct SoftMerchantCapReq { #[derive(Debug, Default, Copy, Serialize, Deserialize, Clone)] #[serde(rename_all = "UPPERCASE")] -pub enum CaptureMethod { +pub enum CapMethod { #[default] Now, Delayed, @@ -842,20 +847,6 @@ impl TryFrom<&JpmorganRouterData<&PaymentsCaptureRouterData>> for JpmorganCaptur .map(|cm| cm.to_string()); let currency = Some(item.router_data.request.currency.to_string()); - - // let company_name : Option = Some(String::from("JPMC")); - // let product_name : Option = Some(String::from("Hyperswitch")); - // let version : Option = Some(String::from("1.235")); - // let software_id : Option = None; - - // let merchant_software = MerchantSoftwareCapReq{ - // company_name, - // product_name, - // version, - // software_id, - // }; - - // let merchant_category_code : Option = item.router_data.address; let amount = item.amount; Ok(Self { capture_method, @@ -960,7 +951,6 @@ pub struct JpmorganPSyncResponse { transaction_id: String, request_id: String, transaction_state: JpmorganTransactionState, - //response_status : String, response_status: JpmorganResponseStatus, response_code: String, response_message: String, @@ -1081,7 +1071,7 @@ pub enum RefundStatus { Processing, } -impl From for enums::RefundStatus { +impl From for common_enums::RefundStatus { fn from(item: RefundStatus) -> Self { match item { RefundStatus::Succeeded => Self::Success, @@ -1172,8 +1162,6 @@ impl TryFrom> #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct JpmorganCancelRequest { - //is_capture: Option, - //capture_method : Option, pub amount: Option, pub is_void: Option, pub reversal_reason: Option, @@ -1282,6 +1270,4 @@ pub struct JpmorganErrorResponse { pub response_status: JpmorganTransactionStatus, pub response_code: String, pub response_message: Option, - // pub validation_errors : Option>, - // pub information : JpmorganErrorInformation, } diff --git a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js index 6d74f9a3da3..36e53ffd995 100644 --- a/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js +++ b/cypress-tests/cypress/e2e/PaymentUtils/Jpmorgan.js @@ -36,7 +36,7 @@ export const connectorDetails = { body: { error: { type: "invalid_request", - message: "Three_ds payments is not supported by Jpmorgan", + message: "3DS payments is not supported by Jpmorgan", code: "IR_00", }, }, @@ -128,66 +128,6 @@ export const connectorDetails = { }, }, }, - /*Refund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, - manualPaymentRefund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, - manualPaymentPartialRefund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - }, - PartialRefund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - body: { - status: "succeeded", - }, - }, - },*/ Refund: { Configs: { TRIGGER_SKIP: true, @@ -268,22 +208,6 @@ export const connectorDetails = { }, }, }, - /*SyncRefund: { - Request: { - payment_method: "card", - payment_method_data: { - card: successfulNo3DSCardDetails, - }, - customer_acceptance: null, - }, - Response: { - status: 200, - trigger_skip: true, - body: { - status: "succeeded", - }, - }, - }*/ SyncRefund: { Configs: { TRIGGER_SKIP: true, From 1f05b80081316faf8c0f66a2f8342de1af58d1e9 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Tue, 10 Dec 2024 14:04:00 +0530 Subject: [PATCH 08/12] chore: Resolve PR Comments --- config/deployments/integration_test.toml | 4 +++ config/deployments/production.toml | 4 +-- config/deployments/sandbox.toml | 4 +++ config/development.toml | 4 +++ .../src/connectors/jpmorgan.rs | 4 +-- .../src/connectors/jpmorgan/transformers.rs | 29 +++++++++---------- 6 files changed, 28 insertions(+), 21 deletions(-) diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index 0ad7a99cc50..e8614982936 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -287,6 +287,10 @@ debit.currency = "USD" ali_pay.currency = "GBP,CNY" we_chat_pay.currency = "GBP,CNY" +[pm.filters.jpmorgan] +debit = { country = "CA, EU, UK, US", currency = "CAD, EUR, GBP, USD" } +credit = { country = "CA, EU, UK, US", currency = "CAD, EUR, GBP, USD" } + [pm_filters.klarna] klarna = { country = "AU,AT,BE,CA,CZ,DK,FI,FR,DE,GR,IE,IT,NL,NZ,NO,PL,PT,ES,SE,CH,GB,US", currency = "CHF,DKK,EUR,GBP,NOK,PLN,SEK,USD,AUD,NZD,CAD" } diff --git a/config/deployments/production.toml b/config/deployments/production.toml index b05dbf308c4..7c14f1252a6 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -322,8 +322,8 @@ ali_pay.currency = "GBP,CNY" we_chat_pay.currency = "GBP,CNY" [pm.filters.jpmorgan] -debit = { country = "CA, EU, UK, US", currency = "AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, ISK, JMD, JPY, KES, KHR, KMF, KRW, KYD, KZT, LAK, LBP, LKR, LRD, LSL, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RWF, SAR, SBD, SCR, SEK, SGD, SHP, SLL, SOS, SRD, STN, SZL, THB, TJS, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, UYU, UZS, VND, VUV, WST, XAF, XCD, XOF, XPF, YER, ZAR, ZMW" } -credit = { country = "CA, EU, UK, US", currency = "AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, ISK, JMD, JPY, KES, KHR, KMF, KRW, KYD, KZT, LAK, LBP, LKR, LRD, LSL, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RWF, SAR, SBD, SCR, SEK, SGD, SHP, SLL, SOS, SRD, STN, SZL, THB, TJS, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, UYU, UZS, VND, VUV, WST, XAF, XCD, XOF, XPF, YER, ZAR, ZMW" } +debit = { country = "CA, EU, UK, US", currency = "CAD, EUR, GBP, USD" } +credit = { country = "CA, EU, UK, US", currency = "CAD, EUR, GBP, USD" } [pm_filters.klarna] klarna = { country = "AU,AT,BE,CA,CZ,DK,FI,FR,DE,GR,IE,IT,NL,NZ,NO,PL,PT,ES,SE,CH,GB,US", currency = "CHF,DKK,EUR,GBP,NOK,PLN,SEK,USD,AUD,NZD,CAD" } diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 4479b2f49cc..35ed8295abb 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -322,6 +322,10 @@ debit.currency = "USD" ali_pay.currency = "GBP,CNY" we_chat_pay.currency = "GBP,CNY" +[pm.filters.jpmorgan] +debit = { country = "CA, EU, UK, US", currency = "CAD, EUR, GBP, USD" } +credit = { country = "CA, EU, UK, US", currency = "CAD, EUR, GBP, USD" } + [pm_filters.klarna] klarna = { country = "AU,AT,BE,CA,CZ,DK,FI,FR,DE,GR,IE,IT,NL,NZ,NO,PL,PT,ES,SE,CH,GB,US", currency = "CHF,DKK,EUR,GBP,NOK,PLN,SEK,USD,AUD,NZD,CAD" } diff --git a/config/development.toml b/config/development.toml index e3a3019c1a5..33fd04aafed 100644 --- a/config/development.toml +++ b/config/development.toml @@ -490,6 +490,10 @@ paypal = { currency = "AUD,BRL,CAD,CNY,CZK,DKK,EUR,HKD,HUF,ILS,JPY,MYR,MXN,TWD,N credit = { currency = "USD" } debit = { currency = "USD" } +[pm.filters.jpmorgan] +debit = { country = "CA, EU, UK, US", currency = "CAD, EUR, GBP, USD" } +credit = { country = "CA, EU, UK, US", currency = "CAD, EUR, GBP, USD" } + [pm_filters.klarna] klarna = { country = "AU,AT,BE,CA,CZ,DK,FI,FR,DE,GR,IE,IT,NL,NZ,NO,PL,PT,ES,SE,CH,GB,US", currency = "AUD,EUR,EUR,CAD,CZK,DKK,EUR,EUR,EUR,EUR,EUR,EUR,EUR,NZD,NOK,PLN,EUR,EUR,SEK,CHF,GBP,USD" } diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index dfb7fe95bbd..3e45bc1f406 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -34,7 +34,7 @@ use hyperswitch_interfaces::{ types::{self, RefreshTokenType, Response}, webhooks, }; -use masking::{Mask, PeekInterface}; +use masking::{Mask, Maskable, PeekInterface}; use transformers::{self as jpmorgan, JpmorganErrorResponse}; use crate::{ @@ -75,8 +75,6 @@ impl ConnectorIntegration ConnectorCommonExt for Jpmorgan where Self: ConnectorIntegration, diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index 388819eba47..fb5393d43e5 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -83,7 +83,7 @@ impl TryFrom> for JpmorganPaym let capture_method = map_capture_method(item.router_data.request.capture_method.unwrap_or_default()); - let currency = item.router_data.request.currency.to_string(); + let currency = item.router_data.request.currency; let merchant_software = JpmorganMerchantSoftware { company_name: String::from("JPMC"), @@ -206,10 +206,8 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym } #[derive(Debug)] pub struct JpmorganAuthType { - #[allow(dead_code)] - pub(super) api_key: Secret, - #[allow(dead_code)] - pub(super) key1: Secret, + pub(super) _api_key: Secret, + pub(super) _key1: Secret, } impl TryFrom<&ConnectorAuthType> for JpmorganAuthType { @@ -217,8 +215,8 @@ impl TryFrom<&ConnectorAuthType> for JpmorganAuthType { fn try_from(auth_type: &ConnectorAuthType) -> Result { match auth_type { ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self { - api_key: api_key.to_owned(), - key1: key1.to_owned(), + _api_key: api_key.to_owned(), + _key1: key1.to_owned(), }), _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), } @@ -263,7 +261,7 @@ pub struct JpmorganPaymentsResponse { approval_code: Option, host_message: Option, amount: Option, - currency: Option, + currency: Option, remaining_refundable_amount: Option, remaining_auth_amount: Option, host_reference_id: Option, @@ -422,7 +420,7 @@ pub struct JpmorganCaptureRequest { original_transaction_id: Option, is_amount_final: Option, amount: MinorUnit, - currency: Option, + currency: Option, merchant_order_number: Option, risk: Option, retail_addenda: Option, @@ -483,7 +481,7 @@ pub struct BusinessInformation { #[serde(rename_all = "camelCase")] pub struct PartnerService { pub external_vendor_product_name: Option, - pub currency: Option, + pub currency: Option, pub external_monthly_service_fee_amount: Option, } @@ -510,7 +508,7 @@ pub struct MerchantReportedRevenue { pub amount: Option, pub start_date: Option, pub end_date: Option, - pub currency: Option, + pub currency: Option, pub amount_type: Option, } @@ -846,7 +844,7 @@ impl TryFrom<&JpmorganRouterData<&PaymentsCaptureRouterData>> for JpmorganCaptur .as_ref() .map(|cm| cm.to_string()); - let currency = Some(item.router_data.request.currency.to_string()); + let currency = Some(item.router_data.request.currency); let amount = item.amount; Ok(Self { capture_method, @@ -874,7 +872,6 @@ impl TryFrom<&JpmorganRouterData<&PaymentsCaptureRouterData>> for JpmorganCaptur } } -//made changes here in JpmorganTransactionState #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct JpmorganCaptureResponse { @@ -1053,7 +1050,7 @@ pub struct JpmorganRefundResponse { pub request_id: String, pub transaction_state: JpmorganTransactionState, pub amount: MinorUnit, - pub currency: String, + pub currency: common_enums::Currency, pub response_status: JpmorganResponseStatus, pub response_code: String, pub response_message: String, @@ -1134,7 +1131,7 @@ pub struct JpmorganRefundSyncResponse { request_id: String, transaction_state: JpmorganTransactionState, amount: MinorUnit, - currency: String, + currency: common_enums::Currency, response_status: JpmorganResponseStatus, response_code: String, } From 00115ff9dcc47cabeecd8a1f43ced6731b15fce3 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Tue, 10 Dec 2024 18:02:48 +0530 Subject: [PATCH 09/12] chore: Resolve PR Comments --- .../src/connectors/jpmorgan.rs | 4 +- .../src/connectors/jpmorgan/transformers.rs | 184 +++++++----------- 2 files changed, 74 insertions(+), 114 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index 3e45bc1f406..f0f150302a8 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -657,9 +657,9 @@ impl ConnectorIntegration for Jpmorga fn get_url( &self, _req: &RefundsRouterData, - connectors: &Connectors, + _connectors: &Connectors, ) -> CustomResult { - Ok(format!("{}/refunds", self.base_url(connectors))) + Err(errors::ConnectorError::NotImplemented("Refunds".to_string()).into()) } fn get_request_body( diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index fb5393d43e5..dd4ec02215f 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -14,13 +14,11 @@ use hyperswitch_domain_models::{ use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; -use strum::Display; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, utils::{ - get_unimplemented_payment_method_error_message, PaymentsAuthorizeRequestData, - RouterData as OtherRouterData, + get_unimplemented_payment_method_error_message, CardData, RouterData as OtherRouterData, }, }; pub struct JpmorganRouterData { @@ -93,7 +91,6 @@ pub struct JpmorganPaymentsRequest { pub struct JpmorganCard { account_number: Secret, expiry: Expiry, - is_bill_payment: bool, } #[derive(Default, Debug, Serialize, Deserialize)] @@ -122,11 +119,17 @@ pub struct JpmorganMerchant { merchant_software: JpmorganMerchantSoftware, } -fn map_capture_method(capture_method: CaptureMethod) -> CapMethod { +fn map_capture_method( + capture_method: CaptureMethod, +) -> Result> { match capture_method { - CaptureMethod::Automatic => CapMethod::Now, - CaptureMethod::Manual | CaptureMethod::ManualMultiple => CapMethod::Manual, - CaptureMethod::Scheduled | CaptureMethod::SequentialAutomatic => CapMethod::Delayed, + CaptureMethod::Automatic => Ok(CapMethod::Now), + CaptureMethod::Manual => Ok(CapMethod::Manual), + CaptureMethod::Scheduled + | CaptureMethod::ManualMultiple + | CaptureMethod::SequentialAutomatic => { + Err(errors::ConnectorError::NotImplemented("Capture Method".to_string()).into()) + } } } @@ -158,8 +161,8 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym let merchant = JpmorganMerchant { merchant_software }; let expiry: Expiry = Expiry { - month: req_card.card_exp_month, - year: req_card.card_exp_year, + month: req_card.card_exp_month.clone(), + year: req_card.get_expiry_year_4_digit(), }; let account_number = Secret::new(req_card.card_number.to_string()); @@ -167,13 +170,12 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym let card = JpmorganCard { account_number, expiry, - is_bill_payment: item.router_data.request.is_auto_capture()?, }; let payment_method_type = JpmorganPaymentMethodType { card }; Ok(Self { - capture_method, + capture_method: capture_method?, currency, amount: item.amount, merchant, @@ -231,7 +233,7 @@ pub enum JpmorganTransactionStatus { Error, } -#[derive(Default, Display, Debug, Serialize, Deserialize, Clone)] +#[derive(Default, Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "UPPERCASE")] pub enum JpmorganTransactionState { Closed, @@ -253,7 +255,7 @@ pub struct JpmorganPaymentsResponse { response_code: String, response_message: Option, payment_method_type: Option, - capture_method: Option, + capture_method: Option, is_capture: Option, initiator_type: Option, account_on_file: Option, @@ -296,7 +298,6 @@ pub struct Card { expiry: Option, card_type: Option, card_type_name: Option, - is_bill_payment: Option, masked_account_number: Option, card_type_indicators: Option, network_response: Option, @@ -325,36 +326,6 @@ pub struct CardTypeIndicators { card_product_types: Vec, } -pub trait FromTransactionState { - fn from_transaction_state(transaction_state: String) -> Self; -} - -impl FromTransactionState for common_enums::AttemptStatus { - fn from_transaction_state(transaction_state: String) -> Self { - match transaction_state.as_str() { - "Authorized" => Self::Authorized, - "Closed" => Self::Charged, - "Declined" | "Error" => Self::Failure, - "Pending" => Self::Pending, - "Voided" => Self::Voided, - _ => Self::Failure, - } - } -} - -pub trait FromResponseStatus { - fn from_response_status(transaction_state: String) -> Self; -} - -impl FromResponseStatus for common_enums::AttemptStatus { - fn from_response_status(transaction_state: String) -> Self { - match transaction_state.as_str() { - "Success" => Self::Voided, - _ => Self::Failure, - } - } -} - impl From for common_enums::AttemptStatus { fn from(item: JpmorganTransactionStatus) -> Self { match item { @@ -364,6 +335,20 @@ impl From for common_enums::AttemptStatus { } } +pub fn attempt_status_from_transaction_state( + transaction_state: JpmorganTransactionState, +) -> common_enums::AttemptStatus { + match transaction_state { + JpmorganTransactionState::Authorized => common_enums::AttemptStatus::Authorized, + JpmorganTransactionState::Closed => common_enums::AttemptStatus::Charged, + JpmorganTransactionState::Declined | JpmorganTransactionState::Error => { + common_enums::AttemptStatus::Failure + } + JpmorganTransactionState::Pending => common_enums::AttemptStatus::Pending, + JpmorganTransactionState::Voided => common_enums::AttemptStatus::Voided, + } +} + impl TryFrom> for RouterData { @@ -372,18 +357,18 @@ impl TryFrom, ) -> Result { - let mut transaction_state = item.response.transaction_state.to_string(); - - if transaction_state == "Closed" { - let capture_method = item.response.capture_method.clone(); - if capture_method == Some("NOW".to_string()) { - transaction_state = String::from("Closed"); - } else if capture_method == Some("MANUAL".to_string()) { - transaction_state = String::from("Authorized"); - } - } - - let status = common_enums::AttemptStatus::from_transaction_state(transaction_state); + let transaction_state = match item.response.transaction_state { + JpmorganTransactionState::Closed => match item.response.capture_method { + Some(CapMethod::Now) => JpmorganTransactionState::Closed, + _ => JpmorganTransactionState::Authorized, + }, + JpmorganTransactionState::Authorized => JpmorganTransactionState::Authorized, + JpmorganTransactionState::Voided => JpmorganTransactionState::Voided, + JpmorganTransactionState::Pending => JpmorganTransactionState::Pending, + JpmorganTransactionState::Declined => JpmorganTransactionState::Declined, + JpmorganTransactionState::Error => JpmorganTransactionState::Error, + }; + let status = attempt_status_from_transaction_state(transaction_state); let connector_response_reference_id = Some(item.response.transaction_id.clone()); @@ -409,7 +394,7 @@ impl TryFrom, + capture_method: Option, merchant: Option, recurring: Option, installment: Option, @@ -734,7 +719,6 @@ pub struct CardCapReq { wallet_provider: Option, cvv: Option, original_network_transaction_id: Option, - is_bill_payment: Option, account_updater: Option, authentication: Option, encryption_integrity_check: Option, @@ -837,17 +821,12 @@ impl TryFrom<&JpmorganRouterData<&PaymentsCaptureRouterData>> for JpmorganCaptur fn try_from( item: &JpmorganRouterData<&PaymentsCaptureRouterData>, ) -> Result { - let capture_method = item - .router_data - .request - .capture_method - .as_ref() - .map(|cm| cm.to_string()); - + let capture_method = + map_capture_method(item.router_data.request.capture_method.unwrap_or_default()); let currency = Some(item.router_data.request.currency); let amount = item.amount; Ok(Self { - capture_method, + capture_method: Some(capture_method?), merchant: None, recurring: None, installment: None, @@ -917,8 +896,8 @@ impl TryFrom, ) -> Result { - let transaction_state = item.response.transaction_state.to_string(); - let status = common_enums::AttemptStatus::from_transaction_state(transaction_state); + let transaction_state = item.response.transaction_state; + let status = attempt_status_from_transaction_state(transaction_state); let transaction_id = item.response.transaction_id.clone(); let connector_response_reference_id = Some(transaction_id.clone()); @@ -970,8 +949,8 @@ impl fn try_from( item: ResponseRouterData, ) -> Result { - let transaction_state = item.response.transaction_state.to_string(); - let status = common_enums::AttemptStatus::from_transaction_state(transaction_state); + let transaction_state = item.response.transaction_state; + let status = attempt_status_from_transaction_state(transaction_state); let transaction_id = item.response.transaction_id.clone(); let connector_response_reference_id = Some(transaction_id.clone()); @@ -1018,24 +997,6 @@ pub struct MerchantRefundReq { pub merchant_software: MerchantSoftware, } -/*impl TryFrom<&JpmorganRouterData<&RefundsRouterData>> for JpmorganRefundRequest { - type Error = error_stack::Report; - fn try_from(item: &JpmorganRouterData<&RefundsRouterData>) -> Result { - let merchant_software = MerchantSoftware { - company_name: String::from("JPMC"), //According to documentation, it should be the company name of software integrated to this API. If merchant is directly integrated, send "JPMC." - product_name: String::from("Hyperswitch"), //According to documentation, it should be the name of the product used for marketing purposes from a customer perspective. I. e. what the customer would recognize. - //https://developer.payments.jpmorgan.com/api/commerce/online-payments/online-payments#/operations/V2PaymentPost - version: Some(String::from("1.235")), //recheck, seek guidance - }; - - let merchant = MerchantRefundReq { merchant_software }; - - let amount = item.amount; - - Ok(Self { merchant, amount }) - } -}*/ - impl TryFrom<&JpmorganRouterData<&RefundsRouterData>> for JpmorganRefundRequest { type Error = error_stack::Report; fn try_from(_item: &JpmorganRouterData<&RefundsRouterData>) -> Result { @@ -1056,7 +1017,6 @@ pub struct JpmorganRefundResponse { pub response_message: String, pub transaction_reference_id: Option, pub remaining_refundable_amount: Option, - //pub payment_request_id : Option, } #[allow(dead_code)] @@ -1084,17 +1044,18 @@ pub struct RefundResponse { status: RefundStatus, } -pub trait FromRefundState { - fn from_transaction_state(transaction_state: String) -> Self; -} - -impl FromRefundState for common_enums::RefundStatus { - fn from_transaction_state(transaction_state: String) -> Self { - match transaction_state.as_str() { - "Closed" | "Authorized" => Self::Success, - "Declined" | "Error" => Self::Failure, - "Pending" => Self::Pending, - _ => Self::Failure, +pub fn refund_status_from_transaction_state( + transaction_state: JpmorganTransactionState, +) -> common_enums::RefundStatus { + match transaction_state { + JpmorganTransactionState::Voided | JpmorganTransactionState::Closed => { + common_enums::RefundStatus::Success + } + JpmorganTransactionState::Declined | JpmorganTransactionState::Error => { + common_enums::RefundStatus::Failure + } + JpmorganTransactionState::Pending | JpmorganTransactionState::Authorized => { + common_enums::RefundStatus::Pending } } } @@ -1112,8 +1073,8 @@ impl TryFrom> .clone() .ok_or(errors::ConnectorError::ResponseHandlingFailed)?; - let transaction_state = item.response.transaction_state.to_string(); - let refund_status = common_enums::RefundStatus::from_transaction_state(transaction_state); + let transaction_state = item.response.transaction_state; + let refund_status = refund_status_from_transaction_state(transaction_state); Ok(Self { response: Ok(RefundsResponseData { connector_refund_id: refund_id, @@ -1144,12 +1105,12 @@ impl TryFrom> item: RefundsResponseRouterData, ) -> Result { let refund_id = item.response.transaction_id.clone(); - let transaction_state = item.response.transaction_state.to_string(); - let status = common_enums::RefundStatus::from_transaction_state(transaction_state); + let transaction_state = item.response.transaction_state; + let refund_status = refund_status_from_transaction_state(transaction_state); Ok(Self { response: Ok(RefundsResponseData { connector_refund_id: refund_id, - refund_status: status, + refund_status, }), ..item.data }) @@ -1215,14 +1176,13 @@ impl PaymentsResponseData, >, ) -> Result { - let response_status = match item.response.response_status { - JpmorganResponseStatus::Success => String::from("Success"), - JpmorganResponseStatus::Denied => String::from("Denied"), - JpmorganResponseStatus::Error => String::from("Error"), + let status = match item.response.response_status { + JpmorganResponseStatus::Success => common_enums::AttemptStatus::Voided, + JpmorganResponseStatus::Denied | JpmorganResponseStatus::Error => { + common_enums::AttemptStatus::Failure + } }; - let status = common_enums::AttemptStatus::from_response_status(response_status); - let transaction_id = item.response.transaction_id.clone(); let resource_id = ResponseId::ConnectorTransactionId(transaction_id.clone()); From 8415fe3d9a10fc020cc8d0d68a13bf7a4d1c257c Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Tue, 17 Dec 2024 15:23:38 +0530 Subject: [PATCH 10/12] chore: Resolve PR Comments --- .../src/connectors/jpmorgan.rs | 50 +++++----- .../src/connectors/jpmorgan/transformers.rs | 99 +++++++------------ 2 files changed, 63 insertions(+), 86 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index f0f150302a8..b301d718c4d 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -88,13 +88,17 @@ where headers::CONTENT_TYPE.to_string(), self.get_content_type().to_string().into(), )]; - let access_token = req - .access_token - .clone() - .ok_or(errors::ConnectorError::FailedToObtainAuthType)?; let auth_header = ( headers::AUTHORIZATION.to_string(), - format!("Bearer {}", access_token.token.peek()).into_masked(), + format!( + "Bearer {}", + req.access_token + .clone() + .ok_or(errors::ConnectorError::FailedToObtainAuthType)? + .token + .peek() + ) + .into_masked(), ); let request_id = ( headers::REQUEST_ID.to_string(), @@ -241,12 +245,12 @@ impl ConnectorIntegration _req: &RefreshTokenRouterData, connectors: &Connectors, ) -> CustomResult { - let access_token_url = connectors + Ok(connectors .jpmorgan .secondary_base_url .as_ref() - .ok_or(errors::ConnectorError::FailedToObtainIntegrationUrl)?; - Ok(access_token_url.to_string()) + .ok_or(errors::ConnectorError::FailedToObtainIntegrationUrl)? + .to_string()) } fn get_request_body( @@ -263,7 +267,7 @@ impl ConnectorIntegration req: &RefreshTokenRouterData, connectors: &Connectors, ) -> CustomResult, errors::ConnectorError> { - let req = Some( + Ok(Some( RequestBuilder::new() .method(Method::Post) .attach_default_headers() @@ -271,8 +275,7 @@ impl ConnectorIntegration .url(&RefreshTokenType::get_url(self, req, connectors)?) .set_body(RefreshTokenType::get_request_body(self, req, connectors)?) .build(), - ); - Ok(req) + )) } fn handle_response( @@ -683,18 +686,19 @@ impl ConnectorIntegration for Jpmorga req: &RefundsRouterData, connectors: &Connectors, ) -> CustomResult, errors::ConnectorError> { - let request = RequestBuilder::new() - .method(Method::Post) - .url(&types::RefundExecuteType::get_url(self, req, connectors)?) - .attach_default_headers() - .headers(types::RefundExecuteType::get_headers( - self, req, connectors, - )?) - .set_body(types::RefundExecuteType::get_request_body( - self, req, connectors, - )?) - .build(); - Ok(Some(request)) + Ok(Some( + RequestBuilder::new() + .method(Method::Post) + .url(&types::RefundExecuteType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::RefundExecuteType::get_headers( + self, req, connectors, + )?) + .set_body(types::RefundExecuteType::get_request_body( + self, req, connectors, + )?) + .build(), + )) } fn handle_response( diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index dd4ec02215f..79ce0d64068 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -151,8 +151,6 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym let capture_method = map_capture_method(item.router_data.request.capture_method.unwrap_or_default()); - let currency = item.router_data.request.currency; - let merchant_software = JpmorganMerchantSoftware { company_name: String::from("JPMC"), product_name: String::from("Hyperswitch"), @@ -176,7 +174,7 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym Ok(Self { capture_method: capture_method?, - currency, + currency: item.router_data.request.currency, amount: item.amount, merchant, payment_method_type, @@ -370,19 +368,17 @@ impl TryFrom> for JpmorganCaptur ) -> Result { let capture_method = map_capture_method(item.router_data.request.capture_method.unwrap_or_default()); - let currency = Some(item.router_data.request.currency); - let amount = item.amount; Ok(Self { capture_method: Some(capture_method?), merchant: None, @@ -836,8 +830,8 @@ impl TryFrom<&JpmorganRouterData<&PaymentsCaptureRouterData>> for JpmorganCaptur account_on_file: None, original_transaction_id: None, is_amount_final: None, - amount, - currency, + amount: item.amount, + currency: Some(item.router_data.request.currency), merchant_order_number: None, risk: None, retail_addenda: None, @@ -896,23 +890,18 @@ impl TryFrom, ) -> Result { - let transaction_state = item.response.transaction_state; - let status = attempt_status_from_transaction_state(transaction_state); - - let transaction_id = item.response.transaction_id.clone(); - let connector_response_reference_id = Some(transaction_id.clone()); - - let resource_id = ResponseId::ConnectorTransactionId(transaction_id.clone()); - + let status = attempt_status_from_transaction_state(item.response.transaction_state); Ok(Self { status, response: Ok(PaymentsResponseData::TransactionResponse { - resource_id, + resource_id: ResponseId::ConnectorTransactionId( + item.response.transaction_id.clone(), + ), redirection_data: Box::new(None), mandate_reference: Box::new(None), connector_metadata: None, network_txn_id: None, - connector_response_reference_id, + connector_response_reference_id: Some(item.response.transaction_id.clone()), incremental_authorization_allowed: None, charge_id: None, }), @@ -949,23 +938,18 @@ impl fn try_from( item: ResponseRouterData, ) -> Result { - let transaction_state = item.response.transaction_state; - let status = attempt_status_from_transaction_state(transaction_state); - - let transaction_id = item.response.transaction_id.clone(); - let connector_response_reference_id = Some(transaction_id.clone()); - - let resource_id = ResponseId::ConnectorTransactionId(transaction_id.clone()); - + let status = attempt_status_from_transaction_state(item.response.transaction_state); Ok(Self { status, response: Ok(PaymentsResponseData::TransactionResponse { - resource_id, + resource_id: ResponseId::ConnectorTransactionId( + item.response.transaction_id.clone(), + ), redirection_data: Box::new(None), mandate_reference: Box::new(None), connector_metadata: None, network_txn_id: None, - connector_response_reference_id, + connector_response_reference_id: Some(item.response.transaction_id.clone()), incremental_authorization_allowed: None, charge_id: None, }), @@ -1067,18 +1051,16 @@ impl TryFrom> fn try_from( item: RefundsResponseRouterData, ) -> Result { - let refund_id = item - .response - .transaction_id - .clone() - .ok_or(errors::ConnectorError::ResponseHandlingFailed)?; - - let transaction_state = item.response.transaction_state; - let refund_status = refund_status_from_transaction_state(transaction_state); Ok(Self { response: Ok(RefundsResponseData { - connector_refund_id: refund_id, - refund_status, + connector_refund_id: item + .response + .transaction_id + .clone() + .ok_or(errors::ConnectorError::ResponseHandlingFailed)?, + refund_status: refund_status_from_transaction_state( + item.response.transaction_state, + ), }), ..item.data }) @@ -1104,13 +1086,12 @@ impl TryFrom> fn try_from( item: RefundsResponseRouterData, ) -> Result { - let refund_id = item.response.transaction_id.clone(); - let transaction_state = item.response.transaction_state; - let refund_status = refund_status_from_transaction_state(transaction_state); Ok(Self { response: Ok(RefundsResponseData { - connector_refund_id: refund_id, - refund_status, + connector_refund_id: item.response.transaction_id.clone(), + refund_status: refund_status_from_transaction_state( + item.response.transaction_state, + ), }), ..item.data }) @@ -1128,13 +1109,10 @@ pub struct JpmorganCancelRequest { impl TryFrom> for JpmorganCancelRequest { type Error = error_stack::Report; fn try_from(item: JpmorganRouterData<&PaymentsCancelRouterData>) -> Result { - let is_void = Some(true); - let amount = item.router_data.request.amount; - let reversal_reason = item.router_data.request.cancellation_reason.clone(); Ok(Self { - amount, - is_void, - reversal_reason, + amount: item.router_data.request.amount, + is_void: Some(true), + reversal_reason: item.router_data.request.cancellation_reason.clone(), }) } } @@ -1182,22 +1160,17 @@ impl common_enums::AttemptStatus::Failure } }; - - let transaction_id = item.response.transaction_id.clone(); - - let resource_id = ResponseId::ConnectorTransactionId(transaction_id.clone()); - - let connector_response_reference_id = Some(transaction_id.clone()); - Ok(Self { status, response: Ok(PaymentsResponseData::TransactionResponse { - resource_id, + resource_id: ResponseId::ConnectorTransactionId( + item.response.transaction_id.clone(), + ), redirection_data: Box::new(None), mandate_reference: Box::new(None), connector_metadata: None, network_txn_id: None, - connector_response_reference_id, + connector_response_reference_id: Some(item.response.transaction_id.clone()), incremental_authorization_allowed: None, charge_id: None, }), From 1ea37c84b89f4c0df4a784a5453fe4c6b0cb9099 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Wed, 18 Dec 2024 16:38:33 +0530 Subject: [PATCH 11/12] chore: Resolve PR Comments --- .../src/connectors/jpmorgan/transformers.rs | 543 ++---------------- 1 file changed, 41 insertions(+), 502 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs index 79ce0d64068..78c1b5eefb5 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs @@ -109,8 +109,8 @@ pub struct Expiry { #[derive(Serialize, Debug, Default, Deserialize)] #[serde(rename_all = "camelCase")] pub struct JpmorganMerchantSoftware { - company_name: String, - product_name: String, + company_name: Secret, + product_name: Secret, } #[derive(Default, Debug, Serialize, Deserialize)] @@ -152,8 +152,8 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym map_capture_method(item.router_data.request.capture_method.unwrap_or_default()); let merchant_software = JpmorganMerchantSoftware { - company_name: String::from("JPMC"), - product_name: String::from("Hyperswitch"), + company_name: String::from("JPMC").into(), + product_name: String::from("Hyperswitch").into(), }; let merchant = JpmorganMerchant { merchant_software }; @@ -204,6 +204,8 @@ impl TryFrom<&JpmorganRouterData<&PaymentsAuthorizeRouterData>> for JpmorganPaym } } } + +//JP Morgan uses access token only due to which we aren't reading the fields in this struct #[derive(Debug)] pub struct JpmorganAuthType { pub(super) _api_key: Secret, @@ -243,29 +245,17 @@ pub enum JpmorganTransactionState { Error, } -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Default, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct JpmorganPaymentsResponse { transaction_id: String, - request_id: Option, + request_id: String, transaction_state: JpmorganTransactionState, response_status: String, response_code: String, - response_message: Option, - payment_method_type: Option, + response_message: String, + payment_method_type: PaymentMethodType, capture_method: Option, - is_capture: Option, - initiator_type: Option, - account_on_file: Option, - transaction_date: Option, - approval_code: Option, - host_message: Option, - amount: Option, - currency: Option, - remaining_refundable_amount: Option, - remaining_auth_amount: Option, - host_reference_id: Option, - merchant: Option, } #[derive(Default, Debug, Serialize, Deserialize)] @@ -279,24 +269,24 @@ pub struct Merchant { #[derive(Default, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MerchantSoftware { - company_name: String, - product_name: String, - version: Option, + company_name: Secret, + product_name: Secret, + version: Option>, } -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Default, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct PaymentMethodType { card: Option, } -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Default, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Card { expiry: Option, - card_type: Option, - card_type_name: Option, - masked_account_number: Option, + card_type: Option>, + card_type_name: Option>, + masked_account_number: Option>, card_type_indicators: Option, network_response: Option, } @@ -304,33 +294,24 @@ pub struct Card { #[derive(Default, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct NetworkResponse { - address_verification_result: Option, - address_verification_result_code: Option, - card_verification_result_code: Option, + address_verification_result: Option>, + address_verification_result_code: Option>, + card_verification_result_code: Option>, } #[derive(Default, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ExpiryResponse { - month: Option, - year: Option, + month: Option>, + year: Option>, } -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct CardTypeIndicators { - issuance_country_code: Option, + issuance_country_code: Option>, is_durbin_regulated: Option, - card_product_types: Vec, -} - -impl From for common_enums::AttemptStatus { - fn from(item: JpmorganTransactionStatus) -> Self { - match item { - JpmorganTransactionStatus::Success => Self::Charged, - JpmorganTransactionStatus::Denied | JpmorganTransactionStatus::Error => Self::Failure, - } - } + card_product_types: Secret>, } pub fn attempt_status_from_transaction_state( @@ -387,420 +368,12 @@ impl TryFrom, - merchant: Option, - recurring: Option, - installment: Option, - payment_method_type: Option, - ship_to: Option, - initiator_type: Option, - account_on_file: Option, - original_transaction_id: Option, - is_amount_final: Option, amount: MinorUnit, currency: Option, - merchant_order_number: Option, - risk: Option, - retail_addenda: Option, - account_holder: Option, - statement_descriptor: Option, - partial_authorization_support: Option, - payment_request_id: Option, - multi_capture: Option, - sub_merchant_supplemental_data: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SubMerchantSupplementalData { - pub custom_data: Option, - pub service_address: Option, - pub business_information: Option, - pub partner_service: Option, - pub shipping_info: Option, - pub recurring_billing: Option, - pub merchant_reported_revenue: Option, - pub order_information: Option, - pub consumer_device: Option, - pub merchant_identification: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CustomData { - pub external_transaction_reference_number: Option, - pub external_transaction_type: Option, - pub external_merchant_id: Option, - pub merchant_order_reference_id: Option, - pub external_batch_id: Option, - pub merchant_expected_deposit_date: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ServiceAddress { - pub line1: Option, - pub line2: Option, - pub city: Option, - pub state: Option, - pub postal_code: Option, - pub country_code: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct BusinessInformation { - pub organization_legal_name: Option, - pub client_business_description_text: Option, - pub organization_d_b_a_name: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PartnerService { - pub external_vendor_product_name: Option, - pub currency: Option, - pub external_monthly_service_fee_amount: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ShippingInfo { - pub shipping_carrier_name: Option, - pub expected_merchant_product_delivery_date: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RecurringBilling { - pub billing_schedule_update_timestamp: Option, - pub payment_frequency_code: Option, - pub billing_cycle_sequence_number: Option, - pub initiator_type: Option, - pub billing_cycles_total_count: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct MerchantReportedRevenue { - pub amount: Option, - pub start_date: Option, - pub end_date: Option, - pub currency: Option, - pub amount_type: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct OrderInformation { - pub order_items: Option>, - pub receipt_url: Option, - pub payment_notes: Option, - pub merchant_url: Option, - pub terms_url: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct OrderItem { - pub merchant_product_identifier: Option, - pub line_item_description_text: Option, - pub unit_price_amount: Option, - pub line_item_unit_quantity: Option, - pub item_comodity_code: Option, - pub chosen_shipping_option: Option, - pub merchant_campaign_name: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ConsumerDevice { - pub session_id: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct MerchantIdentification { - pub sub_merchant_id: Option, - pub service_entitlement_number: Option, - pub seller_identifier: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct MultiCapture { - multi_capture_sequence_number: Option, - multi_capture_record_count: Option, - is_final_capture: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct AccountHolderCapReq { - reference_id: Option, - consumer_id_creation_date: String, - full_name: Option, - email: Option, - mobile: Option, - phone: Option, - i_p_address: Option, - billing_address: Option, - national_id: Option, - first_name: Option, - last_name: Option, - middle_name: Option, - consumer_profile_info: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct PhoneNumber { - country_code: Option, - phone_number: String, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct BillingAddress { - line1: Option, - line2: Option, - city: Option, - state: Option, - postal_code: Option, - country_code: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct ConsumerProfileInfo { - consumer_profile_request_type: Option, - legacy_consumer_profile_id: Option, - external_consumer_profile_identifier: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RetailAddendaCapReq { - purchase_order_number: Option, - order_date: Option, - tax_amount: Option, - is_taxable: Option, - level3: Option, - gratuity_amount: Option, - surcharge_amount: Option, - health_care_data: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct HealthCareDataCapReq { - total_healthcare_amount: Option, - total_vision_amount: Option, - total_clinic_amount: Option, - total_dental_amount: Option, - total_prescription_amount: Option, - is_i_i_a_s: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Level3 { - total_shipping_amount: Option, - duty_amount: Option, - ship_to_address_postal_code: Option, - ship_to_address_country_code: Option, - ship_from_address_postal_code: Option, - total_transaction_discount_amount: Option, - value_added_tax_amount: Option, - value_added_tax_percent: Option, - shipping_value_added_tax_percent: Option, - order_discount_treatment_code: Option, - value_added_tax_invoice_reference_number: Option, - shipping_value_added_tax_amount: Option, - party_tax_government_issued_identifier: Option, - alternate_tax_amount: Option, - line_items: Option, - tax_treatment_code: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct LineItemsCapReq { - line_item_description_text: Option, - merchant_product_identifier: Option, - item_commodity_code: Option, - line_item_unit_quantity: Option, - line_item_unit_of_measure_code: Option, - unit_price_amount: Option, - tax_inclusive_line_item_total_amount: Option, - transaction_discount_amount: Option, - purchase_transaction_discount_percent: Option, - line_item_discount_treatment_code: Option, - line_item_detail_code: Option, - line_item_tax_indicator: Option, - line_item_discount_indicator: Option, - line_item_taxes: Option>, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct LineItemTaxesCapReq { - tax_type_code: Option, - line_item_tax_amount: Option, - tax_percent: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RiskCapReq { - request_fraud_score: Option, - transaction_risk_score: Option, - token_risk_score: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ShipToCapReq { - shipping_description: Option, - shipping_address: Option, - full_name: Option, - email: Option, - mobile: Option, - phone: Option, - first_name: Option, - last_name: Option, - middle_name: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PhoneCapReq { - country_code: Option, - phone_number: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct MobileCapReq { - country_code: Option, - phone_number: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ShippingAddressCapReq { - line1: Option, - line2: Option, - city: Option, - state: Option, - postal_code: Option, - country_code: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PaymentMethodTypeCapReq { - card: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CardCapReq { - account_number_type: Option, - account_number: String, - expiry: Option, - wallet_provider: Option, - cvv: Option, - original_network_transaction_id: Option, - account_updater: Option, - authentication: Option, - encryption_integrity_check: Option, - preferred_payment_network_name_list: Vec, - merchant_sales_channel_name: Option, - merchant_preferred_routing: Option, - card_type_funding: Option, - pie_key_id: Option, - pie_phase_id: Option, - encrypted_payload: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PaymentAuthenticationCapReq {} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct AuthenticationCapReq { - authentication_id: Option, - electronic_commerce_indicator: Option, - token_authentication_value: Option, - s_c_a_exemption_reason: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct AccountUpdaterCapReq { - request_account_updater: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ExpiryCapReq { - month: i32, - year: i32, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct InstallmentCapReq { - installment_count: Option, - total_installments: Option, - number_of_deferrals: Option, - plan_id: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RecurringCapReq { - recurring_sequence: Option, - agreement_id: Option, - payment_agreement_expiry_date: Option, - is_variable_amount: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct MerchantCapReq { - merchant_software: MerchantSoftwareCapReq, - merchant_category_code: Option, - merchant_logo_url: Option, - soft_merchant: SoftMerchantCapReq, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct MerchantSoftwareCapReq { - company_name: Option, - product_name: Option, - version: Option, - software_id: Option, -} - -#[derive(Default, Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SoftMerchantCapReq { - name: Option, - phone: Option, - email: Option, - url: Option, - merchant_purchase_description: Option, - visa_merchant_verification_value_id: Option, - master_card_merchant_verification_value_id: Option, - merchant_incorporation_status: Option, - foreign_merchant_indicator: Option, } #[derive(Debug, Default, Copy, Serialize, Deserialize, Clone)] @@ -817,30 +390,13 @@ impl TryFrom<&JpmorganRouterData<&PaymentsCaptureRouterData>> for JpmorganCaptur fn try_from( item: &JpmorganRouterData<&PaymentsCaptureRouterData>, ) -> Result { - let capture_method = - map_capture_method(item.router_data.request.capture_method.unwrap_or_default()); + let capture_method = Some(map_capture_method( + item.router_data.request.capture_method.unwrap_or_default(), + )?); Ok(Self { - capture_method: Some(capture_method?), - merchant: None, - recurring: None, - installment: None, - payment_method_type: None, - ship_to: None, - initiator_type: None, - account_on_file: None, - original_transaction_id: None, - is_amount_final: None, + capture_method, amount: item.amount, currency: Some(item.router_data.request.currency), - merchant_order_number: None, - risk: None, - retail_addenda: None, - account_holder: None, - statement_descriptor: None, - partial_authorization_support: None, - payment_request_id: None, - multi_capture: None, - sub_merchant_supplemental_data: None, }) } } @@ -866,21 +422,9 @@ pub struct PaymentMethodTypeCapRes { #[derive(Default, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CardCapRes { - pub card_type: Option, - pub card_type_name: Option, - unmasked_account_number: Option, -} - -impl From for common_enums::AttemptStatus { - fn from(item: JpmorganTransactionState) -> Self { - match item { - JpmorganTransactionState::Authorized => Self::Authorized, - JpmorganTransactionState::Closed => Self::Charged, - JpmorganTransactionState::Declined | JpmorganTransactionState::Error => Self::Failure, - JpmorganTransactionState::Pending => Self::Pending, - JpmorganTransactionState::Voided => Self::Voided, - } - } + pub card_type: Option>, + pub card_type_name: Option>, + unmasked_account_number: Option>, } impl TryFrom> @@ -910,16 +454,11 @@ impl TryFrom #[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct TransactionData { - payment_type: Option, - status_code: i32, - txn_secret: Option, + payment_type: Option>, + status_code: Secret, + txn_secret: Option>, tid: Option>, - test_mode: Option, + test_mode: Option>, status: Option, } @@ -1137,8 +676,8 @@ pub struct JpmorganPaymentMethodTypeCancelResponse { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CardCancelResponse { - pub card_type: String, - pub card_type_name: String, + pub card_type: Secret, + pub card_type_name: Secret, } impl From 2045fbada62a0e9e62998275399c56adfc201c31 Mon Sep 17 00:00:00 2001 From: Sayak Bhattacharya Date: Thu, 19 Dec 2024 18:58:43 +0530 Subject: [PATCH 12/12] fix: Resolve PR Comments --- config/config.example.toml | 2 +- config/deployments/integration_test.toml | 2 +- config/deployments/production.toml | 2 +- config/deployments/sandbox.toml | 2 +- config/development.toml | 2 +- config/docker_compose.toml | 2 +- .../src/connectors/jpmorgan.rs | 14 ++++++++------ loadtest/config/development.toml | 2 +- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index 17430426602..d34ecc327bd 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -223,7 +223,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" -jpmorgan.secondary_base_url= "https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" +jpmorgan.secondary_base_url= "https://id.payments.jpmorgan.com" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index e8614982936..0feec3cdb25 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -65,7 +65,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" -jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/deployments/production.toml b/config/deployments/production.toml index 7c14f1252a6..a1a03c7f5d6 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -69,7 +69,7 @@ iatapay.base_url = "https://iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://secure.api.itau/" jpmorgan.base_url = "https://api-ms.payments.jpmorgan.com/api/v2" -jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com" klarna.base_url = "https://api{{klarna_region}}.klarna.com/" mifinity.base_url = "https://secure.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 35ed8295abb..4b9ac0c29d0 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -69,7 +69,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" -jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/development.toml b/config/development.toml index 33fd04aafed..f8fa07217b2 100644 --- a/config/development.toml +++ b/config/development.toml @@ -240,7 +240,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" -jpmorgan.secondary_base_url= "https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" +jpmorgan.secondary_base_url= "https://id.payments.jpmorgan.com" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 7ee0de7e593..ce6499eb4b3 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -154,7 +154,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" -jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" diff --git a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs index b301d718c4d..9e5a24faab5 100644 --- a/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs +++ b/crates/hyperswitch_connectors/src/connectors/jpmorgan.rs @@ -245,12 +245,14 @@ impl ConnectorIntegration _req: &RefreshTokenRouterData, connectors: &Connectors, ) -> CustomResult { - Ok(connectors - .jpmorgan - .secondary_base_url - .as_ref() - .ok_or(errors::ConnectorError::FailedToObtainIntegrationUrl)? - .to_string()) + Ok(format!( + "{}/am/oauth2/alpha/access_token", + connectors + .jpmorgan + .secondary_base_url + .as_ref() + .ok_or(errors::ConnectorError::FailedToObtainIntegrationUrl)? + )) } fn get_request_body( diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index 25a391b70d2..dd348b4a2d9 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -120,7 +120,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" -jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" +jpmorgan.secondary_base_url="https://id.payments.jpmorgan.com" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/"