Skip to content

Commit ebcc587

Browse files
Debarati GhatakDebarati Ghatak
authored andcommitted
feat(core): add additional fields to authentication table
1 parent 96de9f2 commit ebcc587

File tree

26 files changed

+263
-30
lines changed

26 files changed

+263
-30
lines changed

crates/diesel_models/src/authentication.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ pub struct Authentication {
6161
pub browser_info: Option<serde_json::Value>,
6262
pub email: Option<Encryption>,
6363
pub profile_acquirer_id: Option<common_utils::id_type::ProfileAcquirerId>,
64+
pub challenge_code: Option<String>,
65+
pub challenge_cancel: Option<String>,
66+
pub challenge_code_reason: Option<String>,
67+
pub message_extension: Option<serde_json::Value>,
6468
}
6569

6670
impl Authentication {
@@ -121,6 +125,10 @@ pub struct AuthenticationNew {
121125
pub browser_info: Option<serde_json::Value>,
122126
pub email: Option<Encryption>,
123127
pub profile_acquirer_id: Option<common_utils::id_type::ProfileAcquirerId>,
128+
pub challenge_code: Option<String>,
129+
pub challenge_cancel: Option<String>,
130+
pub challenge_code_reason: Option<String>,
131+
pub message_extension: Option<serde_json::Value>,
124132
}
125133

126134
#[derive(Debug)]
@@ -167,11 +175,17 @@ pub enum AuthenticationUpdate {
167175
authentication_status: common_enums::AuthenticationStatus,
168176
ds_trans_id: Option<String>,
169177
eci: Option<String>,
178+
challenge_code: Option<String>,
179+
challenge_cancel: Option<String>,
180+
challenge_code_reason: Option<String>,
181+
message_extension: Option<serde_json::Value>,
170182
},
171183
PostAuthenticationUpdate {
172184
trans_status: common_enums::TransactionStatus,
173185
eci: Option<String>,
174186
authentication_status: common_enums::AuthenticationStatus,
187+
challenge_cancel: Option<String>,
188+
challenge_code_reason: Option<String>,
175189
},
176190
ErrorUpdate {
177191
error_message: Option<String>,
@@ -227,6 +241,10 @@ pub struct AuthenticationUpdateInternal {
227241
pub browser_info: Option<serde_json::Value>,
228242
pub email: Option<Encryption>,
229243
pub profile_acquirer_id: Option<common_utils::id_type::ProfileAcquirerId>,
244+
pub challenge_code: Option<String>,
245+
pub challenge_cancel: Option<String>,
246+
pub challenge_code_reason: Option<String>,
247+
pub message_extension: Option<serde_json::Value>,
230248
}
231249

232250
impl Default for AuthenticationUpdateInternal {
@@ -267,6 +285,10 @@ impl Default for AuthenticationUpdateInternal {
267285
browser_info: Default::default(),
268286
email: Default::default(),
269287
profile_acquirer_id: Default::default(),
288+
challenge_code: Default::default(),
289+
challenge_cancel: Default::default(),
290+
challenge_code_reason: Default::default(),
291+
message_extension: Default::default(),
270292
}
271293
}
272294
}
@@ -309,6 +331,10 @@ impl AuthenticationUpdateInternal {
309331
browser_info,
310332
email,
311333
profile_acquirer_id,
334+
challenge_code,
335+
challenge_cancel,
336+
challenge_code_reason,
337+
message_extension,
312338
} = self;
313339
Authentication {
314340
connector_authentication_id: connector_authentication_id
@@ -350,6 +376,10 @@ impl AuthenticationUpdateInternal {
350376
browser_info: browser_info.or(source.browser_info),
351377
email: email.or(source.email),
352378
profile_acquirer_id: profile_acquirer_id.or(source.profile_acquirer_id),
379+
challenge_code: challenge_code.or(source.challenge_code),
380+
challenge_cancel: challenge_cancel.or(source.challenge_cancel),
381+
challenge_code_reason: challenge_code_reason.or(source.challenge_code_reason),
382+
message_extension: message_extension.or(source.message_extension),
353383
..source
354384
}
355385
}
@@ -438,6 +468,10 @@ impl From<AuthenticationUpdate> for AuthenticationUpdateInternal {
438468
authentication_status,
439469
ds_trans_id,
440470
eci,
471+
challenge_code,
472+
challenge_cancel,
473+
challenge_code_reason,
474+
message_extension,
441475
} => Self {
442476
trans_status: Some(trans_status),
443477
authentication_type: Some(authentication_type),
@@ -450,16 +484,24 @@ impl From<AuthenticationUpdate> for AuthenticationUpdateInternal {
450484
authentication_status: Some(authentication_status),
451485
ds_trans_id,
452486
eci,
487+
challenge_code,
488+
challenge_cancel,
489+
challenge_code_reason,
490+
message_extension,
453491
..Default::default()
454492
},
455493
AuthenticationUpdate::PostAuthenticationUpdate {
456494
trans_status,
457495
eci,
458496
authentication_status,
497+
challenge_cancel,
498+
challenge_code_reason,
459499
} => Self {
460500
trans_status: Some(trans_status),
461501
eci,
462502
authentication_status: Some(authentication_status),
503+
challenge_cancel,
504+
challenge_code_reason,
463505
..Default::default()
464506
},
465507
AuthenticationUpdate::PreAuthenticationVersionCallUpdate {

crates/diesel_models/src/schema.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ diesel::table! {
137137
email -> Nullable<Bytea>,
138138
#[max_length = 128]
139139
profile_acquirer_id -> Nullable<Varchar>,
140+
challenge_code -> Nullable<Varchar>,
141+
challenge_cancel -> Nullable<Varchar>,
142+
challenge_code_reason -> Nullable<Varchar>,
143+
message_extension -> Nullable<Jsonb>,
140144
}
141145
}
142146

crates/diesel_models/src/schema_v2.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ diesel::table! {
137137
email -> Nullable<Bytea>,
138138
#[max_length = 128]
139139
profile_acquirer_id -> Nullable<Varchar>,
140+
challenge_code-> Nullable<Varchar>,
141+
challenge_cancel-> Nullable<Varchar>,
142+
challenge_code_reason-> Nullable<Varchar>,
143+
message_extension->Nullable<Jsonb>,
140144
}
141145
}
142146

crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use error_stack::ResultExt;
1414
use hyperswitch_domain_models::{
1515
address::{AddressDetails, PhoneDetails},
1616
router_flow_types::PoFulfill,
17+
router_request_types::authentication::MessageExtensionAttribute,
1718
router_response_types::PayoutsResponseData,
1819
types::PayoutsRouterData,
1920
};
@@ -393,6 +394,20 @@ pub struct CybersourceConsumerAuthInformation {
393394
pares_status: Option<CybersourceParesStatus>,
394395
//This field is used to send the authentication date in yyyyMMDDHHMMSS format
395396
authentication_date: Option<String>,
397+
/// This field indicates the authentication type or challenge presented to the cardholder at checkout.
398+
challenge_code: Option<String>,
399+
/// This field indicates the reason for payer authentication response status. It is only supported for secure transactions in France.
400+
pares_status_reason: Option<String>,
401+
/// This field indicates the reason why strong authentication was cancelled. It is only supported for secure transactions in France.
402+
challenge_cancel_code: Option<String>,
403+
/// This field indicates the score calculated by the 3D Securing platform. It is only supported for secure transactions in France.
404+
network_score: Option<u32>,
405+
}
406+
407+
#[derive(Debug, Serialize)]
408+
pub enum EffectiveAuthenticationType {
409+
CH,
410+
FR,
396411
}
397412

398413
#[derive(Debug, Serialize)]
@@ -1231,6 +1246,17 @@ fn convert_metadata_to_merchant_defined_info(metadata: Value) -> Vec<MerchantDef
12311246
}
12321247
vector
12331248
}
1249+
fn extract_score_id(message_extensions: &[MessageExtensionAttribute]) -> Option<u32> {
1250+
message_extensions
1251+
.iter()
1252+
.find(|attr| attr.id.ends_with("CB-SCORE"))
1253+
.and_then(|attr| {
1254+
attr.id
1255+
.split('_')
1256+
.next()
1257+
.and_then(|prefix| prefix.trim_start_matches('A').parse::<u32>().ok())
1258+
})
1259+
}
12341260

