Skip to content

Commit

Permalink
Merge branch 'feat/profile_specific_fallback_routing' of https://gith…
Browse files Browse the repository at this point in the history
…ub.com/juspay/hyperswitch into feat/profile_specific_fallback_routing
  • Loading branch information
prajjwalkumar17 committed Nov 8, 2023
2 parents 48ce244 + 5d423fd commit 555b4da
Show file tree
Hide file tree
Showing 25 changed files with 582 additions and 547 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: PR Title Checks
name: Conventional Commit Message Check

on:
# This is a dangerous event trigger as it causes the workflow to run in the
Expand Down Expand Up @@ -35,21 +35,6 @@ env:
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse

jobs:
typos:
name: Spell check PR title
runs-on: ubuntu-latest
steps:
- name: Store PR title in a file
shell: bash
env:
TITLE: ${{ github.event.pull_request.title }}
run: echo $TITLE > pr_title.txt

- name: Spell check
uses: crate-ci/typos@master
with:
files: ./pr_title.txt

pr_title_check:
name: Verify PR title follows conventional commit standards
runs-on: ubuntu-latest
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/pr-title-spell-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: PR Title Spell Check

on:
pull_request:
types:
- opened
- edited
- synchronize

jobs:
typos:
name: Spell check PR title
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Store PR title in a file
shell: bash
env:
TITLE: ${{ github.event.pull_request.title }}
run: echo $TITLE > pr_title.txt

- name: Spell check
uses: crate-ci/typos@master
with:
files: ./pr_title.txt
3 changes: 3 additions & 0 deletions crates/router/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@ pub(crate) const MERCHANT_ID_FIELD_EXTENSION_ID: &str = "1.2.840.113635.100.6.32
pub(crate) const METRICS_HOST_TAG_NAME: &str = "host";
pub const MAX_ROUTING_CONFIGS_PER_MERCHANT: usize = 100;
pub const ROUTING_CONFIG_ID_LENGTH: usize = 10;

pub const LOCKER_REDIS_PREFIX: &str = "LOCKER_PM_TOKEN";
pub const LOCKER_REDIS_EXPIRY_SECONDS: u32 = 60 * 15; // 15 minutes
11 changes: 10 additions & 1 deletion crates/router/src/core/payment_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use diesel_models::enums;
use crate::{
core::{errors::RouterResult, payments::helpers},
routes::AppState,
types::api::{self, payments},
types::{
api::{self, payments},
domain,
},
};

pub struct Oss;
Expand All @@ -25,6 +28,7 @@ pub trait PaymentMethodRetrieve {
state: &AppState,
payment_intent: &PaymentIntent,
payment_attempt: &PaymentAttempt,
merchant_key_store: &domain::MerchantKeyStore,
) -> RouterResult<(Option<payments::PaymentMethodData>, Option<String>)>;
}

