feat(connector): add psync for authorizedotnet (#7)

This commit is contained in:
Narayan Bhat
2022-11-25 17:03:52 +05:30
committed by GitHub
parent 38a29a0ad9
commit d41159591e
2 changed files with 187 additions and 12 deletions

View File

@ -60,7 +60,6 @@ impl
// Not Implemented (R)
}
#[allow(dead_code)]
type PSync = dyn services::ConnectorIntegration<
api::PSync,
types::PaymentsRequestSyncData,
@ -73,7 +72,109 @@ impl
types::PaymentsResponseData,
> for Authorizedotnet
{
// Not Implemented (R)
fn get_headers(
&self,
_req: &types::PaymentsRouterSyncData,
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
// This connector does not require an auth header, the authentication details are sent in the request body
Ok(vec![
(
headers::CONTENT_TYPE.to_string(),
PSync::get_content_type(self).to_string(),
),
(headers::X_ROUTER.to_string(), "test".to_string()),
])
}
fn get_content_type(&self) -> &'static str {
"application/json"
}
fn get_url(
&self,
_req: &types::PaymentsRouterSyncData,
connectors: Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Ok(self.base_url(connectors))
}
fn get_request_body(
&self,
req: &types::PaymentsRouterSyncData,
) -> CustomResult<Option<String>, errors::ConnectorError> {
let sync_request =
utils::Encode::<authorizedotnet::AuthorizedotnetCreateSyncRequest>::convert_and_encode(
req,
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
Ok(Some(sync_request))
}
fn build_request(
&self,
req: &types::PaymentsRouterSyncData,
connectors: Connectors,
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
let request = services::RequestBuilder::new()
.method(services::Method::Post)
.url(&PSync::get_url(self, req, connectors)?)
.headers(PSync::get_headers(self, req)?)
.body(PSync::get_request_body(self, req)?)
.build();
Ok(Some(request))
}
fn handle_response(
&self,
data: &types::PaymentsRouterSyncData,
res: Response,
) -> CustomResult<types::PaymentsRouterSyncData, errors::ConnectorError> {
use bytes::Buf;
// Handle the case where response bytes contains U+FEFF (BOM) character sent by connector
let encoding = encoding_rs::UTF_8;
let intermediate_response = encoding.decode_with_bom_removal(res.response.chunk());
let intermediate_response =
bytes::Bytes::copy_from_slice(intermediate_response.0.as_bytes());
let response: authorizedotnet::AuthorizedotnetSyncResponse = intermediate_response
.parse_struct("AuthorizedotnetSyncResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
types::RouterData::try_from(types::ResponseRouterData {
response,
data: data.clone(),
http_code: res.status_code,
})
.change_context(errors::ConnectorError::ResponseHandlingFailed)
}
fn get_error_response(
&self,
res: Bytes,
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
let response: authorizedotnet::AuthorizedotnetPaymentsResponse = res
.parse_struct("AuthorizedotnetPaymentsResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let error = response
.transaction_response
.errors
.and_then(|errors| {
errors.first().map(|error| types::ErrorResponse {
code: error.error_code.clone(),
message: error.error_text.clone(),
reason: None,
})
})
.unwrap_or_else(|| types::ErrorResponse {
code: consts::NO_ERROR_CODE.to_string(),
message: consts::NO_ERROR_MESSAGE.to_string(),
reason: None,
});
Ok(error)
}
}
type Authorize = dyn services::ConnectorIntegration<
@ -487,7 +588,9 @@ impl
req: &types::RefundsRouterData<api::RSync>,
) -> CustomResult<Option<String>, errors::ConnectorError> {
let sync_request =
utils::Encode::<authorizedotnet::CreateSyncRequest>::convert_and_encode(req)
utils::Encode::<authorizedotnet::AuthorizedotnetCreateSyncRequest>::convert_and_encode(
req,
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
Ok(Some(sync_request))
}
@ -519,8 +622,8 @@ impl
let intermediate_response =
bytes::Bytes::copy_from_slice(intermediate_response.0.as_bytes());
let response: authorizedotnet::SyncResponse = intermediate_response
.parse_struct("SyncResponse")
let response: authorizedotnet::AuthorizedotnetSyncResponse = intermediate_response
.parse_struct("AuthorizedotnetSyncResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
types::RouterData::try_from(types::ResponseRouterData {

View File

@ -427,11 +427,11 @@ pub struct TransactionDetails {
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateSyncRequest {
pub struct AuthorizedotnetCreateSyncRequest {
get_transaction_details_request: TransactionDetails,
}
impl<F> TryFrom<&types::RefundsRouterData<F>> for CreateSyncRequest {
impl<F> TryFrom<&types::RefundsRouterData<F>> for AuthorizedotnetCreateSyncRequest {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
@ -441,7 +441,27 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for CreateSyncRequest {
.map(|refund_response_data| refund_response_data.connector_refund_id.clone());
let merchant_authentication = MerchantAuthentication::try_from(&item.connector_auth_type)?;
let payload = CreateSyncRequest {
let payload = AuthorizedotnetCreateSyncRequest {
get_transaction_details_request: TransactionDetails {
merchant_authentication,
transaction_id,
},
};
Ok(payload)
}
}
impl TryFrom<&types::PaymentsRouterSyncData> for AuthorizedotnetCreateSyncRequest {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::PaymentsRouterSyncData) -> Result<Self, Self::Error> {
let transaction_id = item
.response
.as_ref()
.map(|payment_response_data| payment_response_data.connector_transaction_id.clone());
let merchant_authentication = MerchantAuthentication::try_from(&item.connector_auth_type)?;
let payload = AuthorizedotnetCreateSyncRequest {
get_transaction_details_request: TransactionDetails {
merchant_authentication,
transaction_id,
@ -456,6 +476,13 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for CreateSyncRequest {
pub enum SyncStatus {
RefundSettledSuccessfully,
RefundPendingSettlement,
AuthorizedPendingCapture,
CapturedPendingSettlement,
SettledSuccessfully,
Declined,
Voided,
CouldNotVoid,
GeneralError,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
@ -466,7 +493,7 @@ pub struct SyncTransactionResponse {
}
#[derive(Debug, Deserialize)]
pub struct SyncResponse {
pub struct AuthorizedotnetSyncResponse {
transaction: SyncTransactionResponse,
}
@ -475,17 +502,33 @@ impl From<SyncStatus> for enums::RefundStatus {
match transaction_status {
SyncStatus::RefundSettledSuccessfully => enums::RefundStatus::Success,
SyncStatus::RefundPendingSettlement => enums::RefundStatus::Pending,
_ => enums::RefundStatus::Failure,
}
}
}
impl TryFrom<types::RefundsResponseRouterData<api::RSync, SyncResponse>>
impl From<SyncStatus> for enums::AttemptStatus {
fn from(transaction_status: SyncStatus) -> Self {
match transaction_status {
SyncStatus::SettledSuccessfully | SyncStatus::CapturedPendingSettlement => {
enums::AttemptStatus::Charged
}
SyncStatus::Declined => enums::AttemptStatus::AuthenticationFailed,
SyncStatus::Voided => enums::AttemptStatus::Voided,
SyncStatus::CouldNotVoid => enums::AttemptStatus::VoidFailed,
SyncStatus::GeneralError => enums::AttemptStatus::Failure,
_ => enums::AttemptStatus::Pending,
}
}
}
impl TryFrom<types::RefundsResponseRouterData<api::RSync, AuthorizedotnetSyncResponse>>
for types::RefundsRouterData<api::RSync>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::RefundsResponseRouterData<api::RSync, SyncResponse>,
item: types::RefundsResponseRouterData<api::RSync, AuthorizedotnetSyncResponse>,
) -> Result<Self, Self::Error> {
let refund_status = enums::RefundStatus::from(item.response.transaction.transaction_status);
Ok(types::RouterData {
@ -498,6 +541,35 @@ impl TryFrom<types::RefundsResponseRouterData<api::RSync, SyncResponse>>
}
}
impl<F, Req>
TryFrom<
types::ResponseRouterData<F, AuthorizedotnetSyncResponse, Req, types::PaymentsResponseData>,
> for types::RouterData<F, Req, types::PaymentsResponseData>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::ResponseRouterData<
F,
AuthorizedotnetSyncResponse,
Req,
types::PaymentsResponseData,
>,
) -> Result<Self, Self::Error> {
let payment_status =
enums::AttemptStatus::from(item.response.transaction.transaction_status);
Ok(types::RouterData {
response: Some(types::PaymentsResponseData {
connector_transaction_id: item.response.transaction.transaction_id,
redirection_data: None,
redirect: false,
}),
status: payment_status,
..item.data
})
}
}
#[derive(Debug, Default, Eq, PartialEq, Deserialize)]
pub struct ErrorDetails {
pub code: Option<String>,