Skip to content

fix(customers): resolve unimplemented payment method deletion in v2#11192

Open
GauravRawat369 wants to merge 8 commits intomainfrom
fix-customer-delete
Open

fix(customers): resolve unimplemented payment method deletion in v2#11192
GauravRawat369 wants to merge 8 commits intomainfrom
fix-customer-delete

Conversation

@GauravRawat369
Copy link
Contributor

@GauravRawat369 GauravRawat369 commented Feb 9, 2026

Type of Change

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

Description

This pull request updates the customer deletion flow to support a new v2 API, refactoring how customer payment methods are deleted and improving type safety and modularity. The main changes involve switching from a provider-based to a platform-based approach, updating trait definitions, and ensuring all associated payment methods are deleted using the new v2 payment method deletion logic.

Refactoring and API improvements:

  • Changed the delete_customer function signature and its usages to accept platform and profile instead of provider, aligning with the v2 API structure. [1] [2]
  • Updated the CustomerDeleteBridge trait, splitting it into v1 and v2 versions, with the v2 version accepting platform and profile for more flexible and accurate context handling. [1] [2]

Payment method deletion enhancements:

  • Replaced the old card-specific deletion logic with a call to the new generic delete_payment_method function for each payment method, ensuring all payment methods are properly deleted during customer deletion in v2.
  • Added necessary imports for PaymentMethodId and delete_payment_method to support the new payment method deletion flow. [1] [2]

Code organization:

  • Scoped the new trait implementation and logic to the v2 feature flag, ensuring backward compatibility with the v1 API. [1] [2]

The function calls delete_card_by_locker_id() which just has todo!(), causing a panic.

{"hostname":"sandbox-v2-hyperswitch-server-78c5ff589d-5fs8h","pid":7,"env":"sandbox","version":"2026.01.28.1-14-geebf25d-eebf25d-2026-01-28T11:48:14.000000000Z","build":"0.1.0-eebf25d-2026-01-28T11:48:14.000000000Z-1.93.0-release-x86_64-unknown-linux-gnu","level":"ERROR","target":"router::core::payment_methods","service":"router","line":2836,"file":"crates/router/src/core/payment_methods.rs","fn":"vault_payment_method_internal","full_name":"router::core::payment_methods::vault_payment_method_internal","time":"2026-02-09T10:21:45.517602948Z","message":"[VAULT_PAYMENT_METHOD_INTERNAL - EVENT] Vault Fingerprint_id error: {\"error\":{\"type\":\"server_not_available\",\"code\":\"HE_00\",\"message\":\"Something went wrong\"}}\n├╴at crates/router/src/core/payment_methods.rs:2834:10\n├╴Failed to find payment method by fingerprint_id\n│\n├─▶ ValueNotFound: Value not found\n│   ╰╴at /router/crates/storage_impl/src/lib.rs:203:23\n│\n├─▶ The requested resource was not found in the database\n│   ├╴at /router/crates/diesel_models/src/query/generics.rs:377:51\n│   ╰╴Error finding record by predicate\n│\n╰─▶ Record not found\n    ╰╴at /router/crates/diesel_models/src/query/generics.rs:377:38","request_method":"POST","merchant_id":"cloth_seller_1afnLq6qTKbtQSDdUffA","flow":"PaymentMethodsCreate","request_id":"019c41eb-e869-7933-b57e-e78db9270f68","request_url_path":"/v2/payment-methods","extra":{"trace_id":"00000000000000000000000000000000","http.flavor":"1.1","http.target":"/v2/payment-methods","http.user_agent":"PostmanRuntime/7.43.2","http.scheme":"http","http.host":"sandbox.hyperswitch.io","http.client_ip":"219.65.110.2","otel.kind":"server","tenant_id":"public","http.route":"/v2/payment-methods","otel.name":"POST /v2/payment-methods","http.method":"POST","lock_action":"NotApplicable"}}

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?

Customer Create Request & Response
curl --location 'http://localhost:8080/v2/customers' \
--header 'x-profile-id: pro_2ChaIEIXfDBmEBibfJ0z' \
--header 'Authorization: api-key=dev_bSROZXyou6FCp0Ou7gtEVaRBHGWdMtqhontwRz10zjH2lnoJUi0iEhClNNomAshN' \
--header 'Content-Type: application/json' \
--data-raw '{   
    "merchant_reference_id": "customer_1770640846",
    "name": "John Doe",
    "email": "[email protected]",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "First customer",
    "default_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"
    },
    "default_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"
    },
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'

res