Expand All @@ -35,6 +39,7 @@ impl PaymentMethodRetrieve for Oss {
state: &AppState,
payment_intent: &PaymentIntent,
payment_attempt: &PaymentAttempt,
merchant_key_store: &domain::MerchantKeyStore,
) -> RouterResult<(Option<payments::PaymentMethodData>, Option<String>)> {
match pm_data {
pm_opt @ Some(pm @ api::PaymentMethodData::Card(_)) => {
Expand All @@ -44,6 +49,7 @@ impl PaymentMethodRetrieve for Oss {
payment_intent,
enums::PaymentMethod::Card,
pm,
merchant_key_store,
)
.await?;

Expand All @@ -64,6 +70,7 @@ impl PaymentMethodRetrieve for Oss {
payment_intent,
enums::PaymentMethod::BankTransfer,
pm,
merchant_key_store,
)
.await?;

Expand All @@ -76,6 +83,7 @@ impl PaymentMethodRetrieve for Oss {
payment_intent,
enums::PaymentMethod::Wallet,
pm,
merchant_key_store,
)
.await?;

Expand All @@ -88,6 +96,7 @@ impl PaymentMethodRetrieve for Oss {
payment_intent,
enums::PaymentMethod::BankRedirect,
pm,
merchant_key_store,
)
.await?;

Expand Down
131 changes: 26 additions & 105 deletions crates/router/src/core/payment_methods/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2009,7 +2009,7 @@ pub async fn list_customer_payment_method(
let hyperswitch_token = generate_id(consts::ID_LENGTH, "token");

let card = if pm.payment_method == enums::PaymentMethod::Card {
get_card_details(&pm, key, state, &hyperswitch_token).await?
get_card_details(&pm, key, state, &hyperswitch_token, &key_store).await?
} else {
None
};
Expand Down Expand Up @@ -2104,6 +2104,7 @@ async fn get_card_details(
key: &[u8],
state: &routes::AppState,
hyperswitch_token: &str,
key_store: &domain::MerchantKeyStore,
) -> errors::RouterResult<Option<api::CardDetailFromLocker>> {
let mut _card_decrypted =
decrypt::<serde_json::Value, masking::WithType>(pm.payment_method_data.clone(), key)
Expand All @@ -2120,14 +2121,15 @@ async fn get_card_details(
});

Ok(Some(
get_lookup_key_from_locker(state, hyperswitch_token, pm).await?,
get_lookup_key_from_locker(state, hyperswitch_token, pm, key_store).await?,
))
}

pub async fn get_lookup_key_from_locker(
state: &routes::AppState,
payment_token: &str,
pm: &storage::PaymentMethod,
merchant_key_store: &domain::MerchantKeyStore,
) -> errors::RouterResult<api::CardDetailFromLocker> {
let card = get_card_from_locker(
state,
Expand All @@ -2142,9 +2144,15 @@ pub async fn get_lookup_key_from_locker(
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Get Card Details Failed")?;
let card = card_detail.clone();
let resp =
BasiliskCardSupport::create_payment_method_data_in_locker(state, payment_token, card, pm)
.await?;

let resp = TempLockerCardSupport::create_payment_method_data_in_temp_locker(
state,
payment_token,
card,
pm,
merchant_key_store,
)
.await?;
Ok(resp)
}

Expand Down Expand Up @@ -2177,6 +2185,7 @@ pub async fn get_lookup_key_for_payout_method(
Some(payout_token.to_string()),
&pm_parsed,
Some(pm.customer_id.to_owned()),
key_store,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
Expand All @@ -2190,110 +2199,16 @@ pub async fn get_lookup_key_for_payout_method(
}
}

pub struct BasiliskCardSupport;
pub struct TempLockerCardSupport;

#[cfg(not(feature = "basilisk"))]
impl BasiliskCardSupport {
async fn create_payment_method_data_in_locker(
state: &routes::AppState,
payment_token: &str,
card: api::CardDetailFromLocker,
pm: &storage::PaymentMethod,
) -> errors::RouterResult<api::CardDetailFromLocker> {
let card_number = card.card_number.clone().get_required_value("card_number")?;
let card_exp_month = card
.expiry_month
.clone()
.expose_option()
.get_required_value("expiry_month")?;
let card_exp_year = card
.expiry_year
.clone()
.expose_option()
.get_required_value("expiry_year")?;
let card_holder_name = card
.card_holder_name
.clone()
.expose_option()
.unwrap_or_default();
let value1 = payment_methods::mk_card_value1(
card_number,
card_exp_year,
card_exp_month,
Some(card_holder_name),
None,
None,
None,
)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Error getting Value1 for locker")?;
let value2 = payment_methods::mk_card_value2(
None,
None,
None,
Some(pm.customer_id.to_string()),
Some(pm.payment_method_id.to_string()),
)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Error getting Value2 for locker")?;

let value1 = vault::VaultPaymentMethod::Card(value1);
let value2 = vault::VaultPaymentMethod::Card(value2);

let value1 = utils::Encode::<vault::VaultPaymentMethod>::encode_to_string_of_json(&value1)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Wrapped value1 construction failed when saving card to locker")?;

let value2 = utils::Encode::<vault::VaultPaymentMethod>::encode_to_string_of_json(&value2)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Wrapped value2 construction failed when saving card to locker")?;

let db_value = vault::MockTokenizeDBValue { value1, value2 };

let value_string =
utils::Encode::<vault::MockTokenizeDBValue>::encode_to_string_of_json(&db_value)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable(
"Mock tokenize value construction failed when saving card to locker",
)?;

let db = &*state.store;

let already_present = db.find_config_by_key(payment_token).await;

if already_present.is_err() {
let config = storage::ConfigNew {
key: payment_token.to_string(),
config: value_string,
};

db.insert_config(config)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Mock tokenization save to db failed")?;
} else {
let config_update = storage::ConfigUpdate::Update {
config: Some(value_string),
};

db.update_config_by_key(payment_token, config_update)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Mock tokenization db update failed")?;
}

Ok(card)
}
}

#[cfg(feature = "basilisk")]
impl BasiliskCardSupport {
impl TempLockerCardSupport {
#[instrument(skip_all)]
async fn create_payment_method_data_in_locker(
async fn create_payment_method_data_in_temp_locker(
state: &routes::AppState,
payment_token: &str,
card: api::CardDetailFromLocker,
pm: &storage::PaymentMethod,
merchant_key_store: &domain::MerchantKeyStore,
) -> errors::RouterResult<api::CardDetailFromLocker> {
let card_number = card.card_number.clone().get_required_value("card_number")?;
let card_exp_month = card
Expand Down Expand Up @@ -2343,8 +2258,14 @@ impl BasiliskCardSupport {
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Wrapped value2 construction failed when saving card to locker")?;

let lookup_key =
vault::create_tokenize(state, value1, Some(value2), payment_token.to_string()).await?;
let lookup_key = vault::create_tokenize(
state,
value1,
Some(value2),
payment_token.to_string(),
merchant_key_store.key.get_inner(),
)
.await?;
vault::add_delete_tokenized_data_task(
&*state.store,
&lookup_key,
Expand Down
Loading

0 comments on commit 555b4da

Please sign in to comment.