Skip to content

feat(router): add support for partial authorization #8833

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 8 commits into from
Aug 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions api-reference/v1/openapi_spec_v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -7972,6 +7972,7 @@
"void_failed",
"auto_refunded",
"partial_charged",
"partially_authorized",
"partial_charged_and_chargeable",
"unresolved",
"pending",
Expand Down Expand Up @@ -14810,6 +14811,7 @@
"payment_cancelled",
"payment_cancelled_post_capture",
"payment_authorized",
"payment_partially_authorized",
"payment_captured",
"payment_expired",
"action_required",
Expand Down Expand Up @@ -16665,6 +16667,7 @@
"requires_capture",
"partially_captured",
"partially_captured_and_capturable",
"partially_authorized_and_requires_capture",
"conflicted",
"expired"
]
Expand Down Expand Up @@ -22697,6 +22700,11 @@
"format": "date-time",
"description": "Date the payer placed the order.",
"nullable": true
},
"enable_partial_authorization": {
"type": "boolean",
"description": "Allow partial authorization for this payment",
"nullable": true
}
}
},
Expand Down Expand Up @@ -23165,6 +23173,11 @@
"format": "date-time",
"description": "Date the payer placed the order.",
"nullable": true
},
"enable_partial_authorization": {
"type": "boolean",
"description": "Allow partial authorization for this payment",
"nullable": true
}
}
},
Expand Down Expand Up @@ -23766,6 +23779,11 @@
"type": "string",
"description": "Contains whole connector response",
"nullable": true
},
"enable_partial_authorization": {
"type": "boolean",
"description": "Allow partial authorization for this payment",
"nullable": true
}
}
},
Expand Down Expand Up @@ -24524,6 +24542,11 @@
"format": "date-time",
"description": "Date the payer placed the order.",
"nullable": true
},
"enable_partial_authorization": {
"type": "boolean",
"description": "Allow partial authorization for this payment",
"nullable": true
}
},
"additionalProperties": false
Expand Down Expand Up @@ -25151,6 +25174,11 @@
"type": "string",
"description": "Contains whole connector response",
"nullable": true
},
"enable_partial_authorization": {
"type": "boolean",
"description": "Allow partial authorization for this payment",
"nullable": true
}
}
},
Expand Down Expand Up @@ -25752,6 +25780,11 @@
"format": "date-time",
"description": "Date the payer placed the order.",
"nullable": true
},
"enable_partial_authorization": {
"type": "boolean",
"description": "Allow partial authorization for this payment",
"nullable": true
}
}
},
Expand Down
3 changes: 3 additions & 0 deletions api-reference/v2/openapi_spec_v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -4909,6 +4909,7 @@
"void_failed",
"auto_refunded",
"partial_charged",
"partially_authorized",
"partial_charged_and_chargeable",
"unresolved",
"pending",
Expand Down Expand Up @@ -10786,6 +10787,7 @@
"payment_cancelled",
"payment_cancelled_post_capture",
"payment_authorized",
"payment_partially_authorized",
"payment_captured",
"payment_expired",
"action_required",
Expand Down Expand Up @@ -12753,6 +12755,7 @@
"requires_capture",
"partially_captured",
"partially_captured_and_capturable",
"partially_authorized_and_requires_capture",
"conflicted",
"expired"
]
Expand Down
6 changes: 6 additions & 0 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,9 @@ pub struct PaymentsRequest {
/// Date the payer placed the order.
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub order_date: Option<PrimitiveDateTime>,

/// Allow partial authorization for this payment
pub enable_partial_authorization: Option<bool>,
}

#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
Expand Down Expand Up @@ -5272,6 +5275,9 @@ pub struct PaymentsResponse {
/// Contains whole connector response
#[schema(value_type = Option<String>)]
pub whole_connector_response: Option<Secret<String>>,

/// Allow partial authorization for this payment
pub enable_partial_authorization: Option<bool>,
}

