Skip to content

feat(core): Implement UCS based upi for paytm and phonepe #8732

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

Merged
merged 22 commits into from
Jul 31, 2025

Conversation

maverox
Copy link
Contributor

@maverox maverox commented Jul 23, 2025

Type of Change

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

Fixed #8734

Description

This PR implements UPI Intent and QR code payment flows for the Unified Connector Service (UCS) integration, adding default implementations for Paytm and PhonePe connectors.

Key Changes:

  • Default Connector Implementations: Added default implementations for Paytm and PhonePe connectors (the actual payment processing integration is handled by UCS)
  • UPI Intent Flow: Implemented UPI Intent payment method support for mobile app integrations through UCS
  • QR Code Flow: Added QR code generation and payment flow support for UPI payments via UCS
  • UCS Enhancement: Extended the Unified Connector Service to route UPI Intent and QR code payment requests
  • Configuration: Added necessary configuration entries for both connectors across all environments
  • Testing: Included test suites for the default implementations

Note: This PR does not implement direct integrations with Paytm or PhonePe APIs. The actual payment processing and API communication is handled by the Unified Connector Service (UCS). This PR provides the necessary scaffolding and routing logic to support these payment methods through UCS.

Additional Changes

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

Configuration changes can be found in:

  • config/development.toml
  • config/deployments/production.toml
  • config/deployments/sandbox.toml
  • config/deployments/integration_test.toml
  • crates/connector_configs/toml/*.toml

Motivation and Context

This change enables merchants to accept UPI payments through Paytm and PhonePe payment gateways using the Unified Connector Service. UPI is a crucial payment method in India, and supporting Intent and QR code flows allows for seamless integration across mobile apps and web platforms.

The implementation leverages the UCS architecture where:

  • Hyperswitch provides the routing and orchestration layer
  • UCS handles the actual integration with Paytm and PhonePe APIs
  • This PR adds the necessary connector definitions and routing logic to support these payment methods

How did you test it?

Automated Tests

  • Added integration tests for both Paytm and PhonePe default implementations in crates/router/tests/connectors/
  • Tests verify:
    • Proper routing of payment requests to UCS
    • UPI Intent payment method handling
    • QR code flow support
    • Status sync operations
    • Refund request routing
    • Webhook handling
  • All tests pass successfully with the new implementations

Manual Testing

  1. Enable UCS configuration:
curl --location 'http://localhost:8080/configs/' \
--header 'Content-Type: application/json' \
--header 'api-key: [REDACTED]' \
--header 'x-tenant-id: public' \
--data '{
    "key": "ucs_enabled",
    "value": "true"
}'
  1. Create a UPI Intent payment request:
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: [REDACTED]' \
--data-raw '{
    "amount": 1000,
    "currency": "INR",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 1000,
    "customer_id": "IatapayCustomer",
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://google.com",
    "payment_method": "upi",
    "payment_method_type": "upi_intent",
    "payment_method_data": {
        "upi": {
            "upi_intent": {}
        },
        "billing": {
            "address": {
                "line1": "1467",
                "line2": "Harrison Street",
                "line3": "Harrison Street",
                "city": "San Fransico",
                "state": "California",
                "zip": "94122",
                "country": "IN",
                "first_name": "Swangi",
                "last_name": "Kumari"
            },
            "phone": {
                "number": "8056594427",
                "country_code": "+91"
            },
            "email": "[email protected]"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "IN",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "[email protected]"
    },
    "shipping": {
        "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"
        },
        "email": "[email protected]"
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "all_keys_required": true
}'
  1. Successful payment response received:
{
    "payment_id": "pay_XzkwJ5pFVTmuGGAXBy3G",
    "merchant_id": "merchant_1753180563",
    "status": "processing",
    "amount": 1000,
    "net_amount": 1000,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "phonepe",
    "client_secret": "[REDACTED]",
    "created": "2025-07-23T08:36:35.265Z",
    "currency": "INR",
    "customer_id": "IatapayCustomer",
    "customer": {
        "id": "IatapayCustomer",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "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": "upi",
    "payment_method_data": {
        "upi": {
            "upi_intent": {}
        },
        "billing": {
            "address": {
                "city": "San Fransico",
                "country": "IN",
                "line1": "1467",
                "line2": "Harrison Street",
                "line3": "Harrison Street",
                "zip": "94122",
                "state": "California",
                "first_name": "Swangi",
                "last_name": "Kumari"
            },
            "phone": {
                "number": "8056594427",
                "country_code": "+91"
            },
            "email": "[email protected]"
        }
    },
    "payment_token": null,
    "shipping": {
        "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": "[email protected]"
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "IN",
            "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": "[email protected]"
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": {
        "type": "qr_code_information",
        "image_data_url": "[REDACTED BASE64 QR CODE DATA]",
        "display_to_timestamp": null,
        "qr_code_url": null,
        "display_text": null,
        "border_color": null
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "upi_intent",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "IatapayCustomer",
        "created_at": 1753259795,
        "expires": 1753263395,
        "secret": "[REDACTED]"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "pay_XzkwJ5pFVTmuGGAXBy3G_1",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_XzkwJ5pFVTmuGGAXBy3G_1",
    "payment_link": null,
    "profile_id": "pro_aDyARAw6YQZAPr6sqHgi",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_fTVznSS9dGiTX3QEXrg3",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-07-23T08:51:35.265Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-07-23T08:36:35.797Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": null,
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": "{\"success\":true,\"code\":\"PAYMENT_INITIATED\",\"message\":\"Payment initiated\",\"data\":{\"merchantId\":\"JUSPAONLINE\",\"merchantTransactionId\":\"pay_XzkwJ5pFVTmuGGAXBy3G_1\",\"instrumentResponse\":{\"type\":\"UPI_INTENT\",\"intentUrl\":\"upi://pay?pa=JUSPAONLINE@ybl&pn=Juspay&am=10.00&mam=10.00&tr=OM2507231406356135400588&tn=Payment%20for%20pay_XzkwJ5pFVTmuGGAXBy3G_1&mc=6051&mode=04&purpose=00&utm_campaign=B2B_PG&utm_medium=JUSPAONLINE&utm_source=OM2507231406356135400588\"}}}"
}

The response shows successful routing through UCS with QR code generation (when invoked from sdk) for UPI payment.

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

@maverox maverox requested review from a team as code owners July 23, 2025 12:23
Copy link

semanticdiff-com bot commented Jul 23, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/connector.rs  98% smaller
  crates/hyperswitch_connectors/src/connectors.rs  61% smaller
  crates/payment_methods/src/configs/payment_connector_required_fields.rs  50% smaller
  crates/common_enums/src/connector_enums.rs  22% smaller
  crates/hyperswitch_connectors/src/default_implementations_v2.rs  19% smaller
  crates/hyperswitch_connectors/src/default_implementations.rs  19% smaller
  crates/router/src/core/unified_connector_service/transformers.rs  4% smaller
  Cargo.lock Unsupported file format
  api-reference/v1/openapi_spec_v1.json  0% smaller
  api-reference/v2/openapi_spec_v2.json  0% 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
  config/payment_required_fields_v2.toml Unsupported file format
  crates/connector_configs/src/connector.rs  0% 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/external_services/Cargo.toml Unsupported file format
  crates/external_services/src/grpc_client/unified_connector_service.rs  0% smaller
  crates/hyperswitch_connectors/src/connectors/paytm.rs  0% smaller
  crates/hyperswitch_connectors/src/connectors/paytm/transformers.rs  0% smaller
  crates/hyperswitch_connectors/src/connectors/phonepe.rs  0% smaller
  crates/hyperswitch_connectors/src/connectors/phonepe/transformers.rs  0% smaller
  crates/hyperswitch_domain_models/src/connector_endpoints.rs  0% smaller
  crates/router/Cargo.toml Unsupported file format
  crates/router/src/core/connector_validation.rs  0% smaller
  crates/router/src/core/unified_connector_service.rs  0% smaller
  crates/router/src/types/api/connector_mapping.rs  0% smaller
  crates/router/src/types/connector_transformers.rs  0% smaller
  crates/router/tests/connectors/main.rs  0% smaller
  crates/router/tests/connectors/paytm.rs  0% smaller
  crates/router/tests/connectors/phonepe.rs  0% smaller
  crates/test_utils/src/connector_auth.rs  0% smaller
  loadtest/config/development.toml Unsupported file format
  scripts/add_connector.sh Unsupported file format

@maverox maverox self-assigned this Jul 23, 2025
@maverox maverox changed the title Implement ucs upi intent paytm phonepe feat(core): Implement UCS based upi for paytm and phonepe Jul 23, 2025
@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Jul 23, 2025
@maverox maverox requested a review from a team as a code owner July 28, 2025 09:48
jarnura
jarnura previously approved these changes Jul 29, 2025
@maverox maverox dismissed stale reviews from su-shivanshmathur and jarnura via 6488248 July 31, 2025 07:10
jarnura
jarnura previously approved these changes Jul 31, 2025
jarnura
jarnura previously approved these changes Jul 31, 2025
@Gnanasundari24 Gnanasundari24 enabled auto-merge July 31, 2025 11:06
maverox added 2 commits July 31, 2025 17:26
Resolved conflicts by including both katapult (from main) and paytm/phonepe (from feature branch) connectors
@maverox maverox dismissed stale reviews from jarnura and su-shivanshmathur via f3cada4 July 31, 2025 12:08
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Jul 31, 2025
Merged via the queue into main with commit 01e9474 Jul 31, 2025
15 of 20 checks passed
@Gnanasundari24 Gnanasundari24 deleted the implement_ucs_upi_intent_paytm_phonepe branch July 31, 2025 14:18
pixincreate added a commit that referenced this pull request Aug 1, 2025
…rver

* 'main' of github.com:juspay/hyperswitch: (25 commits)
  chore: `xof` currency to cybersource cards (#8799)
  chore(version): 2025.08.01.0
  feat(core): Implement UCS based  upi for  paytm and phonepe (#8732)
  feat(connector): [katapult]add template code for katapult (#8783)
  feat(router): introduce `feature`  and `feature_data` to gsm (#7771)
  feat(connector): [cybersource] add changes for field CybersourceConsumerAuthInformation (#8768)
  feat(authentication): added authentication sync api (#8596)
  feat(connector): [facilitapay] fix refunds, add webhook and void support (#8778)
  feat(connector): [payload] add recurring payments (#8597)
  chore(version): 2025.07.31.0
  feat(connector): [Flexiti]Add support for flexiti connector  (#8743)
  chore(router): events enhancement for kafka (#8780)
  ci(cypress): Making a mandate payment with large customer user agents (#8790)
  fix(openapi): update create_platform endpoint in api-reference docs (#8782)
  chore(version): 2025.07.30.0
  fix(connector): [GLOBALPAY] Added Tokenization Flow for CITs (#8568)
  feat(routing): Add api-refs for new decision engine endpoints (#8709)
  fix: replace xtrim with xdel to support  older redis version (#8515)
  fix(connector): [Worldpay] handle multiple ddc submission for CompleteAuthorize (#8741)
  feat(connector): [Adyen] receive incoming webhooks for pix expiry (#8720)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
M-api-contract-changes Metadata: This PR involves API contract changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(core): Implement UCS based upi for paytm and phonepe
4 participants