refactor(router): store network_transaction_id for off_session payments irrespective of the is_connector_agnostic_mit_enabled config (#7083)

Co-authored-by: Gnanasundari24 <118818938+Gnanasundari24@users.noreply.github.com>
Co-authored-by: Pa1NarK <69745008+pixincreate@users.noreply.github.com>
This commit is contained in:
Shankar Singh C
2025-02-06 15:57:34 +05:30
committed by GitHub
parent c044ffff0c
commit f9a4713a60
3 changed files with 410 additions and 50 deletions

View File

@ -576,7 +576,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSyncData> for
merchant_account: &domain::MerchantAccount, merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore, key_store: &domain::MerchantKeyStore,
payment_data: &mut PaymentData<F>, payment_data: &mut PaymentData<F>,
business_profile: &domain::Profile, _business_profile: &domain::Profile,
) -> CustomResult<(), errors::ApiErrorResponse> ) -> CustomResult<(), errors::ApiErrorResponse>
where where
F: 'b + Clone + Send + Sync, F: 'b + Clone + Send + Sync,
@ -617,7 +617,6 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSyncData> for
resp.status, resp.status,
resp.response.clone(), resp.response.clone(),
merchant_account.storage_scheme, merchant_account.storage_scheme,
business_profile.is_connector_agnostic_mit_enabled,
) )
.await?; .await?;
Ok(()) Ok(())
@ -1201,7 +1200,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::CompleteAuthorizeData
merchant_account: &domain::MerchantAccount, merchant_account: &domain::MerchantAccount,
key_store: &domain::MerchantKeyStore, key_store: &domain::MerchantKeyStore,
payment_data: &mut PaymentData<F>, payment_data: &mut PaymentData<F>,
business_profile: &domain::Profile, _business_profile: &domain::Profile,
) -> CustomResult<(), errors::ApiErrorResponse> ) -> CustomResult<(), errors::ApiErrorResponse>
where where
F: 'b + Clone + Send + Sync, F: 'b + Clone + Send + Sync,
@ -1241,7 +1240,6 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::CompleteAuthorizeData
resp.status, resp.status,
resp.response.clone(), resp.response.clone(),
merchant_account.storage_scheme, merchant_account.storage_scheme,
business_profile.is_connector_agnostic_mit_enabled,
) )
.await?; .await?;
Ok(()) Ok(())
@ -2068,7 +2066,6 @@ async fn update_payment_method_status_and_ntid<F: Clone>(
attempt_status: common_enums::AttemptStatus, attempt_status: common_enums::AttemptStatus,
payment_response: Result<types::PaymentsResponseData, ErrorResponse>, payment_response: Result<types::PaymentsResponseData, ErrorResponse>,
storage_scheme: enums::MerchantStorageScheme, storage_scheme: enums::MerchantStorageScheme,
is_connector_agnostic_mit_enabled: Option<bool>,
) -> RouterResult<()> { ) -> RouterResult<()> {
todo!() todo!()
} }
@ -2084,7 +2081,6 @@ async fn update_payment_method_status_and_ntid<F: Clone>(
attempt_status: common_enums::AttemptStatus, attempt_status: common_enums::AttemptStatus,
payment_response: Result<types::PaymentsResponseData, ErrorResponse>, payment_response: Result<types::PaymentsResponseData, ErrorResponse>,
storage_scheme: enums::MerchantStorageScheme, storage_scheme: enums::MerchantStorageScheme,
is_connector_agnostic_mit_enabled: Option<bool>,
) -> RouterResult<()> { ) -> RouterResult<()> {
// If the payment_method is deleted then ignore the error related to retrieving payment method // If the payment_method is deleted then ignore the error related to retrieving payment method
// This should be handled when the payment method is soft deleted // This should be handled when the payment method is soft deleted
@ -2119,13 +2115,11 @@ async fn update_payment_method_status_and_ntid<F: Clone>(
}) })
.ok() .ok()
.flatten(); .flatten();
let network_transaction_id = let network_transaction_id = if payment_data.payment_intent.setup_future_usage
if let Some(network_transaction_id) = pm_resp_network_transaction_id {
if is_connector_agnostic_mit_enabled == Some(true)
&& payment_data.payment_intent.setup_future_usage
== Some(diesel_models::enums::FutureUsage::OffSession) == Some(diesel_models::enums::FutureUsage::OffSession)
{ {
Some(network_transaction_id) if pm_resp_network_transaction_id.is_some() {
pm_resp_network_transaction_id
} else { } else {
logger::info!("Skip storing network transaction id"); logger::info!("Skip storing network transaction id");
None None

View File

@ -111,12 +111,11 @@ where
}; };
let network_transaction_id = let network_transaction_id =
if let Some(network_transaction_id) = network_transaction_id { if save_payment_method_data.request.get_setup_future_usage()
if business_profile.is_connector_agnostic_mit_enabled == Some(true)
&& save_payment_method_data.request.get_setup_future_usage()
== Some(storage_enums::FutureUsage::OffSession) == Some(storage_enums::FutureUsage::OffSession)
{ {
Some(network_transaction_id) if network_transaction_id.is_some() {
network_transaction_id
} else { } else {
logger::info!("Skip storing network transaction id"); logger::info!("Skip storing network transaction id");
None None

View File

@ -13,13 +13,38 @@ Flow:
- Make a Payment - Make a Payment
- List Payment Method for Customer using Client Secret (will get PMID) - List Payment Method for Customer using Client Secret (will get PMID)
- Create Business Profile with connector agnostic feature enabled - Create Business Profile with connector agnostic feature disabled
- Create Merchant Connector Account - Create Merchant Connector Account
- Create Payment Intent - Create Payment Intent
- List Payment Method for Customer -- Empty list; i.e., no payment method should be listed - List Payment Method for Customer -- Empty list; i.e., no payment method should be listed
- Confirm Payment with PMID from previous step (should fail as Connector Mandate ID is not present in the newly created Profile) - Confirm Payment with PMID from previous step (should fail as Connector Mandate ID is not present in the newly created Profile)
- Create Business Profile with connector agnostic feature enabled
- Create Merchant Connector Account and Customer
- Make a Payment
- List Payment Method for Customer using Client Secret (will get PMID)
- Create Business Profile with connector agnostic feature disabled
- Create Merchant Connector Account
- Create Payment Intent
- List Payment Method for Customer -- Empty list; i.e., no payment method should be listed
- Confirm Payment with PMID from previous step (should fail as Connector Mandate ID is not present in the newly created Profile)
- Create Business Profile with connector agnostic feature disabled
- Create Merchant Connector Account and Customer
- Make a Payment
- List Payment Method for Customer using Client Secret (will get PMID)
- Create Business Profile with connector agnostic feature enabled
- Create Merchant Connector Account
- Create Payment Intent
- List Payment Method for Customer using Client Secret (will get PMID which is same as the one from previous step along with Payment Token)
- Confirm Payment with PMID from previous step (should pass as NTID is present in the DB)
- Create Business Profile with connector agnostic feature enabled - Create Business Profile with connector agnostic feature enabled
- Create Merchant Connector Account and Customer - Create Merchant Connector Account and Customer
- Make a Payment - Make a Payment
@ -62,6 +87,371 @@ describe("Connector Agnostic Tests", () => {
after("flush global state", () => { after("flush global state", () => {
cy.task("setGlobalState", globalState.data); cy.task("setGlobalState", globalState.data);
}); });
context(
"Connector Agnostic Disabled for both Profile 1 and Profile 2",
() => {
let shouldContinue = true;
beforeEach(function () {
if (!shouldContinue) {
this.skip();
}
});
it("Create business profile", () => {
utils.createBusinessProfile(
fixtures.businessProfile.bpCreate,
globalState
);
});
it("Create merchant connector account", () => {
utils.createMerchantConnectorAccount(
"payment_processor",
fixtures.createConnectorBody,
globalState,
payment_methods_enabled
);
});
it("Create Customer", () => {
cy.createCustomerCallTest(fixtures.customerCreateBody, globalState);
});
it("Create Payment Intent", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["PaymentIntentOffSession"];
cy.createPaymentIntentTest(
fixtures.createPaymentBody,
data,
"no_three_ds",
"automatic",
globalState
);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
it("Confirm Payment", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["SaveCardUseNo3DSAutoCaptureOffSession"];
cy.confirmCallTest(fixtures.confirmBody, data, true, globalState);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
it("List Payment Method for Customer using Client Secret", () => {
cy.listCustomerPMByClientSecret(globalState);
});
it("Create business profile", () => {
utils.createBusinessProfile(
fixtures.businessProfile.bpCreate,
globalState
);
});
it("Create merchant connector account", () => {
utils.createMerchantConnectorAccount(
"payment_processor",
fixtures.createConnectorBody,
globalState,
payment_methods_enabled
);
});
it("Create Payment Intent", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["PaymentIntentOffSession"];
cy.createPaymentIntentTest(
fixtures.createPaymentBody,
data,
"no_three_ds",
"automatic",
globalState
);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
it("List Payment Method for Customer", () => {
cy.listCustomerPMByClientSecret(globalState);
});
it("Confirm No 3DS MIT (PMID)", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["MITAutoCapture"];
const commonData = getConnectorDetails(globalState.get("commons"))[
"card_pm"
]["MITAutoCapture"];
const newData = {
...data,
Response: utils.getConnectorFlowDetails(
data,
commonData,
"ResponseCustom"
),
};
cy.mitUsingPMId(
fixtures.pmIdConfirmBody,
newData,
7000,
true,
"automatic",
globalState
);
});
it("Create Payment Intent", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["PaymentIntentOffSession"];
cy.createPaymentIntentTest(
fixtures.createPaymentBody,
data,
"no_three_ds",
"automatic",
globalState
);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
it("List Payment Method for Customer", () => {
cy.listCustomerPMByClientSecret(globalState);
});
it("Confirm No 3DS MIT (Token)", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["SaveCardConfirmAutoCaptureOffSession"];
const commonData = getConnectorDetails(globalState.get("commons"))[
"card_pm"
]["SaveCardConfirmAutoCaptureOffSession"];
const newData = {
...data,
Response: utils.getConnectorFlowDetails(
data,
commonData,
"ResponseCustom"
),
};
cy.saveCardConfirmCallTest(
fixtures.saveCardConfirmBody,
newData,
globalState
);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
}
);
context(
"Connector Agnostic Enabled for Profile 1 and Disabled for Profile 2",
() => {
let shouldContinue = true;
beforeEach(function () {
if (!shouldContinue) {
this.skip();
}
});
it("Create business profile", () => {
utils.createBusinessProfile(
fixtures.businessProfile.bpCreate,
globalState
);
});
it("Enable Connector Agnostic for Business Profile", () => {
utils.updateBusinessProfile(
fixtures.businessProfile.bpUpdate,
true, // is_connector_agnostic_enabled
false, // collect_billing_address_from_wallet_connector
false, // collect_shipping_address_from_wallet_connector
false, // always_collect_billing_address_from_wallet_connector
false, // always_collect_shipping_address_from_wallet_connector
globalState
);
});
it("Create merchant connector account", () => {
utils.createMerchantConnectorAccount(
"payment_processor",
fixtures.createConnectorBody,
globalState,
payment_methods_enabled
);
});
it("Create Customer", () => {
cy.createCustomerCallTest(fixtures.customerCreateBody, globalState);
});
it("Create Payment Intent", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["PaymentIntentOffSession"];
cy.createPaymentIntentTest(
fixtures.createPaymentBody,
data,
"no_three_ds",
"automatic",
globalState
);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
it("Confirm Payment", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["SaveCardUseNo3DSAutoCaptureOffSession"];
cy.confirmCallTest(fixtures.confirmBody, data, true, globalState);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
it("List Payment Method for Customer using Client Secret", () => {
cy.listCustomerPMByClientSecret(globalState);
});
it("Create business profile", () => {
utils.createBusinessProfile(
fixtures.businessProfile.bpCreate,
globalState
);
});
it("Create merchant connector account", () => {
utils.createMerchantConnectorAccount(
"payment_processor",
fixtures.createConnectorBody,
globalState,
payment_methods_enabled
);
});
it("Create Payment Intent", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["PaymentIntentOffSession"];
cy.createPaymentIntentTest(
fixtures.createPaymentBody,
data,
"no_three_ds",
"automatic",
globalState
);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
it("List Payment Method for Customer", () => {
cy.listCustomerPMByClientSecret(globalState);
});
it("Confirm No 3DS MIT (PMID)", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["MITAutoCapture"];
const commonData = getConnectorDetails(globalState.get("commons"))[
"card_pm"
]["MITAutoCapture"];
const newData = {
...data,
Response: utils.getConnectorFlowDetails(
data,
commonData,
"ResponseCustom"
),
};
cy.mitUsingPMId(
fixtures.pmIdConfirmBody,
newData,
7000,
true,
"automatic",
globalState
);
});
it("Create Payment Intent", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["PaymentIntentOffSession"];
cy.createPaymentIntentTest(
fixtures.createPaymentBody,
data,
"no_three_ds",
"automatic",
globalState
);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
it("List Payment Method for Customer", () => {
cy.listCustomerPMByClientSecret(globalState);
});
it("Confirm No 3DS MIT (Token)", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm"
]["SaveCardConfirmAutoCaptureOffSession"];
const commonData = getConnectorDetails(globalState.get("commons"))[
"card_pm"
]["SaveCardConfirmAutoCaptureOffSession"];
const newData = {
...data,
Response: utils.getConnectorFlowDetails(
data,
commonData,
"ResponseCustom"
),
};
cy.saveCardConfirmCallTest(
fixtures.saveCardConfirmBody,
newData,
globalState
);
if (shouldContinue)
shouldContinue = utils.should_continue_further(data);
});
}
);
context( context(
"Connector Agnostic Disabled for Profile 1 and Enabled for Profile 2", "Connector Agnostic Disabled for Profile 1 and Enabled for Profile 2",
() => { () => {
@ -178,22 +568,10 @@ describe("Connector Agnostic Tests", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[ const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm" "card_pm"
]["MITAutoCapture"]; ]["MITAutoCapture"];
const commonData = getConnectorDetails(globalState.get("commons"))[
"card_pm"
]["MITAutoCapture"];
const newData = {
...data,
Response: utils.getConnectorFlowDetails(
data,
commonData,
"ResponseCustom"
),
};
cy.mitUsingPMId( cy.mitUsingPMId(
fixtures.pmIdConfirmBody, fixtures.pmIdConfirmBody,
newData, data,
7000, 7000,
true, true,
"automatic", "automatic",
@ -226,21 +604,10 @@ describe("Connector Agnostic Tests", () => {
const data = getConnectorDetails(globalState.get("connectorId"))[ const data = getConnectorDetails(globalState.get("connectorId"))[
"card_pm" "card_pm"
]["SaveCardConfirmAutoCaptureOffSession"]; ]["SaveCardConfirmAutoCaptureOffSession"];
const commonData = getConnectorDetails(globalState.get("commons"))[
"card_pm"
]["SaveCardConfirmAutoCaptureOffSession"];
const newData = {
...data,
Response: utils.getConnectorFlowDetails(
data,
commonData,
"ResponseCustom"
),
};
cy.saveCardConfirmCallTest( cy.saveCardConfirmCallTest(
fixtures.saveCardConfirmBody, fixtures.saveCardConfirmBody,
newData, data,
globalState globalState
); );