Skip to content

Commit 1c3f057

Browse files
NISHANTH1221Nishanth Challahyperswitch-bot[bot]
authored
feat(connector): [Stripebilling] add record back support for stripebilling (#7561)
Co-authored-by: Nishanth Challa <[email protected]> Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
1 parent 86306bd commit 1c3f057

File tree

3 files changed

+150
-2
lines changed

3 files changed

+150
-2
lines changed

Diff for: crates/hyperswitch_connectors/src/connectors/stripebilling.rs

+101
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ use hyperswitch_domain_models::{
2727
RefundSyncRouterData, RefundsRouterData,
2828
},
2929
};
30+
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
31+
use hyperswitch_domain_models::{
32+
router_flow_types::RecoveryRecordBack,
33+
router_request_types::revenue_recovery::RevenueRecoveryRecordBackRequest,
34+
router_response_types::revenue_recovery::RevenueRecoveryRecordBackResponse,
35+
types::RevenueRecoveryRecordBackRouterData,
36+
};
3037
use hyperswitch_interfaces::{
3138
api::{
3239
self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
@@ -68,6 +75,8 @@ impl api::Refund for Stripebilling {}
6875
impl api::RefundExecute for Stripebilling {}
6976
impl api::RefundSync for Stripebilling {}
7077
impl api::PaymentToken for Stripebilling {}
78+
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
79+
impl api::revenue_recovery::RevenueRecoveryRecordBack for Stripebilling {}
7180

7281
impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
7382
for Stripebilling
@@ -550,6 +559,98 @@ impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Stripebil
550559
}
551560
}
552561

