Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(router): add an api to migrate the payment method #5186

Merged
merged 28 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1a440dd
feat(router): add an api to migrate the payment method
ShankarSinghC Jul 3, 2024
dcf9fb4
Merge branch 'main' of https://github.com/juspay/hyperswitch into pay…
ShankarSinghC Jul 3, 2024
1fa0c30
chore: run formatter
hyperswitch-bot[bot] Jul 3, 2024
496e480
docs(openapi): re-generate OpenAPI specification
hyperswitch-bot[bot] Jul 3, 2024
0d2cfbb
make the payment method migration api admin api key auth
ShankarSinghC Jul 3, 2024
7f65067
Merge branch 'payment_methods/migration_api' of https://github.com/ju…
ShankarSinghC Jul 3, 2024
e70bbc2
accept masked card as input for the payment method migration
ShankarSinghC Jul 4, 2024
57e3dab
construct additional card info for the payment method being migrated
ShankarSinghC Jul 4, 2024
7398a18
populate card bin details in the save card flow
ShankarSinghC Jul 5, 2024
477937e
add debug logs
ShankarSinghC Jul 5, 2024
429f351
fix clippy errors
ShankarSinghC Jul 5, 2024
ec73369
use network transaction id in the payment method migrate request
ShankarSinghC Jul 5, 2024
a0e1cfa
add validation for the masked card number
ShankarSinghC Jul 8, 2024
40aca36
Merge branch 'main' of https://github.com/juspay/hyperswitch into pay…
ShankarSinghC Jul 8, 2024
b0ce373
address pr comments
ShankarSinghC Jul 8, 2024
5604a12
Merge branch 'main' of https://github.com/juspay/hyperswitch into pay…
ShankarSinghC Jul 8, 2024
4673992
chore: run formatter
hyperswitch-bot[bot] Jul 8, 2024
693c138
docs(openapi): re-generate OpenAPI specification
hyperswitch-bot[bot] Jul 8, 2024
81028df
list customer payment method even if the save to locker is false
ShankarSinghC Jul 9, 2024
052c53f
Merge branch 'main' of https://github.com/juspay/hyperswitch into pay…
ShankarSinghC Jul 9, 2024
bb4c141
chore: run formatter
hyperswitch-bot[bot] Jul 9, 2024
5def39d
Merge branch 'main' of https://github.com/juspay/hyperswitch into pay…
ShankarSinghC Jul 9, 2024
0f39878
Merge branch 'payment_methods/migration_api' of https://github.com/ju…
ShankarSinghC Jul 9, 2024
a0e1195
address pr comments
ShankarSinghC Jul 9, 2024
7067664
Merge branch 'main' of https://github.com/juspay/hyperswitch into pay…
ShankarSinghC Jul 9, 2024
1ab86c6
Merge branch 'main' into payment_methods/migration_api
ShankarSinghC Jul 10, 2024
9bf49b3
address pr comments
ShankarSinghC Jul 10, 2024
882af1c
address pr comments
ShankarSinghC Jul 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -13756,6 +13756,14 @@
}
],
"nullable": true
},
"billing": {
"allOf": [
{
"$ref": "#/components/schemas/Address"
}
],
"nullable": true
}
},
"additionalProperties": false
Expand Down
2 changes: 2 additions & 0 deletions crates/api_models/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,8 @@ pub struct ConnectorAgnosticMitChoice {

impl common_utils::events::ApiEventMetric for ConnectorAgnosticMitChoice {}

impl common_utils::events::ApiEventMetric for payment_methods::PaymentMethodMigrate {}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ExtendedCardInfoConfig {
/// Merchant public key
Expand Down
165 changes: 165 additions & 0 deletions crates/api_models/src/payment_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,134 @@ pub struct PaymentMethodCreate {
/// Payment method data to be passed in case of client
/// based flow
pub payment_method_data: Option<PaymentMethodCreateData>,

/// The billing details of the payment method
#[schema(value_type = Option<Address>)]
pub billing: Option<payments::Address>,

#[serde(skip_deserializing)]
/// The connector mandate details of the payment method, this is added only for cards migration
/// api and is skipped during deserialization of the payment method create request as this
/// it should not be passed in the request
pub connector_mandate_details: Option<PaymentsMandateReference>,

#[serde(skip_deserializing)]
/// The transaction id of a CIT (customer initiated transaction) associated with the payment method,
/// this is added only for cards migration api and is skipped during deserialization of the
/// payment method create request as it should not be passed in the request
pub network_transaction_id: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
/// This struct is only used by and internal api to migrate payment method
pub struct PaymentMethodMigrate {
/// Merchant id
pub merchant_id: String,

/// The type of payment method use for the payment.
pub payment_method: Option<api_enums::PaymentMethod>,

/// This is a sub-category of payment method.
pub payment_method_type: Option<api_enums::PaymentMethodType>,

/// The name of the bank/ provider issuing the payment method to the end user
pub payment_method_issuer: Option<String>,

/// A standard code representing the issuer of payment method
pub payment_method_issuer_code: Option<api_enums::PaymentMethodIssuerCode>,

/// Card Details
pub card: Option<MigrateCardDetail>,

/// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
pub metadata: Option<pii::SecretSerdeValue>,

/// The unique identifier of the customer.
pub customer_id: Option<id_type::CustomerId>,

/// The card network
pub card_network: Option<String>,

/// Payment method details from locker
#[cfg(feature = "payouts")]
pub bank_transfer: Option<payouts::Bank>,

/// Payment method details from locker
#[cfg(feature = "payouts")]
pub wallet: Option<payouts::Wallet>,

/// For Client based calls, SDK will use the client_secret
/// in order to call /payment_methods
/// Client secret will be generated whenever a new
/// payment method is created
pub client_secret: Option<String>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is suppose to be server to server right? so client_secret is not required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes correct, as client secret is only required while adding a payment method through sdk it can be removed in this migration api.


/// Payment method data to be passed in case of client
/// based flow
pub payment_method_data: Option<PaymentMethodCreateData>,

/// The billing details of the payment method
pub billing: Option<payments::Address>,

/// The connector mandate details of the payment method
pub connector_mandate_details: Option<PaymentsMandateReference>,

// The CIT (customer initiated transaction) transaction id associated with the payment method
pub network_transaction_id: Option<String>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaymentsMandateReference(pub HashMap<String, PaymentsMandateReferenceRecord>);

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaymentsMandateReferenceRecord {
pub connector_mandate_id: String,
pub payment_method_type: Option<common_enums::PaymentMethodType>,
pub original_payment_authorized_amount: Option<i64>,
pub original_payment_authorized_currency: Option<common_enums::Currency>,
}

impl PaymentMethodCreate {
pub fn get_payment_method_create_from_payment_method_migrate(
card_number: CardNumber,
payment_method_migrate: &PaymentMethodMigrate,
) -> Self {
let card_details =
payment_method_migrate
.card
.as_ref()
.map(|payment_method_migrate_card| CardDetail {
card_number,
card_exp_month: payment_method_migrate_card.card_exp_month.clone(),
card_exp_year: payment_method_migrate_card.card_exp_year.clone(),
card_holder_name: payment_method_migrate_card.card_holder_name.clone(),
nick_name: payment_method_migrate_card.nick_name.clone(),
card_issuing_country: payment_method_migrate_card.card_issuing_country.clone(),
card_network: payment_method_migrate_card.card_network.clone(),
card_issuer: payment_method_migrate_card.card_issuer.clone(),
card_type: payment_method_migrate_card.card_type.clone(),
});

Self {
customer_id: payment_method_migrate.customer_id.clone(),
payment_method: payment_method_migrate.payment_method,
payment_method_type: payment_method_migrate.payment_method_type,
payment_method_issuer: payment_method_migrate.payment_method_issuer.clone(),
payment_method_issuer_code: payment_method_migrate.payment_method_issuer_code,
metadata: payment_method_migrate.metadata.clone(),
payment_method_data: payment_method_migrate.payment_method_data.clone(),
connector_mandate_details: payment_method_migrate.connector_mandate_details.clone(),
client_secret: payment_method_migrate.client_secret.clone(),
billing: payment_method_migrate.billing.clone(),
card: card_details,
card_network: payment_method_migrate.card_network.clone(),
#[cfg(feature = "payouts")]
bank_transfer: payment_method_migrate.bank_transfer.clone(),
#[cfg(feature = "payouts")]
wallet: payment_method_migrate.wallet.clone(),
network_transaction_id: payment_method_migrate.network_transaction_id.clone(),
}
}
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
Expand Down Expand Up @@ -139,6 +267,43 @@ pub struct CardDetail {
pub card_type: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct MigrateCardDetail {
/// Card Number
#[schema(value_type = String,example = "4111111145551142")]
pub card_number: String,
ShankarSinghC marked this conversation as resolved.
Show resolved Hide resolved

/// Card Expiry Month
#[schema(value_type = String,example = "10")]
pub card_exp_month: masking::Secret<String>,

/// Card Expiry Year
#[schema(value_type = String,example = "25")]
pub card_exp_year: masking::Secret<String>,

/// Card Holder Name
#[schema(value_type = String,example = "John Doe")]
pub card_holder_name: Option<masking::Secret<String>>,

/// Card Holder's Nick Name
#[schema(value_type = Option<String>,example = "John Doe")]
pub nick_name: Option<masking::Secret<String>>,

/// Card Issuing Country
pub card_issuing_country: Option<String>,

/// Card's Network
#[schema(value_type = Option<CardNetwork>)]
pub card_network: Option<api_enums::CardNetwork>,

/// Issuer Bank for Card
pub card_issuer: Option<String>,

/// Card Type
pub card_type: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct CardDetailUpdate {
Expand Down
3 changes: 3 additions & 0 deletions crates/router/src/core/locker_migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ pub async fn call_to_locker(
card_network: card.card_brand,
client_secret: None,
payment_method_data: None,
billing: None,
connector_mandate_details: None,
network_transaction_id: None,
};

let add_card_result = cards::add_card_hs(
Expand Down
Loading
Loading