Skip to content

Commit

Permalink
feat(router): implement post_update_tracker for SessionUpdate Flow an…
Browse files Browse the repository at this point in the history
…d add support for session_update_flow for Paypal (#6299)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
swangi-kumari and hyperswitch-bot[bot] authored Oct 15, 2024
1 parent 342529e commit 7e90031
Show file tree
Hide file tree
Showing 29 changed files with 541 additions and 136 deletions.
5 changes: 5 additions & 0 deletions api-reference-v2/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -14572,6 +14572,11 @@
},
"payment_method_type": {
"$ref": "#/components/schemas/PaymentMethodType"
},
"session_id": {
"type": "string",
"description": "Session Id",
"nullable": true
}
}
},
Expand Down
5 changes: 5 additions & 0 deletions api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -17837,6 +17837,11 @@
},
"payment_method_type": {
"$ref": "#/components/schemas/PaymentMethodType"
},
"session_id": {
"type": "string",
"description": "Session Id",
"nullable": true
}
}
},
Expand Down
2 changes: 2 additions & 0 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4916,6 +4916,8 @@ pub struct PaymentsDynamicTaxCalculationRequest {
/// Payment method type
#[schema(value_type = PaymentMethodType)]
pub payment_method_type: api_enums::PaymentMethodType,
/// Session Id
pub session_id: Option<String>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
Expand Down
38 changes: 19 additions & 19 deletions crates/common_enums/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,25 +404,25 @@ pub enum AuthorizationStatus {
Unresolved,
}

// #[derive(
// Clone,
// Debug,
// Eq,
// PartialEq,
// serde::Deserialize,
// serde::Serialize,
// strum::Display,
// strum::EnumString,
// ToSchema,
// Hash,
// )]
// #[router_derive::diesel_enum(storage_type = "text")]
// #[serde(rename_all = "snake_case")]
// #[strum(serialize_all = "snake_case")]
// pub enum SessionUpdateStatus {
// Success,
// Failure,
// }
#[derive(
Clone,
Debug,
Eq,
PartialEq,
serde::Deserialize,
serde::Serialize,
strum::Display,
strum::EnumString,
ToSchema,
Hash,
)]
#[router_derive::diesel_enum(storage_type = "text")]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum SessionUpdateStatus {
Success,
Failure,
}

#[derive(
Clone,
Expand Down
3 changes: 3 additions & 0 deletions crates/hyperswitch_domain_models/src/router_request_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,9 @@ pub struct PaymentsTaxCalculationData {
pub struct SdkPaymentsSessionUpdateData {
pub order_tax_amount: MinorUnit,
pub net_amount: MinorUnit,
pub amount: MinorUnit,
pub currency: storage_enums::Currency,
pub session_id: Option<String>,
}

#[derive(Debug, Clone)]
Expand Down
6 changes: 3 additions & 3 deletions crates/hyperswitch_domain_models/src/router_response_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ pub enum PaymentsResponseData {
PostProcessingResponse {
session_token: Option<api_models::payments::OpenBankingSessionToken>,
},
// SessionUpdateResponse {
// status: common_enums::SessionUpdateStatus,
// },
SessionUpdateResponse {
status: common_enums::SessionUpdateStatus,
},
}

#[derive(Debug, Clone)]
Expand Down
11 changes: 7 additions & 4 deletions crates/hyperswitch_interfaces/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use hyperswitch_domain_models::{
payments::{
Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize,
CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync,
PaymentMethodToken, PostProcessing, PostSessionTokens, PreProcessing, Session,
SetupMandate, Void,
PaymentMethodToken, PostProcessing, PostSessionTokens, PreProcessing, SdkSessionUpdate,
Session, SetupMandate, Void,
},
refunds::{Execute, RSync},
webhooks::VerifyWebhookSource,
Expand All @@ -22,8 +22,8 @@ use hyperswitch_domain_models::{
PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData,
PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData,
PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData,
RetrieveFileRequestData, SetupMandateRequestData, SubmitEvidenceRequestData,
UploadFileRequestData, VerifyWebhookSourceRequestData,
RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SetupMandateRequestData,
SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData,
},
router_response_types::{
AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData,
Expand Down Expand Up @@ -65,6 +65,9 @@ pub type PaymentsPostSessionTokensType = dyn ConnectorIntegration<
PaymentsPostSessionTokensData,
PaymentsResponseData,
>;
/// Type alias for `ConnectorIntegration<SdkSessionUpdate, SdkPaymentsSessionUpdateData, PaymentsResponseData>`
pub type SdkSessionUpdateType =
dyn ConnectorIntegration<SdkSessionUpdate, SdkPaymentsSessionUpdateData, PaymentsResponseData>;
/// Type alias for `ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData>`
pub type SetupMandateType =
dyn ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData>;
Expand Down
138 changes: 133 additions & 5 deletions crates/router/src/connector/paypal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use common_utils::{
use diesel_models::enums;
use error_stack::ResultExt;
use masking::{ExposeInterface, PeekInterface, Secret};
use router_env::logger;
#[cfg(feature = "payouts")]
use router_env::{instrument, tracing};
use transformers as paypal;
Expand Down Expand Up @@ -74,6 +75,7 @@ impl api::RefundExecute for Paypal {}
impl api::RefundSync for Paypal {}
impl api::ConnectorVerifyWebhookSource for Paypal {}
impl api::PaymentPostSessionTokens for Paypal {}
impl api::PaymentSessionUpdate for Paypal {}

impl api::Payouts for Paypal {}
#[cfg(feature = "payouts")]
Expand Down Expand Up @@ -482,7 +484,7 @@ impl ConnectorIntegration<api::PoFulfill, types::PayoutsData, types::PayoutsResp
req.request.minor_amount,
req.request.destination_currency,
)?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount, req))?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount, None, None, req))?;
let connector_req = paypal::PaypalFulfillRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}
Expand Down Expand Up @@ -687,6 +689,7 @@ impl
.url(&types::PaymentsPostSessionTokensType::get_url(
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::PaymentsPostSessionTokensType::get_headers(
self, req, connectors,
)?)
Expand All @@ -707,7 +710,7 @@ impl
req.request.amount,
req.request.currency,
)?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount, req))?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount, None, None, req))?;
let connector_req = paypal::PaypalPaymentsRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}
Expand Down Expand Up @@ -740,6 +743,129 @@ impl
}
}

