Skip to content

Commit

Permalink
feat(payments_v2): implement payments capture v2 (#6722)
Browse files Browse the repository at this point in the history
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
Narayanbhat166 and hyperswitch-bot[bot] authored Dec 20, 2024
1 parent 22de8ad commit 977cb70
Show file tree
Hide file tree
Showing 22 changed files with 1,925 additions and 287 deletions.
202 changes: 86 additions & 116 deletions api-reference-v2/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -6495,88 +6495,6 @@
"greater_than_equal"
]
},
"ConfirmIntentAmountDetailsResponse": {
"type": "object",
"required": [
"currency",
"external_tax_calculation",
"surcharge_calculation",
"net_amount",
"amount_capturable"
],
"properties": {
"order_amount": {
"type": "integer",
"format": "int64",
"description": "The payment amount. Amount for the payment in the lowest denomination of the currency, (i.e) in cents for USD denomination, in yen for JPY denomination etc. E.g., Pass 100 to charge $1.00 and 1 for 1¥ since ¥ is a zero-decimal currency. Read more about [the Decimal and Non-Decimal Currencies](https://github.com/juspay/hyperswitch/wiki/Decimal-and-Non%E2%80%90Decimal-Currencies)",
"example": 6540,
"minimum": 0
},
"currency": {
"$ref": "#/components/schemas/Currency"
},
"shipping_cost": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"order_tax_amount": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"external_tax_calculation": {
"$ref": "#/components/schemas/TaxCalculationOverride"
},
"surcharge_calculation": {
"$ref": "#/components/schemas/SurchargeCalculationOverride"
},
"surcharge_amount": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"tax_on_surcharge": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"net_amount": {
"$ref": "#/components/schemas/MinorUnit"
},
"amount_to_capture": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"amount_capturable": {
"$ref": "#/components/schemas/MinorUnit"
},
"amount_captured": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
}
}
},
"Connector": {
"type": "string",
"description": "A connector is an integration to fulfill payments",
Expand Down Expand Up @@ -12605,6 +12523,88 @@
}
}
},
"PaymentAmountDetailsResponse": {
"type": "object",
"required": [
"currency",
"external_tax_calculation",
"surcharge_calculation",
"net_amount",
"amount_capturable"
],
"properties": {
"order_amount": {
"type": "integer",
"format": "int64",
"description": "The payment amount. Amount for the payment in the lowest denomination of the currency, (i.e) in cents for USD denomination, in yen for JPY denomination etc. E.g., Pass 100 to charge $1.00 and 1 for 1¥ since ¥ is a zero-decimal currency. Read more about [the Decimal and Non-Decimal Currencies](https://github.com/juspay/hyperswitch/wiki/Decimal-and-Non%E2%80%90Decimal-Currencies)",
"example": 6540,
"minimum": 0
},
"currency": {
"$ref": "#/components/schemas/Currency"
},
"shipping_cost": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"order_tax_amount": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"external_tax_calculation": {
"$ref": "#/components/schemas/TaxCalculationOverride"
},
"surcharge_calculation": {
"$ref": "#/components/schemas/SurchargeCalculationOverride"
},
"surcharge_amount": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"tax_on_surcharge": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"net_amount": {
"$ref": "#/components/schemas/MinorUnit"
},
"amount_to_capture": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
},
"amount_capturable": {
"$ref": "#/components/schemas/MinorUnit"
},
"amount_captured": {
"allOf": [
{
"$ref": "#/components/schemas/MinorUnit"
}
],
"nullable": true
}
}
},
"PaymentAttemptResponse": {
"type": "object",
"required": [
Expand Down Expand Up @@ -14467,42 +14467,12 @@
},
"PaymentsCaptureRequest": {
"type": "object",
"required": [
"amount_to_capture"
],
"properties": {
"merchant_id": {
"type": "string",
"description": "The unique identifier for the merchant",
"nullable": true
},
"amount_to_capture": {
"type": "integer",
"format": "int64",
"description": "The Amount to be captured/ debited from the user's payment method.",
"example": 6540
},
"refund_uncaptured_amount": {
"type": "boolean",
"description": "Decider to refund the uncaptured amount",
"nullable": true
},
"statement_descriptor_suffix": {
"type": "string",
"description": "Provides information about a card payment that customers see on their statements.",
"nullable": true
},
"statement_descriptor_prefix": {
"type": "string",
"description": "Concatenated with the statement descriptor suffix that’s set on the account to form the complete statement descriptor.",
"nullable": true
},
"merchant_connector_details": {
"allOf": [
{
"$ref": "#/components/schemas/MerchantConnectorDetailsWrap"
}
],
"description": "The Amount to be captured/ debited from the user's payment method. If not passed the full amount will be captured.",
"example": 6540,
"nullable": true
}
}
Expand Down Expand Up @@ -14605,7 +14575,7 @@
"$ref": "#/components/schemas/IntentStatus"
},
"amount": {
"$ref": "#/components/schemas/ConfirmIntentAmountDetailsResponse"
"$ref": "#/components/schemas/PaymentAmountDetailsResponse"
},
"customer_id": {
"type": "string",
Expand Down Expand Up @@ -16354,7 +16324,7 @@
"$ref": "#/components/schemas/IntentStatus"
},
"amount": {
"$ref": "#/components/schemas/ConfirmIntentAmountDetailsResponse"
"$ref": "#/components/schemas/PaymentAmountDetailsResponse"
},
"customer_id": {
"type": "string",
Expand Down
2 changes: 1 addition & 1 deletion api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -17372,7 +17372,7 @@
"amount_to_capture": {
"type": "integer",
"format": "int64",
"description": "The Amount to be captured/ debited from the user's payment method.",
"description": "The Amount to be captured/ debited from the user's payment method. If not passed the full amount will be captured.",
"example": 6540
},
"refund_uncaptured_amount": {
Expand Down
11 changes: 10 additions & 1 deletion crates/api_models/src/events/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{
))]
use crate::payment_methods::CustomerPaymentMethodsListResponse;
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
use crate::payment_methods::CustomerPaymentMethodsListResponse;
use crate::{events, payment_methods::CustomerPaymentMethodsListResponse};
use crate::{
payment_methods::{
CustomerDefaultPaymentMethodResponse, DefaultPaymentMethod, ListCountriesCurrenciesRequest,
Expand Down Expand Up @@ -418,3 +418,12 @@ impl ApiEventMetric for PaymentStartRedirectionRequest {
})
}
}

