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(router): add support for Samsung Pay payment method #5955

Merged
merged 7 commits into from
Sep 20, 2024

Conversation

ShankarSinghC
Copy link
Contributor

@ShankarSinghC ShankarSinghC commented Sep 19, 2024

Type of Change

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

Description

This pr is to support for Samsung pay as a payment method.
This pr also adds a new field in merchant connector account create connector_wallet_details which is required to collect the required credentials for Samsung Pay. As this column in the data base stores the data in the encrypted format we also want to migrate apple pay certificates from metadata to connector_wallet_details, for which we are inserting apple pay details passed in the metadata to connector_wallet_details.

Once the frontend changes are done to pass the apple pay credentials in the connector_wallet_details this fallback can be removed.

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?

Test Samsung Pay flow
-> Enable Samsung Pay payment method for the connector

{
    "connector_type": "payment_processor",
    "connector_name": "cybersource",
    "connector_account_details": {
        "auth_type": "SignatureKey",
        "api_secret": "api_secret",
        "key1": "key1",
        "api_key": "api_key"
    },
    "test_mode": true,
    "disabled": false,
    "payment_methods_enabled": [
        {
            "payment_method": "pay_later",
            "payment_method_types": [
                {
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true,
                    "payment_experience": "invoke_sdk_client",
                    "payment_method_type": "klarna"
                }
            ]
        },
        {
            "payment_method": "pay_later",
            "payment_method_types": [
                {
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true,
                    "payment_experience": "redirect_to_url",
                    "payment_method_type": "klarna"
                }
            ]
        },
        {
            "payment_method": "card",
            "payment_method_types": [
                {
                    "payment_method_type": "credit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard",
                        "Discover",
                        "DinersClub"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "debit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method": "bank_debit",
            "payment_method_types": [
                {
                    "payment_method_type": "ach",
                    "recurring_enabled": true,
                    "installment_payment_enabled": true,
                    "minimum_amount": 0,
                    "maximum_amount": 10000
                }
            ]
        },
        {
            "payment_method": "wallet",
            "payment_method_types": [
                {
                    "payment_method_type": "google_pay",
                    "payment_experience": "invoke_sdk_client",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "samsung_pay",
                    "payment_experience": "invoke_sdk_client",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "apple_pay",
                    "payment_experience": "invoke_sdk_client",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "paypal",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        }
    ],
    "connector_wallets_details": {
        "samsung_pay": {
            "service_id": "49400558c67f4a97b3925f",
            "merchant_display_name": "Hyperswitch",
            "merchant_business_country": "IN",
            "allowed_brands": [
                "visa",
                "masterCard",
                "amex",
                "discover"
            ]
        }
    },
    "connector_webhook_details": {
        "merchant_secret": "merchant_secret"
    }
}

-> Create a payment

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_cjSDZPveYx7AbdI5cMRMuPKVdteJ7aIi3ULRasYhU89JtFRZWp9BeNn7PQDLQv8W' \
--data '{
  "amount": 100000,
  "currency": "INR",
  "capture_method": "automatic",
  "authentication_type": "no_three_ds",
  "confirm": false,
  "customer_id": "cu_1726743607"
}'
{
    "payment_id": "pay_on1wv5l8OM8A3VuDe2GN",
    "merchant_id": "merchant_1726725490",
    "status": "requires_payment_method",
    "amount": 100000,
    "net_amount": 100000,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": null,
    "client_secret": "pay_on1wv5l8OM8A3VuDe2GN_secret_o5JrhSWuWKjcUgrvASpi",
    "created": "2024-09-19T11:00:15.562Z",
    "currency": "INR",
    "customer_id": "cu_1726743615",
    "customer": {
        "id": "cu_1726743615",
        "name": null,
        "email": null,
        "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": null,
    "payment_method_data": null,
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": null,
    "name": null,
    "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": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "cu_1726743615",
        "created_at": 1726743615,
        "expires": 1726747215,
        "secret": "epk_3d5ad79c88554ee7bf0748ae18ecd05b"
    },
    "manual_retry_allowed": null,
    "connector_transaction_id": null,
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_XdGC3A6KTKR5n2WDLON5",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": null,
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-09-19T11:15:15.562Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-09-19T11:00:15.680Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null
}

-> Session call

curl --location 'http://localhost:8080/payments/session_tokens' \
--header 'Content-Type: application/json' \
--header 'x-browser-name: Safari' \
--header 'x-merchant-domain: sdk-test-app.netlify.app' \
--header 'api-key: pk_dev_c23e25c5054241288a778316e463e309' \
--data '{
    "payment_id": "pay_on1wv5l8OM8A3VuDe2GN",
    "wallets": [],
    "client_secret": "pay_on1wv5l8OM8A3VuDe2GN_secret_o5JrhSWuWKjcUgrvASpi"
}'
{
    "payment_id": "pay_on1wv5l8OM8A3VuDe2GN",
    "client_secret": "pay_on1wv5l8OM8A3VuDe2GN_secret_o5JrhSWuWKjcUgrvASpi",
    "session_token": [
        {
            "wallet_name": "samsung_pay",
            "version": "2",
            "service_id": "49400558c67f4a97b3925f",
            "order_number": "pay_on1wv5l8OM8A3VuDe2GN",
            "merchant": {
                "name": "Hyperswitch",
                "url": "sdk-test-app.netlify.app",
                "country_code": "IN"
            },
            "amount": {
                "option": "FORMAT_TOTAL_PRICE_ONLY",
                "currency_code": "INR",
                "total": "1000.00"
            },
            "protocol": "PROTOCOL3DS",
            "allowed_brands": [
                "visa",
                "masterCard",
                "amex",
                "discover"
            ]
        }
    ]
}

-> Confirm call

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_cjSDZPveYx7AbdI5cMRMuPKVdteJ7aIi3ULRasYhU89JtFRZWp9BeNn7PQDLQv8W' \
--data-raw '{
    "amount": 1,
    "currency": "USD",
    "confirm": true,
    "business_country": "US",
    "business_label": "default",
    "amount_to_capture": 1,
    "customer_id": "custhype123",
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "return_url": "https://google.com",
    "email": "[email protected]",
    "name": "Joseph Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "Its my first payment request",
    "statement_descriptor_name": "Juspay",
    "statement_descriptor_suffix": "Router",
    "payment_method": "wallet",
    "payment_method_type": "samsung_pay",
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "payment_method_data": {
        "wallet": {
            "samsung_pay": {
                "payment_credential": {
                    "card_brand": "visa",
                    "recurring_payment": false,
                    "card_last4digits": "1234",
                    "method": "3DS",
                    "3_d_s": {
                        "type": "S",
                        "version": "100",
                        "data": "encrypted samsung pay data"
                    }
                }
            }
        }
    }
}'
{
    "payment_id": "pay_0lHEl7IAq7cFn680x4HJ",
    "merchant_id": "merchant_1726725490",
    "status": "failed",
    "amount": 1,
    "net_amount": 1,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "cybersource",
    "client_secret": "pay_0lHEl7IAq7cFn680x4HJ_secret_3bsNpl8N5rArpWizVWik",
    "created": "2024-09-19T11:28:58.596Z",
    "currency": "USD",
    "customer_id": "custhype123",
    "customer": {
        "id": "custhype123",
        "name": "Joseph Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "description": "Its my first payment request",
    "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": "wallet",
    "payment_method_data": {
        "wallet": {},
        "billing": 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": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "Joseph Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "Juspay",
    "statement_descriptor_suffix": "Router",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": "INVALID_DATA",
    "error_message": "Declined - One or more fields in the request contains invalid data, detailed_error_information: paymentInformation.fluidData.value : INVALID_DATA",
    "unified_code": "UE_000",
    "unified_message": "Something went wrong",
    "payment_experience": null,
    "payment_method_type": "samsung_pay",
    "connector_label": "cybersource_US_default_default",
    "business_country": "US",
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "custhype123",
        "created_at": 1726745338,
        "expires": 1726748938,
        "secret": "epk_48f2e9de3ad641578f3df9e9a46d9c80"
    },
    "manual_retry_allowed": true,
    "connector_transaction_id": null,
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_XdGC3A6KTKR5n2WDLON5",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_TO5NdOnj3ohWTfxBKGsc",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-09-19T11:43:58.596Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-09-19T11:29:00.222Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null
}

The status will be failed as Samsung does not have a test card and cybersource returns invalid data error for live cards

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

@ShankarSinghC ShankarSinghC requested review from a team as code owners September 19, 2024 08:10
Copy link

semanticdiff-com bot commented Sep 19, 2024

Review changes with SemanticDiff.

Analyzed 21 of 27 files.

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

File Information
Filename Status
✔️ crates/router/src/types/api.rs Analyzed
✔️ crates/router/src/types/transformers.rs Analyzed
✔️ crates/router/src/core/admin.rs 76.42% smaller
✔️ crates/router/src/core/payments/helpers.rs 9.68% smaller
✔️ crates/router/src/core/payments/operations/payment_session.rs Analyzed
✔️ crates/router/src/core/payments/flows/session_flow.rs Analyzed
✔️ crates/router/src/core/errors/utils.rs 20.67% smaller
✔️ crates/router/src/core/connector_onboarding/paypal.rs Analyzed
✔️ crates/router/src/connector/cybersource/transformers.rs 0.59% smaller
✔️ crates/router/src/connector/adyen/transformers.rs 29.44% smaller
✔️ crates/openapi/src/openapi.rs 4.98% smaller
✔️ crates/openapi/src/openapi_v2.rs 3.91% smaller
✔️ crates/kgraph_utils/src/mca.rs Analyzed
✔️ crates/kgraph_utils/benches/evaluation.rs Analyzed
✔️ crates/hyperswitch_interfaces/src/errors.rs Analyzed
✔️ crates/hyperswitch_domain_models/src/payment_method_data.rs 11.22% smaller
✔️ crates/connector_configs/src/transformer.rs 2.7% smaller
✔️ crates/api_models/src/admin.rs Analyzed
✔️ crates/api_models/src/payments.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

@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Sep 19, 2024
@ShankarSinghC ShankarSinghC changed the title feat(router): apple support for Samsung Pay payment method feat(router): add support for Samsung Pay payment method Sep 19, 2024
config/development.toml Show resolved Hide resolved
crates/api_models/src/admin.rs Outdated Show resolved Hide resolved
crates/api_models/src/payments.rs Show resolved Hide resolved
crates/api_models/src/payments.rs Outdated Show resolved Hide resolved
crates/api_models/src/payments.rs Outdated Show resolved Hide resolved
crates/api_models/src/payments.rs Outdated Show resolved Hide resolved
crates/api_models/src/payments.rs Outdated Show resolved Hide resolved
crates/router/src/connector/cybersource/transformers.rs Outdated Show resolved Hide resolved
crates/router/src/types/transformers.rs Outdated Show resolved Hide resolved
config/deployments/sandbox.toml Outdated Show resolved Hide resolved
crates/api_models/src/admin.rs Outdated Show resolved Hide resolved
crates/api_models/src/payments.rs Outdated Show resolved Hide resolved
crates/router/src/types/transformers.rs Outdated Show resolved Hide resolved
@ShankarSinghC ShankarSinghC force-pushed the samsung_pay branch 2 times, most recently from e401e06 to d1b3080 Compare September 19, 2024 14:44
@ShankarSinghC ShankarSinghC self-assigned this Sep 19, 2024
@ShankarSinghC ShankarSinghC added C-feature Category: Feature request or enhancement A-payment-methods Area: Payment Methods labels Sep 19, 2024
@ShankarSinghC ShankarSinghC linked an issue Sep 19, 2024 that may be closed by this pull request
SanchithHegde
SanchithHegde previously approved these changes Sep 19, 2024
Copy link
Contributor

@deepanshu-iiitu deepanshu-iiitu left a comment

Choose a reason for hiding this comment

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

Approving on behalf of connectors

Chethan-rao
Chethan-rao previously approved these changes Sep 20, 2024
crates/api_models/src/payments.rs Outdated Show resolved Hide resolved
crates/api_models/src/payments.rs Outdated Show resolved Hide resolved
crates/router/src/core/payments/flows/session_flow.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@apoorvdixit88 apoorvdixit88 left a comment

Choose a reason for hiding this comment

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

Dashboard specific change looks fine

@likhinbopanna likhinbopanna added this pull request to the merge queue Sep 20, 2024
Merged via the queue into main with commit fe15cc7 Sep 20, 2024
12 of 14 checks passed
@likhinbopanna likhinbopanna deleted the samsung_pay branch September 20, 2024 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-payment-methods Area: Payment Methods 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.

Add support for Samsung Pay payment method
6 participants