mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
Sessions flow for wallets (#60)
This commit is contained in:
@ -53,6 +53,18 @@ impl api::PaymentAuthorize for Aci {}
|
||||
impl api::PaymentSync for Aci {}
|
||||
impl api::PaymentVoid for Aci {}
|
||||
impl api::PaymentCapture for Aci {}
|
||||
impl api::PaymentSession for Aci {}
|
||||
|
||||
impl
|
||||
services::ConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
> for Aci
|
||||
{
|
||||
// Not Implemented (R)
|
||||
}
|
||||
|
||||
impl api::PreVerify for Aci {}
|
||||
|
||||
impl
|
||||
|
||||
@ -213,9 +213,8 @@ impl<F, T>
|
||||
status: enums::AttemptStatus::from(AciPaymentStatus::from_str(
|
||||
&item.response.result.code,
|
||||
)?),
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
//TODO: Add redirection details here
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
}),
|
||||
|
||||
@ -65,6 +65,18 @@ impl
|
||||
// TODO: Critical implement
|
||||
}
|
||||
|
||||
impl api::PaymentSession for Adyen {}
|
||||
|
||||
impl
|
||||
services::ConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
> for Adyen
|
||||
{
|
||||
// Not Implemented (R)
|
||||
}
|
||||
|
||||
impl
|
||||
services::ConnectorIntegration<
|
||||
api::Capture,
|
||||
|
||||
@ -405,7 +405,7 @@ impl TryFrom<types::PaymentsCancelResponseRouterData<AdyenCancelResponse>>
|
||||
};
|
||||
Ok(types::RouterData {
|
||||
status,
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.psp_reference),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
@ -445,7 +445,7 @@ pub fn get_adyen_response(
|
||||
None
|
||||
};
|
||||
|
||||
let payments_response_data = types::PaymentsResponseData {
|
||||
let payments_response_data = types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(response.psp_reference),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
@ -509,7 +509,7 @@ pub fn get_redirection_response(
|
||||
};
|
||||
|
||||
// We don't get connector transaction id for redirections in Adyen.
|
||||
let payments_response_data = types::PaymentsResponseData {
|
||||
let payments_response_data = types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::NoResponseId,
|
||||
redirection_data: Some(redirection_data),
|
||||
redirect: true,
|
||||
|
||||
@ -43,6 +43,18 @@ impl api::PaymentAuthorize for Authorizedotnet {}
|
||||
impl api::PaymentSync for Authorizedotnet {}
|
||||
impl api::PaymentVoid for Authorizedotnet {}
|
||||
impl api::PaymentCapture for Authorizedotnet {}
|
||||
impl api::PaymentSession for Authorizedotnet {}
|
||||
|
||||
impl
|
||||
services::ConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
> for Authorizedotnet
|
||||
{
|
||||
// Not Implemented (R)
|
||||
}
|
||||
|
||||
impl api::PreVerify for Authorizedotnet {}
|
||||
|
||||
impl
|
||||
|
||||
@ -298,16 +298,13 @@ impl<F, T>
|
||||
status,
|
||||
response: match error {
|
||||
Some(err) => Err(err),
|
||||
None => {
|
||||
Ok(types::PaymentsResponseData {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
item.response.transaction_response.transaction_id,
|
||||
),
|
||||
//TODO: Add redirection details here
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
})
|
||||
}
|
||||
None => Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
item.response.transaction_response.transaction_id,
|
||||
),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
}),
|
||||
},
|
||||
..item.data
|
||||
})
|
||||
@ -472,10 +469,15 @@ impl TryFrom<&types::PaymentsSyncRouterData> for AuthorizedotnetCreateSyncReques
|
||||
.response
|
||||
.as_ref()
|
||||
.ok()
|
||||
.map(|payment_response_data| {
|
||||
payment_response_data
|
||||
.resource_id
|
||||
.get_connector_transaction_id()
|
||||
.map(|payment_response_data| match payment_response_data {
|
||||
types::PaymentsResponseData::TransactionResponse { resource_id, .. } => {
|
||||
resource_id.get_connector_transaction_id()
|
||||
}
|
||||
_ => Err(error_stack::report!(
|
||||
errors::ValidationError::MissingRequiredField {
|
||||
field_name: "transaction_id".to_string()
|
||||
}
|
||||
)),
|
||||
})
|
||||
.transpose()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)?;
|
||||
@ -580,7 +582,7 @@ impl<F, Req>
|
||||
let payment_status =
|
||||
enums::AttemptStatus::from(item.response.transaction.transaction_status);
|
||||
Ok(types::RouterData {
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
item.response.transaction.transaction_id,
|
||||
),
|
||||
|
||||
@ -51,6 +51,19 @@ impl api::PaymentAuthorize for Braintree {}
|
||||
impl api::PaymentSync for Braintree {}
|
||||
impl api::PaymentVoid for Braintree {}
|
||||
impl api::PaymentCapture for Braintree {}
|
||||
|
||||
impl api::PaymentSession for Braintree {}
|
||||
|
||||
impl
|
||||
services::ConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
> for Braintree
|
||||
{
|
||||
//TODO: implement sessions flow
|
||||
}
|
||||
|
||||
impl api::PreVerify for Braintree {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
@ -140,7 +140,7 @@ impl<F, T>
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(types::RouterData {
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
item.response.transaction.id,
|
||||
),
|
||||
|
||||
@ -57,6 +57,18 @@ impl api::PaymentAuthorize for Checkout {}
|
||||
impl api::PaymentSync for Checkout {}
|
||||
impl api::PaymentVoid for Checkout {}
|
||||
impl api::PaymentCapture for Checkout {}
|
||||
impl api::PaymentSession for Checkout {}
|
||||
|
||||
impl
|
||||
services::ConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
> for Checkout
|
||||
{
|
||||
// Not Implemented (R)
|
||||
}
|
||||
|
||||
impl api::PreVerify for Checkout {}
|
||||
|
||||
impl
|
||||
|
||||
@ -207,7 +207,7 @@ impl TryFrom<types::PaymentsResponseRouterData<PaymentsResponse>>
|
||||
item.response.status,
|
||||
item.data.request.capture_method,
|
||||
)),
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirect: redirection_data.is_some(),
|
||||
redirection_data,
|
||||
@ -226,7 +226,7 @@ impl TryFrom<types::PaymentsSyncResponseRouterData<PaymentsResponse>>
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(types::RouterData {
|
||||
status: enums::AttemptStatus::from((item.response.status, None)),
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
//TODO: Add redirection details here
|
||||
redirection_data: None,
|
||||
@ -267,7 +267,7 @@ impl TryFrom<types::PaymentsCancelResponseRouterData<PaymentVoidResponse>>
|
||||
) -> Result<Self, Self::Error> {
|
||||
let response = &item.response;
|
||||
Ok(types::RouterData {
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(response.action_id.clone()),
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
|
||||
@ -55,6 +55,18 @@ impl api::PaymentAuthorize for Stripe {}
|
||||
impl api::PaymentSync for Stripe {}
|
||||
impl api::PaymentVoid for Stripe {}
|
||||
impl api::PaymentCapture for Stripe {}
|
||||
impl api::PaymentSession for Stripe {}
|
||||
|
||||
impl
|
||||
services::ConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
> for Stripe
|
||||
{
|
||||
// Not Implemented (R)
|
||||
}
|
||||
|
||||
impl api::PreVerify for Stripe {}
|
||||
|
||||
impl
|
||||
|
||||
@ -365,7 +365,7 @@ impl<F, T>
|
||||
// description: item.response.description.map(|x| x.as_str()),
|
||||
// statement_descriptor_suffix: item.response.statement_descriptor_suffix.map(|x| x.as_str()),
|
||||
// three_ds_form,
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirect: redirection_data.is_some(),
|
||||
redirection_data,
|
||||
@ -402,7 +402,7 @@ impl<F, T>
|
||||
|
||||
Ok(types::RouterData {
|
||||
status: enums::AttemptStatus::from(item.response.status),
|
||||
response: Ok(types::PaymentsResponseData {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirect: redirection_data.is_some(),
|
||||
redirection_data,
|
||||
|
||||
@ -294,7 +294,7 @@ where
|
||||
let stime_connector = Instant::now();
|
||||
|
||||
let router_data = payment_data
|
||||
.construct_r_d(state, connector.connector.id(), merchant_account)
|
||||
.construct_router_data(state, connector.connector.id(), merchant_account)
|
||||
.await?;
|
||||
let (res, payment_data) = router_data
|
||||
.decide_flows(
|
||||
|
||||
@ -2,6 +2,7 @@ mod authorize_flow;
|
||||
mod cancel_flow;
|
||||
mod capture_flow;
|
||||
mod psync_flow;
|
||||
mod session_flow;
|
||||
mod verfiy_flow;
|
||||
|
||||
use async_trait::async_trait;
|
||||
@ -19,7 +20,7 @@ use crate::{
|
||||
|
||||
#[async_trait]
|
||||
pub trait ConstructFlowSpecificData<F, Req, Res> {
|
||||
async fn construct_r_d<'a>(
|
||||
async fn construct_router_data<'a>(
|
||||
&self,
|
||||
state: &AppState,
|
||||
connector_id: &str,
|
||||
|
||||
@ -28,7 +28,7 @@ impl
|
||||
types::PaymentsResponseData,
|
||||
> for PaymentData<api::Authorize>
|
||||
{
|
||||
async fn construct_r_d<'a>(
|
||||
async fn construct_router_data<'a>(
|
||||
&self,
|
||||
state: &AppState,
|
||||
connector_id: &str,
|
||||
@ -40,19 +40,18 @@ impl
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
> {
|
||||
let output = transformers::construct_payment_router_data::<
|
||||
api::Authorize,
|
||||
types::PaymentsAuthorizeData,
|
||||
>(state, self.clone(), connector_id, merchant_account)
|
||||
.await?;
|
||||
Ok(output.1)
|
||||
transformers::construct_payment_router_data::<api::Authorize, types::PaymentsAuthorizeData>(
|
||||
state,
|
||||
self.clone(),
|
||||
connector_id,
|
||||
merchant_account,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Feature<api::Authorize, types::PaymentsAuthorizeData>
|
||||
for types::RouterData<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
|
||||
{
|
||||
impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAuthorizeRouterData {
|
||||
async fn decide_flows<'a>(
|
||||
self,
|
||||
state: &AppState,
|
||||
|
||||
@ -19,18 +19,19 @@ use crate::{
|
||||
impl ConstructFlowSpecificData<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
|
||||
for PaymentData<api::Void>
|
||||
{
|
||||
async fn construct_r_d<'a>(
|
||||
async fn construct_router_data<'a>(
|
||||
&self,
|
||||
state: &AppState,
|
||||
connector_id: &str,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
) -> RouterResult<PaymentsCancelRouterData> {
|
||||
let output = transformers::construct_payment_router_data::<
|
||||
api::Void,
|
||||
types::PaymentsCancelData,
|
||||
>(state, self.clone(), connector_id, merchant_account)
|
||||
.await?;
|
||||
Ok(output.1)
|
||||
transformers::construct_payment_router_data::<api::Void, types::PaymentsCancelData>(
|
||||
state,
|
||||
self.clone(),
|
||||
connector_id,
|
||||
merchant_account,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -20,18 +20,19 @@ impl
|
||||
ConstructFlowSpecificData<api::Capture, types::PaymentsCaptureData, types::PaymentsResponseData>
|
||||
for PaymentData<api::Capture>
|
||||
{
|
||||
async fn construct_r_d<'a>(
|
||||
async fn construct_router_data<'a>(
|
||||
&self,
|
||||
state: &AppState,
|
||||
connector_id: &str,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
) -> RouterResult<PaymentsCaptureRouterData> {
|
||||
let output = transformers::construct_payment_router_data::<
|
||||
api::Capture,
|
||||
types::PaymentsCaptureData,
|
||||
>(state, self.clone(), connector_id, merchant_account)
|
||||
.await?;
|
||||
Ok(output.1)
|
||||
transformers::construct_payment_router_data::<api::Capture, types::PaymentsCaptureData>(
|
||||
state,
|
||||
self.clone(),
|
||||
connector_id,
|
||||
merchant_account,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ use crate::{
|
||||
impl ConstructFlowSpecificData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
|
||||
for PaymentData<api::PSync>
|
||||
{
|
||||
async fn construct_r_d<'a>(
|
||||
async fn construct_router_data<'a>(
|
||||
&self,
|
||||
state: &AppState,
|
||||
connector_id: &str,
|
||||
@ -27,12 +27,13 @@ impl ConstructFlowSpecificData<api::PSync, types::PaymentsSyncData, types::Payme
|
||||
) -> RouterResult<
|
||||
types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>,
|
||||
> {
|
||||
let output = transformers::construct_payment_router_data::<
|
||||
api::PSync,
|
||||
types::PaymentsSyncData,
|
||||
>(state, self.clone(), connector_id, merchant_account)
|
||||
.await?;
|
||||
Ok(output.1)
|
||||
transformers::construct_payment_router_data::<api::PSync, types::PaymentsSyncData>(
|
||||
state,
|
||||
self.clone(),
|
||||
connector_id,
|
||||
merchant_account,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
94
crates/router/src/core/payments/flows/session_flow.rs
Normal file
94
crates/router/src/core/payments/flows/session_flow.rs
Normal file
@ -0,0 +1,94 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
use super::{ConstructFlowSpecificData, Feature};
|
||||
use crate::{
|
||||
core::{
|
||||
errors::{ConnectorErrorExt, RouterResult},
|
||||
payments::{self, transformers, PaymentData},
|
||||
},
|
||||
routes, services,
|
||||
types::{
|
||||
self, api,
|
||||
storage::{self, enums},
|
||||
},
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
impl
|
||||
ConstructFlowSpecificData<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
|
||||
for PaymentData<api::Session>
|
||||
{
|
||||
async fn construct_router_data<'a>(
|
||||
&self,
|
||||
state: &routes::AppState,
|
||||
connector_id: &str,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
) -> RouterResult<types::PaymentsSessionRouterData> {
|
||||
transformers::construct_payment_router_data::<api::Session, types::PaymentsSessionData>(
|
||||
state,
|
||||
self.clone(),
|
||||
connector_id,
|
||||
merchant_account,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Feature<api::Session, types::PaymentsSessionData> for types::PaymentsSessionRouterData {
|
||||
async fn decide_flows<'a>(
|
||||
self,
|
||||
state: &routes::AppState,
|
||||
connector: api::ConnectorData,
|
||||
customer: &Option<storage::Customer>,
|
||||
payment_data: PaymentData<api::Session>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_storage_schema: enums::MerchantStorageScheme,
|
||||
) -> (RouterResult<Self>, PaymentData<api::Session>) {
|
||||
let resp = self
|
||||
.decide_flow(
|
||||
state,
|
||||
connector,
|
||||
customer,
|
||||
Some(true),
|
||||
call_connector_action,
|
||||
)
|
||||
.await;
|
||||
|
||||
(resp, payment_data)
|
||||
}
|
||||
}
|
||||
|
||||
impl types::PaymentsSessionRouterData {
|
||||
pub async fn decide_flow<'a, 'b>(
|
||||
&'b self,
|
||||
state: &'a routes::AppState,
|
||||
connector: api::ConnectorData,
|
||||
_customer: &Option<storage::Customer>,
|
||||
_confirm: Option<bool>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
) -> RouterResult<types::PaymentsSessionRouterData>
|
||||
where
|
||||
dyn api::Connector + Sync: services::ConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
let connector_integration: services::BoxedConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
> = connector.connector.get_connector_integration();
|
||||
let resp = services::execute_connector_processing_step(
|
||||
state,
|
||||
connector_integration,
|
||||
self,
|
||||
call_connector_action,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| error.to_payment_failed_response())?;
|
||||
|
||||
Ok(resp)
|
||||
}
|
||||
}
|
||||
@ -22,19 +22,19 @@ use crate::{
|
||||
impl ConstructFlowSpecificData<api::Verify, types::VerifyRequestData, types::PaymentsResponseData>
|
||||
for PaymentData<api::Verify>
|
||||
{
|
||||
async fn construct_r_d<'a>(
|
||||
async fn construct_router_data<'a>(
|
||||
&self,
|
||||
state: &AppState,
|
||||
connector_id: &str,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
) -> RouterResult<types::VerifyRouterData> {
|
||||
let (_, router_data) = transformers::construct_payment_router_data::<
|
||||
api::Verify,
|
||||
types::VerifyRequestData,
|
||||
>(state, self.clone(), connector_id, merchant_account)
|
||||
.await?;
|
||||
|
||||
Ok(router_data)
|
||||
transformers::construct_payment_router_data::<api::Verify, types::VerifyRequestData>(
|
||||
state,
|
||||
self.clone(),
|
||||
connector_id,
|
||||
merchant_account,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -45,14 +45,15 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthorizeData
|
||||
payment_data.mandate_id = payment_data
|
||||
.mandate_id
|
||||
.or_else(|| router_data.request.mandate_id.clone());
|
||||
Ok(payment_response_ut(
|
||||
|
||||
payment_response_update_tracker(
|
||||
db,
|
||||
payment_id,
|
||||
payment_data,
|
||||
Some(router_data),
|
||||
storage_scheme,
|
||||
)
|
||||
.await?)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +72,8 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSyncData> for
|
||||
where
|
||||
F: 'b + Send,
|
||||
{
|
||||
Ok(payment_response_ut(db, payment_id, payment_data, response, storage_scheme).await?)
|
||||
payment_response_update_tracker(db, payment_id, payment_data, response, storage_scheme)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +94,8 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCaptureData>
|
||||
where
|
||||
F: 'b + Send,
|
||||
{
|
||||
Ok(payment_response_ut(db, payment_id, payment_data, response, storage_scheme).await?)
|
||||
payment_response_update_tracker(db, payment_id, payment_data, response, storage_scheme)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +114,8 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCancelData> f
|
||||
where
|
||||
F: 'b + Send,
|
||||
{
|
||||
Ok(payment_response_ut(db, payment_id, payment_data, response, storage_scheme).await?)
|
||||
payment_response_update_tracker(db, payment_id, payment_data, response, storage_scheme)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,11 +134,12 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::VerifyRequestData> fo
|
||||
where
|
||||
F: 'b + Send,
|
||||
{
|
||||
Ok(payment_response_ut(db, payment_id, payment_data, response, storage_scheme).await?)
|
||||
payment_response_update_tracker(db, payment_id, payment_data, response, storage_scheme)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
async fn payment_response_ut<F: Clone, T>(
|
||||
async fn payment_response_update_tracker<F: Clone, T>(
|
||||
db: &dyn StorageInterface,
|
||||
_payment_id: &api::PaymentIdType,
|
||||
mut payment_data: PaymentData<F>,
|
||||
@ -142,68 +147,77 @@ async fn payment_response_ut<F: Clone, T>(
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentData<F>> {
|
||||
let router_data = response.ok_or(report!(errors::ApiErrorResponse::InternalServerError))?;
|
||||
let mut connector_response_data = None;
|
||||
|
||||
let payment_attempt_update = match router_data.response.clone() {
|
||||
Err(err) => storage::PaymentAttemptUpdate::ErrorUpdate {
|
||||
status: storage::enums::AttemptStatus::Failure,
|
||||
error_message: Some(err.message),
|
||||
},
|
||||
Ok(response) => {
|
||||
connector_response_data = Some(response.clone());
|
||||
|
||||
storage::PaymentAttemptUpdate::ResponseUpdate {
|
||||
status: router_data.status,
|
||||
connector_transaction_id: match response.resource_id {
|
||||
let (payment_attempt_update, connector_response_update) = match router_data.response.clone() {
|
||||
Err(err) => (
|
||||
Some(storage::PaymentAttemptUpdate::ErrorUpdate {
|
||||
status: storage::enums::AttemptStatus::Failure,
|
||||
error_message: Some(err.message),
|
||||
}),
|
||||
None,
|
||||
),
|
||||
Ok(payments_response) => match payments_response {
|
||||
types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id,
|
||||
redirection_data,
|
||||
redirect,
|
||||
} => {
|
||||
let connector_transaction_id = match resource_id {
|
||||
types::ResponseId::NoResponseId => None,
|
||||
_ => Some(
|
||||
response
|
||||
.resource_id
|
||||
.get_connector_transaction_id()
|
||||
.change_context(errors::ApiErrorResponse::ResourceIdNotFound)?,
|
||||
),
|
||||
},
|
||||
authentication_type: None,
|
||||
payment_method_id: Some(router_data.payment_method_id),
|
||||
redirect: Some(response.redirect),
|
||||
mandate_id: payment_data.mandate_id.clone(),
|
||||
types::ResponseId::ConnectorTransactionId(id)
|
||||
| types::ResponseId::EncodedData(id) => Some(id),
|
||||
};
|
||||
|
||||
let encoded_data = payment_data.connector_response.encoded_data.clone();
|
||||
|
||||
let authentication_data = redirection_data
|
||||
.map(|data| utils::Encode::<RedirectForm>::encode_to_value(&data))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Could not parse the connector response")?;
|
||||
|
||||
let payment_attempt_update = storage::PaymentAttemptUpdate::ResponseUpdate {
|
||||
status: router_data.status,
|
||||
connector_transaction_id: connector_transaction_id.clone(),
|
||||
authentication_type: None,
|
||||
payment_method_id: Some(router_data.payment_method_id),
|
||||
redirect: Some(redirect),
|
||||
mandate_id: payment_data.mandate_id.clone(),
|
||||
};
|
||||
|
||||
let connector_response_update = storage::ConnectorResponseUpdate::ResponseUpdate {
|
||||
connector_transaction_id,
|
||||
authentication_data,
|
||||
encoded_data,
|
||||
};
|
||||
|
||||
(
|
||||
Some(payment_attempt_update),
|
||||
Some(connector_response_update),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
types::PaymentsResponseData::SessionResponse { .. } => (None, None),
|
||||
},
|
||||
};
|
||||
|
||||
payment_data.payment_attempt = db
|
||||
.update_payment_attempt(
|
||||
payment_data.payment_attempt,
|
||||
payment_attempt_update,
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))?;
|
||||
payment_data.payment_attempt = match payment_attempt_update {
|
||||
Some(payment_attempt_update) => db
|
||||
.update_payment_attempt(
|
||||
payment_data.payment_attempt,
|
||||
payment_attempt_update,
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| {
|
||||
error.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
|
||||
})?,
|
||||
None => payment_data.payment_attempt,
|
||||
};
|
||||
|
||||
payment_data.connector_response = match connector_response_data {
|
||||
Some(connector_response) => {
|
||||
let authentication_data = connector_response
|
||||
.redirection_data
|
||||
.map(|data| utils::Encode::<RedirectForm>::encode_to_value(&data))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Could not parse the connector response")?;
|
||||
|
||||
let connector_response_update = storage::ConnectorResponseUpdate::ResponseUpdate {
|
||||
connector_transaction_id: match connector_response.resource_id {
|
||||
types::ResponseId::NoResponseId => None,
|
||||
_ => Some(
|
||||
connector_response
|
||||
.resource_id
|
||||
.get_connector_transaction_id()
|
||||
.change_context(errors::ApiErrorResponse::ResourceIdNotFound)?,
|
||||
),
|
||||
},
|
||||
authentication_data,
|
||||
encoded_data: payment_data.connector_response.encoded_data.clone(),
|
||||
};
|
||||
|
||||
db.update_connector_response(
|
||||
payment_data.connector_response = match connector_response_update {
|
||||
Some(connector_response_update) => db
|
||||
.update_connector_response(
|
||||
payment_data.connector_response,
|
||||
connector_response_update,
|
||||
storage_scheme,
|
||||
@ -211,8 +225,7 @@ async fn payment_response_ut<F: Clone, T>(
|
||||
.await
|
||||
.map_err(|error| {
|
||||
error.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
|
||||
})?
|
||||
}
|
||||
})?,
|
||||
None => payment_data.connector_response,
|
||||
};
|
||||
|
||||
|
||||
@ -26,10 +26,7 @@ pub async fn construct_payment_router_data<'a, F, T>(
|
||||
payment_data: PaymentData<F>,
|
||||
connector_id: &str,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
) -> RouterResult<(
|
||||
PaymentData<F>,
|
||||
types::RouterData<F, T, types::PaymentsResponseData>,
|
||||
)>
|
||||
) -> RouterResult<types::RouterData<F, T, types::PaymentsResponseData>>
|
||||
where
|
||||
T: TryFrom<PaymentData<F>>,
|
||||
types::RouterData<F, T, types::PaymentsResponseData>: Feature<F, T>,
|
||||
@ -62,13 +59,13 @@ where
|
||||
.or(payment_data.payment_attempt.payment_method)
|
||||
.get_required_value("payment_method_type")?;
|
||||
|
||||
//FIXME[#44]: why should response be filled during request
|
||||
let response = payment_data
|
||||
.payment_attempt
|
||||
.connector_transaction_id
|
||||
.as_ref()
|
||||
.map(|id| types::PaymentsResponseData {
|
||||
.map(|id| types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(id.to_string()),
|
||||
//TODO: Add redirection details here
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
});
|
||||
@ -100,7 +97,7 @@ where
|
||||
response: response.map_or_else(|| Err(types::ErrorResponse::default()), Ok),
|
||||
};
|
||||
|
||||
Ok((payment_data, router_data))
|
||||
Ok(router_data)
|
||||
}
|
||||
|
||||
pub trait ToResponse<Req, D, Op>
|
||||
@ -417,6 +414,14 @@ impl<F: Clone> TryFrom<PaymentData<F>> for types::PaymentsCancelData {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Clone> TryFrom<PaymentData<F>> for types::PaymentsSessionData {
|
||||
type Error = errors::ApiErrorResponse;
|
||||
|
||||
fn try_from(_payment_data: PaymentData<F>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Clone> TryFrom<PaymentData<F>> for types::VerifyRequestData {
|
||||
type Error = error_stack::Report<errors::ApiErrorResponse>;
|
||||
|
||||
|
||||
@ -26,6 +26,8 @@ pub type PaymentsSyncRouterData = RouterData<api::PSync, PaymentsSyncData, Payme
|
||||
pub type PaymentsCaptureRouterData =
|
||||
RouterData<api::Capture, PaymentsCaptureData, PaymentsResponseData>;
|
||||
pub type PaymentsCancelRouterData = RouterData<api::Void, PaymentsCancelData, PaymentsResponseData>;
|
||||
pub type PaymentsSessionRouterData =
|
||||
RouterData<api::Session, PaymentsSessionData, PaymentsResponseData>;
|
||||
pub type RefundsRouterData<F> = RouterData<F, RefundsData, RefundsResponseData>;
|
||||
|
||||
pub type PaymentsResponseRouterData<R> =
|
||||
@ -114,6 +116,16 @@ pub struct PaymentsCancelData {
|
||||
pub cancellation_reason: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PaymentsSessionData {
|
||||
//TODO: Add the fields here as required
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PaymentsSessionResponseData {
|
||||
pub client_token: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VerifyRequestData {
|
||||
pub payment_method_data: payments::PaymentMethod,
|
||||
@ -124,12 +136,17 @@ pub struct VerifyRequestData {
|
||||
pub off_session: Option<bool>,
|
||||
pub setup_mandate_details: Option<payments::MandateData>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PaymentsResponseData {
|
||||
pub resource_id: ResponseId,
|
||||
// pub amount_received: Option<i32>, // Calculation for amount received not in place yet
|
||||
pub redirection_data: Option<services::RedirectForm>,
|
||||
pub redirect: bool,
|
||||
pub enum PaymentsResponseData {
|
||||
TransactionResponse {
|
||||
resource_id: ResponseId,
|
||||
redirection_data: Option<services::RedirectForm>,
|
||||
redirect: bool,
|
||||
},
|
||||
SessionResponse {
|
||||
session_token: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
||||
@ -275,6 +275,9 @@ pub struct PSync;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Void;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Session;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Verify;
|
||||
|
||||
@ -710,6 +713,11 @@ pub trait PaymentCapture:
|
||||
{
|
||||
}
|
||||
|
||||
pub trait PaymentSession:
|
||||
api::ConnectorIntegration<Session, types::PaymentsSessionData, types::PaymentsResponseData>
|
||||
{
|
||||
}
|
||||
|
||||
pub trait PreVerify:
|
||||
api::ConnectorIntegration<Verify, types::VerifyRequestData, types::PaymentsResponseData>
|
||||
{
|
||||
@ -722,8 +730,10 @@ pub trait Payment:
|
||||
+ PaymentCapture
|
||||
+ PaymentVoid
|
||||
+ PreVerify
|
||||
+ PaymentSession
|
||||
{
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct PaymentsRetrieveRequest {
|
||||
pub resource_id: PaymentIdType,
|
||||
|
||||
@ -195,12 +195,12 @@ async fn refund_for_successful_payments() {
|
||||
types::RefundsResponseData,
|
||||
> = connector.connector.get_connector_integration();
|
||||
let mut refund_request = construct_refund_router_data();
|
||||
refund_request.request.connector_transaction_id = response
|
||||
.response
|
||||
.unwrap()
|
||||
.resource_id
|
||||
.get_connector_transaction_id()
|
||||
.unwrap();
|
||||
refund_request.request.connector_transaction_id = match response.response.unwrap() {
|
||||
types::PaymentsResponseData::TransactionResponse { resource_id, .. } => {
|
||||
resource_id.get_connector_transaction_id().unwrap()
|
||||
}
|
||||
_ => panic!("Connector transaction id not found"),
|
||||
};
|
||||
let response = services::api::execute_connector_processing_step(
|
||||
&state,
|
||||
connector_integration,
|
||||
|
||||
@ -167,12 +167,12 @@ async fn test_checkout_refund_success() {
|
||||
> = connector.connector.get_connector_integration();
|
||||
let mut refund_request = construct_refund_router_data();
|
||||
|
||||
refund_request.request.connector_transaction_id = response
|
||||
.response
|
||||
.unwrap()
|
||||
.resource_id
|
||||
.get_connector_transaction_id()
|
||||
.unwrap();
|
||||
refund_request.request.connector_transaction_id = match response.response.unwrap() {
|
||||
types::PaymentsResponseData::TransactionResponse { resource_id, .. } => {
|
||||
resource_id.get_connector_transaction_id().unwrap()
|
||||
}
|
||||
_ => panic!("Connector transaction id not found"),
|
||||
};
|
||||
|
||||
let response = services::api::execute_connector_processing_step(
|
||||
&state,
|
||||
@ -260,12 +260,12 @@ async fn test_checkout_refund_failure() {
|
||||
types::RefundsResponseData,
|
||||
> = connector.connector.get_connector_integration();
|
||||
let mut refund_request = construct_refund_router_data();
|
||||
refund_request.request.connector_transaction_id = response
|
||||
.response
|
||||
.unwrap()
|
||||
.resource_id
|
||||
.get_connector_transaction_id()
|
||||
.unwrap();
|
||||
refund_request.request.connector_transaction_id = match response.response.unwrap() {
|
||||
types::PaymentsResponseData::TransactionResponse { resource_id, .. } => {
|
||||
resource_id.get_connector_transaction_id().unwrap()
|
||||
}
|
||||
_ => panic!("Connector transaction id not found"),
|
||||
};
|
||||
|
||||
// Higher amout than that of payment
|
||||
refund_request.request.refund_amount = 696969;
|
||||
|
||||
Reference in New Issue
Block a user