Skip to content

Conversation

srujanchikke
Copy link
Contributor

@srujanchikke srujanchikke commented Apr 21, 2025

Type of Change

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

Description

Generally in case of external payments we don't get the network error code and error messages from the billing connector. Since this data is important we need to fetch them using Psync call for the Payment connectors and update our payment attempts. In this PR we have added support for Psync in record attempt flow .

Additional Changes

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

Motivation and Context

We are currently recording external attempts from billing connector. To populate necessary data to take decision from ML model we will call payment connector to get network error code and network error message.
Note : this step should be avoided for interal payments which uses record attempt flow.

How did you test it?

Note: Can't test this flow via chargebee, becuase chargebee supports stripe and braintree. And we can't get stripe and braintree network error code or network error message to update the payment attempt from PSYNC call. But providing steps to check this flow for future reference.

  1. create any payment processor
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-merchant-id: cloth_seller_u1obmbS8P5wzyGRLpGoG' \
--header 'x-profile-id: pro_aco3I1QJWu0ZWyKxzIDo' \
--header 'Authorization: admin-api-key=test_admin' \
--header 'api-key: ••••••' \
--data '{
  "connector_type": "payment_processor",
  "connector_name": "stripe",
  "connector_account_details": {
        "auth_type": "HeaderKey",
        "api_key": "stripe_api_key"
    },
  "connector_webhook_details": {
    "merchant_secret": ""
  },
  "metadata" : {
    "prefix_url" :""
  },
  "profile_id": "pro_aco3I1QJWu0ZWyKxzIDo"
}'
  1. create any billing processor, and add payment processor in revenue recovery feature metadata
curl --location 'http://localhost:8080/v2/connector-accounts' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-merchant-id: cloth_seller_u1obmbS8P5wzyGRLpGoG' \
--header 'x-profile-id: pro_aco3I1QJWu0ZWyKxzIDo' \
--header 'Authorization: admin-api-key=test_admin' \
--header 'api-key: test_admin' \
--data '{
    "connector_type": "billing_processor",
    "connector_name": "chargebee",
    "connector_account_details": {
        "auth_type": "HeaderKey",
        "api_key": "chargebee_api_key"
    },
    "connector_webhook_details": {
        "merchant_secret": "username",
        "additional_secret" : "password"
    },
    "feature_metadata": {
        "revenue_recovery": {
            "max_retry_count": 27,
            "billing_connector_retry_threshold": 2,
            "billing_account_reference": {
                "mca_HM2cIezxfzOFtlys1R53": "gw_AzZixQUeNJUxX9ye"
            }
        }
    },
    "metadata": {
        "site": "nish-test"
    },
    "profile_id": "pro_aco3I1QJWu0ZWyKxzIDo"
}'
  1. trigger payment failed external webhook from billing processor(this can be trigger from either dashboard of cb or use below curl)
curl --location 'http://localhost:8080/v2/webhooks/recovery/cloth_seller_u1obmbS8P5wzyGRLpGoG/pro_aco3I1QJWu0ZWyKxzIDo/mca_X3udn11zAvLQkJ1r7Yyo' \
--header 'Content-Type: application/json' \
--header 'Authorization: ••••••' \
--data-raw '{
  "id": "ev_169vy3UaPFn4L4mf",
  "occurred_at": 1737361021,
  "source": "admin_console",
  "user": "[email protected]",
  "object": "event",
  "api_version": "v2",
  "content": {
    "transaction": {
      "id": "txn_169vy3UaPFmC44mq",
      "customer_id": "Azq8o5UaLqWWvyGd",
      "subscription_id": "Azq8o5UaLr2WnyHG",
      "gateway_account_id": "gw_AzZixQUeNJUxX9ye",
      "payment_source_id": "pm_169vy3UaPDo0t4hL",
      "payment_method": "card",
      "gateway": "stripe",
      "type": "payment",
      "date": 1737361019,
      "exchange_rate": 1,
      "amount": 5,
      "id_at_gateway": "pi_3RLK2JSH4GMzd3pv0BWF0cuj",
      "status": "failure",
      "updated_at": 1737361021,
      "fraud_reason": "Payment complete.",
      "resource_version": 1737361021397,
      "deleted": false,
      "object": "transaction",
      "masked_card_number": "************4242",
      "currency_code": "INR",
      "base_currency_code": "INR",
      "amount_unused": 0,
      "linked_invoices": [
        {
          "invoice_id": "9",
          "applied_amount": 500000,
          "applied_at": 1737361021,
          "invoice_date": 1737361018,
          "invoice_total": 500000,
          "invoice_status": "paid"
        }
      ],
      "linked_refunds": [],
      "initiator_type": "merchant",
      "three_d_secure": false,
      "payment_method_details": "{\"card\":{\"first_name\":\"test2\",\"last_name\":\"name2\",\"iin\":\"424242\",\"last4\":\"4242\",\"funding_type\":\"credit\",\"expiry_month\":12,\"expiry_year\":2026,\"billing_addr1\":\"asdf\",\"billing_addr2\":\"asd\",\"billing_city\":\"asdf\",\"billing_state\":\"asdfaf\",\"billing_country\":\"AF\",\"billing_zip\":\"12345\",\"masked_number\":\"************4242\",\"object\":\"card\",\"brand\":\"visa\"}}"
    },
    "invoice": {
      "id": "2234r5tgfasasdfdfad3",
      "customer_id": "Azq8o5UaLqWWvyGd",
      "subscription_id": "Azq8o5UaLr2WnyHG",
      "recurring": false,
      "status": "paid",
      "price_type": "tax_exclusive",
      "date": 1737361018,
      "due_date": 1737361018,
      "net_term_days": 0,
      "exchange_rate": 1,
      "total": 5,
      "amount_paid": 0,
      "amount_adjusted": 0,
      "write_off_amount": 0,
      "credits_applied": 0,
      "amount_due": 0,
      "paid_at": 1737361019,
      "updated_at": 1737361021,
      "resource_version": 1737361021401,
      "deleted": false,
      "object": "invoice",
      "first_invoice": false,
      "amount_to_collect": 0,
      "round_off_amount": 0,
      "has_advance_charges": false,
      "currency_code": "INR",
      "base_currency_code": "INR",
      "generated_at": 1737361018,
      "is_gifted": false,
      "term_finalized": true,
      "channel": "web",
      "tax": 0,
      "line_items": [
        {
          "id": "li_169vy3UaPFmBR4md",
          "date_from": 1737361004,
          "date_to": 1737361004,
          "unit_amount": 500000,
          "quantity": 1,
          "amount": 500000,
          "pricing_model": "flat_fee",
          "is_taxed": false,
          "tax_amount": 0,
          "object": "line_item",
          "subscription_id": "Azq8o5UaLr2WnyHG",
          "customer_id": "Azq8o5UaLqWWvyGd",
          "description": "Implementation Charge",
          "entity_type": "charge_item_price",
          "entity_id": "cbdemo_implementation-charge-INR",
          "tax_exempt_reason": "tax_not_configured",
          "discount_amount": 0,
          "item_level_discount_amount": 0
        }
      ],
      "sub_total": 500000,
      "linked_payments": [
        {
          "txn_id": "txn_169vy3UaPFmC44me",
          "applied_amount": 500000,
          "applied_at": 1737361021,
          "txn_status": "success",
          "txn_date": 1737361019,
          "txn_amount": 500000
        }
      ],
      "applied_credits": [],
      "adjustment_credit_notes": [],
      "issued_credit_notes": [],
      "linked_orders": [],
      "dunning_attempts": [],
      "billing_address": {
        "first_name": "test1",
        "last_name": "name",
        "email": "[email protected]",
        "company": "johndoe",
        "phone": "+91 83 17 575848",
        "line1": "asdf",
        "line2": "asd",
        "line3": "ahjkd",
        "city": "asdf",
        "state_code": "TG",
        "state": "Telangana",
        "country": "IN",
        "zip": "561432",
        "validation_status": "not_validated",
        "object": "billing_address"
      },
      "site_details_at_creation": {
        "timezone": "Asia/Calcutta"
      }
    },
    "customer": {
      "id": "Azq8o5UaLqWWvyGd",
      "first_name": "john",
      "last_name": "doe",
      "email": "[email protected]",
      "phone": "831 757 5848",
      "company": "johndoe",
      "auto_collection": "on",
      "net_term_days": 0,
      "allow_direct_debit": false,
      "created_at": 1737310670,
      "created_from_ip": "205.254.163.189",
      "taxability": "taxable",
      "updated_at": 1737360899,
      "pii_cleared": "active",
      "channel": "web",
      "resource_version": 1737360899990,
      "deleted": false,
      "object": "customer",
      "billing_address": {
        "first_name": "test1",
        "last_name": "name",
        "email": "[email protected]",
        "company": "johndoe",
        "phone": "+91 83 17 575848",
        "line1": "asdf",
        "line2": "asd",
        "line3": "ahjkd",
        "city": "asdf",
        "state_code": "TG",
        "state": "Telangana",
        "country": "IN",
        "zip": "561432",
        "validation_status": "not_validated",
        "object": "billing_address"
      },
      "card_status": "valid",
      "promotional_credits": 0,
      "refundable_credits": 0,
      "excess_payments": 0,
      "unbilled_charges": 0,
      "preferred_currency_code": "INR",
      "mrr": 0,
      "primary_payment_source_id": "pm_169vy3UaPDo0t4hL",
      "payment_method": {
        "object": "payment_method",
        "type": "card",
        "reference_id": "cus_RcUo8xTwe0sHP7/card_1QjG2dSHworDX2hs6YIjKdML",
        "gateway": "stripe",
        "gateway_account_id": "gw_AzZixQUeNJUxX9ye",
        "status": "valid"
      }
    },
    "subscription": {
      "id": "Azq8o5UaLr2WnyHG",
      "billing_period": 1,
      "billing_period_unit": "month",
      "customer_id": "Azq8o5UaLqWWvyGd",
      "status": "active",
      "current_term_start": 1737310793,
      "current_term_end": 1739989193,
      "next_billing_at": 1739989193,
      "created_at": 1737310793,
      "started_at": 1737310793,
      "activated_at": 1737310793,
      "created_from_ip": "205.254.163.189",
      "updated_at": 1737310799,
      "has_scheduled_changes": false,
      "channel": "web",
      "resource_version": 1737310799688,
      "deleted": false,
      "object": "subscription",
      "currency_code": "INR",
      "subscription_items": [
        {
          "item_price_id": "cbdemo_premium-INR-monthly",
          "item_type": "plan",
          "quantity": 1,
          "unit_price": 100000,
          "amount": 0,
          "free_quantity": 3,
          "object": "subscription_item"
        }
      ],
      "shipping_address": {
        "first_name": "test1",
        "last_name": "name",
        "email": "[email protected]",
        "company": "johndoe",
        "phone": "+91 83 17 575848",
        "line1": "asdf",
        "line2": "asd",
        "line3": "ahjkd",
        "city": "asdf",
        "state_code": "TG",
        "state": "Telangana",
        "country": "IN",
        "zip": "561432",
        "validation_status": "not_validated",
        "object": "shipping_address"
      },
      "due_invoices_count": 0,
      "mrr": 0,
      "exchange_rate": 1,
      "base_currency_code": "INR",
      "has_scheduled_advance_invoices": false
    }
  },
  "event_type": "payment_failed",
  "webhook_status": "scheduled",
  "webhooks": [
    {
      "id": "whv2_6oZfZUaLmtchA5Bl",
      "webhook_status": "scheduled",
      "object": "webhook"
    }
  ]
}'
  1. Using gateway transaction id, recovery record attempt flow should call the connector and fetch network error code and network error message.

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

Copy link

semanticdiff-com bot commented Apr 21, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/hyperswitch_domain_models/src/payments.rs  0% smaller
  crates/router/src/core/payments.rs  0% smaller
  crates/router/src/core/payments/operations/payment_attempt_record.rs  0% smaller

@srujanchikke srujanchikke self-assigned this Apr 22, 2025
@srujanchikke srujanchikke added the A-core Area: Core flows label Apr 22, 2025
@srujanchikke srujanchikke marked this pull request as ready for review April 22, 2025 07:33
@srujanchikke srujanchikke requested review from a team as code owners April 22, 2025 07:33
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue May 12, 2025
Merged via the queue into main with commit 60835ab May 12, 2025
32 of 36 checks passed
@Gnanasundari24 Gnanasundari24 deleted the psync_external_payments branch May 12, 2025 14:30
pixincreate added a commit that referenced this pull request May 12, 2025
…adyen-ideal

* 'main' of github.com:juspay/hyperswitch: (62 commits)
  fix(core): language consumption from locale in payment and payout links (#7993)
  feat(refunds_v2): Add refunds list flow in v2 apis (#7966)
  refactor(connector): [Noon] auth header (#7977)
  fix(connector): [Novalnet] send decoded token for apple pay payment (#7973)
  feat(business_profile): add business_profile config to enable external vault (#7876)
  feat(vsaas): integrate onboarding flow for vertical saas (#7884)
  feat(connector): Introduce connector template code for WorldpayXML  (#7968)
  feat(connector): [ADYEN, CHECKOUT] Added In Feature Matrix API (#7914)
  feat(core): add psync support for recovery external payments (#7855)
  refactor(open_router): call elimination routing of open router if enabled instead of dynamo (#7961)
  feat(payment_methods): add v2 api for fetching token data (#7629)
  ci(cypress): Fix Bank Redirects for stripe test (#8004)
  chore(version): 2025.05.12.0
  refactor(authentication): moved cavv storing from table to temp locker (#7978)
  chore(version): 2025.05.09.0
  feat(connector): [paypal, trustpay] add in feature matrix (#7911)
  fix(update_metadata): Update Metadata for any connectors other than stripe gives 500 error (#7984)
  fix(router): Fixed stack over flow for session call in authentication connectors (#7983)
  chore(version): 2025.05.08.0
  fix(payment): disable payment update via client config (#7970)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-core Area: Core flows
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants