mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-11-04 14:07:18 +08:00 
			
		
		
		
	Co-authored-by: Sangamesh Kulkarni <59434228+Sangamesh26@users.noreply.github.com> Co-authored-by: ItsMeShashank <shashank.attarde@juspay.in> Co-authored-by: Abhishek <abhishek.marrivagu@juspay.in> Co-authored-by: Jagan <jaganelavarasan@gmail.com> Co-authored-by: SamraatBansal <55536657+SamraatBansal@users.noreply.github.com> Co-authored-by: Sampras Lopes <lsampras@protonmail.com>
This commit is contained in:
		@ -166,8 +166,20 @@ pub enum StripeErrorCode {
 | 
			
		||||
    },
 | 
			
		||||
    #[error(error_type = StripeErrorType::InvalidRequestError, code = "", message = "The mandate information is invalid. {message}")]
 | 
			
		||||
    PaymentIntentMandateInvalid { message: String },
 | 
			
		||||
 | 
			
		||||
    #[error(error_type = StripeErrorType::InvalidRequestError, code = "", message = "The payment with the specified payment_id '{payment_id}' already exists in our records.")]
 | 
			
		||||
    DuplicatePayment { payment_id: String },
 | 
			
		||||
 | 
			
		||||
    #[error(error_type = StripeErrorType::ConnectorError, code = "", message = "{code}: {message}")]
 | 
			
		||||
    ExternalConnectorError {
 | 
			
		||||
        code: String,
 | 
			
		||||
        message: String,
 | 
			
		||||
        connector: String,
 | 
			
		||||
        status_code: u16,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    #[error(error_type = StripeErrorType::HyperswitchError, code = "", message = "The connector provided in the request is incorrect or not available")]
 | 
			
		||||
    IncorrectConnectorNameGiven,
 | 
			
		||||
    // [#216]: https://github.com/juspay/hyperswitch/issues/216
 | 
			
		||||
    // Implement the remaining stripe error codes
 | 
			
		||||
 | 
			
		||||
@ -323,6 +335,8 @@ pub enum StripeErrorType {
 | 
			
		||||
    ApiError,
 | 
			
		||||
    CardError,
 | 
			
		||||
    InvalidRequestError,
 | 
			
		||||
    ConnectorError,
 | 
			
		||||
    HyperswitchError,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<errors::ApiErrorResponse> for StripeErrorCode {
 | 
			
		||||
@ -369,8 +383,21 @@ impl From<errors::ApiErrorResponse> for StripeErrorCode {
 | 
			
		||||
            errors::ApiErrorResponse::RefundFailed { data } => Self::RefundFailed, // Nothing at stripe to map
 | 
			
		||||
 | 
			
		||||
            errors::ApiErrorResponse::InternalServerError => Self::InternalServerError, // not a stripe code
 | 
			
		||||
            errors::ApiErrorResponse::ExternalConnectorError { .. } => Self::InternalServerError,
 | 
			
		||||
            errors::ApiErrorResponse::IncorrectConnectorNameGiven => Self::InternalServerError,
 | 
			
		||||
            errors::ApiErrorResponse::ExternalConnectorError {
 | 
			
		||||
                code,
 | 
			
		||||
                message,
 | 
			
		||||
                connector,
 | 
			
		||||
                status_code,
 | 
			
		||||
                ..
 | 
			
		||||
            } => Self::ExternalConnectorError {
 | 
			
		||||
                code,
 | 
			
		||||
                message,
 | 
			
		||||
                connector,
 | 
			
		||||
                status_code,
 | 
			
		||||
            },
 | 
			
		||||
            errors::ApiErrorResponse::IncorrectConnectorNameGiven => {
 | 
			
		||||
                Self::IncorrectConnectorNameGiven
 | 
			
		||||
            }
 | 
			
		||||
            errors::ApiErrorResponse::MandateActive => Self::MandateActive, //not a stripe code
 | 
			
		||||
            errors::ApiErrorResponse::CustomerRedacted => Self::CustomerRedacted, //not a stripe code
 | 
			
		||||
            errors::ApiErrorResponse::ConfigNotFound => Self::ConfigNotFound, // not a stripe code
 | 
			
		||||
@ -474,12 +501,16 @@ impl actix_web::ResponseError for StripeErrorCode {
 | 
			
		||||
            | Self::ResourceIdNotFound
 | 
			
		||||
            | Self::PaymentIntentMandateInvalid { .. }
 | 
			
		||||
            | Self::PaymentIntentUnexpectedState { .. }
 | 
			
		||||
            | Self::DuplicatePayment { .. } => StatusCode::BAD_REQUEST,
 | 
			
		||||
            | Self::DuplicatePayment { .. }
 | 
			
		||||
            | Self::IncorrectConnectorNameGiven => StatusCode::BAD_REQUEST,
 | 
			
		||||
            Self::RefundFailed
 | 
			
		||||
            | Self::InternalServerError
 | 
			
		||||
            | Self::MandateActive
 | 
			
		||||
            | Self::CustomerRedacted => StatusCode::INTERNAL_SERVER_ERROR,
 | 
			
		||||
            Self::ReturnUrlUnavailable => StatusCode::SERVICE_UNAVAILABLE,
 | 
			
		||||
            Self::ExternalConnectorError { status_code, .. } => {
 | 
			
		||||
                StatusCode::from_u16(*status_code).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -116,7 +116,7 @@ impl From<Shipping> for payments::Address {
 | 
			
		||||
#[derive(PartialEq, Eq, Deserialize, Clone)]
 | 
			
		||||
pub struct StripePaymentIntentRequest {
 | 
			
		||||
    pub amount: Option<i64>, //amount in cents, hence passed as integer
 | 
			
		||||
    pub connector: Option<api_enums::Connector>,
 | 
			
		||||
    pub connector: Option<Vec<api_enums::Connector>>,
 | 
			
		||||
    pub currency: Option<String>,
 | 
			
		||||
    #[serde(rename = "amount_to_capture")]
 | 
			
		||||
    pub amount_capturable: Option<i64>,
 | 
			
		||||
@ -126,7 +126,7 @@ pub struct StripePaymentIntentRequest {
 | 
			
		||||
    pub description: Option<String>,
 | 
			
		||||
    pub payment_method_data: Option<StripePaymentMethodData>,
 | 
			
		||||
    pub receipt_email: Option<pii::Secret<String, pii::Email>>,
 | 
			
		||||
    pub return_url: Option<String>,
 | 
			
		||||
    pub return_url: Option<url::Url>,
 | 
			
		||||
    pub setup_future_usage: Option<api_enums::FutureUsage>,
 | 
			
		||||
    pub shipping: Option<Shipping>,
 | 
			
		||||
    pub billing_details: Option<StripeBillingDetails>,
 | 
			
		||||
@ -265,40 +265,110 @@ pub struct StripeCaptureRequest {
 | 
			
		||||
#[derive(Default, Eq, PartialEq, Serialize)]
 | 
			
		||||
pub struct StripePaymentIntentResponse {
 | 
			
		||||
    pub id: Option<String>,
 | 
			
		||||
    pub object: String,
 | 
			
		||||
    pub object: &'static str,
 | 
			
		||||
    pub amount: i64,
 | 
			
		||||
    pub amount_received: Option<i64>,
 | 
			
		||||
    pub amount_capturable: Option<i64>,
 | 
			
		||||
    pub currency: String,
 | 
			
		||||
    pub status: StripePaymentStatus,
 | 
			
		||||
    pub client_secret: Option<masking::Secret<String>>,
 | 
			
		||||
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
 | 
			
		||||
    pub created: Option<time::PrimitiveDateTime>,
 | 
			
		||||
    pub created: Option<i64>,
 | 
			
		||||
    pub customer: Option<String>,
 | 
			
		||||
    pub refunds: Option<Vec<refunds::RefundResponse>>,
 | 
			
		||||
    pub mandate_id: Option<String>,
 | 
			
		||||
    pub metadata: Option<Value>,
 | 
			
		||||
    pub charges: Charges,
 | 
			
		||||
    pub connector: Option<String>,
 | 
			
		||||
    pub description: Option<String>,
 | 
			
		||||
    pub mandate_data: Option<payments::MandateData>,
 | 
			
		||||
    pub setup_future_usage: Option<api_models::enums::FutureUsage>,
 | 
			
		||||
    pub off_session: Option<bool>,
 | 
			
		||||
    pub return_url: Option<String>,
 | 
			
		||||
    pub authentication_type: Option<api_models::enums::AuthenticationType>,
 | 
			
		||||
    pub next_action: Option<payments::NextAction>,
 | 
			
		||||
    pub cancellation_reason: Option<String>,
 | 
			
		||||
    pub payment_method: Option<api_models::enums::PaymentMethodType>,
 | 
			
		||||
    pub payment_method_data: Option<payments::PaymentMethodDataResponse>,
 | 
			
		||||
    pub shipping: Option<payments::Address>,
 | 
			
		||||
    pub billing: Option<payments::Address>,
 | 
			
		||||
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
 | 
			
		||||
    pub capture_on: Option<time::PrimitiveDateTime>,
 | 
			
		||||
    pub payment_token: Option<String>,
 | 
			
		||||
    pub email: Option<masking::Secret<String, common_utils::pii::Email>>,
 | 
			
		||||
    pub phone: Option<masking::Secret<String>>,
 | 
			
		||||
    pub error_code: Option<String>,
 | 
			
		||||
    pub error_message: Option<String>,
 | 
			
		||||
    pub statement_descriptor_suffix: Option<String>,
 | 
			
		||||
    pub statement_descriptor_name: Option<String>,
 | 
			
		||||
    pub capture_method: Option<api_models::enums::CaptureMethod>,
 | 
			
		||||
    pub name: Option<masking::Secret<String>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<payments::PaymentsResponse> for StripePaymentIntentResponse {
 | 
			
		||||
    fn from(resp: payments::PaymentsResponse) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            object: "payment_intent".to_owned(),
 | 
			
		||||
            amount: resp.amount,
 | 
			
		||||
            amount_received: resp.amount_received,
 | 
			
		||||
            amount_capturable: resp.amount_capturable,
 | 
			
		||||
            currency: resp.currency.to_lowercase(),
 | 
			
		||||
            status: StripePaymentStatus::from(resp.status),
 | 
			
		||||
            client_secret: resp.client_secret,
 | 
			
		||||
            created: resp.created,
 | 
			
		||||
            customer: resp.customer_id,
 | 
			
		||||
            object: "payment_intent",
 | 
			
		||||
            id: resp.payment_id,
 | 
			
		||||
            status: StripePaymentStatus::from(resp.status),
 | 
			
		||||
            amount: resp.amount,
 | 
			
		||||
            amount_capturable: resp.amount_capturable,
 | 
			
		||||
            amount_received: resp.amount_received,
 | 
			
		||||
            connector: resp.connector,
 | 
			
		||||
            client_secret: resp.client_secret,
 | 
			
		||||
            created: resp.created.map(|t| t.assume_utc().unix_timestamp()),
 | 
			
		||||
            currency: resp.currency.to_lowercase(),
 | 
			
		||||
            customer: resp.customer_id,
 | 
			
		||||
            description: resp.description,
 | 
			
		||||
            refunds: resp.refunds,
 | 
			
		||||
            mandate_id: resp.mandate_id,
 | 
			
		||||
            mandate_data: resp.mandate_data,
 | 
			
		||||
            setup_future_usage: resp.setup_future_usage,
 | 
			
		||||
            off_session: resp.off_session,
 | 
			
		||||
            capture_on: resp.capture_on,
 | 
			
		||||
            capture_method: resp.capture_method,
 | 
			
		||||
            payment_method: resp.payment_method,
 | 
			
		||||
            payment_method_data: resp.payment_method_data,
 | 
			
		||||
            payment_token: resp.payment_token,
 | 
			
		||||
            shipping: resp.shipping,
 | 
			
		||||
            billing: resp.billing,
 | 
			
		||||
            email: resp.email,
 | 
			
		||||
            name: resp.name,
 | 
			
		||||
            phone: resp.phone,
 | 
			
		||||
            return_url: resp.return_url,
 | 
			
		||||
            authentication_type: resp.authentication_type,
 | 
			
		||||
            statement_descriptor_name: resp.statement_descriptor_name,
 | 
			
		||||
            statement_descriptor_suffix: resp.statement_descriptor_suffix,
 | 
			
		||||
            next_action: resp.next_action,
 | 
			
		||||
            cancellation_reason: resp.cancellation_reason,
 | 
			
		||||
            error_code: resp.error_code,
 | 
			
		||||
            error_message: resp.error_message,
 | 
			
		||||
            metadata: resp.metadata,
 | 
			
		||||
            charges: Charges::new(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Eq, PartialEq, Serialize)]
 | 
			
		||||
pub struct Charges {
 | 
			
		||||
    object: &'static str,
 | 
			
		||||
    data: Vec<String>,
 | 
			
		||||
    has_more: bool,
 | 
			
		||||
    total_count: i32,
 | 
			
		||||
    url: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Charges {
 | 
			
		||||
    fn new() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            object: "list",
 | 
			
		||||
            data: vec![],
 | 
			
		||||
            has_more: false,
 | 
			
		||||
            total_count: 0,
 | 
			
		||||
            url: "http://placeholder".to_string(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug, serde::Deserialize)]
 | 
			
		||||
#[serde(deny_unknown_fields)]
 | 
			
		||||
pub struct StripePaymentListConstraints {
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ use std::{convert::From, default::Default};
 | 
			
		||||
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
use crate::types::api::refunds;
 | 
			
		||||
use crate::{core::errors, types::api::refunds};
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
 | 
			
		||||
pub struct StripeCreateRefundRequest {
 | 
			
		||||
@ -23,6 +23,8 @@ pub struct StripeCreateRefundResponse {
 | 
			
		||||
    pub currency: String,
 | 
			
		||||
    pub payment_intent: String,
 | 
			
		||||
    pub status: StripeRefundStatus,
 | 
			
		||||
    pub created: Option<i64>,
 | 
			
		||||
    pub metadata: serde_json::Value,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Serialize, Deserialize, Eq, PartialEq)]
 | 
			
		||||
@ -40,6 +42,7 @@ impl From<StripeCreateRefundRequest> for refunds::RefundRequest {
 | 
			
		||||
            amount: req.amount,
 | 
			
		||||
            payment_id: req.payment_intent,
 | 
			
		||||
            reason: req.reason,
 | 
			
		||||
            refund_type: Some(refunds::RefundType::Instant),
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -65,14 +68,17 @@ impl From<refunds::RefundStatus> for StripeRefundStatus {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<refunds::RefundResponse> for StripeCreateRefundResponse {
 | 
			
		||||
    fn from(res: refunds::RefundResponse) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
impl TryFrom<refunds::RefundResponse> for StripeCreateRefundResponse {
 | 
			
		||||
    type Error = error_stack::Report<errors::ApiErrorResponse>;
 | 
			
		||||
    fn try_from(res: refunds::RefundResponse) -> Result<Self, Self::Error> {
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            id: res.refund_id,
 | 
			
		||||
            amount: res.amount,
 | 
			
		||||
            currency: res.currency.to_ascii_lowercase(),
 | 
			
		||||
            payment_intent: res.payment_id,
 | 
			
		||||
            status: res.status.into(),
 | 
			
		||||
        }
 | 
			
		||||
            created: res.created_at.map(|t| t.assume_utc().unix_timestamp()),
 | 
			
		||||
            metadata: res.metadata.unwrap_or(serde_json::json!({})),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -116,7 +116,7 @@ pub struct StripeSetupIntentRequest {
 | 
			
		||||
    pub description: Option<String>,
 | 
			
		||||
    pub payment_method_data: Option<StripePaymentMethodData>,
 | 
			
		||||
    pub receipt_email: Option<pii::Secret<String, pii::Email>>,
 | 
			
		||||
    pub return_url: Option<String>,
 | 
			
		||||
    pub return_url: Option<url::Url>,
 | 
			
		||||
    pub setup_future_usage: Option<api_enums::FutureUsage>,
 | 
			
		||||
    pub shipping: Option<Shipping>,
 | 
			
		||||
    pub billing_details: Option<StripeBillingDetails>,
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ where
 | 
			
		||||
    F: Fn(&'b A, U, T) -> Fut,
 | 
			
		||||
    Fut: Future<Output = RouterResult<api::ApplicationResponse<Q>>>,
 | 
			
		||||
    Q: Serialize + std::fmt::Debug + 'a,
 | 
			
		||||
    S: From<Q> + Serialize,
 | 
			
		||||
    S: TryFrom<Q> + Serialize,
 | 
			
		||||
    E: Serialize + error_stack::Context + actix_web::ResponseError + Clone,
 | 
			
		||||
    errors::ApiErrorResponse: ErrorSwitch<E>,
 | 
			
		||||
    T: std::fmt::Debug,
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user