refactor: Replace Bach with Application on every naming (#292)

This commit is contained in:
Kartikeya Hegde
2023-01-10 18:07:32 +05:30
committed by GitHub
parent aaf7088afc
commit 3cdf50c942
36 changed files with 218 additions and 209 deletions

View File

@ -40,6 +40,10 @@ locker_decryption_key2 = ""
wallets = ["klarna", "braintree", "applepay"] wallets = ["klarna", "braintree", "applepay"]
cards = ["stripe", "adyen", "authorizedotnet", "checkout", "braintree", "aci", "shift4", "cybersource", "worldpay"] cards = ["stripe", "adyen", "authorizedotnet", "checkout", "braintree", "aci", "shift4", "cybersource", "worldpay"]
[refund]
max_attempts = 10
max_age = 365
[eph_key] [eph_key]
validity = 1 validity = 1

View File

@ -89,6 +89,11 @@ locker_decryption_key1 = "" # private key 1 in pem format, corresponding public
locker_decryption_key2 = "" # private key 2 in pem format, corresponding public key in basilisk locker_decryption_key2 = "" # private key 2 in pem format, corresponding public key in basilisk
# Refund configuration
[refund]
max_attempts = 10 # Number of refund attempts allowed
max_age = 365 # Max age of a refund in days.
# Validity of an Ephemeral Key in Hours # Validity of an Ephemeral Key in Hours
[eph_key] [eph_key]
validity = 1 validity = 1

View File

@ -52,6 +52,10 @@ port = 6379
cluster_enabled = true cluster_enabled = true
cluster_urls = ["redis-queue:6379"] cluster_urls = ["redis-queue:6379"]
[refund]
max_attempts = 10
max_age = 365
[connectors.aci] [connectors.aci]
base_url = "https://eu-test.oppwa.com/" base_url = "https://eu-test.oppwa.com/"

View File

@ -1,12 +1,12 @@
use router::{ use router::{
configs::settings::{CmdLineConf, Settings, Subcommand}, configs::settings::{CmdLineConf, Settings, Subcommand},
core::errors::{BachError, BachResult}, core::errors::{ApplicationError, ApplicationResult},
logger, logger,
}; };
use structopt::StructOpt; use structopt::StructOpt;
#[actix_web::main] #[actix_web::main]
async fn main() -> BachResult<()> { async fn main() -> ApplicationResult<()> {
// get commandline config before initializing config // get commandline config before initializing config
let cmd_line = CmdLineConf::from_args(); let cmd_line = CmdLineConf::from_args();
@ -41,7 +41,7 @@ async fn main() -> BachResult<()> {
state.store.close().await; state.store.close().await;
Err(BachError::from(std::io::Error::new( Err(ApplicationError::from(std::io::Error::new(
std::io::ErrorKind::Other, std::io::ErrorKind::Other,
"Server shut down", "Server shut down",
))) )))

View File

@ -21,7 +21,7 @@ pub async fn compatibility_api_wrap<'a, 'b, U, T, Q, F, Fut, S, E>(
) -> HttpResponse ) -> HttpResponse
where where
F: Fn(&'b routes::AppState, U, T) -> Fut, F: Fn(&'b routes::AppState, U, T) -> Fut,
Fut: Future<Output = RouterResult<api::BachResponse<Q>>>, Fut: Future<Output = RouterResult<api::ApplicationResponse<Q>>>,
Q: Serialize + std::fmt::Debug + 'a, Q: Serialize + std::fmt::Debug + 'a,
S: From<Q> + Serialize, S: From<Q> + Serialize,
E: From<errors::ApiErrorResponse> + Serialize + error_stack::Context + actix_web::ResponseError, E: From<errors::ApiErrorResponse> + Serialize + error_stack::Context + actix_web::ResponseError,
@ -29,7 +29,7 @@ where
{ {
let resp = api::server_wrap_util(state, request, payload, func, api_authentication).await; let resp = api::server_wrap_util(state, request, payload, func, api_authentication).await;
match resp { match resp {
Ok(api::BachResponse::Json(router_resp)) => { Ok(api::ApplicationResponse::Json(router_resp)) => {
let pg_resp = S::try_from(router_resp); let pg_resp = S::try_from(router_resp);
match pg_resp { match pg_resp {
Ok(pg_resp) => match serde_json::to_string(&pg_resp) { Ok(pg_resp) => match serde_json::to_string(&pg_resp) {
@ -51,9 +51,9 @@ where
), ),
} }
} }
Ok(api::BachResponse::StatusOk) => api::http_response_ok(), Ok(api::ApplicationResponse::StatusOk) => api::http_response_ok(),
Ok(api::BachResponse::TextPlain(text)) => api::http_response_plaintext(text), Ok(api::ApplicationResponse::TextPlain(text)) => api::http_response_plaintext(text),
Ok(api::BachResponse::JsonForRedirection(response)) => { Ok(api::ApplicationResponse::JsonForRedirection(response)) => {
match serde_json::to_string(&response) { match serde_json::to_string(&response) {
Ok(res) => api::http_redirect_response(res, response), Ok(res) => api::http_redirect_response(res, response),
Err(_) => api::http_response_err( Err(_) => api::http_response_err(
@ -65,7 +65,7 @@ where
), ),
} }
} }
Ok(api::BachResponse::Form(form_data)) => api::build_redirection_form(&form_data) Ok(api::ApplicationResponse::Form(form_data)) => api::build_redirection_form(&form_data)
.respond_to(request) .respond_to(request)
.map_into_boxed_body(), .map_into_boxed_body(),
Err(error) => { Err(error) => {

View File

@ -42,6 +42,10 @@ jwt_secret="secret"
[eph_key] [eph_key]
validity = 1 validity = 1
[refund]
max_attempts = 10
max_age = 365
[scheduler] [scheduler]
stream = "SCHEDULER_STREAM" stream = "SCHEDULER_STREAM"
consumer_group = "SCHEDULER_GROUP" consumer_group = "SCHEDULER_GROUP"

View File

@ -7,7 +7,7 @@ use serde::Deserialize;
use structopt::StructOpt; use structopt::StructOpt;
use crate::{ use crate::{
core::errors::{BachError, BachResult}, core::errors::{ApplicationError, ApplicationResult},
env::{self, logger, Env}, env::{self, logger, Env},
}; };
@ -42,6 +42,7 @@ pub struct Settings {
pub keys: Keys, //remove this during refactoring pub keys: Keys, //remove this during refactoring
pub locker: Locker, pub locker: Locker,
pub connectors: Connectors, pub connectors: Connectors,
pub refund: Refund,
pub eph_key: EphemeralConfig, pub eph_key: EphemeralConfig,
pub scheduler: Option<SchedulerSettings>, pub scheduler: Option<SchedulerSettings>,
#[cfg(feature = "kv_store")] #[cfg(feature = "kv_store")]
@ -67,6 +68,12 @@ pub struct Locker {
pub basilisk_host: String, pub basilisk_host: String,
} }
#[derive(Debug, Deserialize, Clone)]
pub struct Refund {
pub max_attempts: usize,
pub max_age: i64,
}
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
pub struct EphemeralConfig { pub struct EphemeralConfig {
pub validity: i64, pub validity: i64,
@ -163,11 +170,11 @@ pub struct DrainerSettings {
} }
impl Settings { impl Settings {
pub fn new() -> BachResult<Self> { pub fn new() -> ApplicationResult<Self> {
Self::with_config_path(None) Self::with_config_path(None)
} }
pub fn with_config_path(config_path: Option<PathBuf>) -> BachResult<Self> { pub fn with_config_path(config_path: Option<PathBuf>) -> ApplicationResult<Self> {
let environment = env::which(); let environment = env::which();
let config_path = router_env::Config::config_path(&environment.to_string(), config_path); let config_path = router_env::Config::config_path(&environment.to_string(), config_path);
@ -199,7 +206,7 @@ impl Settings {
serde_path_to_error::deserialize(config).map_err(|error| { serde_path_to_error::deserialize(config).map_err(|error| {
logger::error!(%error, "Unable to deserialize application configuration"); logger::error!(%error, "Unable to deserialize application configuration");
eprintln!("Unable to deserialize application configuration: {error}"); eprintln!("Unable to deserialize application configuration: {error}");
BachError::from(error.into_inner()) ApplicationError::from(error.into_inner())
}) })
} }
} }

View File

@ -720,8 +720,9 @@ impl api::IncomingWebhook for Adyen {
fn get_webhook_api_response( fn get_webhook_api_response(
&self, &self,
) -> CustomResult<services::api::BachResponse<serde_json::Value>, errors::ConnectorError> { ) -> CustomResult<services::api::ApplicationResponse<serde_json::Value>, errors::ConnectorError>
Ok(services::api::BachResponse::TextPlain( {
Ok(services::api::ApplicationResponse::TextPlain(
"[accepted]".to_string(), "[accepted]".to_string(),
)) ))
} }

View File

@ -78,7 +78,7 @@ pub async fn create_merchant_account(
.map_err(|error| { .map_err(|error| {
error.to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount) error.to_duplicate_response(errors::ApiErrorResponse::DuplicateMerchantAccount)
})?; })?;
Ok(service_api::BachResponse::Json(response)) Ok(service_api::ApplicationResponse::Json(response))
} }
pub async fn get_merchant_account( pub async fn get_merchant_account(
@ -128,7 +128,7 @@ pub async fn get_merchant_account(
publishable_key: merchant_account.publishable_key, publishable_key: merchant_account.publishable_key,
locker_id: merchant_account.locker_id, locker_id: merchant_account.locker_id,
}; };
Ok(service_api::BachResponse::Json(response)) Ok(service_api::ApplicationResponse::Json(response))
} }
pub async fn merchant_account_update( pub async fn merchant_account_update(
@ -226,7 +226,7 @@ pub async fn merchant_account_update(
db.update_merchant(merchant_account, updated_merchant_account) db.update_merchant(merchant_account, updated_merchant_account)
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError)?; .change_context(errors::ApiErrorResponse::InternalServerError)?;
Ok(service_api::BachResponse::Json(response)) Ok(service_api::ApplicationResponse::Json(response))
} }
pub async fn merchant_account_delete( pub async fn merchant_account_delete(
@ -243,7 +243,7 @@ pub async fn merchant_account_delete(
merchant_id, merchant_id,
deleted: is_deleted, deleted: is_deleted,
}; };
Ok(service_api::BachResponse::Json(response)) Ok(service_api::ApplicationResponse::Json(response))
} }
async fn get_parent_merchant( async fn get_parent_merchant(
@ -340,7 +340,7 @@ pub async fn create_payment_connector(
})?; })?;
response.merchant_connector_id = Some(mca.merchant_connector_id); response.merchant_connector_id = Some(mca.merchant_connector_id);
Ok(service_api::BachResponse::Json(response)) Ok(service_api::ApplicationResponse::Json(response))
} }
pub async fn retrieve_payment_connector( pub async fn retrieve_payment_connector(
@ -365,7 +365,9 @@ pub async fn retrieve_payment_connector(
error.to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound) error.to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound)
})?; })?;
Ok(service_api::BachResponse::Json(mca.foreign_try_into()?)) Ok(service_api::ApplicationResponse::Json(
mca.foreign_try_into()?,
))
} }
pub async fn list_payment_connectors( pub async fn list_payment_connectors(
@ -393,7 +395,7 @@ pub async fn list_payment_connectors(
response.push(mca.foreign_try_into()?); response.push(mca.foreign_try_into()?);
} }
Ok(service_api::BachResponse::Json(response)) Ok(service_api::ApplicationResponse::Json(response))
} }
pub async fn update_payment_connector( pub async fn update_payment_connector(
@ -460,7 +462,7 @@ pub async fn update_payment_connector(
payment_methods_enabled: req.payment_methods_enabled, payment_methods_enabled: req.payment_methods_enabled,
metadata: req.metadata, metadata: req.metadata,
}; };
Ok(service_api::BachResponse::Json(response)) Ok(service_api::ApplicationResponse::Json(response))
} }
pub async fn delete_payment_connector( pub async fn delete_payment_connector(
@ -489,5 +491,5 @@ pub async fn delete_payment_connector(
merchant_connector_id, merchant_connector_id,
deleted: is_deleted, deleted: is_deleted,
}; };
Ok(service_api::BachResponse::Json(response)) Ok(service_api::ApplicationResponse::Json(response))
} }

View File

@ -80,7 +80,7 @@ pub async fn create_customer(
let mut customer_response: customers::CustomerResponse = customer.into(); let mut customer_response: customers::CustomerResponse = customer.into();
customer_response.address = customer_data.address; customer_response.address = customer_data.address;
Ok(services::BachResponse::Json(customer_response)) Ok(services::ApplicationResponse::Json(customer_response))
} }
#[instrument(skip(db))] #[instrument(skip(db))]
@ -94,7 +94,7 @@ pub async fn retrieve_customer(
.await .await
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::CustomerNotFound))?; .map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::CustomerNotFound))?;
Ok(services::BachResponse::Json(response.into())) Ok(services::ApplicationResponse::Json(response.into()))
} }
#[instrument(skip_all)] #[instrument(skip_all)]
@ -190,7 +190,7 @@ pub async fn delete_customer(
address_deleted: true, address_deleted: true,
payment_methods_deleted: true, payment_methods_deleted: true,
}; };
Ok(services::BachResponse::Json(response)) Ok(services::ApplicationResponse::Json(response))
} }
#[instrument(skip(db))] #[instrument(skip(db))]
@ -247,5 +247,7 @@ pub async fn update_customer(
let mut customer_update_response: customers::CustomerResponse = response.into(); let mut customer_update_response: customers::CustomerResponse = response.into();
customer_update_response.address = update_customer.address; customer_update_response.address = update_customer.address;
Ok(services::BachResponse::Json(customer_update_response)) Ok(services::ApplicationResponse::Json(
customer_update_response,
))
} }

View File

