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(connector): [DataTrans] ADD 3DS Flow #6026

Conversation

awasthi21
Copy link
Contributor

@awasthi21 awasthi21 commented Sep 25, 2024

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

Added 3DS Flow

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

Three 3ds

**Request**
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_iClV9gEjhQBYt3sTzwjloL1IGSd6VpSC2JR0BBJ9gbrFEo6eHkfD5SSJudjoHlzq' \
--data-raw '{
    "amount": 1500,
    "currency": "USD",
    "amount_to_capture": 1500,
    "confirm": true,
    "capture_method": "automatic",
    "authentication_type": "three_ds",
    "payment_method": "card",
    "payment_method_type": "credit",
      "email": "guest@example.com",
    "payment_method_data": {
        "card": {
            "card_number": "4111111111111111",
            "card_exp_month": "06",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "card_cvc": "123"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "Zurich",
            "state": "asd",
            "zip": "8008",
            "country": "CH",
            "first_name": "joseph",
            "last_name": "Doe"
        }
    }
}'
**Response:**

{
    "payment_id": "pay_vHjy5fKzjHZxKtxI098X",
    "merchant_id": "postman_merchant_GHAction_89a6aa6f-012b-407e-9a8c-34ca16816f21",
    "status": "requires_customer_action",
    "amount": 1500,
    "net_amount": 1500,
    "amount_capturable": 1500,
    "amount_received": null,
    "connector": "datatrans",
    "client_secret": "pay_vHjy5fKzjHZxKtxI098X_secret_u75qIY4GA4cpgHEVxe9J",
    "created": "2024-09-25T11:27:14.567Z",
    "currency": "USD",
    "customer_id": null,
    "customer": {
        "id": null,
        "name": null,
        "email": "guest@example.com",
        "phone": null,
        "phone_country_code": null
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1111",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "411111",
            "card_extended_bin": null,
            "card_exp_month": "06",
            "card_exp_year": "25",
            "card_holder_name": null,
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": "Zurich",
            "country": "CH",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "8008",
            "state": "asd",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": null,
    "authentication_type": "three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": {
        "type": "redirect_to_url",
        "redirect_to_url": "http://localhost:8080/payments/redirect/pay_vHjy5fKzjHZxKtxI098X/postman_merchant_GHAction_89a6aa6f-012b-407e-9a8c-34ca16816f21/pay_vHjy5fKzjHZxKtxI098X_1"
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": null,
    "connector_transaction_id": "240925132715468655",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_42yrBwduYyd6qykBOXCS",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_KFw9ms4pVBoP3ovswSEu",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-09-25T11:42:14.567Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-09-25T11:27:15.520Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}
**Redirect Response :**
{
    "payment_id": "pay_vHjy5fKzjHZxKtxI098X",
    "merchant_id": "postman_merchant_GHAction_89a6aa6f-012b-407e-9a8c-34ca16816f21",
    "status": "succeeded",
    "amount": 1500,
    "net_amount": 1500,
    "amount_capturable": 0,
    "amount_received": 1500,
    "connector": "datatrans",
    "client_secret": "pay_vHjy5fKzjHZxKtxI098X_secret_u75qIY4GA4cpgHEVxe9J",
    "created": "2024-09-25T11:27:14.567Z",
    "currency": "USD",
    "customer_id": null,
    "customer": {
        "id": null,
        "name": null,
        "email": "guest@example.com",
        "phone": null,
        "phone_country_code": null
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1111",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "411111",
            "card_extended_bin": null,
            "card_exp_month": "06",
            "card_exp_year": "25",
            "card_holder_name": null,
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": "Zurich",
            "country": "CH",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "8008",
            "state": "asd",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": null,
    "authentication_type": "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": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": false,
    "connector_transaction_id": "240925132715468655",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_42yrBwduYyd6qykBOXCS",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_KFw9ms4pVBoP3ovswSEu",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-09-25T11:42:14.567Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-09-25T11:28:51.196Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

@awasthi21 awasthi21 added the A-connector-integration Area: Connector integration label Sep 25, 2024
@awasthi21 awasthi21 self-assigned this Sep 25, 2024
@awasthi21 awasthi21 requested review from a team as code owners September 25, 2024 11:12
Copy link

semanticdiff-com bot commented Sep 25, 2024

Review changes with  SemanticDiff

Changed Files
File Status
  crates/hyperswitch_connectors/src/connectors/paybox/transformers.rs  63% smaller
  crates/hyperswitch_connectors/src/connectors/datatrans.rs  60% smaller
  crates/hyperswitch_connectors/src/connectors/datatrans/transformers.rs  4% smaller
  config/config.example.toml Unsupported file format
  config/deployments/integration_test.toml Unsupported file format
  config/deployments/production.toml Unsupported file format
  config/deployments/sandbox.toml Unsupported file format
  config/development.toml Unsupported file format
  config/docker_compose.toml Unsupported file format
  crates/hyperswitch_connectors/src/utils.rs  0% smaller
  crates/hyperswitch_interfaces/src/configs.rs  0% smaller
  crates/router/src/configs/defaults/payment_connector_required_fields.rs  0% smaller
  loadtest/config/development.toml Unsupported file format

@awasthi21 awasthi21 force-pushed the 6211-featconnector-datatrans-implement-advanced-payment-flows branch from ce511fb to 35b85d5 Compare September 25, 2024 11:25
@awasthi21 awasthi21 linked an issue Sep 26, 2024 that may be closed by this pull request
Comment on lines 140 to 147
pub struct CardHolder {
cardholder_name: Secret<String>,
email: Email,
bill_addr_line1: Secret<String>,
bill_addr_post_code: Secret<String>,
bill_addr_city: String,
bill_addr_state: Secret<String>,
bill_addr_country: common_enums::CountryAlpha2,
Copy link
Contributor

Choose a reason for hiding this comment

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

Make only required fields as mandatory and add the in crates/router/src/configs/defaults.rs.
Make strongly recommended fields as optional and add a comment highlighting those fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

Comment on lines 418 to 425
incremental_authorization_allowed: Some(
status == enums::AttemptStatus::Authorized,
),
Copy link
Contributor

Choose a reason for hiding this comment

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

This will always be false hence no need to pass it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
let base_url = self.base_url(connectors);
Ok(format!("{base_url}v1/transactions/authorize"))
if req.is_three_ds() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please test PSYNC, Capture, Refunds and Incremental Auth for 3DS transactions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tested ,
For incremental Auth we have a different merchant account. Not able to test 3ds + incremental Auth
Except that everything is working

@awasthi21 awasthi21 force-pushed the 6211-featconnector-datatrans-implement-advanced-payment-flows branch 2 times, most recently from 4303fba to 7c59b17 Compare September 26, 2024 13:03
Comment on lines 23 to 24
const REDIRECTION_SBX_URL: &str = "https://pay.sandbox.datatrans.com";
const REDIRECTION_PROD_URL: &str = "https://pay.datatrans.com";
Copy link
Member

Choose a reason for hiding this comment

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

Why have we hardcoded these URLs?

Copy link
Contributor Author

@awasthi21 awasthi21 Sep 27, 2024

Choose a reason for hiding this comment

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

This URL is used in the 3DS redirection

    fn handle_response(
        &self,
        data: &types::PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
        let response: datatrans::DatatransResponse = res
            .response
            .parse_struct("Datatrans PaymentsAuthorizeResponse")
            .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::ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

in handle response there's no other way to retrieve the base/secondary_url ( connectors: &settings::Connectors, not there in handle_response) ,Had to hard code it

@@ -129,6 +129,8 @@ pub struct PaymentsIncrementalAuthorizationData {
pub currency: storage_enums::Currency,
pub reason: Option<String>,
pub connector_transaction_id: String,
pub minor_additional_amount: MinorUnit,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think, instead of adding new minor fields here, we should refactor the existing fields as minor unit

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

@awasthi21 awasthi21 force-pushed the 6211-featconnector-datatrans-implement-advanced-payment-flows branch from 7c59b17 to 9522536 Compare February 3, 2025 09:16
@awasthi21 awasthi21 force-pushed the 6211-featconnector-datatrans-implement-advanced-payment-flows branch from 8c2c8d2 to d9d162e Compare February 5, 2025 12:18
@awasthi21 awasthi21 changed the title feat(connector): [DataTrans] ADD 3DS and Incremental Auth feat(connector): [DataTrans] ADD 3DS Flow Feb 5, 2025
router_env::logger::info!(connector_response=?response);
Ok(ErrorResponse {
status_code: res.status_code,
code: response.clone(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make this NO_ERROR_CODE

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

deepanshu-iiitu
deepanshu-iiitu previously approved these changes Feb 6, 2025
deepanshu-iiitu
deepanshu-iiitu previously approved these changes Feb 6, 2025
@awasthi21 awasthi21 requested a review from jagan-jaya February 6, 2025 09:31
@awasthi21 awasthi21 force-pushed the 6211-featconnector-datatrans-implement-advanced-payment-flows branch from 7826e2c to 6a846de Compare February 6, 2025 09:57
@deepanshu-iiitu deepanshu-iiitu self-requested a review February 6, 2025 11:36
deepanshu-iiitu
deepanshu-iiitu previously approved these changes Feb 6, 2025
@awasthi21 awasthi21 force-pushed the 6211-featconnector-datatrans-implement-advanced-payment-flows branch from 4ec716d to d1fbbb3 Compare February 6, 2025 12:37
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Feb 7, 2025
Merged via the queue into main with commit 4693d21 Feb 7, 2025
17 of 20 checks passed
@Gnanasundari24 Gnanasundari24 deleted the 6211-featconnector-datatrans-implement-advanced-payment-flows branch February 7, 2025 05:36
pixincreate added a commit that referenced this pull request Feb 7, 2025
…unt-configurable

* 'main' of github.com:juspay/hyperswitch: (37 commits)
  refactor(router): add display_name field to connector feature api  (#7121)
  ci(cypress): Add Tests for Customer Deletion and Psync flows (#7158)
  feat(connector): [DataTrans] ADD 3DS Flow (#6026)
  chore(version): 2025.02.07.0
  chore(connectors): [fiuu] update pm_filters for apple pay and google pay (#7182)
  feat(router): add `organization_id` in authentication table and add it in authentication events (#7168)
  fix(dashboard_metadata): mask `poc_email` and `data_value` for DashboardMetadata (#7130)
  feat(core): Add support for v2 payments get intent using merchant reference id (#7123)
  refactor(customer): return redacted customer instead of error (#7122)
  fix(connector): handle unexpected error response from bluesnap connector (#7120)
  feat(routing): Contract based routing integration  (#6761)
  refactor(dynamic_fields): dynamic fields for Adyen and Stripe, renaming klarnaCheckout, WASM for KlarnaCheckout (#7015)
  feat(connector): [COINGATE] Add Template PR  (#7052)
  chore(roles): remove redundant variant from PermissionGroup (#6985)
  refactor(router): store `network_transaction_id` for `off_session` payments irrespective of the `is_connector_agnostic_mit_enabled` config (#7083)
  chore(connector): [Fiuu] log keys in the PSync response (#7189)
  ci(cypress): fix nmi and paypal (#7173)
  chore(version): 2025.02.06.0
  chore(postman): update Postman collection files
  feat(connector): [Deutschebank] Add Access Token Error struct (#7127)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-connector-integration Area: Connector integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants