Skip to content

feat(router): add support for Samsung Pay payment method#5955

Merged
likhinbopanna merged 7 commits intomainfrom
samsung_pay
Sep 20, 2024
Merged

feat(router): add support for Samsung Pay payment method#5955
likhinbopanna merged 7 commits intomainfrom
samsung_pay

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": "something@gmail.com",
    "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": "something@gmail.com",
        "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": "something@gmail.com",
    "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
@semanticdiff-com
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
@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
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
@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