#[cfg(feature = "v2")]
impl ApiEventMetric for events::PaymentsCaptureResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payment {
payment_id: self.id.clone(),
})
}
}
31 changes: 27 additions & 4 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ pub struct AmountDetailsResponse {

#[cfg(feature = "v2")]
#[derive(Clone, Debug, PartialEq, serde::Serialize, ToSchema)]
pub struct ConfirmIntentAmountDetailsResponse {
pub struct PaymentAmountDetailsResponse {
/// The payment amount. Amount for the payment in the lowest denomination of the currency, (i.e) in cents for USD denomination, in yen for JPY denomination etc. E.g., Pass 100 to charge $1.00 and 1 for 1¥ since ¥ is a zero-decimal currency. Read more about [the Decimal and Non-Decimal Currencies](https://github.com/juspay/hyperswitch/wiki/Decimal-and-Non%E2%80%90Decimal-Currencies)
#[schema(value_type = u64, example = 6540)]
#[serde(default, deserialize_with = "amount::deserialize")]
Expand Down Expand Up @@ -4077,6 +4077,7 @@ pub struct PhoneDetails {
pub country_code: Option<String>,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct PaymentsCaptureRequest {
/// The unique identifier for the payment
Expand All @@ -4085,7 +4086,7 @@ pub struct PaymentsCaptureRequest {
/// The unique identifier for the merchant
#[schema(value_type = Option<String>)]
pub merchant_id: Option<id_type::MerchantId>,
/// The Amount to be captured/ debited from the user's payment method.
/// The Amount to be captured/ debited from the user's payment method. If not passed the full amount will be captured.
#[schema(value_type = i64, example = 6540)]
pub amount_to_capture: Option<MinorUnit>,
/// Decider to refund the uncaptured amount
Expand All @@ -4099,6 +4100,28 @@ pub struct PaymentsCaptureRequest {
pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct PaymentsCaptureRequest {
/// The Amount to be captured/ debited from the user's payment method. If not passed the full amount will be captured.
#[schema(value_type = Option<i64>, example = 6540)]
pub amount_to_capture: Option<MinorUnit>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
pub struct PaymentsCaptureResponse {
/// The unique identifier for the payment
pub id: id_type::GlobalPaymentId,

/// Status of the payment
#[schema(value_type = IntentStatus, example = "succeeded")]
pub status: common_enums::IntentStatus,

/// Amount details related to the payment
pub amount: PaymentAmountDetailsResponse,
}

#[derive(Default, Clone, Debug, Eq, PartialEq, serde::Serialize)]
pub struct UrlDetails {
pub url: String,
Expand Down Expand Up @@ -4801,7 +4824,7 @@ pub struct PaymentsConfirmIntentResponse {
pub status: api_enums::IntentStatus,

/// Amount related information for this payment and attempt
pub amount: ConfirmIntentAmountDetailsResponse,
pub amount: PaymentAmountDetailsResponse,

/// The identifier for the customer
#[schema(
Expand Down Expand Up @@ -4879,7 +4902,7 @@ pub struct PaymentsRetrieveResponse {
pub status: api_enums::IntentStatus,

/// Amount related information for this payment and attempt
pub amount: ConfirmIntentAmountDetailsResponse,
pub amount: PaymentAmountDetailsResponse,

/// The identifier for the customer
#[schema(
Expand Down
4 changes: 2 additions & 2 deletions crates/diesel_models/src/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,6 @@ pub enum PaymentAttemptUpdate {
#[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)]
#[diesel(table_name = payment_attempt)]
pub struct PaymentAttemptUpdateInternal {
// net_amount: Option<MinorUnit>,
pub status: Option<storage_enums::AttemptStatus>,
// authentication_type: Option<storage_enums::AuthenticationType>,
pub error_message: Option<String>,
Expand All @@ -774,7 +773,8 @@ pub struct PaymentAttemptUpdateInternal {
// multiple_capture_count: Option<i16>,
// pub surcharge_amount: Option<MinorUnit>,
// tax_on_surcharge: Option<MinorUnit>,
// amount_capturable: Option<MinorUnit>,
pub amount_capturable: Option<MinorUnit>,
pub amount_to_capture: Option<MinorUnit>,
pub updated_by: String,
pub merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
pub connector: Option<String>,
Expand Down
20 changes: 19 additions & 1 deletion crates/diesel_models/src/payment_intent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,23 @@ pub struct PaymentIntentNew {
pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PaymentIntentUpdate {
/// Update the payment intent details on payment intent confirmation, before calling the connector
ConfirmIntent {
status: storage_enums::IntentStatus,
active_attempt_id: common_utils::id_type::GlobalAttemptId,
updated_by: String,
},
/// Update the payment intent details on payment intent confirmation, after calling the connector
ConfirmIntentPostUpdate {
status: storage_enums::IntentStatus,
amount_captured: Option<MinorUnit>,
updated_by: String,
},
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PaymentIntentUpdate {
Expand Down Expand Up @@ -514,8 +531,9 @@ pub struct PaymentIntentUpdateFields {
#[diesel(table_name = payment_intent)]
pub struct PaymentIntentUpdateInternal {
pub status: Option<storage_enums::IntentStatus>,
pub active_attempt_id: Option<common_utils::id_type::GlobalAttemptId>,
pub amount_captured: Option<MinorUnit>,
pub modified_at: PrimitiveDateTime,
pub active_attempt_id: Option<common_utils::id_type::GlobalAttemptId>,
pub amount: Option<MinorUnit>,
pub currency: Option<storage_enums::Currency>,
pub shipping_cost: Option<MinorUnit>,
Expand Down
Loading

0 comments on commit 977cb70

Please sign in to comment.