-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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): [BOA] implement mandates for cards and wallets #4232
Conversation
action_list, | ||
action_token_types, | ||
authorization_options, | ||
commerce_indicator: String::from("internet"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consult @deepanshu-iiitu on hard-coding of commerce_indicator for BoA production sanity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For apple pay payments, the commerce indicator needs to be specific to the card network.
In line |
incremental_authorization_allowed: Some( | ||
mandate_status == enums::AttemptStatus::Authorized, | ||
), | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incremental Authorization is not implemented for BOA. Please put this value as none.
let is_setup_mandate_payment = item.router_data.request.is_setup_mandate_payment(); | ||
|
||
let capture = Some( | ||
!((is_setup_mandate_payment && is_capture_automatic) | ||
|| (!is_setup_mandate_payment && !is_capture_automatic)), | ||
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check this logic and maybe try to keep this logic at connector level on the basis of amount.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AkshayaFoiger Avoid duplicating code and try to reuse the code by having from, try_from impl
commerce_indicator, | ||
consumer_authentication_information, | ||
) = match item.request.payment_method_data.clone() { | ||
api::PaymentMethodData::Card(ccard) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Break the impl for cards and wallets into smaller from & try_from. Keep the code modular and readable
let email = item.router_data.request.get_email()?; | ||
let bill_to = | ||
build_bill_to(item.router_data.get_billing()?, email)?; | ||
let order_information = | ||
OrderInformationWithBill::from((item, bill_to)); | ||
let processing_information = | ||
ProcessingInformation::try_from(( | ||
item, | ||
Some(PaymentSolution::ApplePay), | ||
Some(apple_pay_data.payment_method.network.clone()), | ||
))?; | ||
let client_reference_information = | ||
ClientReferenceInformation::from(item); | ||
let payment_information = PaymentInformation::ApplePayToken( | ||
ApplePayTokenPaymentInformation { | ||
fluid_data: FluidData { | ||
value: Secret::from(apple_pay_data.payment_data), | ||
}, | ||
tokenized_card: ApplePayTokenizedCard { | ||
transaction_type: TransactionType::ApplePay, | ||
}, | ||
}, | ||
); | ||
let merchant_defined_information = | ||
item.router_data.request.metadata.clone().map(|metadata| { | ||
Vec::<MerchantDefinedInformation>::foreign_from( | ||
metadata.peek().to_owned(), | ||
) | ||
}); | ||
let ucaf_collection_indicator = match apple_pay_data | ||
.payment_method | ||
.network | ||
.to_lowercase() | ||
.as_str() | ||
{ | ||
"mastercard" => Some("2".to_string()), | ||
_ => None, | ||
}; | ||
Ok(Self { | ||
processing_information, | ||
payment_information, | ||
order_information, | ||
merchant_defined_information, | ||
client_reference_information, | ||
consumer_authentication_information: Some( | ||
BankOfAmericaConsumerAuthInformation { | ||
ucaf_collection_indicator, | ||
cavv: None, | ||
ucaf_authentication_data: None, | ||
xid: None, | ||
directory_server_transaction_id: None, | ||
specification_version: None, | ||
}, | ||
), | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, move this to from or try_from impl
let error_reason = error_response | ||
.error_information | ||
.message | ||
.to_owned() | ||
.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()); | ||
let error_message = error_response.error_information.reason.to_owned(); | ||
let response = Err(types::ErrorResponse { | ||
code: error_message | ||
.clone() | ||
.unwrap_or(consts::NO_ERROR_CODE.to_string()), | ||
message: error_message.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), | ||
reason: Some(error_reason), | ||
status_code: item.http_code, | ||
attempt_status: None, | ||
connector_transaction_id: Some(error_response.id.clone()), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are rewriting this logic in multiple places, why can't we handle it in a from impl here and wherever BankOfAmericaErrorInformation -> ErrorResponse?
1143fca
Type of Change
Description
Implement zero auth and non-zero auth mandates for card and wallet (Googlepay and Applepay)
Test Cases
a. Create a customer initiated transaction
three_ds_type =
no_three_ds
andthree_ds
capture_method =
automatic
andmanual
Response
b. Create a merchant initiated transaction
Response
{
"payment_id": "pay_780HcHAxkY7TwXAP1Iap",
"merchant_id": "merchant_1711534931",
"status": "succeeded",
"amount": 700,
"net_amount": 700,
"amount_capturable": 0,
"amount_received": 700,
"connector": "bankofamerica",
"client_secret": "pay_6pzAF0lBIhs3QaTxDNYC_secret_k1PSnHM3Zi7Mr9nr5Pth",
"created": "2024-03-27T10:46:17.199Z",
"currency": "USD",
"customer_id": "CustomerX",
"description": "Initiated by merchant",
"refunds": null,
"disputes": null,
"mandate_id": "man_Tbk17RquWB6pVvYqOh9r",
"mandate_data": null,
"setup_future_usage": null,
"off_session": null,
"capture_on": null,
"capture_method": "automatic",
"payment_method": "wallet",
"payment_method_data": null,
"payment_token": null,
"shipping": null,
"billing": {
"address": {
"city": "San Fransico",
"country": "US",
"line1": "1467",
"line2": "Harrison Street",
"line3": "Harrison Street",
"zip": "94122",
"state": "California",
"first_name": "John",
"last_name": "Doe"
},
"phone": null,
"email": null
},
"order_details": null,
"email": "[email protected]",
"name": "John Doe",
"phone": "999999999",
"return_url": null,
"authentication_type": "no_three_ds",
"statement_descriptor_name": null,
"statement_descriptor_suffix": null,
"next_action": null,
"cancellation_reason": null,
"error_code": null,
"error_message": null,
"unified_code": null,
"unified_message": null,
"payment_experience": null,
"payment_method_type": "google_pay",
"connector_label": null,
"business_country": null,
"business_label": "default",
"business_sub_label": null,
"allowed_payment_method_types": null,
"ephemeral_key": {
"customer_id": "CustomerX",
"created_at": 1711536377,
"expires": 1711539977,
"secret": "epk_dc15cccfe220420db145d6a5b7c685ed"
},
"manual_retry_allowed": false,
"connector_transaction_id": "7115351119116878404954",
"frm_message": null,
"metadata": null,
"connector_metadata": null,
"feature_metadata": null,
"reference_id": "pay_6pzAF0lBIhs3QaTxDNYC_1",
"payment_link": null,
"profile_id": "pro_i1Wo0aXT2i3N9PFvlykZ",
"surcharge_details": null,
"attempt_count": 1,
"merchant_decision": null,
"merchant_connector_id": "mca_yo3dWvdwsZXGwKrq1GIu",
"incremental_authorization_allowed": null,
"authorization_count": null,
"incremental_authorizations": null,
"external_authentication_details": null,
"external_3ds_authentication_attempted": false,
"expires_on": "2024-03-27T11:01:17.199Z",
"fingerprint": null,
"payment_method_id": null,
"payment_method_status": null
}
2. Google mandate payment in Bank Of America
a. Create a customer initiated transaction
Response
b. Create a merchant initiated transaction
Response
a. Setup Intent
Response
b. MIT
Response
4.Setup mandate with Bank of America googlepay
a.Create a setup mandate
Response
b. Create a MIT
Response
capture_method =
automatic
andmanual
three_ds_type =
no_three_ds
andthree_ds
Response
Response
Note: Mandates Mit, must be tested with the new payment_method_id flow. Additionally, Mandates 3ds is not working for Cybersource and with this PR for BOA too. An issue regarding this is raised.
Checklist
cargo +nightly fmt --all
cargo clippy