562+
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
563+
impl
564+
ConnectorIntegration<
565+
RecoveryRecordBack,
566+
RevenueRecoveryRecordBackRequest,
567+
RevenueRecoveryRecordBackResponse,
568+
> for Stripebilling
569+
{
570+
fn get_headers(
571+
&self,
572+
req: &RevenueRecoveryRecordBackRouterData,
573+
connectors: &Connectors,
574+
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
575+
self.build_headers(req, connectors)
576+
}
577+
578+
fn get_content_type(&self) -> &'static str {
579+
self.common_get_content_type()
580+
}
581+
582+
fn get_url(
583+
&self,
584+
req: &RevenueRecoveryRecordBackRouterData,
585+
connectors: &Connectors,
586+
) -> CustomResult<String, errors::ConnectorError> {
587+
let invoice_id = req
588+
.request
589+
.merchant_reference_id
590+
.get_string_repr()
591+
.to_string();
592+
match req.request.attempt_status {
593+
common_enums::AttemptStatus::Charged => Ok(format!(
594+
"{}/v1/invoices/{invoice_id}/pay?paid_out_of_band=true",
595+
self.base_url(connectors),
596+
)),
597+
common_enums::AttemptStatus::Failure => Ok(format!(
598+
"{}/v1/invoices/{invoice_id}/void",
599+
self.base_url(connectors),
600+
)),
601+
_ => Err(errors::ConnectorError::FailedToObtainIntegrationUrl.into()),
602+
}
603+
}
604+
605+
fn build_request(
606+
&self,
607+
req: &RevenueRecoveryRecordBackRouterData,
608+
connectors: &Connectors,
609+
) -> CustomResult<Option<Request>, errors::ConnectorError> {
610+
Ok(Some(
611+
RequestBuilder::new()
612+
.method(Method::Post)
613+
.url(&types::RevenueRecoveryRecordBackType::get_url(
614+
self, req, connectors,
615+
)?)
616+
.attach_default_headers()
617+
.headers(types::RevenueRecoveryRecordBackType::get_headers(
618+
self, req, connectors,
619+
)?)
620+
.build(),
621+
))
622+
}
623+
624+
fn handle_response(
625+
&self,
626+
data: &RevenueRecoveryRecordBackRouterData,
627+
event_builder: Option<&mut ConnectorEvent>,
628+
res: Response,
629+
) -> CustomResult<RevenueRecoveryRecordBackRouterData, errors::ConnectorError> {
630+
let response = res
631+
.response
632+
.parse_struct::<stripebilling::StripebillingRecordBackResponse>(
633+
"StripebillingRecordBackResponse",
634+
)
635+
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
636+
event_builder.map(|i| i.set_response_body(&response));
637+
router_env::logger::info!(connector_response=?response);
638+
RevenueRecoveryRecordBackRouterData::try_from(ResponseRouterData {
639+
response,
640+
data: data.clone(),
641+
http_code: res.status_code,
642+
})
643+
}
644+
645+
fn get_error_response(
646+
&self,
647+
res: Response,
648+
event_builder: Option<&mut ConnectorEvent>,
649+
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
650+
self.build_error_response(res, event_builder)
651+
}
652+
}
653+
553654
#[async_trait::async_trait]
554655
impl webhooks::IncomingWebhook for Stripebilling {
555656
fn get_webhook_source_verification_algorithm(

Diff for: crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs

+49-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
use std::str::FromStr;
33

44
use common_enums::enums;
5+
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
6+
use common_utils::id_type;
57
use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::StringMinorUnit};
68
use error_stack::ResultExt;
79
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
@@ -14,6 +16,13 @@ use hyperswitch_domain_models::{
1416
router_response_types::{PaymentsResponseData, RefundsResponseData},
1517
types::{PaymentsAuthorizeRouterData, RefundsRouterData},
1618
};
19+
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
20+
use hyperswitch_domain_models::{
21+
router_flow_types::RecoveryRecordBack,
22+
router_request_types::revenue_recovery::RevenueRecoveryRecordBackRequest,
23+
router_response_types::revenue_recovery::RevenueRecoveryRecordBackResponse,
24+
types::RevenueRecoveryRecordBackRouterData,
25+
};
1726
use hyperswitch_interfaces::errors;
1827
use masking::Secret;
1928
use serde::{Deserialize, Serialize};
@@ -360,7 +369,7 @@ impl TryFrom<StripebillingInvoiceBody> for revenue_recovery::RevenueRecoveryInvo
360369
type Error = error_stack::Report<errors::ConnectorError>;
361370
fn try_from(item: StripebillingInvoiceBody) -> Result<Self, Self::Error> {
362371
let merchant_reference_id =
363-
common_utils::id_type::PaymentReferenceId::from_str(&item.data.object.invoice_id)
372+
id_type::PaymentReferenceId::from_str(&item.data.object.invoice_id)
364373
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
365374
Ok(Self {
366375
amount: item.data.object.amount,
@@ -369,3 +378,42 @@ impl TryFrom<StripebillingInvoiceBody> for revenue_recovery::RevenueRecoveryInvo
369378
})
370379
}
371380
}
381+
382+
#[derive(Debug, Deserialize, Serialize, Clone)]
383+
pub struct StripebillingRecordBackResponse {
384+
pub id: String,
385+
}
386+
387+
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
388+
impl
389+
TryFrom<
390+
ResponseRouterData<
391+
RecoveryRecordBack,
392+
StripebillingRecordBackResponse,
393+
RevenueRecoveryRecordBackRequest,
394+
RevenueRecoveryRecordBackResponse,
395+
>,
396+
> for RevenueRecoveryRecordBackRouterData
397+
{
398+
type Error = error_stack::Report<errors::ConnectorError>;
399+
fn try_from(
400+
item: ResponseRouterData<
401+
RecoveryRecordBack,
402+
StripebillingRecordBackResponse,
403+
RevenueRecoveryRecordBackRequest,
404+
RevenueRecoveryRecordBackResponse,
405+
>,
406+
) -> Result<Self, Self::Error> {
407+
Ok(Self {
408+
response: Ok(RevenueRecoveryRecordBackResponse {
409+
merchant_reference_id: id_type::PaymentReferenceId::from_str(
410+
item.response.id.as_str(),
411+
)
412+
.change_context(errors::ConnectorError::MissingRequiredField {
413+
field_name: "invoice_id in the response",
414+
})?,
415+
}),
416+
..item.data
417+
})
418+
}
419+
}

Diff for: crates/hyperswitch_connectors/src/default_implementations.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3743,7 +3743,6 @@ default_imp_for_revenue_recovery_record_back!(
37433743
connectors::Shift4,
37443744
connectors::Stax,
37453745
connectors::Square,
3746-
connectors::Stripebilling,
37473746
connectors::Taxjar,
37483747
connectors::Thunes,
37493748
connectors::Trustpay,

0 commit comments

Comments
 (0)