Skip to content

feat(connector): [FISERVEMEA] Integrate cards#5672

Merged
Gnanasundari24 merged 18 commits intomainfrom
fiservemea-cards
Aug 28, 2024
Merged

feat(connector): [FISERVEMEA] Integrate cards#5672
Gnanasundari24 merged 18 commits intomainfrom
fiservemea-cards

Conversation

@deepanshu-iiitu
Copy link
Contributor

@deepanshu-iiitu deepanshu-iiitu commented Aug 22, 2024

Type of Change

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

Description

Integrate card payments for new connector Fiserv-EMEA
https://docs.fiserv.dev/

Additional Changes

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

Motivation and Context

#5671

How did you test it?

Following flows need to be tested for card payments for new connector FiservEMEA:

  1. Authorize:
    Request:
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_patS2PyLZVJvSG2Ik9brOOFlHKdIWJdkDaRBnfgNe5qNKNMAlTaYugK5gEIbxlks' \
--data-raw '{
    "amount": 1212,
    "currency": "EUR",
    "confirm": true,
    "profile_id": "pro_NP3j3oHUpby6juMfh84Q",
    "capture_method": "automatic",
    "customer": {
        "id": "custom1234",
        "name": "John Doe",
        "email": "customer@gmail.com"
    },
    "routing": { 
        "type": "single",
        "data": "fiservemea"
    },
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "5204740000001002",
            "card_exp_month": "10",
            "card_exp_year": "24",
            "card_holder_name": "joseph Doe",
            "card_cvc": "002"
        }
    }
}'

Response:

{
    "payment_id": "pay_GIEAyY9nxrGPnOdnJiMV",
    "merchant_id": "merchant_1724327816",
    "status": "succeeded",
    "amount": 1212,
    "net_amount": 1212,
    "amount_capturable": 0,
    "amount_received": 1212,
    "connector": "fiservemea",
    "client_secret": "pay_GIEAyY9nxrGPnOdnJiMV_secret_PHfwCA6AfIxfhQjweIYA",
    "created": "2024-08-26T12:17:59.861Z",
    "currency": "EUR",
    "customer_id": "custom1234",
    "customer": {
        "id": "custom1234",
        "name": "John Doe",
        "email": "customer@gmail.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": "1002",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "520474",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "24",
            "card_holder_name": null,
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": "customer@gmail.com",
    "name": "John Doe",
    "phone": null,
    "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": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "custom1234",
        "created_at": 1724674679,
        "expires": 1724678279,
        "secret": "epk_c3ab3c993c5847febcda59695a87b1e1"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "84665967780",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_GIEAyY9nxrGPnOdnJiMV_1",
    "payment_link": null,
    "profile_id": "pro_NP3j3oHUpby6juMfh84Q",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_c0KwedmN1LCB446Q3E14",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-08-26T12:32:59.861Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-08-26T12:18:02.551Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null
}
  1. Capture:
    Request:
curl --location 'http://localhost:8080/payments/pay_3gqMd6a03V9O81pzFitu/capture' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_patS2PyLZVJvSG2Ik9brOOFlHKdIWJdkDaRBnfgNe5qNKNMAlTaYugK5gEIbxlks' \
--data '{
  "statement_descriptor_name": "Joseph",
  "statement_descriptor_prefix" :"joseph",
  "statement_descriptor_suffix": "JS"
}'

Response:

{
    "payment_id": "pay_3gqMd6a03V9O81pzFitu",
    "merchant_id": "merchant_1724327816",
    "status": "succeeded",
    "amount": 1212,
    "net_amount": 1212,
    "amount_capturable": 0,
    "amount_received": 1212,
    "connector": "fiservemea",
    "client_secret": "pay_3gqMd6a03V9O81pzFitu_secret_fv0iv7EjtuZgOR1StM6e",
    "created": "2024-08-26T12:23:18.684Z",
    "currency": "EUR",
    "customer_id": "custom1234",
    "customer": {
        "id": "custom1234",
        "name": "John Doe",
        "email": "customer@gmail.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": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1002",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "520474",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "24",
            "card_holder_name": null,
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": "customer@gmail.com",
    "name": "John Doe",
    "phone": null,
    "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": "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": "84665968022",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_3gqMd6a03V9O81pzFitu_1",
    "payment_link": null,
    "profile_id": "pro_NP3j3oHUpby6juMfh84Q",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_c0KwedmN1LCB446Q3E14",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-08-26T12:38:18.683Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-08-26T12:23:30.244Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null
}
  1. Void:
    Request:
curl --location 'http://localhost:8080/payments/pay_60FywCJo2ZpuMRPzFCQZ/cancel' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_patS2PyLZVJvSG2Ik9brOOFlHKdIWJdkDaRBnfgNe5qNKNMAlTaYugK5gEIbxlks' \
--data '{
}'

Response:

{
    "payment_id": "pay_60FywCJo2ZpuMRPzFCQZ",
    "merchant_id": "merchant_1724327816",
    "status": "cancelled",
    "amount": 1212,
    "net_amount": 1212,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "fiservemea",
    "client_secret": "pay_60FywCJo2ZpuMRPzFCQZ_secret_rnSGK2xGOtwbMF8YDLQR",
    "created": "2024-08-26T12:23:45.007Z",
    "currency": "EUR",
    "customer_id": "custom1234",
    "customer": {
        "id": "custom1234",
        "name": "John Doe",
        "email": "customer@gmail.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": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1002",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "520474",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "24",
            "card_holder_name": null,
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": "customer@gmail.com",
    "name": "John Doe",
    "phone": null,
    "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": "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": "84665968043",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_60FywCJo2ZpuMRPzFCQZ_1",
    "payment_link": null,
    "profile_id": "pro_NP3j3oHUpby6juMfh84Q",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_c0KwedmN1LCB446Q3E14",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-08-26T12:38:45.007Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-08-26T12:23:52.932Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null
}
  1. Refunds:
    Request:
curl --location 'http://localhost:8080/refunds' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_patS2PyLZVJvSG2Ik9brOOFlHKdIWJdkDaRBnfgNe5qNKNMAlTaYugK5gEIbxlks' \
--data '{
    "payment_id": "pay_3gqMd6a03V9O81pzFitu",
    "refund_type": "instant"
}'

Response:

{
    "refund_id": "ref_EbXtA5W6YIYZOYvjf0k1",
    "payment_id": "pay_3gqMd6a03V9O81pzFitu",
    "amount": 1212,
    "currency": "EUR",
    "status": "succeeded",
    "reason": null,
    "metadata": null,
    "error_message": null,
    "error_code": null,
    "created_at": "2024-08-26T12:24:20.690Z",
    "updated_at": "2024-08-26T12:24:23.132Z",
    "connector": "fiservemea",
    "profile_id": "pro_NP3j3oHUpby6juMfh84Q",
    "merchant_connector_id": "mca_c0KwedmN1LCB446Q3E14",
    "charges": null
}

Cypress Test Cases also added for Non-3DS Cards:
Screenshot 2024-08-26 at 7 13 41 PM

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

@deepanshu-iiitu deepanshu-iiitu added A-connector-integration Area: Connector integration C-feature Category: Feature request or enhancement labels Aug 22, 2024
@deepanshu-iiitu deepanshu-iiitu self-assigned this Aug 22, 2024
@deepanshu-iiitu deepanshu-iiitu requested review from a team as code owners August 22, 2024 12:30
@semanticdiff-com
Copy link

semanticdiff-com bot commented Aug 22, 2024

Review changes with SemanticDiff.

Analyzed 12 of 23 files.

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

File Information
Filename Status
loadtest/config/development.toml Unsupported file format
cypress-tests/cypress/e2e/PaymentUtils/Fiservemea.js Unsupported file format
✔️ cypress-tests/cypress/e2e/PaymentUtils/Utils.js Analyzed
✔️ crates/router/src/types/api.rs Analyzed
✔️ crates/router/src/types/transformers.rs Analyzed
✔️ crates/router/src/core/admin.rs Analyzed
✔️ crates/hyperswitch_connectors/src/constants.rs Analyzed
✔️ crates/hyperswitch_connectors/src/connectors/fiservemea.rs 11.43% smaller
✔️ crates/hyperswitch_connectors/src/connectors/fiservemea/transformers.rs 18.04% smaller
crates/connector_configs/toml/development.toml Unsupported file format
crates/connector_configs/toml/production.toml Unsupported file format
crates/connector_configs/toml/sandbox.toml Unsupported file format
✔️ crates/connector_configs/src/connector.rs Analyzed
✔️ crates/common_enums/src/enums.rs Analyzed
✔️ crates/api_models/src/enums.rs Analyzed
config/config.example.toml Unsupported file format
config/development.toml Unsupported file format
config/docker_compose.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
✔️ api-reference-v2/openapi_spec.json Analyzed
✔️ api-reference/openapi_spec.json Analyzed

@deepanshu-iiitu deepanshu-iiitu linked an issue Aug 22, 2024 that may be closed by this pull request
2 tasks
@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Aug 22, 2024
Comment on lines +112 to +122
merchant_transaction_id: item
.router_data
.connector_request_reference_id
.clone(),
transaction_amount: FiservemeaTransactionAmount {
total: item.amount.clone(),
currency: item.router_data.request.currency,
},
order: FiservemeaOrder {
order_id: item.router_data.connector_request_reference_id.clone(),
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Either merchant_transaction_id or order we should pass merchant_order_reference_id, if its available else pass connector_request_reference_id

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

complete: item.router_data.request.is_auto_capture()?,
expiry_date: FiservemeaExpiryDate {
month: req_card.card_exp_month,
year: req_card.card_exp_year,
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it accepts both 2 digit and 4 digit year?

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 accepts 2 digit expiry year and this bug is fixed.

Comment on lines +316 to +318
None => Err(errors::ConnectorError::MissingRequiredField {
field_name: "transactionResult",
}),
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 trigger 4xx and mark payment as failure, please check and remove this error

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These payments will be marked as pending if no status is returned from connector.

Comment on lines +275 to +286
if transaction_type == FiservemeaTransactionType::Preauth {
Ok(common_enums::AttemptStatus::Authorized)
} else if transaction_type == FiservemeaTransactionType::Void {
Ok(common_enums::AttemptStatus::Voided)
} else if matches!(
transaction_type,
FiservemeaTransactionType::Sale | FiservemeaTransactionType::Postauth
) {
Ok(common_enums::AttemptStatus::Charged)
} else {
Ok(common_enums::AttemptStatus::Failure)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

match statement will be more clean

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

@SamraatBansal SamraatBansal left a comment

Choose a reason for hiding this comment

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

  • Connector Configs are missing for the dashboard
  • Add Cypress Test Cases

@deepanshu-iiitu deepanshu-iiitu requested a review from a team as a code owner August 26, 2024 13:44
Comment on lines +1498 to +1499
[fiservemea.connector_webhook_details]
merchant_secret="Source verification key"
Copy link
Contributor

Choose a reason for hiding this comment

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

Webhooks are not implemented no need of this field

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

Comment on lines +1264 to +1265
[fiservemea.connector_webhook_details]
merchant_secret="Source verification key"
Copy link
Contributor

Choose a reason for hiding this comment

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

Webhooks are not implemented remove this field

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

Comment on lines +1496 to +1497
[fiservemea.connector_webhook_details]
merchant_secret="Source verification key"
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Removed

let fiservemea::FiservemeaAuthType {
api_key,
secret_key,
..
Copy link
Contributor

Choose a reason for hiding this comment

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

There are only 2 fields in the struct, no need for default ..

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

Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
let connector_payment_id = req
.request
.connector_transaction_id
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 sync using our reference id, in case of timeouts it will cause issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No we cannot sync with our reference id

connectors: &Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
let connector_payment_id = req.request.get_connector_refund_id()?;
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 sync using our reference?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No we cannot sync with our reference id

SamraatBansal
SamraatBansal previously approved these changes Aug 27, 2024
SanchithHegde
SanchithHegde previously approved these changes Aug 27, 2024
Gnanasundari24
Gnanasundari24 previously approved these changes Aug 28, 2024
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Aug 28, 2024
Merged via the queue into main with commit 32dd3f9 Aug 28, 2024
@Gnanasundari24 Gnanasundari24 deleted the fiservemea-cards branch August 28, 2024 10:10
pixincreate added a commit that referenced this pull request Aug 28, 2024
* 'main' of github.com:juspay/hyperswitch:
  feat(connector): [FISERVEMEA] Integrate cards (#5672)
  ci(cypress): Add routing testcases (#5571)
  fix(router): skip external three_ds flow for recurring payments (#5730)
  refactor(customer_v2): fixed customer_v2 create panic issue (#5699)
  feat(user_roles): support switch for new hierarchy (#5692)
  refactor(router): add domain type for merchant_connector_account id (#5685)
  refactor(cypress_tests): handle api keys check in api key list call (#5719)
  feat(connector): [NEXIXPAY] Add template code (#5684)
  refactor(connector): [itau] refactor error reason and code mapping for itau (#5718)
  fix(core): fix merchant connector account create for v2  (#5716)
  chore(version): 2024.08.28.0
  fix(routing): fix routing routes to deserialise correctly (#5724)
  feat(euclid): add a new variant in payment type i.e ppt_mandate (#5681)
  feat(core): Add mTLS certificates for each request (#5636)
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 C-feature Category: Feature request or enhancement M-api-contract-changes Metadata: This PR involves API contract changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] [FISERVEMEA] Integrate card payments

6 participants