feat(router): add fallback while add card and retrieve card from rust locker (#2888)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Shankar Singh C
2023-11-16 22:54:14 +05:30
committed by GitHub
parent 6ebf14aabc
commit f735fb0551
7 changed files with 208 additions and 131 deletions

View File

@ -24,6 +24,7 @@ optin = "optin" # Boku preflow name
optin_id = "optin_id" # Boku's id for optin flow optin_id = "optin_id" # Boku's id for optin flow
deriver = "deriver" deriver = "deriver"
Deriver = "Deriver" Deriver = "Deriver"
requestor_card_reference = "requestor_card_reference"
[default.extend-words] [default.extend-words]
aci = "aci" # Name of a connector aci = "aci" # Name of a connector

View File

@ -366,7 +366,10 @@ afterpay_clearpay = {fields = {stripe = [ # payment_method_type = afterpay_clea
# Required fields vector with its respective display name in front-end and field_type # Required fields vector with its respective display name in front-end and field_type
{ required_field = "shipping.address.first_name", display_name = "first_name", field_type = "text" }, { required_field = "shipping.address.first_name", display_name = "first_name", field_type = "text" },
{ required_field = "shipping.address.last_name", display_name = "last_name", field_type = "text" }, { required_field = "shipping.address.last_name", display_name = "last_name", field_type = "text" },
{ required_field = "shipping.address.country", display_name = "country", field_type = { drop_down = { options = [ "US", "IN" ] } } }, { required_field = "shipping.address.country", display_name = "country", field_type = { drop_down = { options = [
"US",
"IN",
] } } },
] } } ] } }
[payouts] [payouts]

View File

@ -106,7 +106,7 @@ pub async fn call_to_locker(
let (_add_card_rs_resp, _is_duplicate) = cards::add_card_hs( let (_add_card_rs_resp, _is_duplicate) = cards::add_card_hs(
state, state,
pm_create, pm_create,
card_details, &card_details,
customer_id.to_string(), customer_id.to_string(),
merchant_account, merchant_account,
api_enums::LockerChoice::Tartarus, api_enums::LockerChoice::Tartarus,

View File

@ -103,16 +103,12 @@ pub async fn add_payment_method(
let merchant_id = &merchant_account.merchant_id; let merchant_id = &merchant_account.merchant_id;
let customer_id = req.customer_id.clone().get_required_value("customer_id")?; let customer_id = req.customer_id.clone().get_required_value("customer_id")?;
let response = match req.card.clone() { let response = match req.card.clone() {
Some(card) => add_card_to_locker( Some(card) => {
&state, add_card_to_locker(&state, req.clone(), &card, &customer_id, merchant_account)
req.clone(),
card,
customer_id.clone(),
merchant_account,
)
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError) .change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Add Card Failed"), .attach_printable("Add Card Failed")
}
None => { None => {
let pm_id = generate_id(consts::ID_LENGTH, "pm"); let pm_id = generate_id(consts::ID_LENGTH, "pm");
let payment_method_response = api::PaymentMethodResponse { let payment_method_response = api::PaymentMethodResponse {
@ -207,18 +203,18 @@ pub async fn update_customer_payment_method(
pub async fn add_card_to_locker( pub async fn add_card_to_locker(
state: &routes::AppState, state: &routes::AppState,
req: api::PaymentMethodCreate, req: api::PaymentMethodCreate,
card: api::CardDetail, card: &api::CardDetail,
customer_id: String, customer_id: &String,
merchant_account: &domain::MerchantAccount, merchant_account: &domain::MerchantAccount,
) -> errors::CustomResult<(api::PaymentMethodResponse, bool), errors::VaultError> { ) -> errors::CustomResult<(api::PaymentMethodResponse, bool), errors::VaultError> {
metrics::STORED_TO_LOCKER.add(&metrics::CONTEXT, 1, &[]); metrics::STORED_TO_LOCKER.add(&metrics::CONTEXT, 1, &[]);
request::record_operation_time( let add_card_to_hs_resp = request::record_operation_time(
async { async {
add_card_hs( add_card_hs(
state, state,
req, req.clone(),
card, card,
customer_id, customer_id.to_string(),
merchant_account, merchant_account,
api_enums::LockerChoice::Basilisk, api_enums::LockerChoice::Basilisk,
None, None,
@ -232,7 +228,34 @@ pub async fn add_card_to_locker(
&metrics::CARD_ADD_TIME, &metrics::CARD_ADD_TIME,
&[], &[],
) )
.await?;
logger::debug!("card added to basilisk locker");
let add_card_to_rs_resp = request::record_operation_time(
async {
add_card_hs(
state,
req,
card,
customer_id.to_string(),
merchant_account,
api_enums::LockerChoice::Tartarus,
Some(&add_card_to_hs_resp.0.payment_method_id),
)
.await .await
.map_err(|error| {
metrics::CARD_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
error
})
},
&metrics::CARD_ADD_TIME,
&[],
)
.await?;
logger::debug!("card added to rust locker");
Ok(add_card_to_rs_resp)
} }
pub async fn get_card_from_locker( pub async fn get_card_from_locker(
@ -243,9 +266,38 @@ pub async fn get_card_from_locker(
) -> errors::RouterResult<payment_methods::Card> { ) -> errors::RouterResult<payment_methods::Card> {
metrics::GET_FROM_LOCKER.add(&metrics::CONTEXT, 1, &[]); metrics::GET_FROM_LOCKER.add(&metrics::CONTEXT, 1, &[]);
request::record_operation_time( let get_card_from_rs_locker_resp = request::record_operation_time(
async { async {
get_card_from_hs_locker(state, customer_id, merchant_id, card_reference) get_card_from_hs_locker(
state,
customer_id,
merchant_id,
card_reference,
api_enums::LockerChoice::Tartarus,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while getting card from basilisk_hs")
.map_err(|error| {
metrics::CARD_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
error
})
},
&metrics::CARD_GET_TIME,
&[],
)
.await;
match get_card_from_rs_locker_resp {
Err(_) => request::record_operation_time(
async {
get_card_from_hs_locker(
state,
customer_id,
merchant_id,
card_reference,
api_enums::LockerChoice::Basilisk,
)
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError) .change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while getting card from basilisk_hs") .attach_printable("Failed while getting card from basilisk_hs")
@ -258,6 +310,15 @@ pub async fn get_card_from_locker(
&[], &[],
) )
.await .await
.map(|inner_card| {
logger::debug!("card retrieved from basilisk locker");
inner_card
}),
Ok(_) => {
logger::debug!("card retrieved from rust locker");
get_card_from_rs_locker_resp
}
}
} }
pub async fn delete_card_from_locker( pub async fn delete_card_from_locker(
@ -287,7 +348,7 @@ pub async fn delete_card_from_locker(
pub async fn add_card_hs( pub async fn add_card_hs(
state: &routes::AppState, state: &routes::AppState,
req: api::PaymentMethodCreate, req: api::PaymentMethodCreate,
card: api::CardDetail, card: &api::CardDetail,
customer_id: String, customer_id: String,
merchant_account: &domain::MerchantAccount, merchant_account: &domain::MerchantAccount,
locker_choice: api_enums::LockerChoice, locker_choice: api_enums::LockerChoice,
@ -296,7 +357,7 @@ pub async fn add_card_hs(
let payload = payment_methods::StoreLockerReq::LockerCard(payment_methods::StoreCardReq { let payload = payment_methods::StoreLockerReq::LockerCard(payment_methods::StoreCardReq {
merchant_id: &merchant_account.merchant_id, merchant_id: &merchant_account.merchant_id,
merchant_customer_id: customer_id.to_owned(), merchant_customer_id: customer_id.to_owned(),
card_reference: card_reference.map(str::to_string), requestor_card_reference: card_reference.map(str::to_string),
card: payment_methods::Card { card: payment_methods::Card {
card_number: card.card_number.to_owned(), card_number: card.card_number.to_owned(),
name_on_card: card.card_holder_name.to_owned(), name_on_card: card.card_holder_name.to_owned(),
@ -307,11 +368,12 @@ pub async fn add_card_hs(
nick_name: card.nick_name.as_ref().map(masking::Secret::peek).cloned(), nick_name: card.nick_name.as_ref().map(masking::Secret::peek).cloned(),
}, },
}); });
let store_card_payload = let store_card_payload =
call_to_locker_hs(state, &payload, &customer_id, locker_choice).await?; call_to_locker_hs(state, &payload, &customer_id, locker_choice).await?;
let payment_method_resp = payment_methods::mk_add_card_response_hs( let payment_method_resp = payment_methods::mk_add_card_response_hs(
card, card.clone(),
store_card_payload.card_reference, store_card_payload.card_reference,
req, req,
&merchant_account.merchant_id, &merchant_account.merchant_id,
@ -351,6 +413,7 @@ pub async fn get_payment_method_from_hs_locker<'a>(
customer_id: &str, customer_id: &str,
merchant_id: &str, merchant_id: &str,
payment_method_reference: &'a str, payment_method_reference: &'a str,
locker_choice: Option<api_enums::LockerChoice>,
) -> errors::CustomResult<Secret<String>, errors::VaultError> { ) -> errors::CustomResult<Secret<String>, errors::VaultError> {
let locker = &state.conf.locker; let locker = &state.conf.locker;
#[cfg(not(feature = "kms"))] #[cfg(not(feature = "kms"))]
@ -365,6 +428,7 @@ pub async fn get_payment_method_from_hs_locker<'a>(
customer_id, customer_id,
merchant_id, merchant_id,
payment_method_reference, payment_method_reference,
locker_choice,
) )
.await .await
.change_context(errors::VaultError::FetchPaymentMethodFailed) .change_context(errors::VaultError::FetchPaymentMethodFailed)
@ -466,6 +530,7 @@ pub async fn get_card_from_hs_locker<'a>(
customer_id: &str, customer_id: &str,
merchant_id: &str, merchant_id: &str,
card_reference: &'a str, card_reference: &'a str,
locker_choice: api_enums::LockerChoice,
) -> errors::CustomResult<payment_methods::Card, errors::VaultError> { ) -> errors::CustomResult<payment_methods::Card, errors::VaultError> {
let locker = &state.conf.locker; let locker = &state.conf.locker;
#[cfg(not(feature = "kms"))] #[cfg(not(feature = "kms"))]
@ -480,6 +545,7 @@ pub async fn get_card_from_hs_locker<'a>(
customer_id, customer_id,
merchant_id, merchant_id,
card_reference, card_reference,
Some(locker_choice),
) )
.await .await
.change_context(errors::VaultError::FetchCardFailed) .change_context(errors::VaultError::FetchCardFailed)
@ -2193,6 +2259,7 @@ pub async fn get_lookup_key_for_payout_method(
&pm.customer_id, &pm.customer_id,
&pm.merchant_id, &pm.merchant_id,
&pm.payment_method_id, &pm.payment_method_id,
None,
) )
.await .await
.change_context(errors::ApiErrorResponse::InternalServerError) .change_context(errors::ApiErrorResponse::InternalServerError)

View File

@ -28,7 +28,7 @@ pub struct StoreCardReq<'a> {
pub merchant_id: &'a str, pub merchant_id: &'a str,
pub merchant_customer_id: String, pub merchant_customer_id: String,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub card_reference: Option<String>, pub requestor_card_reference: Option<String>,
pub card: Card, pub card: Card,
} }
@ -428,6 +428,7 @@ pub async fn mk_get_card_request_hs(
customer_id: &str, customer_id: &str,
merchant_id: &str, merchant_id: &str,
card_reference: &str, card_reference: &str,
locker_choice: Option<api_enums::LockerChoice>,
) -> CustomResult<services::Request, errors::VaultError> { ) -> CustomResult<services::Request, errors::VaultError> {
let merchant_customer_id = customer_id.to_owned(); let merchant_customer_id = customer_id.to_owned();
let card_req_body = CardReqBody { let card_req_body = CardReqBody {
@ -448,11 +449,16 @@ pub async fn mk_get_card_request_hs(
.await .await
.change_context(errors::VaultError::RequestEncodingFailed)?; .change_context(errors::VaultError::RequestEncodingFailed)?;
let jwe_payload = mk_basilisk_req(jwekey, &jws, api_enums::LockerChoice::Basilisk).await?; let target_locker = locker_choice.unwrap_or(api_enums::LockerChoice::Basilisk);
let jwe_payload = mk_basilisk_req(jwekey, &jws, target_locker).await?;
let body = utils::Encode::<encryption::JweBody>::encode_to_value(&jwe_payload) let body = utils::Encode::<encryption::JweBody>::encode_to_value(&jwe_payload)
.change_context(errors::VaultError::RequestEncodingFailed)?; .change_context(errors::VaultError::RequestEncodingFailed)?;
let mut url = locker.host.to_owned(); let mut url = match target_locker {
api_enums::LockerChoice::Basilisk => locker.host.to_owned(),
api_enums::LockerChoice::Tartarus => locker.host_rs.to_owned(),
};
url.push_str("/cards/retrieve"); url.push_str("/cards/retrieve");
let mut request = services::Request::new(services::Method::Post, &url); let mut request = services::Request::new(services::Method::Post, &url);
request.add_header(headers::CONTENT_TYPE, "application/json".into()); request.add_header(headers::CONTENT_TYPE, "application/json".into());

View File

@ -183,8 +183,8 @@ pub async fn save_in_locker(
Some(card) => payment_methods::cards::add_card_to_locker( Some(card) => payment_methods::cards::add_card_to_locker(
state, state,
payment_method_request, payment_method_request,
card, &card,
customer_id, &customer_id,
merchant_account, merchant_account,
) )
.await .await

View File

@ -152,7 +152,7 @@ pub async fn save_payout_data_to_locker(
card_isin: None, card_isin: None,
nick_name: None, nick_name: None,
}, },
card_reference: None, requestor_card_reference: None,
}); });
( (
payload, payload,