-
Notifications
You must be signed in to change notification settings - Fork 4.2k
feat(core): consume card details from billing connectors and first error codes and store them in payment intent table #8250
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
feat(core): consume card details from billing connectors and first error codes and store them in payment intent table #8250
Conversation
…tion_monitoring_feilds
WalkthroughThis change extends payment and revenue recovery data models to include new fields for card network, card issuer, and additional error codes related to payment attempts. It updates struct definitions, API schemas, and transformation logic across multiple modules, introducing asynchronous operations for fetching card issuer details and enhancing metadata propagation throughout the payment and revenue recovery workflows. Changes
Sequence Diagram(s)sequenceDiagram
participant Webhook
participant RecoveryAttempt
participant Store
participant PaymentRecord
Webhook->>RecoveryAttempt: record_payment_attempt()
RecoveryAttempt->>RecoveryAttempt: create_payment_record_request(state, ...)
alt card_isin present
RecoveryAttempt->>Store: fetch_card_info(card_isin)
Store-->>RecoveryAttempt: card_info (may include issuer)
RecoveryAttempt->>RecoveryAttempt: extract card_issuer
end
RecoveryAttempt-->>PaymentRecord: PaymentsAttemptRecordRequest (with card_network, card_issuer, error codes)
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (3)
crates/router/src/core/webhooks/recovery_incoming.rs (1)
618-633
: LGTM! Error handling implementation addresses previous review feedback.The implementation correctly logs the error when fetching card info fails, rather than ignoring it silently, which addresses the previous review comment by srujanchikke.
crates/hyperswitch_domain_models/src/payments.rs (1)
972-1010
: Error code extraction logic correctly handles PG and network codes separately.The implementation correctly retrieves PG error codes and network codes (advice/decline) as separate fields without replacing one with the other. This addresses the concern raised in the previous review comment by srujanchikke.
crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs (1)
562-563
: TODO comment appropriately addresses the card issuer implementation challenge.The comment clearly explains why card issuer details cannot be fetched in the same way as other billing connectors (Stripe doesn't provide card bin info) and indicates that an alternative approach needs to be found. This addresses the previous review comment by srujanchikke.
🧹 Nitpick comments (9)
crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs (1)
31-34
: Doc-string typo & mis-spelled acronym
/// card netword network
has a duplicated word and ISIN is almost certainly meant to be IIN (Issuer Identification Number). Consider:- /// card netword network + /// card network ... - /// card isin + /// card iin (issuer identification number – first 6-8 digits)This is only documentation so the change is low-risk but improves clarity.
crates/hyperswitch_domain_models/src/revenue_recovery.rs (1)
278-280
: Naming consistency –isin
vsissuer
These lines use
card_isin
, whereas the payment-attempt code paths usecard_issuer
. Decide on one term (card_iin
is industry-standard) and refactor. Inconsistent naming will silently drop data when converting between structs.crates/diesel_models/src/types.rs (1)
177-186
: Addskip_serializing_if
to optional fieldsThe newly-added optional fields will always be emitted as
null
, increasing payload size and breaking some strict-schema consumers. A lightweight tweak keeps the JSON clean:- pub card_network: Option<common_enums::enums::CardNetwork>, + #[serde(skip_serializing_if = "Option::is_none")] + pub card_network: Option<common_enums::enums::CardNetwork>,(repeat for the remaining
Option<String>
fields)Purely cosmetic but improves API ergonomics.
api-reference-v2/openapi_spec.json (1)
17838-17840
: Enhancecard_network
documentation
Thecard_network
property references theCardNetwork
schema but lacks its owndescription
andexample
. Consider enriching it for API consumers. For example:"card_network": { - "$ref": "#/components/schemas/CardNetwork" + "$ref": "#/components/schemas/CardNetwork", + "description": "Card network used for the payment method", + "example": "VISA" }crates/hyperswitch_domain_models/src/lib.rs (1)
308-315
: Round-trip consistency test missingThe
convert_back
implementation now emits the new metadata, which is great. To avoid regressions, please add a unit test that:
- Creates a fully-populated
ApiRevenueRecoveryMetadata
,- Converts it to
PaymentRevenueRecoveryMetadata
withconvert_from
,- Converts it back with
convert_back
,- Asserts equality with the original.
This will ensure all fields – especially the newly introduced ones – survive the round-trip unchanged.
crates/api_models/src/payments.rs (3)
8687-8691
:value_type = Option<String>
is redundant and misleading
utoipa
automatically interpretsOption<T>
from the field’s real type. Encoding the option in thevalue_type
is unnecessary and may generate an incorrect schema.- #[schema(value_type = Option<String>, example = "JP MORGAN CHASE")] + #[schema(example = "JP MORGAN CHASE")] … - #[schema(value_type = Option<String>, example = "card_declined")] + #[schema(example = "card_declined")]Apply the same simplification to all three newly-added
String
option fields.
8693-8697
: Doc string / field-name mismatch (“Error” vs “Decline”)The comment says “Network Error Code” while the field is named
first_payment_attempt_network_decline_code
. Pick one terminology across API, DB and docs to avoid confusion for integrators.
8817-8819
: Addvalue_type
for consistency or drop from both fieldsIn the first struct you provide
value_type
forcard_issuer
; here it’s omitted. Either add it or remove it from the earlier struct to keep the OpenAPI spec uniform.crates/hyperswitch_domain_models/src/payments.rs (1)
977-999
: Consider simplifying the error code extraction logic.The nested logic could be more readable by extracting error codes in a single pass.
- let (first_pg_error_code, first_network_advice_code, first_network_decline_code) = - feature_metadata_first_pg_error_code.map_or_else( - || { - let first_pg_error_code = self - .payment_attempt - .error - .as_ref() - .map(|error| error.code.clone()); - let first_network_advice_code = self - .payment_attempt - .error - .as_ref() - .and_then(|error| error.network_advice_code.clone()); - let first_network_decline_code = self - .payment_attempt - .error - .as_ref() - .and_then(|error| error.network_decline_code.clone()); - ( - first_pg_error_code, - first_network_advice_code, - first_network_decline_code, - ) - }, - |pg_code| { - let advice_code = revenue_recovery - .as_ref() - .and_then(|data| data.first_payment_attempt_network_advice_code.clone()); - let decline_code = revenue_recovery - .as_ref() - .and_then(|data| data.first_payment_attempt_network_decline_code.clone()); - (Some(pg_code), advice_code, decline_code) - }, - ); + let (first_pg_error_code, first_network_advice_code, first_network_decline_code) = + match feature_metadata_first_pg_error_code { + Some(pg_code) => { + let revenue_recovery_ref = revenue_recovery.as_ref(); + ( + Some(pg_code), + revenue_recovery_ref.and_then(|data| data.first_payment_attempt_network_advice_code.clone()), + revenue_recovery_ref.and_then(|data| data.first_payment_attempt_network_decline_code.clone()), + ) + } + None => { + self.payment_attempt.error.as_ref().map_or( + (None, None, None), + |error| ( + Some(error.code.clone()), + error.network_advice_code.clone(), + error.network_decline_code.clone(), + ) + ) + } + };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
api-reference-v2/openapi_spec.json
(2 hunks)crates/api_models/src/payments.rs
(2 hunks)crates/diesel_models/src/types.rs
(1 hunks)crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs
(2 hunks)crates/hyperswitch_connectors/src/connectors/recurly/transformers.rs
(2 hunks)crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs
(5 hunks)crates/hyperswitch_domain_models/src/lib.rs
(2 hunks)crates/hyperswitch_domain_models/src/payments.rs
(4 hunks)crates/hyperswitch_domain_models/src/revenue_recovery.rs
(2 hunks)crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs
(1 hunks)crates/router/src/core/payments/operations/payment_attempt_record.rs
(1 hunks)crates/router/src/core/payments/transformers.rs
(1 hunks)crates/router/src/core/revenue_recovery/api.rs
(1 hunks)crates/router/src/core/webhooks/recovery_incoming.rs
(4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: Validate generated OpenAPI spec file
- GitHub Check: Check wasm build
- GitHub Check: Run Cypress tests
- GitHub Check: Run tests on stable toolchain (ubuntu-latest)
- GitHub Check: Check compilation for V2 features
- GitHub Check: Check compilation on MSRV toolchain (ubuntu-latest)
🔇 Additional comments (11)
crates/router/src/core/payments/operations/payment_attempt_record.rs (1)
195-204
:✅ Verification successful
Double-check
card_issuer
versuscard_isin
naming consistencyThe new struct fields are cloned in correctly, but elsewhere in the PR (
revenue_recovery.rs
, connector transformers) the equivalent concept is namedcard_isin
. A silent mismatch betweencard_issuer
here andcard_isin
elsewhere will compile yet produceNone
in one half of the pipeline – losing the information you are trying to persist.- card_issuer: request.card_issuer.clone(), + /* make sure this name matches the field in + hyperswitch_domain_models::payments::RevenueRecoveryData + and the JSON produced by connectors */Please audit the entire codebase (or run
rg card_issuer
/rg card_isin
) and align the nomenclature to a single term.
🏁 Script executed:
#!/bin/bash # Check for inconsistent usage of card_issuer vs card_isin rg --line-number -e 'card_issuer' -e 'card_isin'Length of output: 55741
🏁 Script executed:
#!/bin/bash # Locate and display the definition of RevenueRecoveryData in the domain models rg --context 5 "struct RevenueRecoveryData" -n crates/hyperswitch_domain_models/srcLength of output: 1052
🏁 Script executed:
#!/bin/bash # Display full definition of RevenueRecoveryData to verify its fields sed -n '940,1000p' crates/hyperswitch_domain_models/src/payments.rsLength of output: 2537
No naming mismatch between
card_issuer
andcard_isin
The
RevenueRecoveryData
struct incrates/hyperswitch_domain_models/src/payments.rs
defines and serializes only acard_issuer
field (there is nocard_isin
on that type), and the code inpayment_attempt_record.rs
correctly maps to it. Downstream transformer code also referencescard_issuer
. Sincecard_issuer
andcard_isin
represent different pieces of metadata and there is no inconsistent use of the same concept under two names here, no changes are required.crates/router/src/core/revenue_recovery/api.rs (1)
186-202
:✅ Verification successful
Potential stale call-sites after async signature change
create_payment_record_request
is now async and takesstate
. This call site is updated, but other invocations may still use the old sync signature, leading to compilation failures.
🏁 Script executed:
#!/bin/bash # locate other call-sites that still use the old signature rg --line-number 'create_payment_record_request\s*\(' | grep -v 'state'Length of output: 368
🏁 Script executed:
#!/bin/bash # Inspect call-sites of create_payment_record_request in recovery_incoming.rs to verify inclusion of `state` rg --line-number '\.create_payment_record_request' -C3 crates/router/src/core/webhooks/recovery_incoming.rsLength of output: 520
All invocations updated to the new async signature
Both call-sites inapi.rs
andrecovery_incoming.rs
now includestate
as the first argument, and there are no remaining stale usages ofcreate_payment_record_request
.crates/hyperswitch_connectors/src/connectors/recurly/transformers.rs (1)
209-211
: Handle absent card metadata & naming consistencyIf the above fields become
Option
, this assignment will not compile.
Additionally, the target struct usescard_isin
, which is semantically an IIN/BIN. The double mis-naming may confuse future readers.- card_network: Some(item.response.payment_method.card_type), - card_isin: Some(item.response.payment_method.first_six), + card_network: item.response.payment_method.card_type, + card_isin: item.response.payment_method.card_iin,Please update the downstream struct definition (or rename to
card_iin
) for coherence.api-reference-v2/openapi_spec.json (4)
17791-17792
: Validate breaking change for required fields
Adding"connector"
and"card_network"
to therequired
array makes these properties mandatory. Confirm that both fields are defined underproperties
and that all existing API consumers have been updated to supply them to avoid a breaking change.
17841-17846
:card_issuer
schema property
Thecard_issuer
field is well-defined withtype
,description
,example
, andnullable: true
. No changes needed.
17847-17852
:first_payment_attempt_pg_error_code
property
The first payment gateway error code is correctly defined with a clear description, example, andnullable: true
.
17859-17864
:first_payment_attempt_network_advice_code
property
This field is consistently named and documented with an example andnullable: true
. No changes required.crates/router/src/core/payments/transformers.rs (1)
4948-4958
:❓ Verification inconclusive
Ensure correct mapping of new revenue recovery fields
The newcard_issuer
,card_network
, and first-attempt error code fields are properly cloned from the source metadata. Confirm that the source struct (diesel_models::types::PaymentRevenueRecoveryMetadata
) declares these fields with the intended types and that the API model (api_models::payments::PaymentRevenueRecoveryMetadata
) matches the updated OpenAPI schema (especially noting thatcard_network
is now required).Run the following to verify definitions align across modules:
🏁 Script executed:
#!/bin/bash # Verify source model has these fields rg -n "struct PaymentRevenueRecoveryMetadata" -A3 crates/diesel_models/src/types.rs # Verify API model declaration rg -n "struct PaymentRevenueRecoveryMetadata" -A10 crates/api_models/src/payments.rsLength of output: 1073
🏁 Script executed:
#!/bin/bash set -e echo "---- diesel_models/src/types.rs ----" rg -n "card_issuer" -A2 crates/diesel_models/src/types.rs rg -n "card_network" -A2 crates/diesel_models/src/types.rs rg -n "first_payment_attempt_network_advice_code" -A2 crates/diesel_models/src/types.rs rg -n "first_payment_attempt_network_decline_code" -A2 crates/diesel_models/src/types.rs rg -n "first_payment_attempt_pg_error_code" -A2 crates/diesel_models/src/types.rs echo "" echo "---- api_models/src/payments.rs ----" rg -n "card_issuer" -A2 crates/api_models/src/payments.rs rg -n "card_network" -A2 crates/api_models/src/payments.rs rg -n "first_payment_attempt_network_advice_code" -A2 crates/api_models/src/payments.rs rg -n "first_payment_attempt_network_decline_code" -A2 crates/api_models/src/payments.rs rg -n "first_payment_attempt_pg_error_code" -A2 crates/api_models/src/payments.rsLength of output: 6355
Verify API and Diesel model field alignment
Both the Diesel and API models now declare the new revenue-recovery fields:• In
crates/diesel_models/src/types.rs
,PaymentRevenueRecoveryMetadata
includes:
card_network: Option<common_enums::enums::CardNetwork>
card_issuer: Option<String>
first_payment_attempt_network_decline_code: Option<String>
first_payment_attempt_network_advice_code: Option<String>
first_payment_attempt_pg_error_code: Option<String>
• In
crates/api_models/src/payments.rs
,PaymentRevenueRecoveryMetadata
declares:
card_network: Option<api_enums::CardNetwork>
card_issuer: Option<String>
first_payment_attempt_network_decline_code: Option<String>
first_payment_attempt_network_advice_code: Option<String>
first_payment_attempt_pg_error_code: Option<String>
Please confirm these definitions align with the updated OpenAPI schema—particularly whether
card_network
is now required (and thus should be a non-optional field in the API model).crates/hyperswitch_domain_models/src/lib.rs (1)
285-292
:✅ Verification successful
Confirm symmetry & default-handling for newly-added fields
payment_connector_transmission
is still normalised withunwrap_or_default()
, whereas the newly-added fields are transferred verbatim.
If any of these new fields areOption<T>
in the API model but non-optional in the Diesel model (or vice-versa), the current pass-through can panic at runtime or silently storeNULL
s. Please double-check the underlying struct definitions and addunwrap_or_default()
/unwrap_or(…)
as appropriate to keep the conversion lossless and consistent with the older fields.
Adding a conversion-roundtrip unit test here would lock in the expected behaviour.
🏁 Script executed:
#!/bin/bash set -eo pipefail # Show mapping context around the newly-added fields rg -n "card_issuer" -C5 crates/hyperswitch_domain_models/src/lib.rs # Show nearby `impl From<...>` blocks to identify source/target types rg -n "impl From<" -C3 crates/hyperswitch_domain_models/src/lib.rsLength of output: 2782
🏁 Script executed:
#!/bin/bash set -eo pipefail # Locate where payment_connector_transmission is mapped rg -n "payment_connector_transmission" -C5 crates/hyperswitch_domain_models/src/lib.rs # Locate usage of unwrap_or_default in the same file for context comparison rg -n "unwrap_or_default" -C5 crates/hyperswitch_domain_models/src/lib.rsLength of output: 2196
🏁 Script executed:
#!/bin/bash set -eo pipefail # Display the full convert_from implementation around the card_issuer mapping sed -n '240,320p' crates/hyperswitch_domain_models/src/lib.rsLength of output: 3922
🏁 Script executed:
#!/bin/bash set -eo pipefail # Locate struct definitions for domain model and API model rg -n "struct PaymentRevenueRecoveryMetadata" -C5 crates/hyperswitch_domain_models/src/lib.rs rg -R "ApiRevenueRecoveryMetadata" -n .Length of output: 114
🏁 Script executed:
#!/bin/bash set -eo pipefail # List all crates in the workspace echo "Crates in workspace:" ls crates # Find domain model struct definition echo -e "\nDomain model struct PaymentRevenueRecoveryMetadata definition:" rg -n "struct PaymentRevenueRecoveryMetadata" -C5 crates # Find API model struct definition echo -e "\nAPI model struct ApiRevenueRecoveryMetadata definition:" rg -n "struct ApiRevenueRecoveryMetadata" -C5 cratesLength of output: 2701
🏁 Script executed:
#!/bin/bash set -eo pipefail # Locate the import or alias for ApiRevenueRecoveryMetadata in hyperswitch_domain_models rg -n "ApiRevenueRecoveryMetadata" -C5 crates/hyperswitch_domain_models/src/lib.rsLength of output: 1802
🏁 Script executed:
#!/bin/bash set -eo pipefail # Show the domain (Diesel) struct definition with all fields rg -n "pub struct PaymentRevenueRecoveryMetadata" -C20 crates/diesel_models/src/types.rs # Show the API model struct definition rg -n "pub struct PaymentRevenueRecoveryMetadata" -C20 crates/api_models/src/payments.rsLength of output: 4221
🏁 Script executed:
#!/bin/bash set -eo pipefail # Full Diesel model struct PaymentRevenueRecoveryMetadata echo "=== Diesel model ===" sed -n '155,260p' crates/diesel_models/src/types.rs # Full API model struct PaymentRevenueRecoveryMetadata echo -e "\n=== API model ===" sed -n '8657,8750p' crates/api_models/src/payments.rsLength of output: 6557
No action needed: Optional fields map symmetrically
A review of the struct definitions shows that all newly-added fields (
card_issuer
,card_network
,first_payment_attempt_pg_error_code
,first_payment_attempt_network_decline_code
,first_payment_attempt_network_advice_code
) are declared asOption<T>
in bothApiRevenueRecoveryMetadata
and the DieselPaymentRevenueRecoveryMetadata
. The direct pass-through inconvert_from
/convert_back
preserves their optional semantics without risk of panics or silentNULL
mismatches—nounwrap_or_default
is required here.• Location:
- Mapping in
crates/hyperswitch_domain_models/src/lib.rs
, lines 285–292- Structs in
crates/api_models/src/payments.rs
andcrates/diesel_models/src/types.rs
Optional: you may still add a conversion-roundtrip unit test to lock in this behaviour and guard against future mismatches.
crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs (2)
442-442
: Comprehensive card network support implementation.The implementation provides thorough coverage of card networks with proper enum variants and conversion logic.
Also applies to: 465-483, 639-659
534-535
:✅ Verification successful
Verify that payment_intent is the correct field for connector_transaction_id.
The change from
charge_id
topayment_intent
for the connector transaction ID might affect transaction tracking. Please ensure this aligns with Stripe's recommended practice for identifying transactions in billing contexts.
🌐 Web query:
What is the difference between charge_id and payment_intent in Stripe, and which one should be used as the primary transaction identifier for Stripe Billing webhooks?
💡 Result:
In Stripe's payment processing model, both
charge_id
andpayment_intent
are important but serve different purposes, especially when dealing with Stripe Billing and webhooks.Charge ID (
charge_id
):
- A
charge_id
represents a single charge made to a payment method.- It is created as part of a payment operation.
- Each charge corresponds to a single payment attempt.
- You may have multiple charges per payment if, for example, you do separate charges or retries.
- In older Stripe integrations (before Payment Intents were introduced), the charge object was the primary way to track transactions.
Payment Intent (
payment_intent
):
- Introduced with Stripe’s newer payment model to support more advanced payment flows (like SCA – Strong Customer Authentication).
- A
payment_intent
represents the entire lifecycle of a payment on a customer’s intent to pay.- It can have multiple associated charges during retries or failure/success flows.
- Acts as a more holistic representation of a transaction from initiation to completion.
- Used extensively in Stripe Billing, Subscriptions, and newer payment flows.
Which one to use as the primary transaction identifier for Stripe Billing webhooks?
- Use the
payment_intent
ID as the primary transaction identifier.- The
payment_intent
ID provides a comprehensive view of the payment process and is the newer, more robust way to track payments.- Stripe Billing webhooks (like
invoice.payment_succeeded
) typically include thepayment_intent
ID, which you should use to reconcile payments.- The
charge_id
can vary or have multiple instances per payment, making it less reliable as a primary transaction reference compared to thepayment_intent
.Summary:
- Charge ID = single payment attempt/charge.
- Payment Intent = entire payment lifecycle (preferred for billing).
- For Stripe Billing webhooks, always use the payment_intent ID as the primary transaction identifier.
If you want me to, I can provide example webhook payloads or further details on handling these IDs in your integration.
Confirmed:
payment_intent
Is the Right Transaction IdentifierThis change aligns with Stripe’s recommendation to use the PaymentIntent ID as the primary identifier for Billing webhooks—providing a holistic view of the payment lifecycle. No further updates are needed.
• File: crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs
• Lines: 534–535
api-reference-v2/openapi_spec.json
Outdated
"first_payment_attempt_network_decline_code": { | ||
"type": "string", | ||
"description": "First Payment Attempt Network Error Code", | ||
"example": "05", | ||
"nullable": true | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Align naming and description for network error code
The key first_payment_attempt_network_decline_code
uses “decline” but the description reads “Network Error Code.” For consistency, either rename the field to first_payment_attempt_network_error_code
or adjust the description to “Network Decline Code.” Example renaming diff:
- "first_payment_attempt_network_decline_code": {
+ "first_payment_attempt_network_error_code": {
"type": "string",
- "description": "First Payment Attempt Network Error Code",
+ "description": "First Payment Attempt Network Error Code",
"example": "05",
"nullable": true
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
"first_payment_attempt_network_decline_code": { | |
"type": "string", | |
"description": "First Payment Attempt Network Error Code", | |
"example": "05", | |
"nullable": true | |
}, | |
"first_payment_attempt_network_error_code": { | |
"type": "string", | |
"description": "First Payment Attempt Network Error Code", | |
"example": "05", | |
"nullable": true | |
}, |
🤖 Prompt for AI Agents
In api-reference-v2/openapi_spec.json around lines 17853 to 17858, the field
name 'first_payment_attempt_network_decline_code' and its description are
inconsistent; the name uses "decline" while the description says "Network Error
Code." To fix this, either rename the field to
'first_payment_attempt_network_error_code' to match the description or change
the description to "Network Decline Code" to match the field name, ensuring both
are aligned in terminology.
crates/api_models/src/payments.rs
Outdated
#[schema(value_type = CardNetwork, example = "Visa")] | ||
/// Card Network | ||
pub card_network: Option<common_enums::CardNetwork>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unqualified CardNetwork
path can break utoipa
macro resolution
CardNetwork
lives under common_enums
. Inside the #[schema]
attribute the path must be fully-qualified (or imported into the module prelude) for the derive macro to compile.
- #[schema(value_type = CardNetwork, example = "Visa")]
+ #[schema(value_type = common_enums::CardNetwork, example = "Visa")]
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
#[schema(value_type = CardNetwork, example = "Visa")] | |
/// Card Network | |
pub card_network: Option<common_enums::CardNetwork>, | |
#[schema(value_type = common_enums::CardNetwork, example = "Visa")] | |
/// Card Network | |
pub card_network: Option<common_enums::CardNetwork>, |
🤖 Prompt for AI Agents
In crates/api_models/src/payments.rs at lines 8683 to 8685, the #[schema]
attribute uses an unqualified CardNetwork type which can cause utoipa macro
resolution to fail. Fix this by fully qualifying the CardNetwork path inside the
#[schema(value_type = ...)] attribute as common_enums::CardNetwork or ensure it
is properly imported into the module prelude before usage.
crates/api_models/src/payments.rs
Outdated
@@ -8680,6 +8680,21 @@ pub struct PaymentRevenueRecoveryMetadata { | |||
pub connector: common_enums::connector_enums::Connector, | |||
/// Invoice Next billing time | |||
pub invoice_next_billing_time: Option<PrimitiveDateTime>, | |||
#[schema(value_type = CardNetwork, example = "Visa")] | |||
/// Card Network | |||
pub card_network: Option<common_enums::CardNetwork>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here the payment_method data is flatten and currently it is specific to cards, when the payment_method is going to change, these field is going to be None always, so change the data structure such a way where specific payment method fields are not flattened
Type of Change
Description
The following details are needed to be stored in the payment intent feature metadata as a part of transaction monitoring system for revenue recovery.
These will be constant through out the lifecycle of the payment intent in revenue recovery system. We need to use these parameters further in revenue recovery system. We need this as training data and need these while Deciding optimal time for the retry.
These information is stored in payment intent because this information will be constant throughout for payment intent and this information cannot be populated every time we retry this payment.
Additional Changes
Motivation and Context
How did you test it?
Can be tested by following the steps mentioned in this PR: #7461. Here are the test results:
Or
Run this Curl by filling our:
This is the expected response
Check the DB for feature metadata and verify the data.
Sample log:

Checklist
cargo +nightly fmt --all
cargo clippy
Summary by CodeRabbit