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): [Payouts] Add payout_method_details to response #5887

Merged
merged 17 commits into from
Sep 26, 2024

Conversation

Sakilmostak
Copy link
Contributor

@Sakilmostak Sakilmostak commented Sep 15, 2024

Type of Change

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

Description

This PR helps in showing masked payout method details in payout response for each payout method.

  • the payout method data get masked and saved in payout_attempt table
  • this happens for both create/confirm and update call
  • new masking strategies are used for masking for some of the fields present in payout method data
  • email and phone number are masked too if included in payout method details

Additional Changes

  • This PR modifies the API contract

add payout_method_data object in response
Eg.

"payout_method_data": {
        "bank": {
            "iban": "NL46T********69112",
            "bank_name": "Deutsche Bank",
            "bank_country_code": "NL",
            "bank_city": "Amsterdam",
            "bic": "ABN**L2A"
        }
    }
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

Tested through postman:

Case 1

  • Create a SEPA payout through Adyen (with confirm false):
{
    "amount": 1,
    "currency": "EUR",
    "customer_id": "{{customer_id}}",
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "Its my first payout request",
    "payout_type": "bank",
    "payout_method_data": {
        "bank": {
            "iban": "NL46TEST0136169112",
            "bic": "ABNANL2A",
            "bank_name": "Deutsche Bank",
            "bank_country_code": "NL",
            "bank_city": "Amsterdam"
        }
    },
    "connector": [
        "adyen"
    ],
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "CA",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "entity_type": "NaturalPerson",
    "recurring": true,
    "metadata": {
        "ref": "123"
    },
    "confirm": true,
    "auto_fulfill": true
}
  • The response should of this format:
{
    "payout_id": "18cfdaf3-3009-4caa-86de-423234e87af8",
    "merchant_id": "merchant_1726401857",
    "amount": 1,
    "currency": "EUR",
    "connector": "adyen",
    "payout_type": "bank",
    "payout_method_data": {
        "bank": {
            "iban": "NL46T********69112",
            "bank_name": "Deutsche Bank",
            "bank_country_code": "NL",
            "bank_city": "Amsterdam",
            "bic": "ABN**L2A"
        }
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "CA",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "auto_fulfill": true,
    "customer_id": "cus_tK8bgOmzhMMqqNlaujVK",
    "customer": {
        "id": "cus_tK8bgOmzhMMqqNlaujVK",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "client_secret": "payout_18cfdaf3-3009-4caa-86de-423234e87af8_secret_TMLHPEg9OE2bTbKrJ8rR",
    "return_url": null,
    "business_country": null,
    "business_label": null,
    "description": "Its my first payout request",
    "entity_type": "NaturalPerson",
    "recurring": true,
    "metadata": {
        "ref": "123"
    },
    "merchant_connector_id": "mca_CdSOWm2GL5MpFvMmKZUY",
    "status": "initiated",
    "error_message": null,
    "error_code": null,
    "profile_id": "pro_pMvW03dGLRFXRF2LyeSj",
    "created": "2024-09-15T12:04:36.861Z",
    "connector_transaction_id": "FT7WLTMTKZSKGK82",
    "priority": null,
    "payout_link": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65"
}

Case 2

  • Create a SEPA payout through Adyen (with confirm false):
{
    "amount": 1,
    "currency": "EUR",
    "customer_id": "{{customer_id}}",
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "Its my first payout request",
    "connector": [
        "adyen"
    ],
    "entity_type": "NaturalPerson",
    "recurring": true,
    "priority": "instant",
    "metadata": {
        "ref": "123"
    },
    "confirm": false,
    "auto_fulfill": true
}
  • The response should be of this format:
{
    "payout_id": "355af028-8a65-46bb-9b72-97f98c2f91f4",
    "merchant_id": "merchant_1726655107",
    "amount": 1,
    "currency": "EUR",
    "connector": null,
    "payout_type": null,
    "payout_method_data": null,
    "billing": null,
    "auto_fulfill": true,
    "customer_id": "cus_tK8bgOmzhMMqqNlaujVK",
    "customer": {
        "id": "cus_tK8bgOmzhMMqqNlaujVK",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "client_secret": "payout_355af028-8a65-46bb-9b72-97f98c2f91f4_secret_U21XrQ6EpKGvZs9vxDDf",
    "return_url": null,
    "business_country": null,
    "business_label": null,
    "description": "Its my first payout request",
    "entity_type": "NaturalPerson",
    "recurring": true,
    "metadata": {
        "ref": "123"
    },
    "merchant_connector_id": null,
    "status": "requires_payout_method_data",
    "error_message": null,
    "error_code": null,
    "profile_id": "pro_gOHbNAWc0E9sbCYHEJj5",
    "created": "2024-09-18T10:25:15.983Z",
    "connector_transaction_id": null,
    "priority": "instant",
    "payout_link": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65"
}
  • Create a payout confirm call:
{
    "payout_type": "bank",
    "payout_method_data": {
        "bank": {
            "iban": "NL46TEST0136169112",
            "bic": "ABNANL2A",
            "bank_name": "Deutsche Bank",
            "bank_country_code": "NL",
            "bank_city": "Amsterdam"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "CA",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "confirm": true,
    "auto_fulfill": true,
    "priority": "instant"
}
  • The response should be of this format:
{
    "payout_id": "355af028-8a65-46bb-9b72-97f98c2f91f4",
    "merchant_id": "merchant_1726655107",
    "amount": 1,
    "currency": "EUR",
    "connector": "adyen",
    "payout_type": "bank",
    "payout_method_data": {
        "bank": {
            "iban": "NL46T********69112",
            "bank_name": "Deutsche Bank",
            "bank_country_code": "NL",
            "bank_city": "Amsterdam",
            "bic": "ABN**L2A"
        }
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "CA",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "auto_fulfill": true,
    "customer_id": "cus_tK8bgOmzhMMqqNlaujVK",
    "customer": {
        "id": "cus_tK8bgOmzhMMqqNlaujVK",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "client_secret": "payout_355af028-8a65-46bb-9b72-97f98c2f91f4_secret_U21XrQ6EpKGvZs9vxDDf",
    "return_url": null,
    "business_country": null,
    "business_label": null,
    "description": "Its my first payout request",
    "entity_type": "NaturalPerson",
    "recurring": true,
    "metadata": {
        "ref": "123"
    },
    "merchant_connector_id": "mca_kHHAxrUQvZ9YCd5NvgNL",
    "status": "initiated",
    "error_message": null,
    "error_code": null,
    "profile_id": "pro_gOHbNAWc0E9sbCYHEJj5",
    "created": "2024-09-18T10:25:15.983Z",
    "connector_transaction_id": "NLG3JPVP2LMLNK82",
    "priority": "instant",
    "payout_link": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65"
}

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

@Sakilmostak Sakilmostak added A-core Area: Core flows C-feature Category: Feature request or enhancement M-database-changes Metadata: This PR involves database schema changes Payouts Area: Payouts labels Sep 15, 2024
@Sakilmostak Sakilmostak self-assigned this Sep 15, 2024
Copy link

semanticdiff-com bot commented Sep 15, 2024

Review changes with SemanticDiff.

Analyzed 18 of 20 files.

Overall, the semantic diff is 1% smaller than the GitHub diff.

Filename Status
migrations/2024-09-15-080630_add_addtional_payout_method_data_column_to_payout_attempt_table/down.sql Unsupported file format
migrations/2024-09-15-080630_add_addtional_payout_method_data_column_to_payout_attempt_table/up.sql Unsupported file format
✔️ crates/storage_impl/src/payouts/payout_attempt.rs Analyzed
✔️ crates/router/src/types/api/payouts.rs 58.93% smaller
✔️ crates/router/src/core/payouts.rs Analyzed
✔️ crates/router/src/core/payouts/helpers.rs 0.02% smaller
✔️ crates/router/src/core/payouts/retry.rs Analyzed
✔️ crates/router/src/core/payouts/transformers.rs Analyzed
✔️ crates/openapi/src/openapi.rs 1.32% smaller
✔️ crates/openapi/src/openapi_v2.rs 1.32% smaller
✔️ crates/hyperswitch_domain_models/src/payouts/payout_attempt.rs 0.24% smaller
✔️ crates/diesel_models/src/payout_attempt.rs 14.88% smaller
✔️ crates/diesel_models/src/schema.rs Analyzed
✔️ crates/diesel_models/src/schema_v2.rs Analyzed
✔️ crates/common_utils/src/lib.rs Analyzed
✔️ crates/common_utils/src/new_type.rs 6.28% smaller
✔️ crates/common_utils/src/payout_method_utils.rs Analyzed
✔️ crates/api_models/src/payouts.rs 0.01% smaller
✔️ api-reference-v2/openapi_spec.json Analyzed
✔️ api-reference/openapi_spec.json Analyzed

@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Sep 16, 2024
@Sakilmostak Sakilmostak marked this pull request as ready for review September 17, 2024 10:35
@Sakilmostak Sakilmostak requested review from a team as code owners September 17, 2024 10:35
Comment on lines 564 to 566
Card(Box<CardPayoutResponse>),
Bank(Box<BankPayoutResponse>),
Wallet(Box<WalletPayoutResponse>),
Copy link
Contributor

Choose a reason for hiding this comment

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

These can directly be CardAdditionalData, BankAdditionalData and WalletAdditionalData

We had added details and we were flattening it for payments for backwards compatibility only

}

#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct CardAdditionalData {
Copy link
Contributor

Choose a reason for hiding this comment

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

Possible to re-use this struct from payments? Or is there anything different here for payins vs payouts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

struct from payment have additional payment fields which are optional but I think it would be better to have our own struct to contain any specific data for card in payouts if required

additional_payout_method_data,
};

payout_attempt = db
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this added for update / confirm flows?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is added for update as well as confirm call

@@ -30,6 +30,7 @@ pub struct PayoutAttempt {
pub profile_id: common_utils::id_type::ProfileId,
pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
pub routing_info: Option<serde_json::Value>,
pub additional_payout_method_data: Option<serde_json::Value>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's make it the optional type - AdditionalPayoutMethodData? We will not need to manually encode or decode the values in our flows that way.

Copy link
Contributor

@kashif-m kashif-m left a comment

Choose a reason for hiding this comment

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

small improvements can be made, other than that, it looks good to me 👍

"authentication_data": null
}
}"#))]
pub payout_method_data: Option<PayoutMethodDataResponse>,
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 re-use AdditionalPayoutMethodData?

match pm_data {
api::PayoutMethodData::Card(card_data) => {
let card_isin = Some(card_data.card_number.get_card_isin());
let enable_extended_bin =db
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this file not formatted? 🤔

kashif-m
kashif-m previously approved these changes Sep 19, 2024
+ &"*".repeat(user_identifier.len() - unmasked_char_count);
format!("{}@{}", masked_user_identifier, domain)
} else {
let masked_value = apply_mask(src.as_ref(), unmasked_char_count, 8);
Copy link
Member

Choose a reason for hiding this comment

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

If we're unable to split by @, then I feel it's better to mask everything, to be on the safer side.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It only unmask the last two and first two character only if the size is greater than 12, else it would only unmask the last two character.

SanchithHegde
SanchithHegde previously approved these changes Sep 19, 2024
ShankarSinghC
ShankarSinghC previously approved these changes Sep 19, 2024
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Sep 19, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to a conflict with the base branch Sep 19, 2024
@likhinbopanna likhinbopanna added this pull request to the merge queue Sep 26, 2024
Merged via the queue into main with commit 5912936 Sep 26, 2024
16 checks passed
@likhinbopanna likhinbopanna deleted the add_payout_method_details branch September 26, 2024 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-core Area: Core flows C-feature Category: Feature request or enhancement M-api-contract-changes Metadata: This PR involves API contract changes M-database-changes Metadata: This PR involves database schema changes Payouts Area: Payouts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants