feat(connector): [Chargebee] Add record back support for chargebee (#7505)

Co-authored-by: Chikke Srujan <chikke.srujan@Chikke-Srujan-N7WRTY72X7.local>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
chikke srujan
2025-03-18 18:12:46 +05:30
committed by GitHub
parent e4c7ab8e68
commit e77bb71c6c
8 changed files with 494 additions and 56 deletions

View File

@ -1,15 +1,23 @@
pub mod transformers;
use base64::Engine;
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
use common_utils::types::{StringMinorUnit, StringMinorUnitForConnector};
use common_utils::{
consts::BASE64_ENGINE,
errors::CustomResult,
ext_traits::BytesExt,
request::{Method, Request, RequestBuilder, RequestContent},
types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector},
types::{AmountConvertor, MinorUnit, MinorUnitForConnector},
};
use error_stack::{report, ResultExt};
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
use hyperswitch_domain_models::revenue_recovery;
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
use hyperswitch_domain_models::{
revenue_recovery, router_flow_types::revenue_recovery::RecoveryRecordBack,
router_request_types::revenue_recovery::RevenueRecoveryRecordBackRequest,
router_response_types::revenue_recovery::RevenueRecoveryRecordBackResponse,
types::RevenueRecoveryRecordBackRouterData,
};
use hyperswitch_domain_models::{
router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
router_flow_types::{
@ -39,20 +47,22 @@ use hyperswitch_interfaces::{
types::{self, Response},
webhooks,
};
use masking::{ExposeInterface, Mask, PeekInterface, Secret};
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
use masking::ExposeInterface;
use masking::{Mask, PeekInterface, Secret};
use transformers as chargebee;
use crate::{constants::headers, types::ResponseRouterData, utils};
#[derive(Clone)]
pub struct Chargebee {
amount_converter: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
amount_converter: &'static (dyn AmountConvertor<Output = MinorUnit> + Sync),
}
impl Chargebee {
pub fn new() -> &'static Self {
&Self {
amount_converter: &StringMinorUnitForConnector,
amount_converter: &MinorUnitForConnector,
}
}
}
@ -69,6 +79,8 @@ impl api::Refund for Chargebee {}
impl api::RefundExecute for Chargebee {}
impl api::RefundSync for Chargebee {}
impl api::PaymentToken for Chargebee {}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
impl api::revenue_recovery::RevenueRecoveryRecordBack for Chargebee {}
impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
for Chargebee
@ -87,7 +99,7 @@ where
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
let mut header = vec![(
headers::CONTENT_TYPE.to_string(),
self.get_content_type().to_string().into(),
self.common_get_content_type().to_string().into(),
)];
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
header.append(&mut api_key);
@ -105,7 +117,7 @@ impl ConnectorCommon for Chargebee {
}
fn common_get_content_type(&self) -> &'static str {
"application/json"
"application/x-www-form-urlencoded"
}
fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
@ -118,9 +130,10 @@ impl ConnectorCommon for Chargebee {
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
let auth = chargebee::ChargebeeAuthType::try_from(auth_type)
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
let encoded_api_key = BASE64_ENGINE.encode(auth.full_access_key_v1.peek());
Ok(vec![(
headers::AUTHORIZATION.to_string(),
auth.api_key.expose().into_masked(),
format!("Basic {encoded_api_key}").into_masked(),
)])
}
@ -139,9 +152,9 @@ impl ConnectorCommon for Chargebee {
Ok(ErrorResponse {
status_code: res.status_code,
code: response.code,
message: response.message,
reason: response.reason,
code: response.api_error_code.clone(),
message: response.api_error_code.clone(),
reason: Some(response.message),
attempt_status: None,
connector_transaction_id: None,
issuer_error_code: None,
@ -546,6 +559,110 @@ impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Chargebee
}
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
impl
ConnectorIntegration<
RecoveryRecordBack,
RevenueRecoveryRecordBackRequest,
RevenueRecoveryRecordBackResponse,
> for Chargebee
{
fn get_headers(
&self,
req: &RevenueRecoveryRecordBackRouterData,
connectors: &Connectors,
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
self.build_headers(req, connectors)
}
fn get_url(
&self,
req: &RevenueRecoveryRecordBackRouterData,
connectors: &Connectors,
) -> CustomResult<String, errors::ConnectorError> {
let metadata: chargebee::ChargebeeMetadata =
utils::to_connector_meta_from_secret(req.connector_meta_data.clone())?;
let url = self
.base_url(connectors)
.to_string()
.replace("$", metadata.site.peek());
let invoice_id = req
.request
.merchant_reference_id
.get_string_repr()
.to_string();
Ok(format!("{url}v2/invoices/{invoice_id}/record_payment"))
}
fn get_content_type(&self) -> &'static str {
self.common_get_content_type()
}
fn get_request_body(
&self,
req: &RevenueRecoveryRecordBackRouterData,
_connectors: &Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let amount = utils::convert_amount(
self.amount_converter,
req.request.amount,
req.request.currency,
)?;
let connector_router_data = chargebee::ChargebeeRouterData::from((amount, req));
let connector_req =
chargebee::ChargebeeRecordPaymentRequest::try_from(&connector_router_data)?;
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn build_request(
&self,
req: &RevenueRecoveryRecordBackRouterData,
connectors: &Connectors,
) -> CustomResult<Option<Request>, errors::ConnectorError> {
Ok(Some(
RequestBuilder::new()
.method(Method::Post)
.url(&types::RevenueRecoveryRecordBackType::get_url(
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::RevenueRecoveryRecordBackType::get_headers(
self, req, connectors,
)?)
.set_body(types::RevenueRecoveryRecordBackType::get_request_body(
self, req, connectors,
)?)
.build(),
))
}
fn handle_response(
&self,
data: &RevenueRecoveryRecordBackRouterData,
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<RevenueRecoveryRecordBackRouterData, errors::ConnectorError> {
let response: chargebee::ChargebeeRecordbackResponse = res
.response
.parse_struct("chargebee ChargebeeRecordbackResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
RouterData::try_from(ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
}
fn get_error_response(
&self,
res: Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res, event_builder)
}
}
#[async_trait::async_trait]
impl webhooks::IncomingWebhook for Chargebee {
fn get_webhook_source_verification_signature(

View File

@ -2,21 +2,23 @@
use std::str::FromStr;
use common_enums::enums;
use common_utils::{
errors::CustomResult,
ext_traits::ByteSliceExt,
types::{MinorUnit, StringMinorUnit},
};
use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, pii, types::MinorUnit};
use error_stack::ResultExt;
#[cfg(all(feature = "revenue_recovery", feature = "v2"))]
use hyperswitch_domain_models::revenue_recovery;
use hyperswitch_domain_models::{
payment_method_data::PaymentMethodData,
router_data::{ConnectorAuthType, RouterData},
router_flow_types::refunds::{Execute, RSync},
router_request_types::ResponseId,
router_response_types::{PaymentsResponseData, RefundsResponseData},
types::{PaymentsAuthorizeRouterData, RefundsRouterData},
router_flow_types::{
refunds::{Execute, RSync},
RecoveryRecordBack,
},
router_request_types::{revenue_recovery::RevenueRecoveryRecordBackRequest, ResponseId},
router_response_types::{
revenue_recovery::RevenueRecoveryRecordBackResponse, PaymentsResponseData,
RefundsResponseData,
},
types::{PaymentsAuthorizeRouterData, RefundsRouterData, RevenueRecoveryRecordBackRouterData},
};
use hyperswitch_interfaces::errors;
use masking::Secret;
@ -25,18 +27,17 @@ use time::PrimitiveDateTime;
use crate::{
types::{RefundsResponseRouterData, ResponseRouterData},
utils::PaymentsAuthorizeRequestData,
utils::{self, PaymentsAuthorizeRequestData},
};
//TODO: Fill the struct with respective fields
pub struct ChargebeeRouterData<T> {
pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
pub amount: MinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
pub router_data: T,
}
impl<T> From<(StringMinorUnit, T)> for ChargebeeRouterData<T> {
fn from((amount, item): (StringMinorUnit, T)) -> Self {
//Todo : use utils to convert the amount to the type of amount that a connector accepts
impl<T> From<(MinorUnit, T)> for ChargebeeRouterData<T> {
fn from((amount, item): (MinorUnit, T)) -> Self {
Self {
amount,
router_data: item,
@ -47,7 +48,7 @@ impl<T> From<(StringMinorUnit, T)> for ChargebeeRouterData<T> {
//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, PartialEq)]
pub struct ChargebeePaymentsRequest {
amount: StringMinorUnit,
amount: MinorUnit,
card: ChargebeeCard,
}
@ -75,7 +76,7 @@ impl TryFrom<&ChargebeeRouterData<&PaymentsAuthorizeRouterData>> for ChargebeePa
complete: item.router_data.request.is_auto_capture()?,
};
Ok(Self {
amount: item.amount.clone(),
amount: item.amount,
card,
})
}
@ -84,10 +85,25 @@ impl TryFrom<&ChargebeeRouterData<&PaymentsAuthorizeRouterData>> for ChargebeePa
}
}
//TODO: Fill the struct with respective fields
// Auth Struct
pub struct ChargebeeAuthType {
pub(super) api_key: Secret<String>,
pub(super) full_access_key_v1: Secret<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ChargebeeMetadata {
pub(super) site: Secret<String>,
}
impl TryFrom<&Option<pii::SecretSerdeValue>> for ChargebeeMetadata {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(meta_data: &Option<pii::SecretSerdeValue>) -> Result<Self, Self::Error> {
let metadata: Self = utils::to_connector_meta_from_secret::<Self>(meta_data.clone())
.change_context(errors::ConnectorError::InvalidConnectorConfig {
config: "metadata",
})?;
Ok(metadata)
}
}
impl TryFrom<&ConnectorAuthType> for ChargebeeAuthType {
@ -95,7 +111,7 @@ impl TryFrom<&ConnectorAuthType> for ChargebeeAuthType {
fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
match auth_type {
ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
api_key: api_key.to_owned(),
full_access_key_v1: api_key.clone(),
}),
_ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
}
@ -158,7 +174,7 @@ impl<F, T> TryFrom<ResponseRouterData<F, ChargebeePaymentsResponse, T, PaymentsR
// Type definition for RefundRequest
#[derive(Default, Debug, Serialize)]
pub struct ChargebeeRefundRequest {
pub amount: StringMinorUnit,
pub amount: MinorUnit,
}
impl<F> TryFrom<&ChargebeeRouterData<&RefundsRouterData<F>>> for ChargebeeRefundRequest {
@ -229,13 +245,10 @@ impl TryFrom<RefundsResponseRouterData<RSync, RefundResponse>> for RefundsRouter
}
}
//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct ChargebeeErrorResponse {
pub status_code: u16,
pub code: String,
pub api_error_code: String,
pub message: String,
pub reason: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
@ -508,3 +521,127 @@ impl TryFrom<ChargebeeInvoiceBody> for revenue_recovery::RevenueRecoveryInvoiceD
})
}
}
#[derive(Debug, Serialize)]
pub struct ChargebeeRecordPaymentRequest {
#[serde(rename = "transaction[amount]")]
pub amount: MinorUnit,
#[serde(rename = "transaction[payment_method]")]
pub payment_method: ChargebeeRecordPaymentMethod,
#[serde(rename = "transaction[id_at_gateway]")]
pub connector_payment_id: Option<String>,
#[serde(rename = "transaction[status]")]
pub status: ChargebeeRecordStatus,
}
#[derive(Debug, Serialize, Clone, Copy)]
#[serde(rename_all = "snake_case")]
pub enum ChargebeeRecordPaymentMethod {
Other,
}
#[derive(Debug, Serialize, Clone, Copy)]
#[serde(rename_all = "snake_case")]
pub enum ChargebeeRecordStatus {
Success,
Failure,
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
impl TryFrom<&ChargebeeRouterData<&RevenueRecoveryRecordBackRouterData>>
for ChargebeeRecordPaymentRequest
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: &ChargebeeRouterData<&RevenueRecoveryRecordBackRouterData>,
) -> Result<Self, Self::Error> {
let req = &item.router_data.request;
Ok(Self {
amount: req.amount,
payment_method: ChargebeeRecordPaymentMethod::Other,
connector_payment_id: req
.connector_transaction_id
.as_ref()
.map(|connector_payment_id| connector_payment_id.get_id().to_string()),
status: ChargebeeRecordStatus::try_from(req.attempt_status)?,
})
}
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
impl TryFrom<enums::AttemptStatus> for ChargebeeRecordStatus {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(status: enums::AttemptStatus) -> Result<Self, Self::Error> {
match status {
enums::AttemptStatus::Charged
| enums::AttemptStatus::PartialCharged
| enums::AttemptStatus::PartialChargedAndChargeable => Ok(Self::Success),
enums::AttemptStatus::Failure
| enums::AttemptStatus::CaptureFailed
| enums::AttemptStatus::RouterDeclined => Ok(Self::Failure),
enums::AttemptStatus::AuthenticationFailed
| enums::AttemptStatus::Started
| enums::AttemptStatus::AuthenticationPending
| enums::AttemptStatus::AuthenticationSuccessful
| enums::AttemptStatus::Authorized
| enums::AttemptStatus::AuthorizationFailed
| enums::AttemptStatus::Authorizing
| enums::AttemptStatus::CodInitiated
| enums::AttemptStatus::Voided
| enums::AttemptStatus::VoidInitiated
| enums::AttemptStatus::CaptureInitiated
| enums::AttemptStatus::VoidFailed
| enums::AttemptStatus::AutoRefunded
| enums::AttemptStatus::Unresolved
| enums::AttemptStatus::Pending
| enums::AttemptStatus::PaymentMethodAwaited
| enums::AttemptStatus::ConfirmationAwaited
| enums::AttemptStatus::DeviceDataCollectionPending => {
Err(errors::ConnectorError::NotSupported {
message: "Record back flow is only supported for terminal status".to_string(),
connector: "chargebee",
}
.into())
}
}
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ChargebeeRecordbackResponse {
pub invoice: ChargebeeRecordbackInvoice,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ChargebeeRecordbackInvoice {
pub id: common_utils::id_type::PaymentReferenceId,
}
impl
TryFrom<
ResponseRouterData<
RecoveryRecordBack,
ChargebeeRecordbackResponse,
RevenueRecoveryRecordBackRequest,
RevenueRecoveryRecordBackResponse,
>,
> for RevenueRecoveryRecordBackRouterData
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: ResponseRouterData<
RecoveryRecordBack,
ChargebeeRecordbackResponse,
RevenueRecoveryRecordBackRequest,
RevenueRecoveryRecordBackResponse,
>,
) -> Result<Self, Self::Error> {
let merchant_reference_id = item.response.invoice.id;
Ok(Self {
response: Ok(RevenueRecoveryRecordBackResponse {
merchant_reference_id,
}),
..item.data
})
}
}

View File

@ -22,6 +22,18 @@ use hyperswitch_domain_models::{
router_request_types::PayoutsData,
router_response_types::PayoutsResponseData,
};
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
use hyperswitch_domain_models::{
router_flow_types::revenue_recovery::{
GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack,
},
router_request_types::revenue_recovery::{
GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest,
},
router_response_types::revenue_recovery::{
GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse,
},
};
use hyperswitch_domain_models::{
router_flow_types::{
dispute::{Accept, Defend, Evidence},
@ -32,15 +44,10 @@ use hyperswitch_domain_models::{
CreateConnectorCustomer, IncrementalAuthorization, PostProcessing, PostSessionTokens,
PreProcessing, Reject, SdkSessionUpdate,
},
revenue_recovery::RecoveryRecordBack,
webhooks::VerifyWebhookSource,
Authenticate, AuthenticationConfirmation, GetAdditionalRevenueRecoveryDetails,
PostAuthenticate, PreAuthenticate,
Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate,
},
router_request_types::{
revenue_recovery::{
GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest,
},
unified_authentication_service::{
UasAuthenticationRequestData, UasAuthenticationResponseData,
UasConfirmationRequestData, UasPostAuthenticationRequestData,
@ -54,9 +61,6 @@ use hyperswitch_domain_models::{
SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData,
},
router_response_types::{
revenue_recovery::{
GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse,
},
AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData,
PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse,
TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData,
@ -72,6 +76,10 @@ use hyperswitch_interfaces::api::payouts::{
PayoutCancel, PayoutCreate, PayoutEligibility, PayoutFulfill, PayoutQuote, PayoutRecipient,
PayoutRecipientAccount, PayoutSync,
};
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
use hyperswitch_interfaces::api::revenue_recovery::{
AdditionalRevenueRecovery, RevenueRecoveryRecordBack,
};
use hyperswitch_interfaces::{
api::{
self,
@ -83,7 +91,7 @@ use hyperswitch_interfaces::{
PaymentSessionUpdate, PaymentsCompleteAuthorize, PaymentsPostProcessing,
PaymentsPreProcessing, TaxCalculation,
},
revenue_recovery::{AdditionalRevenueRecovery, RevenueRecovery, RevenueRecoveryRecordBack},
revenue_recovery::RevenueRecovery,
ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, UasAuthentication,
UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication,
UnifiedAuthenticationService,
@ -3651,6 +3659,7 @@ default_imp_for_uas_authentication_confirmation!(
connectors::Zsl
);
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
macro_rules! default_imp_for_revenue_recovery_record_back {
($($path:ident::$connector:ident),*) => {
$( impl RevenueRecoveryRecordBack for $path::$connector {}
@ -3665,6 +3674,7 @@ macro_rules! default_imp_for_revenue_recovery_record_back {
};
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
default_imp_for_revenue_recovery_record_back!(
connectors::Aci,
connectors::Adyen,
@ -3680,7 +3690,6 @@ default_imp_for_revenue_recovery_record_back!(
connectors::Braintree,
connectors::Boku,
connectors::Cashtocode,
connectors::Chargebee,
connectors::Checkout,
connectors::Coinbase,
connectors::Coingate,
@ -3751,10 +3760,10 @@ default_imp_for_revenue_recovery_record_back!(
connectors::Zsl
);
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
macro_rules! default_imp_for_additional_revenue_recovery_call {
($($path:ident::$connector:ident),*) => {
$(
impl RevenueRecovery for $path::$connector {}
impl AdditionalRevenueRecovery for $path::$connector {}
impl
ConnectorIntegration<
@ -3767,6 +3776,7 @@ macro_rules! default_imp_for_additional_revenue_recovery_call {
};
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
default_imp_for_additional_revenue_recovery_call!(
connectors::Aci,
connectors::Adyen,
@ -3852,3 +3862,97 @@ default_imp_for_additional_revenue_recovery_call!(
connectors::Zen,
connectors::Zsl
);
macro_rules! default_imp_for_revenue_recovery {
($($path:ident::$connector:ident),*) => {
$(
impl RevenueRecovery for $path::$connector {}
)*
};
}
default_imp_for_revenue_recovery!(
connectors::Aci,
connectors::Adyen,
connectors::Airwallex,
connectors::Amazonpay,
connectors::Authorizedotnet,
connectors::Bambora,
connectors::Bamboraapac,
connectors::Bankofamerica,
connectors::Billwerk,
connectors::Bluesnap,
connectors::Bitpay,
connectors::Braintree,
connectors::Boku,
connectors::Cashtocode,
connectors::Chargebee,
connectors::Checkout,
connectors::Coinbase,
connectors::Coingate,
connectors::Cryptopay,
connectors::CtpMastercard,
connectors::Cybersource,
connectors::Datatrans,
connectors::Deutschebank,
connectors::Digitalvirgo,
connectors::Dlocal,
connectors::Elavon,
connectors::Fiserv,
connectors::Fiservemea,
connectors::Fiuu,
connectors::Forte,
connectors::Getnet,
connectors::Globalpay,
connectors::Globepay,
connectors::Gocardless,
connectors::Hipay,
connectors::Helcim,
connectors::Iatapay,
connectors::Inespay,
connectors::Itaubank,
connectors::Jpmorgan,
connectors::Juspaythreedsserver,
connectors::Klarna,
connectors::Nomupay,
connectors::Noon,
connectors::Novalnet,
connectors::Nexinets,
connectors::Nexixpay,
connectors::Nuvei,
connectors::Opayo,
connectors::Opennode,
connectors::Payeezy,
connectors::Paypal,
connectors::Paystack,
connectors::Payu,
connectors::Powertranz,
connectors::Prophetpay,
connectors::Mifinity,
connectors::Mollie,
connectors::Moneris,
connectors::Multisafepay,
connectors::Paybox,
connectors::Payme,
connectors::Placetopay,
connectors::Rapyd,
connectors::Razorpay,
connectors::Recurly,
connectors::Redsys,
connectors::Shift4,
connectors::Stax,
connectors::Square,
connectors::Stripebilling,
connectors::Taxjar,
connectors::Thunes,
connectors::Trustpay,
connectors::Tsys,
connectors::UnifiedAuthenticationService,
connectors::Worldline,
connectors::Worldpay,
connectors::Wellsfargo,
connectors::Volt,
connectors::Xendit,
connectors::Zen,
connectors::Zsl
);

View File

@ -1,2 +1,3 @@
pub struct GetAdditionalRevenueRecoveryDetails;
#[derive(Debug, Clone)]
pub struct RecoveryRecordBack;

View File

@ -10,8 +10,11 @@ use hyperswitch_domain_models::{
},
};
use super::{ConnectorCommon, ConnectorIntegration};
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
use super::ConnectorCommon;
use super::ConnectorIntegration;
/// trait RevenueRecovery
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
pub trait RevenueRecovery:
ConnectorCommon + AdditionalRevenueRecovery + RevenueRecoveryRecordBack
{
@ -36,3 +39,7 @@ pub trait RevenueRecoveryRecordBack:
>
{
}
#[cfg(not(all(feature = "v2", feature = "revenue_recovery")))]
/// trait RevenueRecovery
pub trait RevenueRecovery {}

View File

@ -1314,6 +1314,7 @@ impl ConnectorAuthTypeAndMetadataValidation<'_> {
}
api_enums::Connector::Chargebee => {
chargebee::transformers::ChargebeeAuthType::try_from(self.auth_type)?;
chargebee::transformers::ChargebeeMetadata::try_from(self.connector_meta_data)?;
Ok(())
}
api_enums::Connector::Checkout => {

View File

@ -12,11 +12,14 @@ pub mod session_update_flow;
pub mod setup_mandate_flow;
use async_trait::async_trait;
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
use hyperswitch_domain_models::router_flow_types::{
revenue_recovery::RecoveryRecordBack, GetAdditionalRevenueRecoveryDetails,
};
use hyperswitch_domain_models::{
mandates::CustomerAcceptance,
router_flow_types::{
revenue_recovery::RecoveryRecordBack, Authenticate, AuthenticationConfirmation,
GetAdditionalRevenueRecoveryDetails, PostAuthenticate, PreAuthenticate,
Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate,
},
router_request_types::PaymentsCaptureData,
};
@ -2216,6 +2219,7 @@ fn handle_post_capture_response(
}
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
macro_rules! default_imp_for_revenue_recovery_record_back {
($($path:ident::$connector:ident),*) => {
$(
@ -2231,8 +2235,10 @@ macro_rules! default_imp_for_revenue_recovery_record_back {
};
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8> api::RevenueRecoveryRecordBack for connector::DummyConnector<T> {}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8>
services::ConnectorIntegration<
@ -2242,7 +2248,7 @@ impl<const T: u8>
> for connector::DummyConnector<T>
{
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
default_imp_for_revenue_recovery_record_back!(
connector::Adyenplatform,
connector::Ebanx,
@ -2259,9 +2265,36 @@ default_imp_for_revenue_recovery_record_back!(
connector::Wise
);
macro_rules! default_imp_for_additional_revenue_recovery_call {
macro_rules! default_imp_for_revenue_recovery {
($($path:ident::$connector:ident),*) => {
$( impl api::RevenueRecovery for $path::$connector {}
)*
};
}
#[cfg(feature = "dummy_connector")]
impl<const T: u8> api::RevenueRecovery for connector::DummyConnector<T> {}
default_imp_for_revenue_recovery! {
connector::Adyenplatform,
connector::Ebanx,
connector::Gpayments,
connector::Netcetera,
connector::Nmi,
connector::Payone,
connector::Plaid,
connector::Riskified,
connector::Signifyd,
connector::Stripe,
connector::Threedsecureio,
connector::Wellsfargopayout,
connector::Wise
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
macro_rules! default_imp_for_additional_revenue_recovery_call {
($($path:ident::$connector:ident),*) => {
$(
impl api::AdditionalRevenueRecovery for $path::$connector {}
impl
services::ConnectorIntegration<
@ -2274,9 +2307,10 @@ macro_rules! default_imp_for_additional_revenue_recovery_call {
};
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8> api::RevenueRecovery for connector::DummyConnector<T> {}
impl<const T: u8> api::AdditionalRevenueRecovery for connector::DummyConnector<T> {}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8>
services::ConnectorIntegration<
@ -2287,6 +2321,7 @@ impl<const T: u8>
{
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
default_imp_for_additional_revenue_recovery_call!(
connector::Adyenplatform,
connector::Ebanx,

View File

@ -10,8 +10,8 @@ use hyperswitch_domain_models::{
router_data_v2::{
flow_common_types::{
AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData,
MandateRevokeFlowData, PaymentFlowData, RefundFlowData, UasFlowData,
WebhookSourceVerifyData,
MandateRevokeFlowData, PaymentFlowData, RefundFlowData, RevenueRecoveryRecordBackData,
UasFlowData, WebhookSourceVerifyData,
},
RouterDataV2,
},
@ -715,6 +715,42 @@ impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp>
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp>
for RevenueRecoveryRecordBackData
{
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
tenant_id: old_router_data.tenant_id.clone(),
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let router_data = get_default_router_data(
new_router_data.tenant_id.clone(),
"recovery_record_back",
new_router_data.request,
new_router_data.response,
);
Ok(router_data)
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for UasFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,