Sessions flow for wallets (#60)

This commit is contained in:
Narayan Bhat
2022-12-09 20:58:15 +05:30
committed by GitHub
parent 3d7d89172c
commit 0e105db216
26 changed files with 378 additions and 162 deletions

View File

@ -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

View File

@ -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,
}),

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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,
),

View File

@ -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)]

View File

@ -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,
),

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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(

View File

@ -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,

View File

@ -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,

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View 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)
}
}

View File

@ -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
}
}

View File

@ -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,
};

View File

@ -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>;

View File

@ -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)]

View File

@ -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,

View File

@ -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,

View File

@ -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;