12351261
impl
12361262
TryFrom<(
@@ -1330,6 +1356,19 @@ impl
13301356
date_time::DateFormat::YYYYMMDDHHmmss,
13311357
)
13321358
.ok();
1359+
let network_score: Option<u32> =
1360+
if ccard.card_network == Some(common_enums::CardNetwork::CartesBancaires) {
1361+
authn_data
1362+
.message_extension
1363+
.clone()
1364+
.and_then(|v| {
1365+
serde_json::from_value::<Vec<MessageExtensionAttribute>>(v).ok()
1366+
})
1367+
.as_ref()
1368+
.and_then(|exts| extract_score_id(exts))
1369+
} else {
1370+
None
1371+
};
13331372
CybersourceConsumerAuthInformation {
13341373
pares_status,
13351374
ucaf_collection_indicator,
@@ -1345,6 +1384,10 @@ impl
13451384
veres_enrolled: Some("Y".to_string()),
13461385
eci_raw: authn_data.eci.clone(),
13471386
authentication_date,
1387+
challenge_code: authn_data.challenge_code.clone(),
1388+
pares_status_reason: authn_data.challenge_code_reason.clone(),
1389+
challenge_cancel_code: authn_data.challenge_cancel.clone(),
1390+
network_score,
13481391
}
13491392
});
13501393

@@ -1429,6 +1472,19 @@ impl
14291472
date_time::DateFormat::YYYYMMDDHHmmss,
14301473
)
14311474
.ok();
1475+
let network_score: Option<u32> =
1476+
if ccard.card_network == Some(common_enums::CardNetwork::CartesBancaires) {
1477+
authn_data
1478+
.message_extension
1479+
.clone()
1480+
.and_then(|v| {
1481+
serde_json::from_value::<Vec<MessageExtensionAttribute>>(v).ok()
1482+
})
1483+
.as_ref()
1484+
.and_then(|exts| extract_score_id(exts))
1485+
} else {
1486+
None
1487+
};
14321488
CybersourceConsumerAuthInformation {
14331489
pares_status,
14341490
ucaf_collection_indicator,
@@ -1444,6 +1500,10 @@ impl
14441500
veres_enrolled: Some("Y".to_string()),
14451501
eci_raw: authn_data.eci.clone(),
14461502
authentication_date,
1503+
challenge_code: authn_data.challenge_code.clone(),
1504+
pares_status_reason: authn_data.challenge_code_reason.clone(),
1505+
challenge_cancel_code: authn_data.challenge_cancel.clone(),
1506+
network_score,
14471507
}
14481508
});
14491509

@@ -1531,6 +1591,20 @@ impl
15311591
date_time::DateFormat::YYYYMMDDHHmmss,
15321592
)
15331593
.ok();
1594+
let network_score: Option<u32> = if token_data.card_network
1595+
== Some(common_enums::CardNetwork::CartesBancaires)
1596+
{
1597+
authn_data
1598+
.message_extension
1599+
.clone()
1600+
.and_then(|v| {
1601+
serde_json::from_value::<Vec<MessageExtensionAttribute>>(v).ok()
1602+
})
1603+
.as_ref()
1604+
.and_then(|exts| extract_score_id(exts))
1605+
} else {
1606+
None
1607+
};
15341608
CybersourceConsumerAuthInformation {
15351609
pares_status,
15361610
ucaf_collection_indicator,
@@ -1546,6 +1620,10 @@ impl
15461620
veres_enrolled: Some("Y".to_string()),
15471621
eci_raw: authn_data.eci.clone(),
15481622
authentication_date,
1623+
challenge_code: authn_data.challenge_code.clone(),
1624+
pares_status_reason: authn_data.challenge_code_reason.clone(),
1625+
challenge_cancel_code: authn_data.challenge_cancel.clone(),
1626+
network_score,
15491627
}
15501628
});
15511629