{
    "id": "12345_cus_019c426b1b25719293136900c9fcfe9a",
    "merchant_reference_id": "customer_1770640841",
    "connector_customer_ids": null,
    "name": "John Doe",
    "email": "[email protected]",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "First customer",
    "default_billing_address": null,
    "default_shipping_address": null,
    "created_at": "2026-02-09T12:40:41.510Z",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "default_payment_method_id": null,
    "tax_registration_id": null
}
Pm create with new created customer_id
curl --location 'http://localhost:8080/v2/payment-methods' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'X-Profile-Id: pro_2ChaIEIXfDBmEBibfJ0z' \
--header 'Authorization: api-key=dev_bSROZXyou6FCp0Ou7gtEVaRBHGWdMtqhontwRz10zjH2lnoJUi0iEhClNNomAshN' \
--data '{
    "customer_id": "12345_cus_019c426b1b25719293136900c9fcfe9a",
    "payment_method_type": "card",
    "payment_method_subtype": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "3056930009020004",
            "card_exp_month": "03",
            "card_exp_year": "2029",
            "card_holder_name": "joseph Doe"
        }
    }

}'

res

{
    "id": "12345_pm_019c426f5d827611ba8a0ee574d6b24b",
    "merchant_id": "cloth_seller_eMv6boDTRoXdNDH9oA7i",
    "customer_id": "12345_cus_019c426b1b25719293136900c9fcfe9a",
    "payment_method_type": "card",
    "payment_method_subtype": "credit",
    "recurring_enabled": false,
    "created": "2026-02-09T12:45:20.643Z",
    "last_used_at": "2026-02-09T12:45:20.643Z",
    "payment_method_data": {
        "card": {
            "issuer_country": null,
            "last4_digits": "0004",
            "expiry_month": "03",
            "expiry_year": "2029",
            "card_holder_name": "joseph Doe",
            "card_fingerprint": null,
            "nick_name": null,
            "card_network": null,
            "card_isin": null,
            "card_issuer": null,
            "card_type": null,
            "saved_to_locker": true
        }
    },
    "connector_tokens": null,
    "network_token": null,
    "storage_type": null,
    "card_cvc_token_storage": null
}
Customer delete
curl --location --request DELETE 'http://localhost:8080/v2/customers/12345_cus_019c426b1b25719293136900c9fcfe9a' \
--header 'x-profile-id: pro_2ChaIEIXfDBmEBibfJ0z' \
--header 'Authorization: api-key=dev_bSROZXyou6FCp0Ou7gtEVaRBHGWdMtqhontwRz10zjH2lnoJUi0iEhClNNomAshN' \
--header 'api-key: dev_bSROZXyou6FCp0Ou7gtEVaRBHGWdMtqhontwRz10zjH2lnoJUi0iEhClNNomAshN'

res

{
    "id": "12345_cus_019c426b1b25719293136900c9fcfe9a",
    "merchant_reference_id": "customer_1770640841",
    "customer_deleted": true,
    "address_deleted": true,
    "payment_methods_deleted": true
}
The payment method is being set to inactive image

Created 2 pm for a customer
vault entry
image
After customer deletion(removed from vault as well)
image

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

@GauravRawat369 GauravRawat369 requested a review from a team as a code owner February 9, 2026 12:51
@semanticdiff-com
Copy link

semanticdiff-com bot commented Feb 9, 2026

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/core/payment_methods.rs  38% smaller
  crates/router/src/core/customers.rs  26% smaller
  crates/router/src/routes/customers.rs  19% smaller

@GauravRawat369 GauravRawat369 changed the title fix(customers): remove commented-out card deletion logic in CustomerDeleteBridge fix(customers): resolve unimplemented payment method deletion in v2 Feb 9, 2026
@GauravRawat369 GauravRawat369 self-assigned this Feb 9, 2026
ShankarSinghC
ShankarSinghC previously approved these changes Feb 13, 2026
@GauravRawat369 GauravRawat369 added the S-test-ready Status: This PR is ready for cypress-tests label Feb 13, 2026
Comment on lines 763 to 769
Box::pin(delete_payment_method(
state.clone(),
pm_id,
platform.clone(),
profile.clone(),
))
.await
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of calling the entire delete_payment_method, for now we can extract the required logic from delete_payment_method_core into a common function and invoke it from both here and delete_payment_method_core.
This way, we can avoid the unnecessary payment method and customer-related database calls made by redact_customer_details_and_generate_response and delete_payment_method_core.

@GauravRawat369 GauravRawat369 requested a review from a team as a code owner February 14, 2026 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-test-ready Status: This PR is ready for cypress-tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants