Skip to content

feat(subscription): domain_model for subscription and invoice#9640

Merged
likhinbopanna merged 27 commits intomainfrom
subscription-domain_model
Oct 9, 2025
Merged

feat(subscription): domain_model for subscription and invoice#9640
likhinbopanna merged 27 commits intomainfrom
subscription-domain_model

Conversation

@AnkitKmrGupta
Copy link
Contributor

@AnkitKmrGupta AnkitKmrGupta commented Oct 1, 2025

Type of Change

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

Description

This pull request introduces new domain models for subscriptions and invoices, and refactors the codebase to use these models instead of the previous Diesel-based models. The changes improve type safety and abstraction for subscription and invoice handling, and update relevant interfaces and function calls throughout the codebase to use the new models.

Domain Model Additions:

  • Added a new Subscription domain model in crates/hyperswitch_domain_models/src/subscription.rs, including the SubscriptionStatus enum, conversion traits, and the SubscriptionInterface trait for standardized operations. Also added the SubscriptionUpdate struct with conversion logic.
  • Added a new Invoice domain model in crates/hyperswitch_domain_models/src/invoice.rs, including conversion traits, the InvoiceInterface trait for CRUD operations, and the InvoiceUpdate struct with conversion logic.

Refactoring and Integration:

  • Refactored all subscription and invoice-related logic in crates/router/src/core/subscription.rs and crates/router/src/core/subscription/billing_processor_handler.rs to use the new domain models (hyperswitch_domain_models::subscription::Subscription and hyperswitch_domain_models::invoice::Invoice) instead of Diesel models. [1] [2] [3] [4] [5] [6] [7] [8]
  • Updated the invoice creation logic in invoice_handler.rs to use the new domain model and retrieve the merchant key store for secure operations.

Module Organization:

  • Registered the new invoice and subscription modules in crates/hyperswitch_domain_models/src/lib.rs for proper integration with the rest of the domain models. [1] [2]

These changes lay the groundwork for improved maintainability and extensibility in handling subscriptions and invoices in the codebase.

How did you test it?

Create Billing Connector

curl --location 'http://localhost:8080/account/merchant_1759737987/connectors' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: ****' \
--data '{
    "connector_type": "billing_processor",
    "connector_name": "chargebee",
    "connector_account_details": {
        "auth_type": "HeaderKey",
        "api_key": "****"
    },
    "business_country": "US",
    "business_label": "default",
    "connector_webhook_details": {
        "merchant_secret": "hyperswitch",
        "additional_secret": "hyperswitch"
    },
    "metadata": {
        "site": "hyperswitch-juspay3-test"
    }
}'
{
    "connector_type": "billing_processor",
    "connector_name": "chargebee",
    "connector_label": "chargebee_US_default",
    "merchant_connector_id": "mca_nyehf3o9gtzGgeVFzsx0",
    "profile_id": "pro_Ba2HYJtnuKdJzv2SBizB",
    "connector_account_details": {
        "auth_type": "HeaderKey",
        "api_key": "te**********************************MK"
    },
    "payment_methods_enabled": null,
    "connector_webhook_details": {
        "merchant_secret": "hyperswitch",
        "additional_secret": "hyperswitch"
    },
    "metadata": {
        "site": "hyperswitch-juspay3-test"
    },
    "test_mode": null,
    "disabled": false,
    "frm_configs": null,
    "business_country": "US",
    "business_label": "default",
    "business_sub_label": null,
    "applepay_verified_domains": null,
    "pm_auth_config": null,
    "status": "active",
    "additional_merchant_data": null,
    "connector_wallets_details": null
}

Update profile to set the billing processor

curl --location 'http://localhost:8080/account/merchant_1759737987/business_profile/pro_Ba2HYJtnuKdJzv2SBizB' \
--header 'Content-Type: application/json' \
--header 'api-key: ****' \
--data '{
  "billing_processor_id": "mca_nyehf3o9gtzGgeVFzsx0"
}'

{
    "merchant_id": "merchant_1759737987",
    "profile_id": "pro_Ba2HYJtnuKdJzv2SBizB",
    "profile_name": "US_default",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "payment_response_hash_key": "BPIswjNm5ivN92rBE9J4ShmB2dfLVLeQ8DRnzY7cR7qsaUlfNpBgvnOCBWRfhR5e",
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": "https://webhook.site",
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true,
        "payment_statuses_enabled": null,
        "refund_statuses_enabled": null,
        "payout_statuses_enabled": null
    },
    "metadata": null,
    "routing_algorithm": null,
    "intent_fulfillment_time": 900,
    "frm_routing_algorithm": null,
    "payout_routing_algorithm": null,
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": null,
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "extended_card_info_config": null,
    "collect_shipping_details_from_wallet_connector": false,
    "collect_billing_details_from_wallet_connector": false,
    "always_collect_shipping_details_from_wallet_connector": false,
    "always_collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null,
    "tax_connector_id": null,
    "is_tax_connector_enabled": false,
    "is_network_tokenization_enabled": false,
    "is_auto_retries_enabled": false,
    "max_auto_retries_enabled": null,
    "always_request_extended_authorization": null,
    "is_click_to_pay_enabled": false,
    "authentication_product_ids": null,
    "card_testing_guard_config": {
        "card_ip_blocking_status": "disabled",
        "card_ip_blocking_threshold": 3,
        "guest_user_card_blocking_status": "disabled",
        "guest_user_card_blocking_threshold": 10,
        "customer_id_blocking_status": "disabled",
        "customer_id_blocking_threshold": 5,
        "card_testing_guard_expiry": 3600
    },
    "is_clear_pan_retries_enabled": false,
    "force_3ds_challenge": false,
    "is_debit_routing_enabled": false,
    "merchant_business_country": null,
    "is_pre_network_tokenization_enabled": false,
    "acquirer_configs": null,
    "is_iframe_redirection_enabled": null,
    "merchant_category_code": null,
    "merchant_country_code": null,
    "dispute_polling_interval": null,
    "is_manual_retry_enabled": null,
    "always_enable_overcapture": null,
    "is_external_vault_enabled": "skip",
    "external_vault_connector_details": null,
    "billing_processor_id": "mca_nyehf3o9gtzGgeVFzsx0"
}

Create Customer

curl --location 'http://localhost:8080/customers' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: ****' \
--data-raw '{
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "First customer",
    "address": {
        "line1": "1467",
        "line2": "Harrison Street",
        "line3": "Harrison Street",
        "city": "San Fransico",
        "state": "California",
        "zip": "94122",
        "country": "US",
        "first_name": "joseph",
        "last_name": "Doe"
    },
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'

{
    "customer_id": "cus_EkIUbktzRFCHooI9Kylq",
    "name": "John Doe",
    "email": "guest@example.com",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "First customer",
    "address": {
        "city": "San Fransico",
        "country": "US",
        "line1": "1467",
        "line2": "Harrison Street",
        "line3": "Harrison Street",
        "zip": "94122",
        "state": "California",
        "first_name": "joseph",
        "last_name": "Doe",
        "origin_zip": null
    },
    "created_at": "2025-10-06T08:08:37.562Z",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "default_payment_method_id": null,
    "tax_registration_id": null
}

Create Subscription

curl --location 'http://localhost:8080/subscriptions/create' \
--header 'Content-Type: application/json' \
--header 'X-Profile-Id: pro_Ba2HYJtnuKdJzv2SBizB' \
--header 'api-key: ****' \
--data '{
    "customer_id": "cus_EkIUbktzRFCHooI9Kylq",
    "amount": 14100,
    "currency": "USD",
    "payment_details": {
        "authentication_type": "no_three_ds",
        "setup_future_usage": "off_session",
        "capture_method": "automatic",
        "return_url": "https://google.com"
    }
}'
{
    "id": "sub_Q1ttH0p1b50OtnDgZfrz",
    "merchant_reference_id": null,
    "status": "created",
    "plan_id": null,
    "profile_id": "pro_Ba2HYJtnuKdJzv2SBizB",
    "client_secret": "sub_Q1ttH0p1b50OtnDgZfrz_secret_jXFTn0oMPowj2RqRUcWX",
    "merchant_id": "merchant_1759737987",
    "coupon_code": null,
    "customer_id": "cus_EkIUbktzRFCHooI9Kylq"
}

Confirm Subscription