@@ -1730,6 +1808,10 @@ impl
17301808
veres_enrolled: None,
17311809
eci_raw: None,
17321810
authentication_date: None,
1811+
challenge_code: None,
1812+
pares_status_reason: None,
1813+
challenge_cancel_code: None,
1814+
network_score: None,
17331815
});
17341816

17351817
let merchant_defined_information = item
@@ -1827,6 +1909,10 @@ impl
18271909
veres_enrolled: None,
18281910
eci_raw: None,
18291911
authentication_date: None,
1912+
challenge_code: None,
1913+
pares_status_reason: None,
1914+
challenge_cancel_code: None,
1915+
network_score: None,
18301916
}),
18311917
merchant_defined_information,
18321918
})
@@ -1971,6 +2057,10 @@ impl
19712057
veres_enrolled: None,
19722058
eci_raw: None,
19732059
authentication_date: None,
2060+
challenge_code: None,
2061+
pares_status_reason: None,
2062+
challenge_cancel_code: None,
2063+
network_score: None,
19742064
}),
19752065
merchant_defined_information,
19762066
})
@@ -2172,6 +2262,10 @@ impl TryFrom<&CybersourceRouterData<&PaymentsAuthorizeRouterData>> for Cybersour
21722262
veres_enrolled: None,
21732263
eci_raw: None,
21742264
authentication_date: None,
2265+
challenge_code: None,
2266+
pares_status_reason: None,
2267+
challenge_cancel_code: None,
2268+
network_score: None,
21752269
},
21762270
),
21772271
})

crates/hyperswitch_connectors/src/connectors/gpayments.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ impl
394394
trans_status: response.trans_status.into(),
395395
authentication_value: response.authentication_value,
396396
eci: response.eci,
397+
challenge_cancel: None,
398+
challenge_code_reason: None,
397399
}),
398400
..data.clone()
399401
})

crates/hyperswitch_connectors/src/connectors/gpayments/transformers.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ impl
295295
ds_trans_id: Some(response_auth.ds_trans_id),
296296
connector_metadata: None,
297297
eci: None,
298+
challenge_code: None,
299+
challenge_cancel: None,
300+
challenge_code_reason: None,
301+
message_extension: None,
298302
});
299303
Ok(Self {
300304
response,

crates/hyperswitch_connectors/src/connectors/netcetera.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ impl IncomingWebhook for Netcetera {
220220
.unwrap_or(common_enums::TransactionStatus::InformationOnly),
221221
authentication_value: webhook_body.authentication_value,
222222
eci: webhook_body.eci,
223+
challenge_cancel: webhook_body.challenge_cancel,
224+
challenge_code_reason: webhook_body.trans_status_reason,
223225
})
224226
}
225227
}

crates/hyperswitch_connectors/src/connectors/netcetera/netcetera_types.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,15 +1713,6 @@ pub struct SplitSdkType {
17131713
limited_ind: Option<String>,
17141714
}
17151715

1716-
#[derive(Serialize, Deserialize, Debug, Clone)]
1717-
#[serde(rename_all = "camelCase")]
1718-
pub struct MessageExtensionAttribute {
1719-
id: String,
1720-
name: String,
1721-
criticality_indicator: bool,
1722-
data: String,
1723-
}
1724-
17251716
#[derive(Serialize, Deserialize, Debug, Clone)]
17261717
pub enum ThreeDSReqAuthMethod {
17271718
/// No 3DS Requestor authentication occurred (i.e. cardholder "logged in" as guest)

0 commit comments

Comments
 (0)