@ -16,11 +16,10 @@ pub use self::api_error_response::ApiErrorResponse;
pub(crate) use self::utils::{ConnectorErrorExt, StorageErrorExt}; pub(crate) use self::utils::{ConnectorErrorExt, StorageErrorExt};
use crate::services; use crate::services;
pub type RouterResult<T> = CustomResult<T, ApiErrorResponse>; pub type RouterResult<T> = CustomResult<T, ApiErrorResponse>;
pub type RouterResponse<T> = CustomResult<services::BachResponse<T>, ApiErrorResponse>; pub type RouterResponse<T> = CustomResult<services::ApplicationResponse<T>, ApiErrorResponse>;
// FIXME: Phase out BachResult and BachResponse pub type ApplicationResult<T> = Result<T, ApplicationError>;
pub type BachResult<T> = Result<T, BachError>; pub type ApplicationResponse<T> = ApplicationResult<services::ApplicationResponse<T>>;
pub type BachResponse<T> = BachResult<services::BachResponse<T>>;
macro_rules! impl_error_display { macro_rules! impl_error_display {
($st: ident, $arg: tt) => { ($st: ident, $arg: tt) => {
@ -50,7 +49,7 @@ macro_rules! impl_error_type {
// FIXME: Make this a derive macro instead // FIXME: Make this a derive macro instead
macro_rules! router_error_error_stack_specific { macro_rules! router_error_error_stack_specific {
($($path: ident)::+ < $st: ident >, $($path2:ident)::* ($($inner_path2:ident)::+ <$st2:ident>) ) => { ($($path: ident)::+ < $st: ident >, $($path2:ident)::* ($($inner_path2:ident)::+ <$st2:ident>) ) => {
impl From<$($path)::+ <$st>> for BachError { impl From<$($path)::+ <$st>> for ApplicationError {
fn from(err: $($path)::+ <$st> ) -> Self { fn from(err: $($path)::+ <$st> ) -> Self {
$($path2)::*(err) $($path2)::*(err)
} }
@ -58,7 +57,7 @@ macro_rules! router_error_error_stack_specific {
}; };
($($path: ident)::+ <$($inner_path:ident)::+>, $($path2:ident)::* ($($inner_path2:ident)::+ <$st2:ident>) ) => { ($($path: ident)::+ <$($inner_path:ident)::+>, $($path2:ident)::* ($($inner_path2:ident)::+ <$st2:ident>) ) => {
impl<'a> From< $($path)::+ <$($inner_path)::+> > for BachError { impl<'a> From< $($path)::+ <$($inner_path)::+> > for ApplicationError {
fn from(err: $($path)::+ <$($inner_path)::+> ) -> Self { fn from(err: $($path)::+ <$($inner_path)::+> ) -> Self {
$($path2)::*(err) $($path2)::*(err)
} }
@ -114,7 +113,7 @@ impl_error_type!(EncryptionError, "Encryption error");
impl_error_type!(UnexpectedError, "Unexpected error"); impl_error_type!(UnexpectedError, "Unexpected error");
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum BachError { pub enum ApplicationError {
// Display's impl can be overridden by the attribute error marco. // Display's impl can be overridden by the attribute error marco.
// Don't use Debug here, Debug gives error stack in response. // Don't use Debug here, Debug gives error stack in response.
#[error("{{ error_description: Error while Authenticating, error_message: {0} }}")] #[error("{{ error_description: Error while Authenticating, error_message: {0} }}")]
@ -150,32 +149,32 @@ pub enum BachError {
router_error_error_stack_specific!( router_error_error_stack_specific!(
error_stack::Report<storage_errors::DatabaseError>, error_stack::Report<storage_errors::DatabaseError>,
BachError::EDatabaseError(error_stack::Report<DatabaseError>) ApplicationError::EDatabaseError(error_stack::Report<DatabaseError>)
); );
router_error_error_stack_specific!( router_error_error_stack_specific!(
error_stack::Report<AuthenticationError>, error_stack::Report<AuthenticationError>,
BachError::EAuthenticationError(error_stack::Report<AuthenticationError>) ApplicationError::EAuthenticationError(error_stack::Report<AuthenticationError>)
); );
router_error_error_stack_specific!( router_error_error_stack_specific!(
error_stack::Report<UnexpectedError>, error_stack::Report<UnexpectedError>,
BachError::EUnexpectedError(error_stack::Report<UnexpectedError>) ApplicationError::EUnexpectedError(error_stack::Report<UnexpectedError>)
); );
router_error_error_stack_specific!( router_error_error_stack_specific!(
error_stack::Report<ParsingError>, error_stack::Report<ParsingError>,
BachError::EParsingError(error_stack::Report<ParsingError>) ApplicationError::EParsingError(error_stack::Report<ParsingError>)
); );
router_error_error_stack_specific!( router_error_error_stack_specific!(
error_stack::Report<EncryptionError>, error_stack::Report<EncryptionError>,
BachError::EEncryptionError(error_stack::Report<EncryptionError>) ApplicationError::EEncryptionError(error_stack::Report<EncryptionError>)
); );
impl From<MetricsError> for BachError { impl From<MetricsError> for ApplicationError {
fn from(err: MetricsError) -> Self { fn from(err: MetricsError) -> Self {
Self::EMetrics(err) Self::EMetrics(err)
} }
} }
impl From<std::io::Error> for BachError { impl From<std::io::Error> for ApplicationError {
fn from(err: std::io::Error) -> Self { fn from(err: std::io::Error) -> Self {
Self::EIo(err) Self::EIo(err)
} }
@ -187,7 +186,7 @@ impl From<ring::error::Unspecified> for EncryptionError {
} }
} }
impl From<ConfigError> for BachError { impl From<ConfigError> for ApplicationError {
fn from(err: ConfigError) -> Self { fn from(err: ConfigError) -> Self {
Self::ConfigurationError(err) Self::ConfigurationError(err)
} }
@ -202,7 +201,7 @@ fn error_response<T: Display>(err: &T) -> actix_web::HttpResponse {
)) ))
} }
impl ResponseError for BachError { impl ResponseError for ApplicationError {
fn status_code(&self) -> StatusCode { fn status_code(&self) -> StatusCode {
match self { match self {
Self::EParsingError(_) Self::EParsingError(_)

View File

@ -30,7 +30,7 @@ pub async fn get_mandate(
.find_mandate_by_merchant_id_mandate_id(&merchant_account.merchant_id, &req.mandate_id) .find_mandate_by_merchant_id_mandate_id(&merchant_account.merchant_id, &req.mandate_id)
.await .await
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::MandateNotFound))?; .map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::MandateNotFound))?;
Ok(services::BachResponse::Json( Ok(services::ApplicationResponse::Json(
mandates::MandateResponse::from_db_mandate(state, mandate, &merchant_account).await?, mandates::MandateResponse::from_db_mandate(state, mandate, &merchant_account).await?,
)) ))
} }
@ -52,7 +52,7 @@ pub async fn revoke_mandate(
.await .await
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::MandateNotFound))?; .map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::MandateNotFound))?;
Ok(services::BachResponse::Json( Ok(services::ApplicationResponse::Json(
mandates::MandateRevokedResponse { mandates::MandateRevokedResponse {
mandate_id: mandate.mandate_id, mandate_id: mandate.mandate_id,
status: mandate.mandate_status.foreign_into(), status: mandate.mandate_status.foreign_into(),
@ -82,7 +82,7 @@ pub async fn get_customer_mandates(
.await?, .await?,
); );
} }
Ok(services::BachResponse::Json(response_vec)) Ok(services::ApplicationResponse::Json(response_vec))
} }
} }

View File

@ -92,7 +92,7 @@ pub async fn add_payment_method(
}) })
} }
} }
.map(services::BachResponse::Json) .map(services::ApplicationResponse::Json)
} }
#[instrument(skip_all)] #[instrument(skip_all)]
@ -383,7 +383,7 @@ pub async fn list_payment_methods(
response response
.is_empty() .is_empty()
.then(|| Err(report!(errors::ApiErrorResponse::PaymentMethodNotFound))) .then(|| Err(report!(errors::ApiErrorResponse::PaymentMethodNotFound)))
.unwrap_or(Ok(services::BachResponse::Json(response))) .unwrap_or(Ok(services::ApplicationResponse::Json(response)))
} }
fn filter_payment_methods( fn filter_payment_methods(
@ -568,7 +568,7 @@ pub async fn list_customer_payment_method(
customer_payment_methods: vec, customer_payment_methods: vec,
}; };
Ok(services::BachResponse::Json(response)) Ok(services::ApplicationResponse::Json(response))
} }
pub async fn get_lookup_key_from_locker( pub async fn get_lookup_key_from_locker(
@ -751,7 +751,8 @@ pub async fn retrieve_payment_method(
} else { } else {
None None
}; };
Ok(services::BachResponse::Json(api::PaymentMethodResponse { Ok(services::ApplicationResponse::Json(
api::PaymentMethodResponse {
merchant_id: pm.merchant_id, merchant_id: pm.merchant_id,
customer_id: Some(pm.customer_id), customer_id: Some(pm.customer_id),
payment_method_id: pm.payment_method_id, payment_method_id: pm.payment_method_id,
@ -761,13 +762,16 @@ pub async fn retrieve_payment_method(
card, card,
metadata: pm.metadata, metadata: pm.metadata,
created: Some(pm.created_at), created: Some(pm.created_at),
payment_method_issuer_code: pm.payment_method_issuer_code.map(ForeignInto::foreign_into), payment_method_issuer_code: pm
.payment_method_issuer_code
.map(ForeignInto::foreign_into),
recurring_enabled: false, //TODO recurring_enabled: false, //TODO
installment_payment_enabled: false, //TODO installment_payment_enabled: false, //TODO
payment_experience: Some(vec![ payment_experience: Some(vec![
api_models::payment_methods::PaymentExperience::RedirectToUrl, api_models::payment_methods::PaymentExperience::RedirectToUrl,
]), //TODO, ]), //TODO,
})) },
))
} }
#[instrument(skip_all)] #[instrument(skip_all)]
@ -801,7 +805,7 @@ pub async fn delete_payment_method(
} }
}; };
Ok(services::BachResponse::Json( Ok(services::ApplicationResponse::Json(
api::DeletePaymentMethodResponse { api::DeletePaymentMethodResponse {
payment_method_id: pm.payment_method_id, payment_method_id: pm.payment_method_id,
deleted: true, deleted: true,

View File

@ -247,7 +247,7 @@ where
let payments_response = let payments_response =
match response.change_context(errors::ApiErrorResponse::NotImplemented)? { match response.change_context(errors::ApiErrorResponse::NotImplemented)? {
services::BachResponse::Json(response) => Ok(response), services::ApplicationResponse::Json(response) => Ok(response),
_ => Err(errors::ApiErrorResponse::InternalServerError) _ => Err(errors::ApiErrorResponse::InternalServerError)
.into_report() .into_report()
.attach_printable("Failed to get the response in json"), .attach_printable("Failed to get the response in json"),
@ -261,7 +261,7 @@ where
) )
.attach_printable("No redirection response")?; .attach_printable("No redirection response")?;
Ok(services::BachResponse::JsonForRedirection(result)) Ok(services::ApplicationResponse::JsonForRedirection(result))
} }
pub async fn payments_response_for_redirection_flows<'a>( pub async fn payments_response_for_redirection_flows<'a>(
@ -562,10 +562,12 @@ pub async fn list_payments(
.into_iter() .into_iter()
.map(ForeignInto::foreign_into) .map(ForeignInto::foreign_into)
.collect(); .collect();
Ok(services::BachResponse::Json(api::PaymentListResponse { Ok(services::ApplicationResponse::Json(
api::PaymentListResponse {
size: data.len(), size: data.len(),
data, data,
})) },
))
} }
pub async fn add_process_sync_task( pub async fn add_process_sync_task(

View File

@ -547,7 +547,7 @@ pub(crate) async fn call_payment_method(
.await .await
.attach_printable("Error on adding payment method")?; .attach_printable("Error on adding payment method")?;
match resp { match resp {
crate::services::BachResponse::Json(payment_method) => { crate::services::ApplicationResponse::Json(payment_method) => {
Ok(payment_method) Ok(payment_method)
} }
_ => Err(report!(errors::ApiErrorResponse::InternalServerError) _ => Err(report!(errors::ApiErrorResponse::InternalServerError)
@ -575,7 +575,9 @@ pub(crate) async fn call_payment_method(
.await .await
.attach_printable("Error on adding payment method")?; .attach_printable("Error on adding payment method")?;
match resp { match resp {
crate::services::BachResponse::Json(payment_method) => Ok(payment_method), crate::services::ApplicationResponse::Json(payment_method) => {
Ok(payment_method)
}
_ => Err(report!(errors::ApiErrorResponse::InternalServerError) _ => Err(report!(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Error on adding payment method")), .attach_printable("Error on adding payment method")),
} }
@ -1156,7 +1158,7 @@ pub async fn make_ephemeral_key(
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError) .change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to create ephemeral key")?; .attach_printable("Unable to create ephemeral key")?;
Ok(services::BachResponse::Json(ek)) Ok(services::ApplicationResponse::Json(ek))
} }
pub async fn delete_ephemeral_key( pub async fn delete_ephemeral_key(
@ -1168,7 +1170,7 @@ pub async fn delete_ephemeral_key(
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError) .change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to delete ephemeral key")?; .attach_printable("Unable to delete ephemeral key")?;
Ok(services::BachResponse::Json(ek)) Ok(services::ApplicationResponse::Json(ek))
} }
pub fn make_pg_redirect_response( pub fn make_pg_redirect_response(

View File

@ -160,7 +160,7 @@ where
_server: &Server, _server: &Server,
_operation: Op, _operation: Op,
) -> RouterResponse<Self> { ) -> RouterResponse<Self> {
Ok(services::BachResponse::Json(Self { Ok(services::ApplicationResponse::Json(Self {
session_token: payment_data.sessions_token, session_token: payment_data.sessions_token,
payment_id: payment_data.payment_attempt.payment_id, payment_id: payment_data.payment_attempt.payment_id,
client_secret: payment_data client_secret: payment_data
@ -186,7 +186,7 @@ where
_server: &Server, _server: &Server,
_operation: Op, _operation: Op,
) -> RouterResponse<Self> { ) -> RouterResponse<Self> {
Ok(services::BachResponse::Json(Self { Ok(services::ApplicationResponse::Json(Self {
verify_id: Some(data.payment_intent.payment_id), verify_id: Some(data.payment_intent.payment_id),
merchant_id: Some(data.payment_intent.merchant_id), merchant_id: Some(data.payment_intent.merchant_id),
client_secret: data.payment_intent.client_secret.map(masking::Secret::new), client_secret: data.payment_intent.client_secret.map(masking::Secret::new),
@ -254,7 +254,7 @@ where
let redirection_data = redirection_data.get_required_value("redirection_data")?; let redirection_data = redirection_data.get_required_value("redirection_data")?;
let form: RedirectForm = serde_json::from_value(redirection_data) let form: RedirectForm = serde_json::from_value(redirection_data)
.map_err(|_| errors::ApiErrorResponse::InternalServerError)?; .map_err(|_| errors::ApiErrorResponse::InternalServerError)?;
services::BachResponse::Form(form) services::ApplicationResponse::Form(form)
} else { } else {
let mut response: api::PaymentsResponse = request let mut response: api::PaymentsResponse = request
.try_into() .try_into()
@ -271,7 +271,7 @@ where
}) })
} }
services::BachResponse::Json( services::ApplicationResponse::Json(
response response
.set_payment_id(Some(payment_attempt.payment_id)) .set_payment_id(Some(payment_attempt.payment_id))
.set_merchant_id(Some(payment_attempt.merchant_id)) .set_merchant_id(Some(payment_attempt.merchant_id))
@ -341,7 +341,7 @@ where
) )
} }
} }
None => services::BachResponse::Json(api::PaymentsResponse { None => services::ApplicationResponse::Json(api::PaymentsResponse {
payment_id: Some(payment_attempt.payment_id), payment_id: Some(payment_attempt.payment_id),
merchant_id: Some(payment_attempt.merchant_id), merchant_id: Some(payment_attempt.merchant_id),
status: payment_intent.status.foreign_into(), status: payment_intent.status.foreign_into(),

View File

@ -2,9 +2,9 @@ pub mod validator;
use error_stack::{report, IntoReport, ResultExt}; use error_stack::{report, IntoReport, ResultExt};
use router_env::{instrument, tracing}; use router_env::{instrument, tracing};
use uuid::Uuid;
use crate::{ use crate::{
consts,
core::{ core::{
errors::{self, ConnectorErrorExt, RouterResponse, RouterResult, StorageErrorExt}, errors::{self, ConnectorErrorExt, RouterResponse, RouterResult, StorageErrorExt},
payments, utils as core_utils, payments, utils as core_utils,
@ -45,9 +45,9 @@ pub async fn refund_create_core(
.change_context(errors::ApiErrorResponse::SuccessfulPaymentNotFound)?; .change_context(errors::ApiErrorResponse::SuccessfulPaymentNotFound)?;
// Amount is not passed in request refer from payment attempt. // Amount is not passed in request refer from payment attempt.
amount = req.amount.unwrap_or(payment_attempt.amount); // FIXME: Need to that capture amount amount = req.amount.unwrap_or(payment_attempt.amount); // [#298]: Need to that capture amount
//TODO: Can we change the flow based on some workflow idea //[#299]: Can we change the flow based on some workflow idea
utils::when(amount <= 0, || { utils::when(amount <= 0, || {
Err(report!(errors::ApiErrorResponse::InvalidDataFormat { Err(report!(errors::ApiErrorResponse::InvalidDataFormat {
field_name: "amount".to_string(), field_name: "amount".to_string(),
@ -82,7 +82,7 @@ pub async fn refund_create_core(
req, req,
) )
.await .await
.map(services::BachResponse::Json) .map(services::ApplicationResponse::Json)
} }
#[instrument(skip_all)] #[instrument(skip_all)]
@ -180,7 +180,7 @@ where
Fut: futures::Future<Output = RouterResult<T>>, Fut: futures::Future<Output = RouterResult<T>>,
T: ForeignInto<refunds::RefundResponse>, T: ForeignInto<refunds::RefundResponse>,
{ {
Ok(services::BachResponse::Json( Ok(services::ApplicationResponse::Json(
f(state, merchant_account, refund_id).await?.foreign_into(), f(state, merchant_account, refund_id).await?.foreign_into(),
)) ))
} }
@ -337,7 +337,7 @@ pub async fn refund_update_core(
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError)?; .change_context(errors::ApiErrorResponse::InternalServerError)?;
Ok(services::BachResponse::Json(response.foreign_into())) Ok(services::ApplicationResponse::Json(response.foreign_into()))
} }
// ********************************************** VALIDATIONS ********************************************** // ********************************************** VALIDATIONS **********************************************
@ -402,21 +402,26 @@ pub async fn validate_and_create_refund(
.attach_printable("Failed to fetch refund")?; .attach_printable("Failed to fetch refund")?;
currency = payment_attempt.currency.get_required_value("currency")?; currency = payment_attempt.currency.get_required_value("currency")?;
// TODO: Add Connector Based Validation here. //[#249]: Add Connector Based Validation here.
validator::validate_payment_order_age(&payment_intent.created_at).change_context( validator::validate_payment_order_age(
errors::ApiErrorResponse::InvalidDataFormat { &payment_intent.created_at,
state.conf.refund.max_age,
)
.change_context(errors::ApiErrorResponse::InvalidDataFormat {
field_name: "created_at".to_string(), field_name: "created_at".to_string(),
expected_format: format!( expected_format: format!(
"created_at not older than {} days", "created_at not older than {} days",
validator::REFUND_MAX_AGE state.conf.refund.max_age,
), ),
}, })?;
)?;
validator::validate_refund_amount(payment_attempt.amount, &all_refunds, refund_amount) validator::validate_refund_amount(payment_attempt.amount, &all_refunds, refund_amount)
.change_context(errors::ApiErrorResponse::RefundAmountExceedsPaymentAmount)?; .change_context(errors::ApiErrorResponse::RefundAmountExceedsPaymentAmount)?;
validator::validate_maximum_refund_against_payment_attempt(&all_refunds) validator::validate_maximum_refund_against_payment_attempt(
&all_refunds,
state.conf.refund.max_attempts,
)
.change_context(errors::ApiErrorResponse::MaximumRefundCount)?; .change_context(errors::ApiErrorResponse::MaximumRefundCount)?;
let connector = payment_attempt.connector.clone().ok_or_else(|| { let connector = payment_attempt.connector.clone().ok_or_else(|| {
@ -424,15 +429,25 @@ pub async fn validate_and_create_refund(
.attach_printable("connector not populated in payment attempt.") .attach_printable("connector not populated in payment attempt.")
})?; })?;
refund_create_req = mk_new_refund( refund_create_req = storage::RefundNew::default()
req, .set_refund_id(refund_id.to_string())
connector, .set_internal_reference_id(utils::generate_id(consts::ID_LENGTH, "refid"))
payment_attempt, .set_external_reference_id(Some(refund_id))
currency, .set_payment_id(req.payment_id)
&refund_id, .set_merchant_id(merchant_account.merchant_id.clone())
&merchant_account.merchant_id, .set_connector_transaction_id(connecter_transaction_id.to_string())
refund_amount, .set_connector(connector)
); .set_refund_type(enums::RefundType::RegularRefund)
.set_total_amount(refund_amount)
.set_currency(currency)
.set_created_at(Some(common_utils::date_time::now()))
.set_modified_at(Some(common_utils::date_time::now()))
.set_refund_status(enums::RefundStatus::Pending)
.set_metadata(req.metadata)
.set_description(req.reason.clone())
.set_attempt_id(payment_attempt.attempt_id.clone())
.set_refund_reason(req.reason)
.to_owned();
refund = db refund = db
.insert_refund(refund_create_req, merchant_account.storage_scheme) .insert_refund(refund_create_req, merchant_account.storage_scheme)
@ -484,53 +499,11 @@ pub async fn refund_list(
utils::when(data.is_empty(), || { utils::when(data.is_empty(), || {
Err(errors::ApiErrorResponse::RefundNotFound) Err(errors::ApiErrorResponse::RefundNotFound)
})?; })?;
Ok(services::BachResponse::Json( Ok(services::ApplicationResponse::Json(
api_models::refunds::RefundListResponse { data }, api_models::refunds::RefundListResponse { data },
)) ))
} }
// ********************************************** UTILS **********************************************
// FIXME: function should not have more than 3 arguments.
// Consider to use builder pattern.
#[instrument]
fn mk_new_refund(
request: refunds::RefundRequest,
connector: String,
payment_attempt: &storage::PaymentAttempt,
currency: enums::Currency,
refund_id: &str,
merchant_id: &str,
refund_amount: i64,
) -> storage::RefundNew {
let current_time = common_utils::date_time::now();
let connecter_transaction_id = match &payment_attempt.connector_transaction_id {
Some(id) => id,
None => "",
};
storage::RefundNew {
refund_id: refund_id.to_string(),
internal_reference_id: Uuid::new_v4().to_string(),
external_reference_id: Some(refund_id.to_string()),
payment_id: request.payment_id,
merchant_id: merchant_id.to_string(),
// FIXME: remove the default.
connector_transaction_id: connecter_transaction_id.to_string(),
connector,
refund_type: enums::RefundType::RegularRefund,
total_amount: refund_amount,
currency,
refund_amount,
created_at: Some(current_time),
modified_at: Some(current_time),
refund_status: enums::RefundStatus::Pending,
metadata: request.metadata,
description: request.reason,
attempt_id: payment_attempt.attempt_id.clone(),
..storage::RefundNew::default()
}
}
impl<F> TryFrom<types::RefundsRouterData<F>> for refunds::RefundResponse { impl<F> TryFrom<types::RefundsRouterData<F>> for refunds::RefundResponse {
type Error = error_stack::Report<errors::ApiErrorResponse>; type Error = error_stack::Report<errors::ApiErrorResponse>;
@ -548,7 +521,7 @@ impl<F> TryFrom<types::RefundsRouterData<F>> for refunds::RefundResponse {
refund_id, refund_id,
amount: data.request.amount / 100, amount: data.request.amount / 100,
currency: data.request.currency.to_string(), currency: data.request.currency.to_string(),
reason: Some("TODO: Not propagated".to_string()), // TODO: Not propagated reason: data.request.reason,
status, status,
metadata: None, metadata: None,
error_message, error_message,
@ -622,7 +595,7 @@ pub async fn schedule_refund_execution(
} }
_ => { _ => {
// Sync the refund for status check // Sync the refund for status check
//TODO: return refund status response //[#300]: return refund status response
match refund_type { match refund_type {
api_models::refunds::RefundType::Scheduled => { api_models::refunds::RefundType::Scheduled => {
add_refund_sync_task(db, &refund, runner) add_refund_sync_task(db, &refund, runner)
@ -661,25 +634,6 @@ pub async fn sync_refund_with_gateway_workflow(
) )
})?; })?;
let merchant_account = state
.store
.find_merchant_account_by_merchant_id(&refund_core.merchant_id)
.await
.map_err(|error| {
error.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)
})?;
// FIXME we actually don't use this?
let _refund = state
.store
.find_refund_by_internal_reference_id_merchant_id(
&refund_core.refund_internal_reference_id,
&refund_core.merchant_id,
merchant_account.storage_scheme,
)
.await
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::RefundNotFound))?;
let merchant_account = state let merchant_account = state
.store .store
.find_merchant_account_by_merchant_id(&refund_core.merchant_id) .find_merchant_account_by_merchant_id(&refund_core.merchant_id)
@ -763,7 +717,6 @@ pub async fn trigger_refund_execute_workflow(
.await .await
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::RefundNotFound))?; .map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::RefundNotFound))?;
match (&refund.sent_to_gateway, &refund.refund_status) { match (&refund.sent_to_gateway, &refund.refund_status) {
//FIXME: Conversion should come from trait
(false, enums::RefundStatus::Pending) => { (false, enums::RefundStatus::Pending) => {
let merchant_account = db let merchant_account = db
.find_merchant_account_by_merchant_id(&refund.merchant_id) .find_merchant_account_by_merchant_id(&refund.merchant_id)

View File

@ -10,9 +10,6 @@ use crate::{
utils, utils,
}; };
pub(super) const REFUND_MAX_AGE: i64 = 365;
pub(super) const REFUND_MAX_ATTEMPTS: usize = 10;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum RefundValidationError { pub enum RefundValidationError {
#[error("The payment attempt was not successful")] #[error("The payment attempt was not successful")]
@ -38,7 +35,6 @@ pub fn validate_success_transaction(
Ok(()) Ok(())
} }
//todo: max refund request count
#[instrument(skip_all)] #[instrument(skip_all)]
pub fn validate_refund_amount( pub fn validate_refund_amount(
payment_attempt_amount: i64, // &storage::PaymentAttempt, payment_attempt_amount: i64, // &storage::PaymentAttempt,
@ -71,11 +67,12 @@ pub fn validate_refund_amount(
#[instrument(skip_all)] #[instrument(skip_all)]
pub fn validate_payment_order_age( pub fn validate_payment_order_age(
created_at: &PrimitiveDateTime, created_at: &PrimitiveDateTime,
refund_max_age: i64,
) -> CustomResult<(), RefundValidationError> { ) -> CustomResult<(), RefundValidationError> {
let current_time = common_utils::date_time::now(); let current_time = common_utils::date_time::now();
utils::when( utils::when(
(current_time - *created_at).whole_days() > REFUND_MAX_AGE, (current_time - *created_at).whole_days() > refund_max_age,
|| Err(report!(RefundValidationError::OrderExpired)), || Err(report!(RefundValidationError::OrderExpired)),
) )
} }
@ -83,9 +80,9 @@ pub fn validate_payment_order_age(
#[instrument(skip_all)] #[instrument(skip_all)]
pub fn validate_maximum_refund_against_payment_attempt( pub fn validate_maximum_refund_against_payment_attempt(
all_refunds: &[storage::Refund], all_refunds: &[storage::Refund],
refund_max_attempts: usize,
) -> CustomResult<(), RefundValidationError> { ) -> CustomResult<(), RefundValidationError> {
// TODO: Make this configurable utils::when(all_refunds.len() > refund_max_attempts, || {
utils::when(all_refunds.len() > REFUND_MAX_ATTEMPTS, || {
Err(report!(RefundValidationError::MaxRefundCountReached)) Err(report!(RefundValidationError::MaxRefundCountReached))
}) })
} }

View File

@ -28,7 +28,6 @@ pub async fn construct_refund_router_data<'a, F>(
refund: &'a storage::Refund, refund: &'a storage::Refund,
) -> RouterResult<types::RefundsRouterData<F>> { ) -> RouterResult<types::RefundsRouterData<F>> {
let db = &*state.store; let db = &*state.store;
//TODO: everytime parsing the json may have impact?
let merchant_connector_account = db let merchant_connector_account = db
.find_merchant_connector_account_by_merchant_id_connector( .find_merchant_connector_account_by_merchant_id_connector(
&merchant_account.merchant_id, &merchant_account.merchant_id,
@ -86,6 +85,7 @@ pub async fn construct_refund_router_data<'a, F>(
refund_amount: refund.refund_amount, refund_amount: refund.refund_amount,
currency, currency,
amount, amount,
reason: refund.refund_reason.clone(),
}, },
response: Ok(types::RefundsResponseData { response: Ok(types::RefundsResponseData {

View File

@ -59,7 +59,7 @@ async fn payments_incoming_webhook_flow(
.change_context(errors::WebhooksFlowError::PaymentsCoreFailed)?; .change_context(errors::WebhooksFlowError::PaymentsCoreFailed)?;
match payments_response { match payments_response {
services::BachResponse::Json(payments_response) => { services::ApplicationResponse::Json(payments_response) => {
let payment_id = payments_response let payment_id = payments_response
.payment_id .payment_id
.clone() .clone()

View File

@ -290,6 +290,7 @@ mod storage {
created_at: new.created_at.unwrap_or_else(date_time::now), created_at: new.created_at.unwrap_or_else(date_time::now),
updated_at: new.created_at.unwrap_or_else(date_time::now), updated_at: new.created_at.unwrap_or_else(date_time::now),
description: new.description.clone(), description: new.description.clone(),
refund_reason: new.refund_reason.clone(),
}; };
let field = format!( let field = format!(
@ -640,6 +641,7 @@ impl RefundInterface for MockDb {
created_at: new.created_at.unwrap_or(current_time), created_at: new.created_at.unwrap_or(current_time),
updated_at: current_time, updated_at: current_time,
description: new.description, description: new.description,
refund_reason: new.refund_reason.clone(),
}; };
refunds.push(refund.clone()); refunds.push(refund.clone());
Ok(refund) Ok(refund)

View File

@ -32,7 +32,7 @@ use routes::AppState;
pub use self::env::logger; pub use self::env::logger;
use crate::{ use crate::{
configs::settings::Settings, configs::settings::Settings,
core::errors::{self, BachResult}, core::errors::{self, ApplicationResult},
}; };
#[cfg(feature = "mimalloc")] #[cfg(feature = "mimalloc")]
@ -110,7 +110,7 @@ pub fn mk_app(
/// # Panics /// # Panics
/// ///
/// Unwrap used because without the value we can't start the server /// Unwrap used because without the value we can't start the server
pub async fn start_server(conf: Settings) -> BachResult<(Server, AppState)> { pub async fn start_server(conf: Settings) -> ApplicationResult<(Server, AppState)> {
logger::debug!(startup_config=?conf); logger::debug!(startup_config=?conf);
let server = conf.server.clone(); let server = conf.server.clone();
let state = routes::AppState::new(conf).await; let state = routes::AppState::new(conf).await;

View File

@ -320,7 +320,7 @@ async fn handle_response(
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum BachResponse<R> { pub enum ApplicationResponse<R> {
Json(R), Json(R),
StatusOk, StatusOk,
TextPlain(String), TextPlain(String),
@ -329,11 +329,11 @@ pub enum BachResponse<R> {
} }
#[derive(Debug, Eq, PartialEq, Serialize)] #[derive(Debug, Eq, PartialEq, Serialize)]
pub struct BachRedirectResponse { pub struct ApplicationRedirectResponse {
pub url: String, pub url: String,
} }
impl From<&storage::PaymentAttempt> for BachRedirectResponse { impl From<&storage::PaymentAttempt> for ApplicationRedirectResponse {
fn from(payment_attempt: &storage::PaymentAttempt) -> Self { fn from(payment_attempt: &storage::PaymentAttempt) -> Self {
Self { Self {
url: format!( url: format!(
@ -376,7 +376,7 @@ pub async fn server_wrap_util<'a, 'b, U, T, Q, F, Fut>(
payload: T, payload: T,
func: F, func: F,
api_auth: &dyn auth::AuthenticateAndFetch<U>, api_auth: &dyn auth::AuthenticateAndFetch<U>,
) -> RouterResult<BachResponse<Q>> ) -> RouterResult<ApplicationResponse<Q>>
where where
F: Fn(&'b AppState, U, T) -> Fut, F: Fn(&'b AppState, U, T) -> Fut,
Fut: Future<Output = RouterResponse<Q>>, Fut: Future<Output = RouterResponse<Q>>,
@ -402,7 +402,7 @@ pub async fn server_wrap<'a, 'b, T, U, Q, F, Fut>(
) -> HttpResponse ) -> HttpResponse
where where
F: Fn(&'b AppState, U, T) -> Fut, F: Fn(&'b AppState, U, T) -> Fut,
Fut: Future<Output = RouterResult<BachResponse<Q>>>, Fut: Future<Output = RouterResult<ApplicationResponse<Q>>>,
Q: Serialize + Debug + 'a, Q: Serialize + Debug + 'a,
T: Debug, T: Debug,
{ {
@ -415,7 +415,7 @@ where
logger::info!(tag = ?Tag::BeginRequest); logger::info!(tag = ?Tag::BeginRequest);
let res = match server_wrap_util(state, request, payload, func, api_auth).await { let res = match server_wrap_util(state, request, payload, func, api_auth).await {
Ok(BachResponse::Json(response)) => match serde_json::to_string(&response) { Ok(ApplicationResponse::Json(response)) => match serde_json::to_string(&response) {
Ok(res) => http_response_json(res), Ok(res) => http_response_json(res),
Err(_) => http_response_err( Err(_) => http_response_err(
r#"{ r#"{
@ -425,9 +425,10 @@ where
}"#, }"#,
), ),
}, },
Ok(BachResponse::StatusOk) => http_response_ok(), Ok(ApplicationResponse::StatusOk) => http_response_ok(),
Ok(BachResponse::TextPlain(text)) => http_response_plaintext(text), Ok(ApplicationResponse::TextPlain(text)) => http_response_plaintext(text),
Ok(BachResponse::JsonForRedirection(response)) => match serde_json::to_string(&response) { Ok(ApplicationResponse::JsonForRedirection(response)) => {
match serde_json::to_string(&response) {
Ok(res) => http_redirect_response(res, response), Ok(res) => http_redirect_response(res, response),
Err(_) => http_response_err( Err(_) => http_response_err(
r#"{ r#"{
@ -436,8 +437,9 @@ where
} }
}"#, }"#,
), ),
}, }
Ok(BachResponse::Form(response)) => build_redirection_form(&response) }
Ok(ApplicationResponse::Form(response)) => build_redirection_form(&response)
.respond_to(request) .respond_to(request)
.map_into_boxed_body(), .map_into_boxed_body(),

View File

@ -200,6 +200,7 @@ pub struct RefundsData {
pub currency: storage_enums::Currency, pub currency: storage_enums::Currency,
/// Amount for the payment against which this refund is issued /// Amount for the payment against which this refund is issued
pub amount: i64, pub amount: i64,
pub reason: Option<String>,
/// Amount to be refunded /// Amount to be refunded
pub refund_amount: i64, pub refund_amount: i64,
} }

View File

@ -136,7 +136,8 @@ pub trait IncomingWebhook: ConnectorCommon + Sync {
fn get_webhook_api_response( fn get_webhook_api_response(
&self, &self,
) -> CustomResult<services::api::BachResponse<serde_json::Value>, errors::ConnectorError> { ) -> CustomResult<services::api::ApplicationResponse<serde_json::Value>, errors::ConnectorError>
Ok(services::api::BachResponse::StatusOk) {
Ok(services::api::ApplicationResponse::StatusOk)
} }
} }

View File

@ -91,6 +91,7 @@ fn construct_refund_router_data<F>() -> types::RefundsRouterData<F> {
}), }),
connector_transaction_id: String::new(), connector_transaction_id: String::new(),
refund_amount: 100, refund_amount: 100,
reason: None,
}, },
payment_method_id: None, payment_method_id: None,
response: Err(types::ErrorResponse::default()), response: Err(types::ErrorResponse::default()),

View File

@ -91,6 +91,7 @@ fn construct_refund_router_data<F>() -> types::RefundsRouterData<F> {
}), }),
connector_transaction_id: String::new(), connector_transaction_id: String::new(),
refund_amount: 1, refund_amount: 1,
reason: None,
}, },
response: Err(types::ErrorResponse::default()), response: Err(types::ErrorResponse::default()),
payment_method_id: None, payment_method_id: None,

View File

@ -88,6 +88,7 @@ fn construct_refund_router_data<F>() -> types::RefundsRouterData<F> {
}), }),
connector_transaction_id: String::new(), connector_transaction_id: String::new(),
refund_amount: 10, refund_amount: 10,
reason: None,
}, },
response: Err(types::ErrorResponse::default()), response: Err(types::ErrorResponse::default()),
payment_method_id: None, payment_method_id: None,

View File

@ -117,6 +117,7 @@ pub trait ConnectorActions: Connector {
payment_method_data: types::api::PaymentMethod::Card(CCardType::default().0), payment_method_data: types::api::PaymentMethod::Card(CCardType::default().0),
connector_transaction_id: transaction_id, connector_transaction_id: transaction_id,
refund_amount: 100, refund_amount: 100,
reason: None,
}), }),
); );
call_connector(request, integration).await call_connector(request, integration).await
@ -139,6 +140,7 @@ pub trait ConnectorActions: Connector {
payment_method_data: types::api::PaymentMethod::Card(CCardType::default().0), payment_method_data: types::api::PaymentMethod::Card(CCardType::default().0),
connector_transaction_id: transaction_id, connector_transaction_id: transaction_id,
refund_amount: 100, refund_amount: 100,
reason: None,
}), }),
); );
call_connector(request, integration).await call_connector(request, integration).await
@ -249,6 +251,7 @@ impl Default for PaymentRefundType {
payment_method_data: types::api::PaymentMethod::Card(CCardType::default().0), payment_method_data: types::api::PaymentMethod::Card(CCardType::default().0),
connector_transaction_id: String::new(), connector_transaction_id: String::new(),
refund_amount: 100, refund_amount: 100,
reason: None,
}; };
Self(data) Self(data)
} }

View File

@ -347,7 +347,7 @@ async fn payments_create_core() {
mandate_id: None, mandate_id: None,
..Default::default() ..Default::default()
}; };
let expected_response = services::BachResponse::Json(expected_response); let expected_response = services::ApplicationResponse::Json(expected_response);
let actual_response = let actual_response =
payments::payments_core::<api::Authorize, api::PaymentsResponse, _, _, _>( payments::payments_core::<api::Authorize, api::PaymentsResponse, _, _, _>(
&state, &state,
@ -406,7 +406,7 @@ async fn payments_create_core() {
// .update(&state.pg_conn, payment_intent_update) // .update(&state.pg_conn, payment_intent_update)
// .unwrap(); // .unwrap();
// let expected_response = services::BachResponse::Form(services::RedirectForm { // let expected_response = services::ApplicationResponse::Form(services::RedirectForm {
// url: "http://example.com/payments".to_string(), // url: "http://example.com/payments".to_string(),
// method: services::Method::Post, // method: services::Method::Post,
// form_fields: HashMap::from([("payment_id".to_string(), payment_id.clone())]), // form_fields: HashMap::from([("payment_id".to_string(), payment_id.clone())]),
@ -491,7 +491,7 @@ async fn payments_create_core_adyen_no_redirect() {
browser_info: None, browser_info: None,
}; };
let expected_response = services::BachResponse::Json(api::PaymentsResponse { let expected_response = services::ApplicationResponse::Json(api::PaymentsResponse {
payment_id: Some(payment_id.clone()), payment_id: Some(payment_id.clone()),
status: api_enums::IntentStatus::Processing, status: api_enums::IntentStatus::Processing,
amount: 6540, amount: 6540,

View File

@ -98,7 +98,7 @@ async fn payments_create_core() {
mandate_id: None, mandate_id: None,
..Default::default() ..Default::default()
}; };
let expected_response = services::BachResponse::Json(expected_response); let expected_response = services::ApplicationResponse::Json(expected_response);
let actual_response = let actual_response =
router::core::payments::payments_core::<api::Authorize, api::PaymentsResponse, _, _, _>( router::core::payments::payments_core::<api::Authorize, api::PaymentsResponse, _, _, _>(
&state, &state,
@ -162,7 +162,7 @@ async fn payments_create_core() {
// .await // .await
// .unwrap(); // .unwrap();
// //
// let expected_response = services::BachResponse::Form(services::RedirectForm { // let expected_response = services::ApplicationResponse::Form(services::RedirectForm {
// url: "http://example.com/payments".to_string(), // url: "http://example.com/payments".to_string(),
// method: services::Method::Post, // method: services::Method::Post,
// form_fields: HashMap::from([("payment_id".to_string(), payment_id.clone())]), // form_fields: HashMap::from([("payment_id".to_string(), payment_id.clone())]),
@ -245,7 +245,7 @@ async fn payments_create_core_adyen_no_redirect() {
browser_info: None, browser_info: None,
}; };
let expected_response = services::BachResponse::Json(api::PaymentsResponse { let expected_response = services::ApplicationResponse::Json(api::PaymentsResponse {
payment_id: Some(payment_id.clone()), payment_id: Some(payment_id.clone()),
status: api_enums::IntentStatus::Processing, status: api_enums::IntentStatus::Processing,
amount: 6540, amount: 6540,

View File

@ -31,6 +31,7 @@ pub struct Refund {
pub updated_at: PrimitiveDateTime, pub updated_at: PrimitiveDateTime,
pub description: Option<String>, pub description: Option<String>,
pub attempt_id: String, pub attempt_id: String,
pub refund_reason: Option<String>,
} }
#[derive( #[derive(
@ -43,6 +44,7 @@ pub struct Refund {
router_derive::DebugAsDisplay, router_derive::DebugAsDisplay,
serde::Serialize, serde::Serialize,
serde::Deserialize, serde::Deserialize,
router_derive::Setter,
)] )]
#[diesel(table_name = refund)] #[diesel(table_name = refund)]
pub struct RefundNew { pub struct RefundNew {
@ -67,6 +69,7 @@ pub struct RefundNew {
pub modified_at: Option<PrimitiveDateTime>, pub modified_at: Option<PrimitiveDateTime>,
pub description: Option<String>, pub description: Option<String>,
pub attempt_id: String, pub attempt_id: String,
pub refund_reason: Option<String>,
} }
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]

View File

@ -327,6 +327,7 @@ diesel::table! {
modified_at -> Timestamp, modified_at -> Timestamp,
description -> Nullable<Varchar>, description -> Nullable<Varchar>,
attempt_id -> Varchar, attempt_id -> Varchar,
refund_reason -> Nullable<Varchar>,
} }
} }

View File

@ -34,6 +34,10 @@ basilisk_host = ""
[eph_key] [eph_key]
validity = 1 validity = 1
[refund]
max_attempts = 10
max_age = 365
[jwekey] [jwekey]
locker_key_identifier1 = "" locker_key_identifier1 = ""
locker_key_identifier2 = "" locker_key_identifier2 = ""

View File

@ -0,0 +1,2 @@
ALTER TABLE REFUND
DROP COLUMN refund_reason;

View File

@ -0,0 +1 @@
ALTER TABLE REFUND ADD COLUMN refund_reason VARCHAR(255) DEFAULT NULL;