#[cfg(feature = "v2")]
Expand Down
9 changes: 8 additions & 1 deletion crates/common_enums/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ pub enum AttemptStatus {
VoidFailed,
AutoRefunded,
PartialCharged,
PartiallyAuthorized,
PartialChargedAndChargeable,
Unresolved,
#[default]
Expand Down Expand Up @@ -178,6 +179,7 @@ impl AttemptStatus {
| Self::AuthenticationPending
| Self::AuthenticationSuccessful
| Self::Authorized
| Self::PartiallyAuthorized
| Self::AuthorizationFailed
| Self::Authorizing
| Self::CodInitiated
Expand Down Expand Up @@ -1560,6 +1562,7 @@ pub enum EventType {
PaymentCancelled,
PaymentCancelledPostCapture,
PaymentAuthorized,
PaymentPartiallyAuthorized,
PaymentCaptured,
PaymentExpired,
ActionRequired,
Expand Down Expand Up @@ -1683,6 +1686,8 @@ pub enum IntentStatus {
PartiallyCaptured,
/// The payment has been captured partially and the remaining amount is capturable
PartiallyCapturedAndCapturable,
/// The payment has been authorized for a partial amount and requires capture
PartiallyAuthorizedAndRequiresCapture,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this status needed? Wouldn't amount_capturable indicate if the payment was Fully authorized or Partially authorized?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There should be some explicit way of communicating the partial authorization to merchant, it's very similar to how we have PartialCharged (even though we give amount_captured value in the response)

/// There has been a discrepancy between the amount/currency sent in the request and the amount/currency received by the processor
Conflicted,
/// The payment expired before it could be captured.
Expand All @@ -1706,6 +1711,7 @@ impl IntentStatus {
| Self::RequiresConfirmation
| Self::RequiresCapture
| Self::PartiallyCapturedAndCapturable
| Self::PartiallyAuthorizedAndRequiresCapture
| Self::Conflicted => false,
}
}
Expand All @@ -1727,7 +1733,7 @@ impl IntentStatus {
| Self::RequiresCustomerAction
| Self::RequiresMerchantAction
| Self::PartiallyCapturedAndCapturable
=> true,
| Self::PartiallyAuthorizedAndRequiresCapture => true,
}
}
}
Expand Down Expand Up @@ -1853,6 +1859,7 @@ impl From<AttemptStatus> for PaymentMethodStatus {
| AttemptStatus::AutoRefunded
| AttemptStatus::PartialCharged
| AttemptStatus::PartialChargedAndChargeable
| AttemptStatus::PartiallyAuthorized
| AttemptStatus::ConfirmationAwaited
| AttemptStatus::DeviceDataCollectionPending
| AttemptStatus::IntegrityFailure
Expand Down
4 changes: 4 additions & 0 deletions crates/common_enums/src/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2125,6 +2125,7 @@ impl From<AttemptStatus> for IntentStatus {
AttemptStatus::Voided => Self::Cancelled,
AttemptStatus::VoidedPostCharge => Self::CancelledPostCapture,
AttemptStatus::Expired => Self::Expired,
AttemptStatus::PartiallyAuthorized => Self::PartiallyAuthorizedAndRequiresCapture,
}
}
}
Expand All @@ -2146,6 +2147,9 @@ impl From<IntentStatus> for Option<EventType> {
}
IntentStatus::RequiresCapture => Some(EventType::PaymentAuthorized),
IntentStatus::RequiresPaymentMethod | IntentStatus::RequiresConfirmation => None,
IntentStatus::PartiallyAuthorizedAndRequiresCapture => {
Some(EventType::PaymentPartiallyAuthorized)
}
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions crates/diesel_models/src/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,6 @@ pub enum PaymentAttemptUpdate {
straight_through_algorithm: Option<serde_json::Value>,
error_code: Option<Option<String>>,
error_message: Option<Option<String>>,
amount_capturable: Option<MinorUnit>,
surcharge_amount: Option<MinorUnit>,
tax_amount: Option<MinorUnit>,
fingerprint_id: Option<String>,
Expand Down Expand Up @@ -2461,7 +2460,6 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
straight_through_algorithm,
error_code,
error_message,
amount_capturable,
updated_by,
merchant_connector_id,
surcharge_amount,
Expand Down Expand Up @@ -2498,7 +2496,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
straight_through_algorithm,
error_code,
error_message,
amount_capturable,
amount_capturable: None,
updated_by,
merchant_connector_id: merchant_connector_id.map(Some),
surcharge_amount,
Expand Down
Loading
Loading