curl --location 'http://localhost:8080/subscriptions/sub_Q1ttH0p1b50OtnDgZfrz/confirm' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_Ba2HYJtnuKdJzv2SBizB' \
--header 'api-key: ****' \
--data '{
    "item_price_id": "cbdemo_enterprise-suite-monthly",
    "customer_id": "cus_EkIUbktzRFCHooI9Kylq",
    "description": "Hello this is description",
    "shipping": {
        "address": {
            "state": "zsaasdas",
            "city": "Banglore",
            "country": "US",
            "line1": "sdsdfsdf",
            "line2": "hsgdbhd",
            "line3": "alsksoe",
            "zip": "571201",
            "first_name": "joseph",
            "last_name": "doe"
        },
        "phone": {
            "number": "123456789",
            "country_code": "+1"
        }
    },
    "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": "123456789",
            "country_code": "+1"
        }
    },
    "payment_details": {
        "payment_method": "card",
        "payment_method_type": "credit",
        "payment_method_data": {
            "card": {
                "card_number": "4111111111111111",
                "card_exp_month": "03",
                "card_exp_year": "2030",
                "card_holder_name": "CLBRW dffdg",
                "card_cvc": "737"
            }
        },
        "customer_acceptance": {
            "acceptance_type": "online",
            "accepted_at": "1963-05-03T04:07:52.723Z",
            "online": {
                "ip_address": "127.0.0.1",
                "user_agent": "amet irure esse"
            }
        }
    }
}'
{
    "id": "sub_Q1ttH0p1b50OtnDgZfrz",
    "merchant_reference_id": null,
    "status": "active",
    "plan_id": null,
    "price_id": null,
    "coupon": null,
    "profile_id": "pro_Ba2HYJtnuKdJzv2SBizB",
    "payment": {
        "payment_id": "pay_uadWety0AlrsIpLa2Dt6",
        "status": "succeeded",
        "amount": 14100,
        "currency": "USD",
        "connector": "stripe",
        "payment_method_id": "pm_HBp7wdIyHsvnta708kxF",
        "payment_experience": null,
        "error_code": null,
        "error_message": null,
        "payment_method_type": "credit"
    },
    "customer_id": "cus_EkIUbktzRFCHooI9Kylq",
    "invoice": {
        "id": "invoice_UwA8TmKbXgxE1a7s6Nux",
        "subscription_id": "sub_Q1ttH0p1b50OtnDgZfrz",
        "merchant_id": "merchant_1759737987",
        "profile_id": "pro_Ba2HYJtnuKdJzv2SBizB",
        "merchant_connector_id": "mca_nyehf3o9gtzGgeVFzsx0",
        "payment_intent_id": "pay_uadWety0AlrsIpLa2Dt6",
        "payment_method_id": "pm_HBp7wdIyHsvnta708kxF",
        "customer_id": "cus_EkIUbktzRFCHooI9Kylq",
        "amount": 14100,
        "currency": "USD",
        "status": "payment_pending"
    },
    "billing_processor_subscription_id": "sub_Q1ttH0p1b50OtnDgZfrz"
}

Screenshots

Screenshot 2025-10-06 at 1 44 10 PM Screenshot 2025-10-06 at 1 44 18 PM

@AnkitKmrGupta AnkitKmrGupta requested review from a team as code owners October 1, 2025 09:39
@semanticdiff-com
Copy link

semanticdiff-com bot commented Oct 1, 2025

@AnkitKmrGupta AnkitKmrGupta changed the title Subscription domain model feat(subscription): subscription conversions Oct 1, 2025
@AnkitKmrGupta AnkitKmrGupta changed the title feat(subscription): subscription conversions feat(subscription): domain_model for subscription and invoice Oct 6, 2025
@AnkitKmrGupta AnkitKmrGupta self-assigned this Oct 6, 2025
@AnkitKmrGupta AnkitKmrGupta linked an issue Oct 7, 2025 that may be closed by this pull request
jagan-jaya
jagan-jaya previously approved these changes Oct 8, 2025
jarnura
jarnura previously approved these changes Oct 8, 2025
@AnkitKmrGupta AnkitKmrGupta dismissed stale reviews from jarnura and jagan-jaya via 1385353 October 8, 2025 16:26
@likhinbopanna likhinbopanna added this pull request to the merge queue Oct 9, 2025
Merged via the queue into main with commit 17986c3 Oct 9, 2025
23 of 25 checks passed
@likhinbopanna likhinbopanna deleted the subscription-domain_model branch October 9, 2025 10:51
chaitak-gorai pushed a commit that referenced this pull request Oct 16, 2025
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Jagan <jaganelavarasan@gmail.com>
drdholu pushed a commit to drdholu/hyperswitch that referenced this pull request Oct 30, 2025
…#9640)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Jagan <jaganelavarasan@gmail.com>
aadityaguptaa pushed a commit that referenced this pull request Nov 10, 2025
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Jagan <jaganelavarasan@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(subscription): domain_model for subscription and invoice

4 participants