mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 19:42:27 +08:00
feat(core): add sessions api endpoint (#104)
This commit is contained in:
@ -36,6 +36,10 @@ locker_encryption_key2 = ""
|
|||||||
locker_decryption_key1 = ""
|
locker_decryption_key1 = ""
|
||||||
locker_decryption_key2 = ""
|
locker_decryption_key2 = ""
|
||||||
|
|
||||||
|
[connectors.supported]
|
||||||
|
wallets = ["klarna","braintree"]
|
||||||
|
cards = ["stripe","adyen","authorizedotnet","checkout","braintree"]
|
||||||
|
|
||||||
[eph_key]
|
[eph_key]
|
||||||
validity = 1
|
validity = 1
|
||||||
|
|
||||||
|
|||||||
@ -99,6 +99,11 @@ pub struct Database {
|
|||||||
pub pool_size: u32,
|
pub pool_size: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
pub struct SupportedConnectors {
|
||||||
|
pub wallets: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct Connectors {
|
pub struct Connectors {
|
||||||
pub aci: ConnectorParams,
|
pub aci: ConnectorParams,
|
||||||
@ -107,6 +112,7 @@ pub struct Connectors {
|
|||||||
pub checkout: ConnectorParams,
|
pub checkout: ConnectorParams,
|
||||||
pub stripe: ConnectorParams,
|
pub stripe: ConnectorParams,
|
||||||
pub braintree: ConnectorParams,
|
pub braintree: ConnectorParams,
|
||||||
|
pub supported: SupportedConnectors,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use time;
|
|||||||
|
|
||||||
pub use self::operations::{
|
pub use self::operations::{
|
||||||
PaymentCancel, PaymentCapture, PaymentConfirm, PaymentCreate, PaymentMethodValidate,
|
PaymentCancel, PaymentCapture, PaymentConfirm, PaymentCreate, PaymentMethodValidate,
|
||||||
PaymentResponse, PaymentStatus, PaymentUpdate,
|
PaymentResponse, PaymentSession, PaymentStatus, PaymentUpdate,
|
||||||
};
|
};
|
||||||
use self::{
|
use self::{
|
||||||
flows::{ConstructFlowSpecificData, Feature},
|
flows::{ConstructFlowSpecificData, Feature},
|
||||||
@ -61,9 +61,6 @@ where
|
|||||||
// To perform router related operation for PaymentResponse
|
// To perform router related operation for PaymentResponse
|
||||||
PaymentResponse: Operation<F, FData>,
|
PaymentResponse: Operation<F, FData>,
|
||||||
{
|
{
|
||||||
let connector = api::ConnectorData::construct(&state.conf.connectors, &merchant_account)
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
|
||||||
|
|
||||||
let operation: BoxedOperation<F, Req> = Box::new(operation);
|
let operation: BoxedOperation<F, Req> = Box::new(operation);
|
||||||
|
|
||||||
let (operation, validate_result) = operation
|
let (operation, validate_result) = operation
|
||||||
@ -78,7 +75,6 @@ where
|
|||||||
state,
|
state,
|
||||||
&validate_result.payment_id,
|
&validate_result.payment_id,
|
||||||
validate_result.merchant_id,
|
validate_result.merchant_id,
|
||||||
connector.connector_name,
|
|
||||||
&req,
|
&req,
|
||||||
validate_result.mandate_type,
|
validate_result.mandate_type,
|
||||||
validate_result.storage_scheme,
|
validate_result.storage_scheme,
|
||||||
@ -110,6 +106,16 @@ where
|
|||||||
.await?;
|
.await?;
|
||||||
payment_data.payment_method_data = payment_method_data;
|
payment_data.payment_method_data = payment_method_data;
|
||||||
|
|
||||||
|
let connector_details = operation
|
||||||
|
.to_domain()?
|
||||||
|
.get_connector(&merchant_account, state)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let api::ConnectorCallType::Single(ref connector) = connector_details {
|
||||||
|
payment_data.payment_attempt.connector =
|
||||||
|
Some(connector.connector_name.to_owned().to_string());
|
||||||
|
}
|
||||||
|
|
||||||
let (operation, mut payment_data) = operation
|
let (operation, mut payment_data) = operation
|
||||||
.to_update_tracker()?
|
.to_update_tracker()?
|
||||||
.update_trackers(
|
.update_trackers(
|
||||||
@ -127,17 +133,32 @@ where
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if should_call_connector(&operation, &payment_data) {
|
if should_call_connector(&operation, &payment_data) {
|
||||||
payment_data = call_connector_service(
|
payment_data = match connector_details {
|
||||||
state,
|
api::ConnectorCallType::Single(connector) => {
|
||||||
&merchant_account,
|
call_connector_service(
|
||||||
&validate_result.payment_id,
|
state,
|
||||||
connector,
|
&merchant_account,
|
||||||
&operation,
|
&validate_result.payment_id,
|
||||||
payment_data,
|
connector,
|
||||||
&customer,
|
&operation,
|
||||||
call_connector_action,
|
payment_data,
|
||||||
)
|
&customer,
|
||||||
.await?;
|
call_connector_action,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
}
|
||||||
|
api::ConnectorCallType::Multiple(connectors) => {
|
||||||
|
call_multiple_connectors_service(
|
||||||
|
state,
|
||||||
|
&merchant_account,
|
||||||
|
connectors,
|
||||||
|
&operation,
|
||||||
|
payment_data,
|
||||||
|
&customer,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok((payment_data, req, customer))
|
Ok((payment_data, req, customer))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,13 +21,14 @@ use crate::{
|
|||||||
routes::AppState,
|
routes::AppState,
|
||||||
services,
|
services,
|
||||||
types::{
|
types::{
|
||||||
|
self,
|
||||||
api::{self, enums as api_enums},
|
api::{self, enums as api_enums},
|
||||||
storage::{self, enums as storage_enums, ephemeral_key},
|
storage::{self, enums as storage_enums, ephemeral_key},
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
self,
|
self,
|
||||||
crypto::{self, SignMessage},
|
crypto::{self, SignMessage},
|
||||||
OptionExt,
|
OptionExt, ValueExt,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -313,13 +314,14 @@ pub fn create_startpay_url(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_redirect_url(server: &Server, payment_attempt: &storage::PaymentAttempt) -> String {
|
pub fn create_redirect_url(
|
||||||
|
server: &Server,
|
||||||
|
payment_attempt: &storage::PaymentAttempt,
|
||||||
|
connector_name: &String,
|
||||||
|
) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{}/payments/{}/{}/response/{}",
|
"{}/payments/{}/{}/response/{}",
|
||||||
server.base_url,
|
server.base_url, payment_attempt.payment_id, payment_attempt.merchant_id, connector_name
|
||||||
payment_attempt.payment_id,
|
|
||||||
payment_attempt.merchant_id,
|
|
||||||
payment_attempt.connector
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn validate_recurring_mandate(req: api::MandateValidationFields) -> RouterResult<()> {
|
fn validate_recurring_mandate(req: api::MandateValidationFields) -> RouterResult<()> {
|
||||||
@ -522,6 +524,44 @@ pub async fn get_customer_from_details(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_connector_default(
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||||
|
let connectors = &state.conf.connectors;
|
||||||
|
let vec_val: Vec<serde_json::Value> = merchant_account
|
||||||
|
.custom_routing_rules
|
||||||
|
.clone()
|
||||||
|
.parse_value("CustomRoutingRulesVec")
|
||||||
|
.change_context(errors::ConnectorError::RoutingRulesParsingError)
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
let custom_routing_rules: api::CustomRoutingRules = vec_val[0]
|
||||||
|
.clone()
|
||||||
|
.parse_value("CustomRoutingRules")
|
||||||
|
.change_context(errors::ConnectorError::RoutingRulesParsingError)
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
let connector_names = custom_routing_rules
|
||||||
|
.connectors_pecking_order
|
||||||
|
.unwrap_or_else(|| vec!["stripe".to_string()]);
|
||||||
|
|
||||||
|
//use routing rules if configured by merchant else query MCA as per PM
|
||||||
|
let connector_list: types::ConnectorsList = types::ConnectorsList {
|
||||||
|
connectors: connector_names,
|
||||||
|
};
|
||||||
|
|
||||||
|
let connector_name = connector_list
|
||||||
|
.connectors
|
||||||
|
.first()
|
||||||
|
.get_required_value("connectors")
|
||||||
|
.change_context(errors::ConnectorError::FailedToObtainPreferredConnector)
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)?
|
||||||
|
.as_str();
|
||||||
|
|
||||||
|
let connector_data = api::ConnectorData::get_connector_by_name(connectors, connector_name)?;
|
||||||
|
|
||||||
|
Ok(api::ConnectorCallType::Single(connector_data))
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
|
pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
|
||||||
operation: BoxedOperation<'a, F, R>,
|
operation: BoxedOperation<'a, F, R>,
|
||||||
|
|||||||
@ -92,7 +92,6 @@ pub trait GetTracker<F, D, R>: Send {
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
connector: types::Connector,
|
|
||||||
request: &R,
|
request: &R,
|
||||||
mandate_type: Option<api::MandateTxnType>,
|
mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
@ -129,6 +128,12 @@ pub trait Domain<F: Clone, R>: Send + Sync {
|
|||||||
) -> CustomResult<(), errors::ApiErrorResponse> {
|
) -> CustomResult<(), errors::ApiErrorResponse> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_connector<'a>(
|
||||||
|
&'a self,
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -224,9 +229,14 @@ where
|
|||||||
if helpers::check_if_operation_confirm(self) {
|
if helpers::check_if_operation_confirm(self) {
|
||||||
metrics::TASKS_ADDED_COUNT.add(&metrics::CONTEXT, 1, &[]); // Metrics
|
metrics::TASKS_ADDED_COUNT.add(&metrics::CONTEXT, 1, &[]); // Metrics
|
||||||
|
|
||||||
|
let connector_name = payment_attempt
|
||||||
|
.connector
|
||||||
|
.clone()
|
||||||
|
.ok_or(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
|
||||||
let schedule_time = payment_sync::get_sync_process_schedule_time(
|
let schedule_time = payment_sync::get_sync_process_schedule_time(
|
||||||
&*state.store,
|
&*state.store,
|
||||||
&payment_attempt.connector,
|
&connector_name,
|
||||||
&payment_attempt.merchant_id,
|
&payment_attempt.merchant_id,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
@ -245,6 +255,14 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_connector<'a>(
|
||||||
|
&'a self,
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||||
|
helpers::get_connector_default(merchant_account, state).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -278,6 +296,14 @@ where
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_connector<'a>(
|
||||||
|
&'a self,
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||||
|
helpers::get_connector_default(merchant_account, state).await
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
async fn make_pm_data<'a>(
|
async fn make_pm_data<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
@ -351,6 +377,14 @@ where
|
|||||||
)> {
|
)> {
|
||||||
Ok((Box::new(self), None))
|
Ok((Box::new(self), None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_connector<'a>(
|
||||||
|
&'a self,
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||||
|
helpers::get_connector_default(merchant_account, state).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -400,4 +434,12 @@ where
|
|||||||
)> {
|
)> {
|
||||||
Ok((Box::new(self), None))
|
Ok((Box::new(self), None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_connector<'a>(
|
||||||
|
&'a self,
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||||
|
helpers::get_connector_default(merchant_account, state).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,6 @@ use crate::{
|
|||||||
types::{
|
types::{
|
||||||
api,
|
api,
|
||||||
storage::{self, enums, Customer},
|
storage::{self, enums, Customer},
|
||||||
Connector,
|
|
||||||
},
|
},
|
||||||
utils::OptionExt,
|
utils::OptionExt,
|
||||||
};
|
};
|
||||||
@ -33,7 +32,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsCancelRequest>
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
_connector: Connector,
|
|
||||||
request: &api::PaymentsCancelRequest,
|
request: &api::PaymentsCancelRequest,
|
||||||
_mandate_type: Option<api::MandateTxnType>,
|
_mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
|
|||||||
@ -16,7 +16,6 @@ use crate::{
|
|||||||
api,
|
api,
|
||||||
api::PaymentsCaptureRequest,
|
api::PaymentsCaptureRequest,
|
||||||
storage::{self, enums},
|
storage::{self, enums},
|
||||||
Connector,
|
|
||||||
},
|
},
|
||||||
utils::OptionExt,
|
utils::OptionExt,
|
||||||
};
|
};
|
||||||
@ -35,7 +34,6 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
_connector: Connector,
|
|
||||||
request: &PaymentsCaptureRequest,
|
request: &PaymentsCaptureRequest,
|
||||||
_mandate_type: Option<api::MandateTxnType>,
|
_mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
|
|||||||
@ -17,7 +17,6 @@ use crate::{
|
|||||||
types::{
|
types::{
|
||||||
self, api,
|
self, api,
|
||||||
storage::{self, enums},
|
storage::{self, enums},
|
||||||
Connector,
|
|
||||||
},
|
},
|
||||||
utils::{self, OptionExt},
|
utils::{self, OptionExt},
|
||||||
};
|
};
|
||||||
@ -34,7 +33,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
_connector: Connector,
|
|
||||||
request: &api::PaymentsRequest,
|
request: &api::PaymentsRequest,
|
||||||
mandate_type: Option<api::MandateTxnType>,
|
mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
@ -194,6 +192,8 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let connector = payment_data.payment_attempt.connector.clone();
|
||||||
|
|
||||||
payment_data.payment_attempt = db
|
payment_data.payment_attempt = db
|
||||||
.update_payment_attempt(
|
.update_payment_attempt(
|
||||||
payment_data.payment_attempt,
|
payment_data.payment_attempt,
|
||||||
@ -201,6 +201,7 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
|||||||
status: attempt_status,
|
status: attempt_status,
|
||||||
payment_method,
|
payment_method,
|
||||||
browser_info,
|
browser_info,
|
||||||
|
connector,
|
||||||
},
|
},
|
||||||
storage_scheme,
|
storage_scheme,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -37,7 +37,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
connector: types::Connector,
|
|
||||||
request: &api::PaymentsRequest,
|
request: &api::PaymentsRequest,
|
||||||
mandate_type: Option<api::MandateTxnType>,
|
mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
@ -84,7 +83,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
|||||||
Self::make_payment_attempt(
|
Self::make_payment_attempt(
|
||||||
&payment_id,
|
&payment_id,
|
||||||
merchant_id,
|
merchant_id,
|
||||||
connector,
|
|
||||||
money,
|
money,
|
||||||
payment_method_type,
|
payment_method_type,
|
||||||
request,
|
request,
|
||||||
@ -117,7 +115,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
|||||||
Self::make_payment_intent(
|
Self::make_payment_intent(
|
||||||
&payment_id,
|
&payment_id,
|
||||||
merchant_id,
|
merchant_id,
|
||||||
&connector.to_string(),
|
|
||||||
money,
|
money,
|
||||||
request,
|
request,
|
||||||
shipping_address.clone().map(|x| x.address_id),
|
shipping_address.clone().map(|x| x.address_id),
|
||||||
@ -314,7 +311,6 @@ impl PaymentCreate {
|
|||||||
fn make_payment_attempt(
|
fn make_payment_attempt(
|
||||||
payment_id: &str,
|
payment_id: &str,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
connector: types::Connector,
|
|
||||||
money: (api::Amount, enums::Currency),
|
money: (api::Amount, enums::Currency),
|
||||||
payment_method: Option<enums::PaymentMethodType>,
|
payment_method: Option<enums::PaymentMethodType>,
|
||||||
request: &api::PaymentsRequest,
|
request: &api::PaymentsRequest,
|
||||||
@ -331,7 +327,6 @@ impl PaymentCreate {
|
|||||||
status,
|
status,
|
||||||
amount: amount.into(),
|
amount: amount.into(),
|
||||||
currency,
|
currency,
|
||||||
connector: connector.to_string(),
|
|
||||||
payment_method,
|
payment_method,
|
||||||
capture_method: request.capture_method.map(Into::into),
|
capture_method: request.capture_method.map(Into::into),
|
||||||
capture_on: request.capture_on,
|
capture_on: request.capture_on,
|
||||||
@ -349,7 +344,6 @@ impl PaymentCreate {
|
|||||||
fn make_payment_intent(
|
fn make_payment_intent(
|
||||||
payment_id: &str,
|
payment_id: &str,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
connector_id: &str,
|
|
||||||
money: (api::Amount, enums::Currency),
|
money: (api::Amount, enums::Currency),
|
||||||
request: &api::PaymentsRequest,
|
request: &api::PaymentsRequest,
|
||||||
shipping_address_id: Option<String>,
|
shipping_address_id: Option<String>,
|
||||||
@ -367,7 +361,6 @@ impl PaymentCreate {
|
|||||||
status,
|
status,
|
||||||
amount: amount.into(),
|
amount: amount.into(),
|
||||||
currency,
|
currency,
|
||||||
connector_id: Some(connector_id.to_string()),
|
|
||||||
description: request.description.clone(),
|
description: request.description.clone(),
|
||||||
created_at,
|
created_at,
|
||||||
modified_at,
|
modified_at,
|
||||||
|
|||||||
@ -66,7 +66,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::VerifyRequest> for Paym
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
connector: types::Connector,
|
|
||||||
request: &api::VerifyRequest,
|
request: &api::VerifyRequest,
|
||||||
_mandate_type: Option<api::MandateTxnType>,
|
_mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: storage_enums::MerchantStorageScheme,
|
storage_scheme: storage_enums::MerchantStorageScheme,
|
||||||
@ -87,7 +86,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::VerifyRequest> for Paym
|
|||||||
Self::make_payment_attempt(
|
Self::make_payment_attempt(
|
||||||
&payment_id,
|
&payment_id,
|
||||||
merchant_id,
|
merchant_id,
|
||||||
connector,
|
|
||||||
request.payment_method,
|
request.payment_method,
|
||||||
request,
|
request,
|
||||||
),
|
),
|
||||||
@ -103,7 +101,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::VerifyRequest> for Paym
|
|||||||
|
|
||||||
payment_intent = match db
|
payment_intent = match db
|
||||||
.insert_payment_intent(
|
.insert_payment_intent(
|
||||||
Self::make_payment_intent(&payment_id, merchant_id, connector, request),
|
Self::make_payment_intent(&payment_id, merchant_id, request),
|
||||||
storage_scheme,
|
storage_scheme,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -256,6 +254,14 @@ where
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_connector<'a>(
|
||||||
|
&'a self,
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||||
|
helpers::get_connector_default(merchant_account, state).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PaymentMethodValidate {
|
impl PaymentMethodValidate {
|
||||||
@ -263,7 +269,6 @@ impl PaymentMethodValidate {
|
|||||||
fn make_payment_attempt(
|
fn make_payment_attempt(
|
||||||
payment_id: &str,
|
payment_id: &str,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
connector: types::Connector,
|
|
||||||
payment_method: Option<api_enums::PaymentMethodType>,
|
payment_method: Option<api_enums::PaymentMethodType>,
|
||||||
_request: &api::VerifyRequest,
|
_request: &api::VerifyRequest,
|
||||||
) -> storage::PaymentAttemptNew {
|
) -> storage::PaymentAttemptNew {
|
||||||
@ -278,7 +283,7 @@ impl PaymentMethodValidate {
|
|||||||
// Amount & Currency will be zero in this case
|
// Amount & Currency will be zero in this case
|
||||||
amount: 0,
|
amount: 0,
|
||||||
currency: Default::default(),
|
currency: Default::default(),
|
||||||
connector: connector.to_string(),
|
connector: None,
|
||||||
payment_method: payment_method.map(Into::into),
|
payment_method: payment_method.map(Into::into),
|
||||||
confirm: true,
|
confirm: true,
|
||||||
created_at,
|
created_at,
|
||||||
@ -291,7 +296,6 @@ impl PaymentMethodValidate {
|
|||||||
fn make_payment_intent(
|
fn make_payment_intent(
|
||||||
payment_id: &str,
|
payment_id: &str,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
connector: types::Connector,
|
|
||||||
request: &api::VerifyRequest,
|
request: &api::VerifyRequest,
|
||||||
) -> storage::PaymentIntentNew {
|
) -> storage::PaymentIntentNew {
|
||||||
let created_at @ modified_at @ last_synced = Some(date_time::now());
|
let created_at @ modified_at @ last_synced = Some(date_time::now());
|
||||||
@ -305,7 +309,7 @@ impl PaymentMethodValidate {
|
|||||||
status,
|
status,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
currency: Default::default(),
|
currency: Default::default(),
|
||||||
connector_id: Some(connector.to_string()),
|
connector_id: None,
|
||||||
created_at,
|
created_at,
|
||||||
modified_at,
|
modified_at,
|
||||||
last_synced,
|
last_synced,
|
||||||
|
|||||||
@ -20,7 +20,7 @@ use crate::{
|
|||||||
#[derive(Debug, Clone, Copy, router_derive::PaymentOperation)]
|
#[derive(Debug, Clone, Copy, router_derive::PaymentOperation)]
|
||||||
#[operation(
|
#[operation(
|
||||||
ops = "post_tracker",
|
ops = "post_tracker",
|
||||||
flow = "syncdata,authorizedata,canceldata,capturedata,verifydata"
|
flow = "syncdata,authorizedata,canceldata,capturedata,verifydata,sessiondata"
|
||||||
)]
|
)]
|
||||||
pub struct PaymentResponse;
|
pub struct PaymentResponse;
|
||||||
|
|
||||||
@ -77,6 +77,28 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSyncData> for
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSessionData>
|
||||||
|
for PaymentResponse
|
||||||
|
{
|
||||||
|
async fn update_tracker<'b>(
|
||||||
|
&'b self,
|
||||||
|
db: &dyn StorageInterface,
|
||||||
|
payment_id: &api::PaymentIdType,
|
||||||
|
payment_data: PaymentData<F>,
|
||||||
|
response: Option<
|
||||||
|
types::RouterData<F, types::PaymentsSessionData, types::PaymentsResponseData>,
|
||||||
|
>,
|
||||||
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
|
) -> RouterResult<PaymentData<F>>
|
||||||
|
where
|
||||||
|
F: 'b + Send,
|
||||||
|
{
|
||||||
|
payment_response_update_tracker(db, payment_id, payment_data, response, storage_scheme)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCaptureData>
|
impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCaptureData>
|
||||||
for PaymentResponse
|
for PaymentResponse
|
||||||
@ -169,6 +191,7 @@ async fn payment_response_update_tracker<F: Clone, T>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let encoded_data = payment_data.connector_response.encoded_data.clone();
|
let encoded_data = payment_data.connector_response.encoded_data.clone();
|
||||||
|
let connector_name = payment_data.payment_attempt.connector.clone();
|
||||||
|
|
||||||
let authentication_data = redirection_data
|
let authentication_data = redirection_data
|
||||||
.map(|data| utils::Encode::<RedirectForm>::encode_to_value(&data))
|
.map(|data| utils::Encode::<RedirectForm>::encode_to_value(&data))
|
||||||
@ -189,6 +212,7 @@ async fn payment_response_update_tracker<F: Clone, T>(
|
|||||||
connector_transaction_id,
|
connector_transaction_id,
|
||||||
authentication_data,
|
authentication_data,
|
||||||
encoded_data,
|
encoded_data,
|
||||||
|
connector_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
|
|||||||
@ -16,7 +16,6 @@ use crate::{
|
|||||||
types::{
|
types::{
|
||||||
api,
|
api,
|
||||||
storage::{self, enums},
|
storage::{self, enums},
|
||||||
Connector,
|
|
||||||
},
|
},
|
||||||
utils::OptionExt,
|
utils::OptionExt,
|
||||||
};
|
};
|
||||||
@ -35,7 +34,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest>
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
_connector: Connector,
|
|
||||||
request: &api::PaymentsSessionRequest,
|
request: &api::PaymentsSessionRequest,
|
||||||
_mandate_type: Option<api::MandateTxnType>,
|
_mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
@ -235,4 +233,38 @@ where
|
|||||||
//No payment method data for this operation
|
//No payment method data for this operation
|
||||||
Ok((Box::new(self), None))
|
Ok((Box::new(self), None))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_connector<'a>(
|
||||||
|
&'a self,
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> RouterResult<api::ConnectorCallType> {
|
||||||
|
let connectors = &state.conf.connectors;
|
||||||
|
let db = &state.store;
|
||||||
|
|
||||||
|
let supported_connectors: &Vec<String> = state.conf.connectors.supported.wallets.as_ref();
|
||||||
|
|
||||||
|
//FIXME: Check if merchant has enabled wallet through the connector
|
||||||
|
let connector_names = db
|
||||||
|
.find_merchant_connector_account_by_merchant_id_list(&merchant_account.merchant_id)
|
||||||
|
.await
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable("Database error when querying for merchant accounts")?
|
||||||
|
.iter()
|
||||||
|
.filter(|connector_account| {
|
||||||
|
supported_connectors.contains(&connector_account.connector_name)
|
||||||
|
})
|
||||||
|
.map(|filtered_connector| filtered_connector.connector_name.clone())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
let mut connectors_data = Vec::with_capacity(connector_names.len());
|
||||||
|
|
||||||
|
for connector_name in connector_names {
|
||||||
|
let connector_data =
|
||||||
|
api::ConnectorData::get_connector_by_name(connectors, &connector_name)?;
|
||||||
|
connectors_data.push(connector_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(api::ConnectorCallType::Multiple(connectors_data))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,6 @@ use crate::{
|
|||||||
types::{
|
types::{
|
||||||
api,
|
api,
|
||||||
storage::{self, enums, Customer},
|
storage::{self, enums, Customer},
|
||||||
Connector,
|
|
||||||
},
|
},
|
||||||
utils::OptionExt,
|
utils::OptionExt,
|
||||||
};
|
};
|
||||||
@ -33,7 +32,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsStartRequest> f
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
_connector: Connector,
|
|
||||||
_request: &api::PaymentsStartRequest,
|
_request: &api::PaymentsStartRequest,
|
||||||
_mandate_type: Option<api::MandateTxnType>,
|
_mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
@ -252,4 +250,12 @@ where
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_connector<'a>(
|
||||||
|
&'a self,
|
||||||
|
merchant_account: &storage::MerchantAccount,
|
||||||
|
state: &AppState,
|
||||||
|
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||||
|
helpers::get_connector_default(merchant_account, state).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,10 +16,10 @@ use crate::{
|
|||||||
types::{
|
types::{
|
||||||
api,
|
api,
|
||||||
storage::{self, enums},
|
storage::{self, enums},
|
||||||
Connector,
|
|
||||||
},
|
},
|
||||||
utils::{self, OptionExt},
|
utils::{self, OptionExt},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PaymentOperation)]
|
#[derive(Debug, Clone, Copy, PaymentOperation)]
|
||||||
#[operation(ops = "all", flow = "sync")]
|
#[operation(ops = "all", flow = "sync")]
|
||||||
pub struct PaymentStatus;
|
pub struct PaymentStatus;
|
||||||
@ -94,7 +94,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRetrieveRequest
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
_connector: Connector,
|
|
||||||
request: &api::PaymentsRetrieveRequest,
|
request: &api::PaymentsRetrieveRequest,
|
||||||
_mandate_type: Option<api::MandateTxnType>,
|
_mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
|
|||||||
@ -17,7 +17,6 @@ use crate::{
|
|||||||
types::{
|
types::{
|
||||||
api,
|
api,
|
||||||
storage::{self, enums},
|
storage::{self, enums},
|
||||||
Connector,
|
|
||||||
},
|
},
|
||||||
utils::{OptionExt, StringExt},
|
utils::{OptionExt, StringExt},
|
||||||
};
|
};
|
||||||
@ -33,7 +32,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
|||||||
state: &'a AppState,
|
state: &'a AppState,
|
||||||
payment_id: &api::PaymentIdType,
|
payment_id: &api::PaymentIdType,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
_connector: Connector,
|
|
||||||
request: &api::PaymentsRequest,
|
request: &api::PaymentsRequest,
|
||||||
mandate_type: Option<api::MandateTxnType>,
|
mandate_type: Option<api::MandateTxnType>,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
|
|||||||
@ -73,6 +73,7 @@ where
|
|||||||
let orca_return_url = Some(helpers::create_redirect_url(
|
let orca_return_url = Some(helpers::create_redirect_url(
|
||||||
&state.conf.server,
|
&state.conf.server,
|
||||||
&payment_data.payment_attempt,
|
&payment_data.payment_attempt,
|
||||||
|
&merchant_connector_account.connector_name,
|
||||||
));
|
));
|
||||||
|
|
||||||
router_data = types::RouterData {
|
router_data = types::RouterData {
|
||||||
@ -145,6 +146,26 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<F, Req, Op> ToResponse<Req, PaymentData<F>, Op> for api::PaymentsSessionResponse
|
||||||
|
where
|
||||||
|
Self: From<Req>,
|
||||||
|
F: Clone,
|
||||||
|
Op: Debug,
|
||||||
|
{
|
||||||
|
fn generate_response(
|
||||||
|
_req: Option<Req>,
|
||||||
|
payment_data: PaymentData<F>,
|
||||||
|
_customer: Option<storage::Customer>,
|
||||||
|
_auth_flow: services::AuthFlow,
|
||||||
|
_server: &Server,
|
||||||
|
_operation: Op,
|
||||||
|
) -> RouterResponse<Self> {
|
||||||
|
Ok(services::BachResponse::Json(Self {
|
||||||
|
session_token: payment_data.sessions_token,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<F, Req, Op> ToResponse<Req, PaymentData<F>, Op> for api::VerifyResponse
|
impl<F, Req, Op> ToResponse<Req, PaymentData<F>, Op> for api::VerifyResponse
|
||||||
where
|
where
|
||||||
Self: From<Req>,
|
Self: From<Req>,
|
||||||
|
|||||||
@ -91,7 +91,11 @@ pub async fn trigger_refund_to_gateway(
|
|||||||
payment_attempt: &storage::PaymentAttempt,
|
payment_attempt: &storage::PaymentAttempt,
|
||||||
payment_intent: &storage::PaymentIntent,
|
payment_intent: &storage::PaymentIntent,
|
||||||
) -> RouterResult<storage::Refund> {
|
) -> RouterResult<storage::Refund> {
|
||||||
let connector_id = payment_attempt.connector.to_string();
|
let connector = payment_attempt
|
||||||
|
.connector
|
||||||
|
.clone()
|
||||||
|
.ok_or(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
let connector_id = connector.to_string();
|
||||||
let connector: api::ConnectorData =
|
let connector: api::ConnectorData =
|
||||||
api::ConnectorData::get_connector_by_name(&state.conf.connectors, &connector_id)
|
api::ConnectorData::get_connector_by_name(&state.conf.connectors, &connector_id)
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
@ -390,9 +394,14 @@ pub async fn validate_and_create_refund(
|
|||||||
validator::validate_maximum_refund_against_payment_attempt(&all_refunds)
|
validator::validate_maximum_refund_against_payment_attempt(&all_refunds)
|
||||||
.change_context(errors::ApiErrorResponse::MaximumRefundCount)?;
|
.change_context(errors::ApiErrorResponse::MaximumRefundCount)?;
|
||||||
|
|
||||||
|
let connector = payment_attempt
|
||||||
|
.connector
|
||||||
|
.clone()
|
||||||
|
.ok_or(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
|
|
||||||
refund_create_req = mk_new_refund(
|
refund_create_req = mk_new_refund(
|
||||||
req,
|
req,
|
||||||
payment_attempt.connector.to_owned(),
|
connector,
|
||||||
payment_attempt,
|
payment_attempt,
|
||||||
currency,
|
currency,
|
||||||
&refund_id,
|
&refund_id,
|
||||||
|
|||||||
@ -75,6 +75,9 @@ impl Payments {
|
|||||||
web::resource("/{payment_id}/{merchant_id}/response/{connector}")
|
web::resource("/{payment_id}/{merchant_id}/response/{connector}")
|
||||||
.route(web::get().to(payments_response)),
|
.route(web::get().to(payments_response)),
|
||||||
)
|
)
|
||||||
|
.service(
|
||||||
|
web::resource("/session_tokens").route(web::get().to(payments_connector_session)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,16 +14,16 @@ use super::app::AppState;
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{errors::http_not_implemented, payments},
|
core::{errors::http_not_implemented, payments},
|
||||||
services::api,
|
services::api,
|
||||||
|
|
||||||
types::api::{
|
types::api::{
|
||||||
self as api_types, enums as api_enums,
|
self as api_types, enums as api_enums,
|
||||||
payments::{
|
payments::{
|
||||||
PaymentIdType, PaymentListConstraints, PaymentsCancelRequest, PaymentsCaptureRequest,
|
PaymentIdType, PaymentListConstraints, PaymentsCancelRequest, PaymentsCaptureRequest,
|
||||||
PaymentsRequest, PaymentsRetrieveRequest,
|
PaymentsRequest, PaymentsResponse, PaymentsRetrieveRequest,
|
||||||
},
|
},
|
||||||
Authorize, Capture, PSync, PaymentRetrieveBody, PaymentsResponse, PaymentsStartRequest,
|
Authorize, Capture, PSync, PaymentRetrieveBody, PaymentsSessionRequest,
|
||||||
Verify, Void,
|
PaymentsSessionResponse, PaymentsStartRequest, Session, Verify, Void,
|
||||||
}, // FIXME imports
|
},
|
||||||
|
//FIXME: remove specific imports
|
||||||
};
|
};
|
||||||
|
|
||||||
#[instrument(skip_all, fields(flow = ?Flow::PaymentsCreate))]
|
#[instrument(skip_all, fields(flow = ?Flow::PaymentsCreate))]
|
||||||
@ -269,6 +269,33 @@ pub(crate) async fn payments_capture(
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip_all, fields(flow = ?Flow::PaymentsSessionToken))]
|
||||||
|
pub(crate) async fn payments_connector_session(
|
||||||
|
state: web::Data<AppState>,
|
||||||
|
req: HttpRequest,
|
||||||
|
json_payload: web::Json<PaymentsSessionRequest>,
|
||||||
|
) -> HttpResponse {
|
||||||
|
let sessions_payload = json_payload.into_inner();
|
||||||
|
|
||||||
|
api::server_wrap(
|
||||||
|
&state,
|
||||||
|
&req,
|
||||||
|
sessions_payload,
|
||||||
|
|state, merchant_account, payload| {
|
||||||
|
payments::payments_core::<Session, PaymentsSessionResponse, _, _, _>(
|
||||||
|
state,
|
||||||
|
merchant_account,
|
||||||
|
payments::PaymentSession,
|
||||||
|
payload,
|
||||||
|
api::AuthFlow::Merchant,
|
||||||
|
payments::CallConnectorAction::Trigger,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
api::MerchantAuthentication::ApiKey,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn payments_response(
|
pub async fn payments_response(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
|
|||||||
@ -60,9 +60,14 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow {
|
|||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
let connector = payment_data
|
||||||
|
.payment_attempt
|
||||||
|
.connector
|
||||||
|
.clone()
|
||||||
|
.ok_or(errors::ProcessTrackerError::MissingRequiredField)?;
|
||||||
retry_sync_task(
|
retry_sync_task(
|
||||||
db,
|
db,
|
||||||
payment_data.payment_attempt.connector,
|
connector,
|
||||||
payment_data.payment_attempt.merchant_id,
|
payment_data.payment_attempt.merchant_id,
|
||||||
process,
|
process,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -45,7 +45,7 @@ diesel::table! {
|
|||||||
txn_id -> Varchar,
|
txn_id -> Varchar,
|
||||||
created_at -> Timestamp,
|
created_at -> Timestamp,
|
||||||
modified_at -> Timestamp,
|
modified_at -> Timestamp,
|
||||||
connector_name -> Varchar,
|
connector_name -> Nullable<Varchar>,
|
||||||
connector_transaction_id -> Nullable<Varchar>,
|
connector_transaction_id -> Nullable<Varchar>,
|
||||||
authentication_data -> Nullable<Json>,
|
authentication_data -> Nullable<Json>,
|
||||||
encoded_data -> Nullable<Text>,
|
encoded_data -> Nullable<Text>,
|
||||||
@ -186,7 +186,7 @@ diesel::table! {
|
|||||||
amount -> Int4,
|
amount -> Int4,
|
||||||
currency -> Nullable<Currency>,
|
currency -> Nullable<Currency>,
|
||||||
save_to_locker -> Nullable<Bool>,
|
save_to_locker -> Nullable<Bool>,
|
||||||
connector -> Varchar,
|
connector -> Nullable<Varchar>,
|
||||||
error_message -> Nullable<Text>,
|
error_message -> Nullable<Text>,
|
||||||
offer_amount -> Nullable<Int4>,
|
offer_amount -> Nullable<Int4>,
|
||||||
surcharge_amount -> Nullable<Int4>,
|
surcharge_amount -> Nullable<Int4>,
|
||||||
|
|||||||
@ -121,7 +121,7 @@ pub struct PaymentsSessionData {
|
|||||||
//TODO: Add the fields here as required
|
//TODO: Add the fields here as required
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, serde::Serialize)]
|
||||||
pub struct ConnectorSessionToken {
|
pub struct ConnectorSessionToken {
|
||||||
pub connector_name: String,
|
pub connector_name: String,
|
||||||
pub session_token: String,
|
pub session_token: String,
|
||||||
|
|||||||
@ -12,14 +12,12 @@ use std::{fmt::Debug, marker, str::FromStr};
|
|||||||
use error_stack::{report, IntoReport, ResultExt};
|
use error_stack::{report, IntoReport, ResultExt};
|
||||||
|
|
||||||
pub use self::{admin::*, customers::*, payment_methods::*, payments::*, refunds::*, webhooks::*};
|
pub use self::{admin::*, customers::*, payment_methods::*, payments::*, refunds::*, webhooks::*};
|
||||||
use super::{storage, ConnectorsList};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
configs::settings::Connectors,
|
configs::settings::Connectors,
|
||||||
connector,
|
connector,
|
||||||
core::errors::{self, CustomResult},
|
core::errors::{self, CustomResult},
|
||||||
services::ConnectorRedirectResponse,
|
services::ConnectorRedirectResponse,
|
||||||
types::{self, api},
|
types,
|
||||||
utils::{OptionExt, ValueExt},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait ConnectorCommon {
|
pub trait ConnectorCommon {
|
||||||
@ -71,45 +69,12 @@ pub struct ConnectorData {
|
|||||||
pub connector_name: types::Connector,
|
pub connector_name: types::Connector,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ConnectorCallType {
|
||||||
|
Single(ConnectorData),
|
||||||
|
Multiple(Vec<ConnectorData>),
|
||||||
|
}
|
||||||
|
|
||||||
impl ConnectorData {
|
impl ConnectorData {
|
||||||
pub fn construct(
|
|
||||||
connectors: &Connectors,
|
|
||||||
merchant_account: &storage::MerchantAccount,
|
|
||||||
) -> CustomResult<ConnectorData, errors::ApiErrorResponse> {
|
|
||||||
// Add Validate also to ParseStruct
|
|
||||||
//FIXME: Need Proper Routing Logic
|
|
||||||
let vec_val: Vec<serde_json::Value> = merchant_account
|
|
||||||
.custom_routing_rules
|
|
||||||
.as_ref()
|
|
||||||
.cloned()
|
|
||||||
.parse_value("CustomRoutingRulesVec")
|
|
||||||
.change_context(errors::ConnectorError::RoutingRulesParsingError)
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
|
||||||
let custom_routing_rules: api::CustomRoutingRules = vec_val[0]
|
|
||||||
.clone()
|
|
||||||
.parse_value("CustomRoutingRules")
|
|
||||||
.change_context(errors::ConnectorError::RoutingRulesParsingError)
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
|
||||||
let connector_names = custom_routing_rules
|
|
||||||
.connectors_pecking_order
|
|
||||||
.unwrap_or_else(|| vec!["stripe".to_string()]);
|
|
||||||
|
|
||||||
//use routing rules if configured by merchant else query MCA as per PM
|
|
||||||
let connector_list: ConnectorsList = ConnectorsList {
|
|
||||||
connectors: connector_names,
|
|
||||||
};
|
|
||||||
|
|
||||||
let connector_name = connector_list
|
|
||||||
.connectors
|
|
||||||
.first()
|
|
||||||
.get_required_value("connectors")
|
|
||||||
.change_context(errors::ConnectorError::FailedToObtainPreferredConnector)
|
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)?
|
|
||||||
.as_str();
|
|
||||||
|
|
||||||
Self::get_connector_by_name(connectors, connector_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_connector_by_name(
|
pub fn get_connector_by_name(
|
||||||
connectors: &Connectors,
|
connectors: &Connectors,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
|||||||
@ -599,6 +599,28 @@ impl From<PaymentsStartRequest> for PaymentsResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<PaymentsSessionRequest> for PaymentsResponse {
|
||||||
|
fn from(item: PaymentsSessionRequest) -> Self {
|
||||||
|
let payment_id = match item.payment_id {
|
||||||
|
api_types::PaymentIdType::PaymentIntentId(id) => Some(id),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
payment_id,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PaymentsSessionRequest> for PaymentsSessionResponse {
|
||||||
|
fn from(_item: PaymentsSessionRequest) -> Self {
|
||||||
|
Self {
|
||||||
|
session_token: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<types::storage::PaymentIntent> for PaymentsResponse {
|
impl From<types::storage::PaymentIntent> for PaymentsResponse {
|
||||||
fn from(item: types::storage::PaymentIntent) -> Self {
|
fn from(item: types::storage::PaymentIntent) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -774,6 +796,11 @@ pub struct PaymentsSessionRequest {
|
|||||||
pub client_secret: String,
|
pub client_secret: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, serde::Serialize, Clone)]
|
||||||
|
pub struct PaymentsSessionResponse {
|
||||||
|
pub session_token: Vec<types::ConnectorSessionToken>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||||
pub struct PaymentRetrieveBody {
|
pub struct PaymentRetrieveBody {
|
||||||
pub merchant_id: Option<String>,
|
pub merchant_id: Option<String>,
|
||||||
|
|||||||
@ -13,7 +13,7 @@ pub struct ConnectorResponseNew {
|
|||||||
pub txn_id: String,
|
pub txn_id: String,
|
||||||
pub created_at: PrimitiveDateTime,
|
pub created_at: PrimitiveDateTime,
|
||||||
pub modified_at: PrimitiveDateTime,
|
pub modified_at: PrimitiveDateTime,
|
||||||
pub connector_name: String,
|
pub connector_name: Option<String>,
|
||||||
pub connector_transaction_id: Option<String>,
|
pub connector_transaction_id: Option<String>,
|
||||||
pub authentication_data: Option<serde_json::Value>,
|
pub authentication_data: Option<serde_json::Value>,
|
||||||
pub encoded_data: Option<String>,
|
pub encoded_data: Option<String>,
|
||||||
@ -30,7 +30,7 @@ pub struct ConnectorResponse {
|
|||||||
pub txn_id: String,
|
pub txn_id: String,
|
||||||
pub created_at: PrimitiveDateTime,
|
pub created_at: PrimitiveDateTime,
|
||||||
pub modified_at: PrimitiveDateTime,
|
pub modified_at: PrimitiveDateTime,
|
||||||
pub connector_name: String,
|
pub connector_name: Option<String>,
|
||||||
pub connector_transaction_id: Option<String>,
|
pub connector_transaction_id: Option<String>,
|
||||||
pub authentication_data: Option<serde_json::Value>,
|
pub authentication_data: Option<serde_json::Value>,
|
||||||
pub encoded_data: Option<String>,
|
pub encoded_data: Option<String>,
|
||||||
@ -43,6 +43,7 @@ pub struct ConnectorResponseUpdateInternal {
|
|||||||
pub authentication_data: Option<serde_json::Value>,
|
pub authentication_data: Option<serde_json::Value>,
|
||||||
pub modified_at: PrimitiveDateTime,
|
pub modified_at: PrimitiveDateTime,
|
||||||
pub encoded_data: Option<String>,
|
pub encoded_data: Option<String>,
|
||||||
|
pub connector_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -51,6 +52,7 @@ pub enum ConnectorResponseUpdate {
|
|||||||
connector_transaction_id: Option<String>,
|
connector_transaction_id: Option<String>,
|
||||||
authentication_data: Option<serde_json::Value>,
|
authentication_data: Option<serde_json::Value>,
|
||||||
encoded_data: Option<String>,
|
encoded_data: Option<String>,
|
||||||
|
connector_name: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,11 +76,13 @@ impl From<ConnectorResponseUpdate> for ConnectorResponseUpdateInternal {
|
|||||||
connector_transaction_id,
|
connector_transaction_id,
|
||||||
authentication_data,
|
authentication_data,
|
||||||
encoded_data,
|
encoded_data,
|
||||||
|
connector_name,
|
||||||
} => Self {
|
} => Self {
|
||||||
connector_transaction_id,
|
connector_transaction_id,
|
||||||
authentication_data,
|
authentication_data,
|
||||||
encoded_data,
|
encoded_data,
|
||||||
modified_at: common_utils::date_time::now(),
|
modified_at: common_utils::date_time::now(),
|
||||||
|
connector_name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ pub struct PaymentAttempt {
|
|||||||
pub amount: i32,
|
pub amount: i32,
|
||||||
pub currency: Option<storage_enums::Currency>,
|
pub currency: Option<storage_enums::Currency>,
|
||||||
pub save_to_locker: Option<bool>,
|
pub save_to_locker: Option<bool>,
|
||||||
pub connector: String,
|
pub connector: Option<String>,
|
||||||
pub error_message: Option<String>,
|
pub error_message: Option<String>,
|
||||||
pub offer_amount: Option<i32>,
|
pub offer_amount: Option<i32>,
|
||||||
pub surcharge_amount: Option<i32>,
|
pub surcharge_amount: Option<i32>,
|
||||||
@ -49,7 +49,7 @@ pub struct PaymentAttemptNew {
|
|||||||
pub currency: Option<storage_enums::Currency>,
|
pub currency: Option<storage_enums::Currency>,
|
||||||
// pub auto_capture: Option<bool>,
|
// pub auto_capture: Option<bool>,
|
||||||
pub save_to_locker: Option<bool>,
|
pub save_to_locker: Option<bool>,
|
||||||
pub connector: String,
|
pub connector: Option<String>,
|
||||||
pub error_message: Option<String>,
|
pub error_message: Option<String>,
|
||||||
pub offer_amount: Option<i32>,
|
pub offer_amount: Option<i32>,
|
||||||
pub surcharge_amount: Option<i32>,
|
pub surcharge_amount: Option<i32>,
|
||||||
@ -88,6 +88,7 @@ pub enum PaymentAttemptUpdate {
|
|||||||
status: storage_enums::AttemptStatus,
|
status: storage_enums::AttemptStatus,
|
||||||
payment_method: Option<storage_enums::PaymentMethodType>,
|
payment_method: Option<storage_enums::PaymentMethodType>,
|
||||||
browser_info: Option<serde_json::Value>,
|
browser_info: Option<serde_json::Value>,
|
||||||
|
connector: Option<String>,
|
||||||
},
|
},
|
||||||
VoidUpdate {
|
VoidUpdate {
|
||||||
status: storage_enums::AttemptStatus,
|
status: storage_enums::AttemptStatus,
|
||||||
@ -117,6 +118,7 @@ pub(super) struct PaymentAttemptUpdateInternal {
|
|||||||
currency: Option<storage_enums::Currency>,
|
currency: Option<storage_enums::Currency>,
|
||||||
status: Option<storage_enums::AttemptStatus>,
|
status: Option<storage_enums::AttemptStatus>,
|
||||||
connector_transaction_id: Option<String>,
|
connector_transaction_id: Option<String>,
|
||||||
|
connector: Option<String>,
|
||||||
authentication_type: Option<storage_enums::AuthenticationType>,
|
authentication_type: Option<storage_enums::AuthenticationType>,
|
||||||
payment_method: Option<storage_enums::PaymentMethodType>,
|
payment_method: Option<storage_enums::PaymentMethodType>,
|
||||||
error_message: Option<String>,
|
error_message: Option<String>,
|
||||||
@ -182,11 +184,13 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
|||||||
status,
|
status,
|
||||||
payment_method,
|
payment_method,
|
||||||
browser_info,
|
browser_info,
|
||||||
|
connector,
|
||||||
} => Self {
|
} => Self {
|
||||||
status: Some(status),
|
status: Some(status),
|
||||||
payment_method,
|
payment_method,
|
||||||
modified_at: Some(common_utils::date_time::now()),
|
modified_at: Some(common_utils::date_time::now()),
|
||||||
browser_info,
|
browser_info,
|
||||||
|
connector,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
PaymentAttemptUpdate::VoidUpdate {
|
PaymentAttemptUpdate::VoidUpdate {
|
||||||
@ -256,7 +260,7 @@ mod tests {
|
|||||||
let current_time = common_utils::date_time::now();
|
let current_time = common_utils::date_time::now();
|
||||||
let payment_attempt = PaymentAttemptNew {
|
let payment_attempt = PaymentAttemptNew {
|
||||||
payment_id: payment_id.clone(),
|
payment_id: payment_id.clone(),
|
||||||
connector: types::Connector::Dummy.to_string(),
|
connector: Some(types::Connector::Dummy.to_string()),
|
||||||
created_at: current_time.into(),
|
created_at: current_time.into(),
|
||||||
modified_at: current_time.into(),
|
modified_at: current_time.into(),
|
||||||
..PaymentAttemptNew::default()
|
..PaymentAttemptNew::default()
|
||||||
@ -287,7 +291,7 @@ mod tests {
|
|||||||
let payment_attempt = PaymentAttemptNew {
|
let payment_attempt = PaymentAttemptNew {
|
||||||
payment_id: payment_id.clone(),
|
payment_id: payment_id.clone(),
|
||||||
merchant_id: merchant_id.clone(),
|
merchant_id: merchant_id.clone(),
|
||||||
connector: types::Connector::Dummy.to_string(),
|
connector: Some(types::Connector::Dummy.to_string()),
|
||||||
created_at: current_time.into(),
|
created_at: current_time.into(),
|
||||||
modified_at: current_time.into(),
|
modified_at: current_time.into(),
|
||||||
..PaymentAttemptNew::default()
|
..PaymentAttemptNew::default()
|
||||||
@ -326,7 +330,7 @@ mod tests {
|
|||||||
let payment_attempt = PaymentAttemptNew {
|
let payment_attempt = PaymentAttemptNew {
|
||||||
payment_id: uuid.clone(),
|
payment_id: uuid.clone(),
|
||||||
merchant_id: "1".to_string(),
|
merchant_id: "1".to_string(),
|
||||||
connector: types::Connector::Dummy.to_string(),
|
connector: Some(types::Connector::Dummy.to_string()),
|
||||||
created_at: current_time.into(),
|
created_at: current_time.into(),
|
||||||
modified_at: current_time.into(),
|
modified_at: current_time.into(),
|
||||||
// Adding a mandate_id
|
// Adding a mandate_id
|
||||||
|
|||||||
@ -18,6 +18,7 @@ enum Derives {
|
|||||||
Start,
|
Start,
|
||||||
Verify,
|
Verify,
|
||||||
Session,
|
Session,
|
||||||
|
SessionData,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Derives {
|
impl From<String> for Derives {
|
||||||
@ -35,6 +36,7 @@ impl From<String> for Derives {
|
|||||||
"verify" => Self::Verify,
|
"verify" => Self::Verify,
|
||||||
"verifydata" => Self::VerifyData,
|
"verifydata" => Self::VerifyData,
|
||||||
"session" => Self::Session,
|
"session" => Self::Session,
|
||||||
|
"sessiondata" => Self::SessionData,
|
||||||
_ => Self::Authorize,
|
_ => Self::Authorize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,6 +109,7 @@ impl Conversion {
|
|||||||
Derives::Verify => syn::Ident::new("VerifyRequest", Span::call_site()),
|
Derives::Verify => syn::Ident::new("VerifyRequest", Span::call_site()),
|
||||||
Derives::VerifyData => syn::Ident::new("VerifyRequestData", Span::call_site()),
|
Derives::VerifyData => syn::Ident::new("VerifyRequestData", Span::call_site()),
|
||||||
Derives::Session => syn::Ident::new("PaymentsSessionRequest", Span::call_site()),
|
Derives::Session => syn::Ident::new("PaymentsSessionRequest", Span::call_site()),
|
||||||
|
Derives::SessionData => syn::Ident::new("PaymentsSessionData", Span::call_site()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,6 +291,7 @@ pub fn operation_derive_inner(token: proc_macro::TokenStream) -> proc_macro::Tok
|
|||||||
PaymentsCaptureData,
|
PaymentsCaptureData,
|
||||||
PaymentsCancelData,
|
PaymentsCancelData,
|
||||||
PaymentsAuthorizeData,
|
PaymentsAuthorizeData,
|
||||||
|
PaymentsSessionData,
|
||||||
|
|
||||||
api::{
|
api::{
|
||||||
PaymentsCaptureRequest,
|
PaymentsCaptureRequest,
|
||||||
|
|||||||
@ -112,6 +112,8 @@ pub enum Flow {
|
|||||||
PaymentsCapture,
|
PaymentsCapture,
|
||||||
/// Payments cancel flow.
|
/// Payments cancel flow.
|
||||||
PaymentsCancel,
|
PaymentsCancel,
|
||||||
|
/// Payments Session Token flow
|
||||||
|
PaymentsSessionToken,
|
||||||
/// Payments start flow.
|
/// Payments start flow.
|
||||||
PaymentsStart,
|
PaymentsStart,
|
||||||
/// Payments list flow.
|
/// Payments list flow.
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE payment_attempt ALTER COLUMN connector SET NOT NULL;
|
||||||
|
ALTER TABLE connector_response ALTER COLUMN connector_name SET NOT NULL;
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE payment_attempt ALTER COLUMN connector DROP NOT NULL;
|
||||||
|
ALTER TABLE connector_response ALTER COLUMN connector_name DROP NOT NULL;
|
||||||
Reference in New Issue
Block a user