mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 01:57:45 +08:00 
			
		
		
		
	This commit is contained in:
		| @ -128,6 +128,21 @@ impl PaymentsAuthorizeRouterData { | ||||
|                             ) | ||||
|                             .await | ||||
|                             .change_context(errors::ApiErrorResponse::MandateNotFound)?; | ||||
|                         let mandate = match mandate.mandate_type { | ||||
|                             storage_enums::MandateType::SingleUse => state | ||||
|                                 .store | ||||
|                                 .update_mandate_by_merchant_id_mandate_id( | ||||
|                                     &resp.merchant_id, | ||||
|                                     mandate_id, | ||||
|                                     storage::MandateUpdate::StatusUpdate { | ||||
|                                         mandate_status: storage_enums::MandateStatus::Revoked, | ||||
|                                     }, | ||||
|                                 ) | ||||
|                                 .await | ||||
|                                 .change_context(errors::ApiErrorResponse::MandateNotFound), | ||||
|                             storage_enums::MandateType::MultiUse => Ok(mandate), | ||||
|                         }?; | ||||
|  | ||||
|                         resp.payment_method_id = Some(mandate.payment_method_id); | ||||
|                     } | ||||
|                     None => { | ||||
| @ -173,19 +188,32 @@ impl PaymentsAuthorizeRouterData { | ||||
|         match (self.request.setup_mandate_details.clone(), customer) { | ||||
|             (Some(data), Some(cus)) => { | ||||
|                 let mandate_id = utils::generate_id(consts::ID_LENGTH, "man"); | ||||
|                 Some(storage::MandateNew { | ||||
|                     mandate_id, | ||||
|                     customer_id: cus.customer_id.clone(), | ||||
|                     merchant_id: self.merchant_id.clone(), | ||||
|                     payment_method_id, | ||||
|                     mandate_status: storage_enums::MandateStatus::Active, | ||||
|                     mandate_type: storage_enums::MandateType::MultiUse, | ||||
|                     customer_ip_address: data.customer_acceptance.get_ip_address().map(Secret::new), | ||||
|                     customer_user_agent: data.customer_acceptance.get_user_agent(), | ||||
|                     customer_accepted_at: Some(data.customer_acceptance.get_accepted_at()), | ||||
|                     ..Default::default() // network_transaction_id: Option<String>, | ||||
|                                          // previous_transaction_id: Option<String>, | ||||
|                                          // created_at: Option<PrimitiveDateTime>, | ||||
|  | ||||
|                 // The construction of the mandate new must be visible | ||||
|                 let mut new_mandate = storage::MandateNew::default(); | ||||
|  | ||||
|                 new_mandate | ||||
|                     .set_mandate_id(mandate_id) | ||||
|                     .set_customer_id(cus.customer_id.clone()) | ||||
|                     .set_merchant_id(self.merchant_id.clone()) | ||||
|                     .set_payment_method_id(payment_method_id) | ||||
|                     .set_mandate_status(storage_enums::MandateStatus::Active) | ||||
|                     .set_customer_ip_address( | ||||
|                         data.customer_acceptance.get_ip_address().map(Secret::new), | ||||
|                     ) | ||||
|                     .set_customer_user_agent(data.customer_acceptance.get_user_agent()) | ||||
|                     .set_customer_accepted_at(Some(data.customer_acceptance.get_accepted_at())); | ||||
|  | ||||
|                 Some(match data.mandate_type { | ||||
|                     api::MandateType::SingleUse(data) => new_mandate | ||||
|                         .set_single_use_amount(Some(data.amount)) | ||||
|                         .set_single_use_currency(Some(data.currency)) | ||||
|                         .set_mandate_type(storage_enums::MandateType::SingleUse) | ||||
|                         .to_owned(), | ||||
|  | ||||
|                     api::MandateType::MultiUse => new_mandate | ||||
|                         .set_mandate_type(storage_enums::MandateType::MultiUse) | ||||
|                         .to_owned(), | ||||
|                 }) | ||||
|             } | ||||
|             (_, _) => None, | ||||
|  | ||||
| @ -139,6 +139,11 @@ pub async fn get_token_for_recurring_mandate( | ||||
|         .await | ||||
|         .map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::MandateNotFound))?; | ||||
|  | ||||
|     utils::when( | ||||
|         mandate.mandate_status != storage_enums::MandateStatus::Active, | ||||
|         Err(errors::ApiErrorResponse::MandateNotFound), | ||||
|     )?; | ||||
|  | ||||
|     let customer = req.customer_id.clone().get_required_value("customer_id")?; | ||||
|  | ||||
|     let payment_method_id = { | ||||
|  | ||||
| @ -137,7 +137,6 @@ where | ||||
|             payment_data.payment_attempt, | ||||
|             payment_data.payment_intent, | ||||
|             payment_data.refunds, | ||||
|             payment_data.mandate_id, | ||||
|             payment_data.payment_method_data, | ||||
|             customer, | ||||
|             auth_flow, | ||||
| @ -198,7 +197,6 @@ pub fn payments_to_payments_response<R, Op>( | ||||
|     payment_attempt: storage::PaymentAttempt, | ||||
|     payment_intent: storage::PaymentIntent, | ||||
|     refunds: Vec<storage::Refund>, | ||||
|     mandate_id: Option<String>, | ||||
|     payment_method_data: Option<api::PaymentMethod>, | ||||
|     customer: Option<storage::Customer>, | ||||
|     auth_flow: services::AuthFlow, | ||||
| @ -216,6 +214,7 @@ where | ||||
|         .as_ref() | ||||
|         .get_required_value("currency")? | ||||
|         .to_string(); | ||||
|     let mandate_id = payment_attempt.mandate_id.clone(); | ||||
|     let refunds_response = if refunds.is_empty() { | ||||
|         None | ||||
|     } else { | ||||
|  | ||||
| @ -14,6 +14,7 @@ use super::app::AppState; | ||||
| use crate::{ | ||||
|     core::{errors::http_not_implemented, payments}, | ||||
|     services::api, | ||||
|  | ||||
|     types::api::{ | ||||
|         enums as api_enums, | ||||
|         payments::{ | ||||
| @ -21,7 +22,7 @@ use crate::{ | ||||
|             PaymentsRequest, PaymentsRetrieveRequest, | ||||
|         }, | ||||
|         Authorize, Capture, PSync, PaymentRetrieveBody, PaymentsResponse, PaymentsStartRequest, | ||||
|         Verify, VerifyRequest, VerifyResponse, Void, | ||||
|         Verify, VerifyResponse, Void, | ||||
|     }, // FIXME imports | ||||
| }; | ||||
|  | ||||
| @ -110,33 +111,6 @@ pub async fn payments_start( | ||||
|     .await | ||||
| } | ||||
|  | ||||
| #[allow(dead_code)] | ||||
| #[instrument(skip(state), fields(flow = ?Flow::ValidatePaymentMethod))] | ||||
| pub async fn validate_pm( | ||||
|     state: web::Data<AppState>, | ||||
|     req: HttpRequest, | ||||
|     json_payload: web::Json<VerifyRequest>, | ||||
| ) -> HttpResponse { | ||||
|     let payload = json_payload.into_inner(); | ||||
|     api::server_wrap( | ||||
|         &state, | ||||
|         &req, | ||||
|         payload, | ||||
|         |state, merchant_account, req| { | ||||
|             payments::payments_core::<Verify, VerifyResponse, _, _, _>( | ||||
|                 state, | ||||
|                 merchant_account, | ||||
|                 payments::PaymentMethodValidate, | ||||
|                 req, | ||||
|                 api::AuthFlow::Merchant, | ||||
|                 payments::CallConnectorAction::Trigger, | ||||
|             ) | ||||
|         }, | ||||
|         api::MerchantAuthentication::ApiKey, | ||||
|     ) | ||||
|     .await | ||||
| } | ||||
|  | ||||
| #[instrument(skip(state), fields(flow = ?Flow::PaymentsRetrieve))] | ||||
| // #[get("/{payment_id}")] | ||||
| pub async fn payments_retrieve( | ||||
|  | ||||
| @ -127,6 +127,8 @@ diesel::table! { | ||||
|         network_transaction_id -> Nullable<Varchar>, | ||||
|         previous_transaction_id -> Nullable<Varchar>, | ||||
|         created_at -> Timestamp, | ||||
|         single_use_amount -> Nullable<Int4>, | ||||
|         single_use_currency -> Nullable<Currency>, | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -7,7 +7,7 @@ use crate::{ | ||||
|     core::errors, | ||||
|     pii, | ||||
|     services::api, | ||||
|     types::{self, api as api_types, api::enums as api_enums}, | ||||
|     types::{self, api as api_types, api::enums as api_enums, storage}, | ||||
|     utils::custom_serde, | ||||
| }; | ||||
|  | ||||
| @ -126,6 +126,14 @@ pub enum MandateTxnType { | ||||
| #[serde(deny_unknown_fields)] | ||||
| pub struct MandateData { | ||||
|     pub customer_acceptance: CustomerAcceptance, | ||||
|     pub mandate_type: MandateType, | ||||
| } | ||||
|  | ||||
| #[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)] | ||||
| pub enum MandateType { | ||||
|     SingleUse(storage::SingleUseMandate), | ||||
|     #[default] | ||||
|     MultiUse, | ||||
| } | ||||
|  | ||||
| #[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)] | ||||
|  | ||||
| @ -24,9 +24,13 @@ pub struct Mandate { | ||||
|     pub network_transaction_id: Option<String>, | ||||
|     pub previous_transaction_id: Option<String>, | ||||
|     pub created_at: PrimitiveDateTime, | ||||
|     pub single_use_amount: Option<i32>, | ||||
|     pub single_use_currency: Option<storage_enums::Currency>, | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay)] | ||||
| #[derive( | ||||
|     router_derive::Setter, Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay, | ||||
| )] | ||||
| #[diesel(table_name = mandate)] | ||||
| pub struct MandateNew { | ||||
|     pub mandate_id: String, | ||||
| @ -41,6 +45,8 @@ pub struct MandateNew { | ||||
|     pub network_transaction_id: Option<String>, | ||||
|     pub previous_transaction_id: Option<String>, | ||||
|     pub created_at: Option<PrimitiveDateTime>, | ||||
|     pub single_use_amount: Option<i32>, | ||||
|     pub single_use_currency: Option<storage_enums::Currency>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| @ -50,6 +56,12 @@ pub enum MandateUpdate { | ||||
|     }, | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Eq, PartialEq, Copy, Debug, Default, serde::Serialize, serde::Deserialize)] | ||||
| pub struct SingleUseMandate { | ||||
|     pub amount: i32, | ||||
|     pub currency: storage_enums::Currency, | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)] | ||||
| #[diesel(table_name = mandate)] | ||||
| pub(super) struct MandateUpdateInternal { | ||||
|  | ||||
| @ -0,0 +1,4 @@ | ||||
| -- This file should undo anything in `up.sql` | ||||
| ALTER TABLE mandate  | ||||
| DROP COLUMN IF EXISTS single_use_amount, | ||||
| DROP COLUMN IF EXISTS single_use_currency; | ||||
| @ -0,0 +1,4 @@ | ||||
| -- Your SQL goes here | ||||
| ALTER TABLE mandate  | ||||
| ADD IF NOT EXISTS single_use_amount INTEGER DEFAULT NULL, | ||||
| ADD IF NOT EXISTS single_use_currency "Currency" DEFAULT NULL; | ||||
		Reference in New Issue
	
	Block a user