feat(connector): [noon] add revoke mandate (#3487)

This commit is contained in:
SamraatBansal
2024-01-30 17:15:04 +05:30
committed by GitHub
parent 431ccb156b
commit b5bc8c4e7c
3 changed files with 167 additions and 5 deletions

View File

@ -46,6 +46,7 @@ impl api::Refund for Noon {}
impl api::RefundExecute for Noon {} impl api::RefundExecute for Noon {}
impl api::RefundSync for Noon {} impl api::RefundSync for Noon {}
impl api::PaymentToken for Noon {} impl api::PaymentToken for Noon {}
impl api::ConnectorMandateRevoke for Noon {}
impl impl
ConnectorIntegration< ConnectorIntegration<
@ -492,6 +493,81 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
} }
} }
impl
ConnectorIntegration<
api::MandateRevoke,
types::MandateRevokeRequestData,
types::MandateRevokeResponseData,
> for Noon
{
fn get_headers(
&self,
req: &types::MandateRevokeRouterData,
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::MandateRevokeRouterData,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Ok(format!("{}payment/v1/order", self.base_url(connectors)))
}
fn build_request(
&self,
req: &types::MandateRevokeRouterData,
connectors: &settings::Connectors,
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
Ok(Some(
services::RequestBuilder::new()
.method(services::Method::Post)
.url(&types::MandateRevokeType::get_url(self, req, connectors)?)
.attach_default_headers()
.headers(types::MandateRevokeType::get_headers(
self, req, connectors,
)?)
.set_body(types::MandateRevokeType::get_request_body(
self, req, connectors,
)?)
.build(),
))
}
fn get_request_body(
&self,
req: &types::MandateRevokeRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_req = noon::NoonRevokeMandateRequest::try_from(req)?;
Ok(RequestContent::Json(Box::new(connector_req)))
}
fn handle_response(
&self,
data: &types::MandateRevokeRouterData,
res: Response,
) -> CustomResult<types::MandateRevokeRouterData, errors::ConnectorError> {
let response: noon::NoonRevokeMandateResponse = res
.response
.parse_struct("Noon NoonRevokeMandateResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
types::RouterData::try_from(types::ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
}
fn get_error_response(
&self,
res: Response,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res)
}
}
impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData> for Noon { impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData> for Noon {
fn get_headers( fn get_headers(
&self, &self,

View File

@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
connector::utils::{ connector::utils::{
self as conn_utils, CardData, PaymentsAuthorizeRequestData, RouterData, WalletData, self as conn_utils, CardData, PaymentsAuthorizeRequestData, RevokeMandateRequestData,
RouterData, WalletData,
}, },
core::errors, core::errors,
services, services,
@ -30,11 +31,13 @@ pub enum NoonSubscriptionType {
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NoonSubscriptionData { pub struct NoonSubscriptionData {
#[serde(rename = "type")] #[serde(rename = "type")]
subscription_type: NoonSubscriptionType, subscription_type: NoonSubscriptionType,
//Short description about the subscription. //Short description about the subscription.
name: String, name: String,
max_amount: Option<String>,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
@ -168,12 +171,13 @@ pub enum NoonPaymentData {
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "UPPERCASE")] #[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum NoonApiOperations { pub enum NoonApiOperations {
Initiate, Initiate,
Capture, Capture,
Reverse, Reverse,
Refund, Refund,
CancelSubscription,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -335,6 +339,21 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for NoonPaymentsRequest {
NoonSubscriptionData { NoonSubscriptionData {
subscription_type: NoonSubscriptionType::Unscheduled, subscription_type: NoonSubscriptionType::Unscheduled,
name: name.clone(), name: name.clone(),
max_amount: item
.request
.setup_mandate_details
.clone()
.and_then(|mandate_details| match mandate_details.mandate_type {
Some(data_models::mandates::MandateDataType::SingleUse(mandate))
| Some(data_models::mandates::MandateDataType::MultiUse(Some(
mandate,
))) => Some(
conn_utils::to_currency_base_unit(mandate.amount, mandate.currency)
.ok(),
),
_ => None,
})
.flatten(),
}, },
true, true,
)) { )) {
@ -450,7 +469,7 @@ impl ForeignFrom<(NoonPaymentStatus, Self)> for enums::AttemptStatus {
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct NoonSubscriptionResponse { pub struct NoonSubscriptionObject {
identifier: String, identifier: String,
} }
@ -475,7 +494,7 @@ pub struct NoonCheckoutData {
pub struct NoonPaymentsResponseResult { pub struct NoonPaymentsResponseResult {
order: NoonPaymentsOrderResponse, order: NoonPaymentsOrderResponse,
checkout_data: Option<NoonCheckoutData>, checkout_data: Option<NoonCheckoutData>,
subscription: Option<NoonSubscriptionResponse>, subscription: Option<NoonSubscriptionObject>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -603,6 +622,25 @@ impl TryFrom<&types::PaymentsCancelRouterData> for NoonPaymentsCancelRequest {
} }
} }
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct NoonRevokeMandateRequest {
api_operation: NoonApiOperations,
subscription: NoonSubscriptionObject,
}
impl TryFrom<&types::MandateRevokeRouterData> for NoonRevokeMandateRequest {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::MandateRevokeRouterData) -> Result<Self, Self::Error> {
Ok(Self {
api_operation: NoonApiOperations::CancelSubscription,
subscription: NoonSubscriptionObject {
identifier: item.request.get_connector_mandate_id()?,
},
})
}
}
impl<F> TryFrom<&types::RefundsRouterData<F>> for NoonPaymentsActionRequest { impl<F> TryFrom<&types::RefundsRouterData<F>> for NoonPaymentsActionRequest {
type Error = error_stack::Report<errors::ConnectorError>; type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> { fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
@ -624,6 +662,55 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for NoonPaymentsActionRequest {
}) })
} }
} }
#[derive(Debug, Deserialize)]
pub enum NoonRevokeStatus {
Cancelled,
}
#[derive(Debug, Deserialize)]
pub struct NoonCancelSubscriptionObject {
status: NoonRevokeStatus,
}
#[derive(Debug, Deserialize)]
pub struct NoonRevokeMandateResult {
subscription: NoonCancelSubscriptionObject,
}
#[derive(Debug, Deserialize)]
pub struct NoonRevokeMandateResponse {
result: NoonRevokeMandateResult,
}
impl<F>
TryFrom<
types::ResponseRouterData<
F,
NoonRevokeMandateResponse,
types::MandateRevokeRequestData,
types::MandateRevokeResponseData,
>,
> for types::RouterData<F, types::MandateRevokeRequestData, types::MandateRevokeResponseData>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::ResponseRouterData<
F,
NoonRevokeMandateResponse,
types::MandateRevokeRequestData,
types::MandateRevokeResponseData,
>,
) -> Result<Self, Self::Error> {
match item.response.result.subscription.status {
NoonRevokeStatus::Cancelled => Ok(Self {
response: Ok(types::MandateRevokeResponseData {
mandate_status: common_enums::MandateStatus::Revoked,
}),
..item.data
}),
}
}
}
#[derive(Debug, Default, Deserialize, Clone)] #[derive(Debug, Default, Deserialize, Clone)]
#[serde(rename_all = "UPPERCASE")] #[serde(rename_all = "UPPERCASE")]

View File

@ -2247,7 +2247,6 @@ default_imp_for_revoking_mandates!(
connector::Multisafepay, connector::Multisafepay,
connector::Nexinets, connector::Nexinets,
connector::Nmi, connector::Nmi,
connector::Noon,
connector::Nuvei, connector::Nuvei,
connector::Opayo, connector::Opayo,
connector::Opennode, connector::Opennode,