impl
ConnectorIntegration<
api::SdkSessionUpdate,
types::SdkPaymentsSessionUpdateData,
types::PaymentsResponseData,
> for Paypal
{
fn get_headers(
&self,
req: &types::SdkSessionUpdateRouterData,
connectors: &settings::Connectors,
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
self.build_headers(req, connectors)
}

fn get_content_type(&self) -> &'static str {
self.common_get_content_type()
}

fn get_url(
&self,
req: &types::SdkSessionUpdateRouterData,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
let session_id =
req.request
.session_id
.clone()
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "session_id",
})?;
Ok(format!(
"{}v2/checkout/orders/{}",
self.base_url(connectors),
session_id
))
}

fn build_request(
&self,
req: &types::SdkSessionUpdateRouterData,
connectors: &settings::Connectors,
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
Ok(Some(
services::RequestBuilder::new()
.method(services::Method::Patch)
.url(&types::SdkSessionUpdateType::get_url(
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::SdkSessionUpdateType::get_headers(
self, req, connectors,
)?)
.set_body(types::SdkSessionUpdateType::get_request_body(
self, req, connectors,
)?)
.build(),
))
}

fn get_request_body(
&self,
req: &types::SdkSessionUpdateRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let order_amount = connector_utils::convert_amount(
self.amount_converter,
req.request.amount,
req.request.currency,
)?;
let amount = connector_utils::convert_amount(
self.amount_converter,
req.request.net_amount,
req.request.currency,
)?;
let order_tax_amount = connector_utils::convert_amount(
self.amount_converter,
req.request.order_tax_amount,
req.request.currency,
)?;
let connector_router_data = paypal::PaypalRouterData::try_from((
amount,
Some(order_tax_amount),
Some(order_amount),
req,
))?;

let connector_req = paypal::PaypalUpdateOrderRequest::try_from(&connector_router_data)?;
// encode only for for urlencoded things.
Ok(RequestContent::Json(Box::new(
connector_req.get_inner_value(),
)))
}

fn handle_response(
&self,
data: &types::SdkSessionUpdateRouterData,
_event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<types::SdkSessionUpdateRouterData, errors::ConnectorError> {
logger::debug!("Expected zero bytes response, skipped parsing of the response");
// https://developer.paypal.com/docs/api/orders/v2/#orders_patch
// If 204 status code, then the session was updated successfully.
let status = if res.status_code == 204 {
enums::SessionUpdateStatus::Success
} else {
enums::SessionUpdateStatus::Failure
};
Ok(types::SdkSessionUpdateRouterData {
response: Ok(types::PaymentsResponseData::SessionUpdateResponse { status }),
..data.clone()
})
}

fn get_error_response(
&self,
res: Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res, event_builder)
}
}

impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
for Paypal
{
Expand Down Expand Up @@ -789,7 +915,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
req.request.minor_amount,
req.request.currency,
)?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount, req))?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount, None, None, req))?;
let connector_req = paypal::PaypalPaymentsRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}
Expand Down Expand Up @@ -817,6 +943,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
.url(&types::PaymentsAuthorizeType::get_url(
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::PaymentsAuthorizeType::get_headers(
self, req, connectors,
)?)
Expand Down Expand Up @@ -1304,7 +1431,8 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
req.request.minor_amount_to_capture,
req.request.currency,
)?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount_to_capture, req))?;
let connector_router_data =
paypal::PaypalRouterData::try_from((amount_to_capture, None, None, req))?;
let connector_req = paypal::PaypalPaymentsCaptureRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}
Expand Down Expand Up @@ -1471,7 +1599,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
req.request.minor_refund_amount,
req.request.currency,
)?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount, req))?;
let connector_router_data = paypal::PaypalRouterData::try_from((amount, None, None, req))?;
let connector_req = paypal::PaypalRefundRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}
Expand Down
Loading

0 comments on commit 7e90031

Please sign in to comment.