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(core): Move RouterData to crate hyperswitch_domain_models #4524

Merged
merged 24 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
eb0bca7
feat(core): Move RouterData to crate hyperswitch_domain_models
deepanshu-iiitu May 2, 2024
27ce1d5
chore: Resolve Errors Part 1
deepanshu-iiitu May 10, 2024
36e842b
chore: Resolve errors
deepanshu-iiitu May 14, 2024
dbf34c0
Merge branch 'main' into move_routerdata
deepanshu-iiitu May 14, 2024
5e5e133
chore: Resolve errors
deepanshu-iiitu May 14, 2024
f7b0ab3
chore: Resolve errors
deepanshu-iiitu May 14, 2024
4c2429f
chore: run formatter
hyperswitch-bot[bot] May 14, 2024
27f6957
chore: Reolve errors
deepanshu-iiitu May 14, 2024
d31958b
chore: Resolve clippy errors
deepanshu-iiitu May 14, 2024
4ac833a
chore: Resolve clippy errors 2
deepanshu-iiitu May 14, 2024
32cb373
chore:[CONNECTOR] Fix template code generation
deepanshu-iiitu May 14, 2024
ef33878
chore: Discard changes in connector tests
deepanshu-iiitu May 14, 2024
dfb501d
chore: Discard Extra Changes
deepanshu-iiitu May 14, 2024
95db74c
chore: Reuse old code
deepanshu-iiitu May 14, 2024
16fe722
chore: Fix compile time errors
deepanshu-iiitu May 14, 2024
b2dcac2
Merge branch 'main' into move_routerdata
deepanshu-iiitu May 14, 2024
5c134c5
chore: Fix warnings
deepanshu-iiitu May 14, 2024
d826b1b
chore: Resolve PR Comments
deepanshu-iiitu May 14, 2024
f18d818
chore: Resolve Clippy errors from PR Comments
deepanshu-iiitu May 14, 2024
152d3a6
Merge branch 'main' into move_routerdata
deepanshu-iiitu May 14, 2024
f5104ca
chore: Fix compilation errors
deepanshu-iiitu May 14, 2024
5a5faf9
chore: Resolve PR Comments 2
deepanshu-iiitu May 14, 2024
bcdf887
chore: Resolve Cargo Check Warnings
deepanshu-iiitu May 14, 2024
c85492a
chore: Resolve Cargo Check Warnings 2
deepanshu-iiitu May 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion connector-template/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use masking::ExposeInterface;
use crate::{
events::connector_api_logs::ConnectorEvent,
configs::settings,
utils::{self, BytesExt},
utils::BytesExt,
core::{
errors::{self, CustomResult},
},
Expand Down
4 changes: 2 additions & 2 deletions connector-template/transformers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
use masking::Secret;
use crate::{connector::utils::{PaymentsAuthorizeRequestData},core::errors,types::{self,api, storage::enums}};
use crate::{connector::utils::{PaymentsAuthorizeRequestData},core::errors,types::{self, domain, api, storage::enums}};

//TODO: Fill the struct with respective fields
pub struct {{project-name | downcase | pascal_case}}RouterData<T> {
Expand Down Expand Up @@ -53,7 +53,7 @@ impl TryFrom<&{{project-name | downcase | pascal_case}}RouterData<&types::Paymen
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &{{project-name | downcase | pascal_case}}RouterData<&types::PaymentsAuthorizeRouterData>) -> Result<Self,Self::Error> {
match item.router_data.request.payment_method_data.clone() {
api::PaymentMethodData::Card(req_card) => {
domain::PaymentMethodData::Card(req_card) => {
let card = {{project-name | downcase | pascal_case}}Card {
number: req_card.card_number,
expiry_month: req_card.card_exp_month,
Expand Down
1 change: 1 addition & 0 deletions crates/hyperswitch_domain_models/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ diesel_models = { version = "0.1.0", path = "../diesel_models", features = ["kv_
# Third party deps
async-trait = "0.1.79"
error-stack = "0.4.1"
http = "0.2.12"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
thiserror = "1.0.58"
Expand Down
2 changes: 2 additions & 0 deletions crates/hyperswitch_domain_models/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
pub mod errors;
pub mod mandates;
pub mod payment_address;
pub mod payments;
#[cfg(feature = "payouts")]
pub mod payouts;
pub mod router_data;

#[cfg(not(feature = "payouts"))]
pub trait PayoutAttemptInterface {}
Expand Down
82 changes: 82 additions & 0 deletions crates/hyperswitch_domain_models/src/payment_address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use api_models::payments::Address;

#[derive(Clone, Default, Debug)]
pub struct PaymentAddress {
shipping: Option<Address>,
billing: Option<Address>,
unified_payment_method_billing: Option<Address>,
payment_method_billing: Option<Address>,
}

impl PaymentAddress {
pub fn new(
shipping: Option<Address>,
billing: Option<Address>,
payment_method_billing: Option<Address>,
should_unify_address: Option<bool>,
) -> Self {
// billing -> .billing, this is the billing details passed in the root of payments request
// payment_method_billing -> .payment_method_data.billing

let unified_payment_method_billing = if should_unify_address.unwrap_or(true) {
// Merge the billing details field from both `payment.billing` and `payment.payment_method_data.billing`
// The unified payment_method_billing will be used as billing address and passed to the connector module
// This unification is required in order to provide backwards compatibility
// so that if `payment.billing` is passed it should be sent to the connector module
// Unify the billing details with `payment_method_data.billing`
payment_method_billing
.as_ref()
.map(|payment_method_billing| {
payment_method_billing
.clone()
.unify_address(billing.as_ref())
})
.or(billing.clone())
} else {
payment_method_billing.clone()
};

Self {
shipping,
billing,
unified_payment_method_billing,
payment_method_billing,
}
}

pub fn get_shipping(&self) -> Option<&Address> {
self.shipping.as_ref()
}

pub fn get_payment_method_billing(&self) -> Option<&Address> {
self.unified_payment_method_billing.as_ref()
}

/// Unify the billing details from `payment_method_data.[payment_method_data].billing details`.
pub fn unify_with_payment_method_data_billing(
self,
payment_method_data_billing: Option<Address>,
) -> Self {
// Unify the billing details with `payment_method_data.billing_details`
let unified_payment_method_billing = payment_method_data_billing
.map(|payment_method_data_billing| {
payment_method_data_billing.unify_address(self.get_payment_method_billing())
})
.or(self.get_payment_method_billing().cloned());

Self {
shipping: self.shipping,
billing: self.billing,
unified_payment_method_billing,
payment_method_billing: self.payment_method_billing,
}
}

pub fn get_request_payment_method_billing(&self) -> Option<&Address> {
self.payment_method_billing.as_ref()
}

pub fn get_payment_billing(&self) -> Option<&Address> {
self.billing.as_ref()
}
}
207 changes: 207 additions & 0 deletions crates/hyperswitch_domain_models/src/router_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
use std::{collections::HashMap, marker::PhantomData};

use masking::Secret;

use crate::payment_address::PaymentAddress;

#[derive(Debug, Clone)]
pub struct RouterData<Flow, Request, Response> {
pub flow: PhantomData<Flow>,
pub merchant_id: String,
pub customer_id: Option<String>,
pub connector_customer: Option<String>,
pub connector: String,
pub payment_id: String,
pub attempt_id: String,
pub status: common_enums::enums::AttemptStatus,
pub payment_method: common_enums::enums::PaymentMethod,
pub connector_auth_type: ConnectorAuthType,
pub description: Option<String>,
pub return_url: Option<String>,
pub address: PaymentAddress,
pub auth_type: common_enums::enums::AuthenticationType,
pub connector_meta_data: Option<common_utils::pii::SecretSerdeValue>,
pub amount_captured: Option<i64>,
pub access_token: Option<AccessToken>,
pub session_token: Option<String>,
pub reference_id: Option<String>,
pub payment_method_token: Option<PaymentMethodToken>,
pub recurring_mandate_payment_data: Option<RecurringMandatePaymentData>,
pub preprocessing_id: Option<String>,
/// This is the balance amount for gift cards or voucher
pub payment_method_balance: Option<PaymentMethodBalance>,

///for switching between two different versions of the same connector
pub connector_api_version: Option<String>,

/// Contains flow-specific data required to construct a request and send it to the connector.
pub request: Request,

/// Contains flow-specific data that the connector responds with.
pub response: Result<Response, ErrorResponse>,

/// Contains a reference ID that should be sent in the connector request
pub connector_request_reference_id: String,

#[cfg(feature = "payouts")]
/// Contains payout method data
pub payout_method_data: Option<api_models::payouts::PayoutMethodData>,

#[cfg(feature = "payouts")]
/// Contains payout's quote ID
pub quote_id: Option<String>,

pub test_mode: Option<bool>,
pub connector_http_status_code: Option<u16>,
pub external_latency: Option<u128>,
/// Contains apple pay flow type simplified or manual
pub apple_pay_flow: Option<common_enums::enums::ApplePayFlow>,

pub frm_metadata: Option<serde_json::Value>,

pub dispute_id: Option<String>,
pub refund_id: Option<String>,

/// This field is used to store various data regarding the response from connector
pub connector_response: Option<ConnectorResponseData>,
pub payment_method_status: Option<common_enums::PaymentMethodStatus>,
}

// Different patterns of authentication.
#[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(tag = "auth_type")]
pub enum ConnectorAuthType {
TemporaryAuth,
HeaderKey {
api_key: Secret<String>,
},
BodyKey {
api_key: Secret<String>,
key1: Secret<String>,
},
SignatureKey {
api_key: Secret<String>,
key1: Secret<String>,
api_secret: Secret<String>,
},
MultiAuthKey {
api_key: Secret<String>,
key1: Secret<String>,
api_secret: Secret<String>,
key2: Secret<String>,
},
CurrencyAuthKey {
auth_key_map: HashMap<common_enums::enums::Currency, common_utils::pii::SecretSerdeValue>,
},
CertificateAuth {
certificate: Secret<String>,
private_key: Secret<String>,
},
#[default]
NoKey,
}

#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
pub struct AccessToken {
pub token: Secret<String>,
pub expires: i64,
}

#[derive(Debug, Clone, serde::Deserialize)]
pub enum PaymentMethodToken {
Token(Secret<String>),
ApplePayDecrypt(Box<ApplePayPredecryptData>),
}

#[derive(Debug, Clone, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplePayPredecryptData {
pub application_primary_account_number: Secret<String>,
pub application_expiration_date: String,
pub currency_code: String,
pub transaction_amount: i64,
pub device_manufacturer_identifier: Secret<String>,
pub payment_data_type: Secret<String>,
pub payment_data: ApplePayCryptogramData,
}

#[derive(Debug, Clone, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplePayCryptogramData {
pub online_payment_cryptogram: Secret<String>,
pub eci_indicator: Option<String>,
}

#[derive(Debug, Default, Clone)]
pub struct RecurringMandatePaymentData {
pub payment_method_type: Option<common_enums::enums::PaymentMethodType>, //required for making recurring payment using saved payment method through stripe
pub original_payment_authorized_amount: Option<i64>,
pub original_payment_authorized_currency: Option<common_enums::enums::Currency>,
}

#[derive(Debug, Clone)]
pub struct PaymentMethodBalance {
pub amount: i64,
pub currency: common_enums::enums::Currency,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ConnectorResponseData {
pub additional_payment_method_data: Option<AdditionalPaymentMethodConnectorResponse>,
}

impl ConnectorResponseData {
pub fn with_additional_payment_method_data(
additional_payment_method_data: AdditionalPaymentMethodConnectorResponse,
) -> Self {
Self {
additional_payment_method_data: Some(additional_payment_method_data),
}
}
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum AdditionalPaymentMethodConnectorResponse {
Card {
/// Details regarding the authentication details of the connector, if this is a 3ds payment.
authentication_data: Option<serde_json::Value>,
/// Various payment checks that are done for a payment
payment_checks: Option<serde_json::Value>,
},
}

#[derive(Clone, Debug, serde::Serialize)]
pub struct ErrorResponse {
pub code: String,
pub message: String,
pub reason: Option<String>,
pub status_code: u16,
pub attempt_status: Option<common_enums::enums::AttemptStatus>,
pub connector_transaction_id: Option<String>,
}

impl Default for ErrorResponse {
fn default() -> Self {
Self {
code: "HE_00".to_string(),
message: "Something went wrong".to_string(),
reason: None,
status_code: http::StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
attempt_status: None,
connector_transaction_id: None,
}
}
}

impl ErrorResponse {
pub fn get_not_implemented() -> Self {
Self {
code: "IR_00".to_string(),
message: "This API is under development and will be made available soon.".to_string(),
reason: None,
status_code: http::StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
attempt_status: None,
connector_transaction_id: None,
}
}
}
10 changes: 5 additions & 5 deletions crates/router/src/connector/adyen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
self,
api::{self, ConnectorCommon},
domain,
transformers::ForeignFrom,
transformers::{ForeignFrom, ForeignTryFrom},
},
utils::{crypto, ByteSliceExt, BytesExt, OptionExt},
};
Expand Down Expand Up @@ -364,7 +364,7 @@ impl
req: &types::SetupMandateRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let authorize_req = types::PaymentsAuthorizeRouterData::from((
let authorize_req = types::PaymentsAuthorizeRouterData::foreign_from((
req,
types::PaymentsAuthorizeData::from(req),
));
Expand Down Expand Up @@ -419,7 +419,7 @@ impl
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
types::RouterData::try_from((
types::RouterData::foreign_try_from((
types::ResponseRouterData {
response,
data: data.clone(),
Expand Down Expand Up @@ -703,7 +703,7 @@ impl
types::SyncRequestType::MultipleCaptureSync(_) => true,
types::SyncRequestType::SinglePaymentSync => false,
};
types::RouterData::try_from((
types::RouterData::foreign_try_from((
types::ResponseRouterData {
response,
data: data.clone(),
Expand Down Expand Up @@ -830,7 +830,7 @@ impl
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
types::RouterData::try_from((
types::RouterData::foreign_try_from((
types::ResponseRouterData {
response,
data: data.clone(),
Expand Down