mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 01:57:45 +08:00 
			
		
		
		
	refactor(router): refactor customer <> address in customers and payments flow (#2158)
This commit is contained in:
		 Sai Harsha Vardhan
					Sai Harsha Vardhan
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							809832213e
						
					
				
				
					commit
					8ee2ce1f4f
				
			| @ -104,176 +104,138 @@ pub fn filter_mca_based_on_business_profile( | ||||
| } | ||||
|  | ||||
| #[instrument(skip_all)] | ||||
| pub async fn get_address_for_payment_request( | ||||
| pub async fn create_or_find_address_for_payment_by_request( | ||||
|     db: &dyn StorageInterface, | ||||
|     req_address: Option<&api::Address>, | ||||
|     address_id: Option<&str>, | ||||
|     merchant_id: &str, | ||||
|     customer_id: Option<&String>, | ||||
|     merchant_key_store: &domain::MerchantKeyStore, | ||||
|     payment_id: &str, | ||||
| ) -> CustomResult<Option<domain::Address>, errors::ApiErrorResponse> { | ||||
|     let key = merchant_key_store.key.get_inner().peek(); | ||||
|  | ||||
|     Ok(match req_address { | ||||
|         Some(address) => { | ||||
|             match address_id { | ||||
|                 Some(id) => { | ||||
|                     let address_update = async { | ||||
|                         Ok(storage::AddressUpdate::Update { | ||||
|                             city: address | ||||
|                                 .address | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.city.clone()), | ||||
|                             country: address.address.as_ref().and_then(|value| value.country), | ||||
|                             line1: address | ||||
|                                 .address | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.line1.clone()) | ||||
|                                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                 .await?, | ||||
|                             line2: address | ||||
|                                 .address | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.line2.clone()) | ||||
|                                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                 .await?, | ||||
|                             line3: address | ||||
|                                 .address | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.line3.clone()) | ||||
|                                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                 .await?, | ||||
|                             state: address | ||||
|                                 .address | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.state.clone()) | ||||
|                                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                 .await?, | ||||
|                             zip: address | ||||
|                                 .address | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.zip.clone()) | ||||
|                                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                 .await?, | ||||
|                             first_name: address | ||||
|                                 .address | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.first_name.clone()) | ||||
|                                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                 .await?, | ||||
|                             last_name: address | ||||
|                                 .address | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.last_name.clone()) | ||||
|                                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                 .await?, | ||||
|                             phone_number: address | ||||
|                                 .phone | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.number.clone()) | ||||
|                                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                 .await?, | ||||
|                             country_code: address | ||||
|                                 .phone | ||||
|                                 .as_ref() | ||||
|                                 .and_then(|value| value.country_code.clone()), | ||||
|                         }) | ||||
|                     } | ||||
|                     .await | ||||
|                     .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|                     .attach_printable("Failed while encrypting address")?; | ||||
|                     Some( | ||||
|                         db.update_address(id.to_owned(), address_update, merchant_key_store) | ||||
|                             .await | ||||
|                             .to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?, | ||||
|                     ) | ||||
|                 } | ||||
|                 None => { | ||||
|                     // generate a new address here | ||||
|                     let customer_id = customer_id.get_required_value("customer_id")?; | ||||
|     Ok(match address_id { | ||||
|         Some(id) => Some( | ||||
|             db.find_address_by_merchant_id_payment_id_address_id( | ||||
|                 merchant_id, | ||||
|                 payment_id, | ||||
|                 id, | ||||
|                 merchant_key_store, | ||||
|             ) | ||||
|             .await, | ||||
|         ) | ||||
|         .transpose() | ||||
|         .to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?, | ||||
|         None => match req_address { | ||||
|             Some(address) => { | ||||
|                 // generate a new address here | ||||
|                 let customer_id = customer_id.get_required_value("customer_id")?; | ||||
|  | ||||
|                     let address_details = address.address.clone().unwrap_or_default(); | ||||
|                     Some( | ||||
|                         db.insert_address( | ||||
|                             async { | ||||
|                                 Ok(domain::Address { | ||||
|                                     phone_number: address | ||||
|                                         .phone | ||||
|                                         .as_ref() | ||||
|                                         .and_then(|a| a.number.clone()) | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                     country_code: address | ||||
|                                         .phone | ||||
|                                         .as_ref() | ||||
|                                         .and_then(|a| a.country_code.clone()), | ||||
|                                     customer_id: customer_id.to_string(), | ||||
|                                     merchant_id: merchant_id.to_string(), | ||||
|                                     address_id: generate_id(consts::ID_LENGTH, "add"), | ||||
|                                     city: address_details.city, | ||||
|                                     country: address_details.country, | ||||
|                                     line1: address_details | ||||
|                                         .line1 | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                     line2: address_details | ||||
|                                         .line2 | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                     line3: address_details | ||||
|                                         .line3 | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                     id: None, | ||||
|                                     state: address_details | ||||
|                                         .state | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                     created_at: common_utils::date_time::now(), | ||||
|                                     first_name: address_details | ||||
|                                         .first_name | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                     last_name: address_details | ||||
|                                         .last_name | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                     modified_at: common_utils::date_time::now(), | ||||
|                                     zip: address_details | ||||
|                                         .zip | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                 }) | ||||
|                             } | ||||
|                             .await | ||||
|                             .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|                             .attach_printable("Failed while encrypting address while insert")?, | ||||
|                             merchant_key_store, | ||||
|                 let address_details = address.address.clone().unwrap_or_default(); | ||||
|                 Some( | ||||
|                     db.insert_address_for_payments( | ||||
|                         payment_id, | ||||
|                         get_domain_address_for_payments( | ||||
|                             address_details, | ||||
|                             address, | ||||
|                             merchant_id, | ||||
|                             customer_id, | ||||
|                             payment_id, | ||||
|                             key, | ||||
|                         ) | ||||
|                         .await | ||||
|                         .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|                         .attach_printable("Failed while inserting new address")?, | ||||
|                         .attach_printable("Failed while encrypting address while insert")?, | ||||
|                         merchant_key_store, | ||||
|                     ) | ||||
|                 } | ||||
|                     .await | ||||
|                     .change_context(errors::ApiErrorResponse::InternalServerError) | ||||
|                     .attach_printable("Failed while inserting new address")?, | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|         None => match address_id { | ||||
|             Some(id) => Some(db.find_address(id, merchant_key_store).await) | ||||
|                 .transpose() | ||||
|                 .to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?, | ||||
|             None => None, | ||||
|         }, | ||||
|     }) | ||||
| } | ||||
|  | ||||
| pub async fn get_domain_address_for_payments( | ||||
|     address_details: api_models::payments::AddressDetails, | ||||
|     address: &api_models::payments::Address, | ||||
|     merchant_id: &str, | ||||
|     customer_id: &str, | ||||
|     payment_id: &str, | ||||
|     key: &[u8], | ||||
| ) -> CustomResult<domain::Address, common_utils::errors::CryptoError> { | ||||
|     async { | ||||
|         Ok(domain::Address { | ||||
|             id: None, | ||||
|             phone_number: address | ||||
|                 .phone | ||||
|                 .as_ref() | ||||
|                 .and_then(|a| a.number.clone()) | ||||
|                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                 .await?, | ||||
|             country_code: address.phone.as_ref().and_then(|a| a.country_code.clone()), | ||||
|             customer_id: customer_id.to_string(), | ||||
|             merchant_id: merchant_id.to_string(), | ||||
|             address_id: generate_id(consts::ID_LENGTH, "add"), | ||||
|             city: address_details.city, | ||||
|             country: address_details.country, | ||||
|             line1: address_details | ||||
|                 .line1 | ||||
|                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                 .await?, | ||||
|             line2: address_details | ||||
|                 .line2 | ||||
|                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                 .await?, | ||||
|             line3: address_details | ||||
|                 .line3 | ||||
|                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                 .await?, | ||||
|             state: address_details | ||||
|                 .state | ||||
|                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                 .await?, | ||||
|             created_at: common_utils::date_time::now(), | ||||
|             first_name: address_details | ||||
|                 .first_name | ||||
|                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                 .await?, | ||||
|             last_name: address_details | ||||
|                 .last_name | ||||
|                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                 .await?, | ||||
|             modified_at: common_utils::date_time::now(), | ||||
|             zip: address_details | ||||
|                 .zip | ||||
|                 .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                 .await?, | ||||
|             payment_id: Some(payment_id.to_owned()), | ||||
|         }) | ||||
|     } | ||||
|     .await | ||||
| } | ||||
|  | ||||
| pub async fn get_address_by_id( | ||||
|     db: &dyn StorageInterface, | ||||
|     address_id: Option<String>, | ||||
|     merchant_key_store: &domain::MerchantKeyStore, | ||||
|     payment_id: String, | ||||
|     merchant_id: String, | ||||
| ) -> CustomResult<Option<domain::Address>, errors::ApiErrorResponse> { | ||||
|     match address_id { | ||||
|         None => Ok(None), | ||||
|         Some(address_id) => Ok(db.find_address(&address_id, merchant_key_store).await.ok()), | ||||
|         Some(address_id) => Ok(db | ||||
|             .find_address_by_merchant_id_payment_id_address_id( | ||||
|                 &merchant_id, | ||||
|                 &payment_id, | ||||
|                 &address_id, | ||||
|                 merchant_key_store, | ||||
|             ) | ||||
|             .await | ||||
|             .ok()), | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1081,15 +1043,18 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( | ||||
|                                         ) | ||||
|                                     }) | ||||
|                                     .await?, | ||||
|                                 phone: request_customer_details | ||||
|                                     .phone | ||||
|                                     .clone() | ||||
|                                     .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                     .await?, | ||||
|                                 phone: Box::new( | ||||
|                                     request_customer_details | ||||
|                                         .phone | ||||
|                                         .clone() | ||||
|                                         .async_lift(|inner| types::encrypt_optional(inner, key)) | ||||
|                                         .await?, | ||||
|                                 ), | ||||
|                                 phone_country_code: request_customer_details.phone_country_code, | ||||
|                                 description: None, | ||||
|                                 connector_customer: None, | ||||
|                                 metadata: None, | ||||
|                                 address_id: None, | ||||
|                             }) | ||||
|                         } | ||||
|                         .await | ||||
| @ -1136,6 +1101,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>( | ||||
|                             metadata: None, | ||||
|                             modified_at: common_utils::date_time::now(), | ||||
|                             connector_customer: None, | ||||
|                             address_id: None, | ||||
|                         }) | ||||
|                     } | ||||
|                     .await | ||||
|  | ||||
		Reference in New Issue
	
	Block a user