mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
feat(connectors): implement capture flow for checkout and adyen connectors (#259)
This commit is contained in:
@ -81,7 +81,90 @@ impl
|
|||||||
types::PaymentsResponseData,
|
types::PaymentsResponseData,
|
||||||
> for Adyen
|
> for Adyen
|
||||||
{
|
{
|
||||||
// Not Implemented (R)
|
fn get_headers(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsCaptureRouterData,
|
||||||
|
_connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||||
|
let mut header = vec![
|
||||||
|
(
|
||||||
|
headers::CONTENT_TYPE.to_string(),
|
||||||
|
self.common_get_content_type().to_string(),
|
||||||
|
),
|
||||||
|
(headers::X_ROUTER.to_string(), "test".to_string()),
|
||||||
|
];
|
||||||
|
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
|
||||||
|
header.append(&mut api_key);
|
||||||
|
Ok(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_url(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsCaptureRouterData,
|
||||||
|
connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<String, errors::ConnectorError> {
|
||||||
|
let id = req.request.connector_transaction_id.as_str();
|
||||||
|
Ok(format!(
|
||||||
|
"{}{}/{}/captures",
|
||||||
|
self.base_url(connectors),
|
||||||
|
"v68/payments",
|
||||||
|
id
|
||||||
|
))
|
||||||
|
}
|
||||||
|
fn get_request_body(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsCaptureRouterData,
|
||||||
|
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
||||||
|
let adyen_req = utils::Encode::<adyen::AdyenCaptureRequest>::convert_and_encode(req)
|
||||||
|
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||||
|
Ok(Some(adyen_req))
|
||||||
|
}
|
||||||
|
fn build_request(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsCaptureRouterData,
|
||||||
|
connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||||
|
Ok(Some(
|
||||||
|
services::RequestBuilder::new()
|
||||||
|
.method(services::Method::Post)
|
||||||
|
.url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
|
||||||
|
.headers(types::PaymentsCaptureType::get_headers(
|
||||||
|
self, req, connectors,
|
||||||
|
)?)
|
||||||
|
.body(types::PaymentsCaptureType::get_request_body(self, req)?)
|
||||||
|
.build(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
fn handle_response(
|
||||||
|
&self,
|
||||||
|
data: &types::PaymentsCaptureRouterData,
|
||||||
|
res: types::Response,
|
||||||
|
) -> CustomResult<types::PaymentsCaptureRouterData, errors::ConnectorError> {
|
||||||
|
let response: adyen::AdyenCaptureResponse = res
|
||||||
|
.response
|
||||||
|
.parse_struct("AdyenCaptureResponse")
|
||||||
|
.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<types::ErrorResponse, errors::ConnectorError> {
|
||||||
|
let response: adyen::ErrorResponse = res
|
||||||
|
.parse_struct("adyen::ErrorResponse")
|
||||||
|
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||||
|
Ok(types::ErrorResponse {
|
||||||
|
code: response.error_code,
|
||||||
|
message: response.message,
|
||||||
|
reason: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl
|
impl
|
||||||
@ -189,12 +272,15 @@ impl
|
|||||||
.response
|
.response
|
||||||
.parse_struct("AdyenPaymentResponse")
|
.parse_struct("AdyenPaymentResponse")
|
||||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||||
|
let is_manual_capture = false;
|
||||||
types::RouterData::try_from(types::ResponseRouterData {
|
types::RouterData::try_from((
|
||||||
response,
|
types::ResponseRouterData {
|
||||||
data: data.clone(),
|
response,
|
||||||
http_code: res.status_code,
|
data: data.clone(),
|
||||||
})
|
http_code: res.status_code,
|
||||||
|
},
|
||||||
|
is_manual_capture,
|
||||||
|
))
|
||||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,12 +380,16 @@ impl
|
|||||||
.response
|
.response
|
||||||
.parse_struct("AdyenPaymentResponse")
|
.parse_struct("AdyenPaymentResponse")
|
||||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||||
|
let is_manual_capture =
|
||||||
types::RouterData::try_from(types::ResponseRouterData {
|
data.request.capture_method == Some(storage_models::enums::CaptureMethod::Manual);
|
||||||
response,
|
types::RouterData::try_from((
|
||||||
data: data.clone(),
|
types::ResponseRouterData {
|
||||||
http_code: res.status_code,
|
response,
|
||||||
})
|
data: data.clone(),
|
||||||
|
http_code: res.status_code,
|
||||||
|
},
|
||||||
|
is_manual_capture,
|
||||||
|
))
|
||||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,16 @@ pub enum AdyenRecurringModel {
|
|||||||
UnscheduledCardOnFile,
|
UnscheduledCardOnFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum AuthType {
|
||||||
|
#[default]
|
||||||
|
PreAuth,
|
||||||
|
}
|
||||||
|
#[derive(Default, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct AdditionalData {
|
||||||
|
authorisation_type: AuthType,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct AdyenPaymentRequest {
|
pub struct AdyenPaymentRequest {
|
||||||
@ -47,6 +57,7 @@ pub struct AdyenPaymentRequest {
|
|||||||
shopper_interaction: AdyenShopperInteraction,
|
shopper_interaction: AdyenShopperInteraction,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
recurring_processing_model: Option<AdyenRecurringModel>,
|
recurring_processing_model: Option<AdyenRecurringModel>,
|
||||||
|
additional_data: Option<AdditionalData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@ -363,6 +374,13 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AdyenPaymentRequest {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let additional_data = match item.request.capture_method {
|
||||||
|
Some(storage_models::enums::CaptureMethod::Manual) => Some(AdditionalData {
|
||||||
|
authorisation_type: AuthType::PreAuth,
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
amount,
|
amount,
|
||||||
merchant_account: auth_type.merchant_account,
|
merchant_account: auth_type.merchant_account,
|
||||||
@ -376,6 +394,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AdyenPaymentRequest {
|
|||||||
shopper_interaction,
|
shopper_interaction,
|
||||||
recurring_processing_model,
|
recurring_processing_model,
|
||||||
browser_info,
|
browser_info,
|
||||||
|
additional_data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,6 +438,7 @@ impl TryFrom<types::PaymentsCancelResponseRouterData<AdyenCancelResponse>>
|
|||||||
|
|
||||||
pub fn get_adyen_response(
|
pub fn get_adyen_response(
|
||||||
response: AdyenResponse,
|
response: AdyenResponse,
|
||||||
|
is_capture_manual: bool,
|
||||||
) -> errors::CustomResult<
|
) -> errors::CustomResult<
|
||||||
(
|
(
|
||||||
storage_enums::AttemptStatus,
|
storage_enums::AttemptStatus,
|
||||||
@ -429,7 +449,13 @@ pub fn get_adyen_response(
|
|||||||
> {
|
> {
|
||||||
let result = response.result_code;
|
let result = response.result_code;
|
||||||
let status = match result.as_str() {
|
let status = match result.as_str() {
|
||||||
"Authorised" => storage_enums::AttemptStatus::Charged,
|
"Authorised" => {
|
||||||
|
if is_capture_manual {
|
||||||
|
storage_enums::AttemptStatus::Authorized
|
||||||
|
} else {
|
||||||
|
storage_enums::AttemptStatus::Charged
|
||||||
|
}
|
||||||
|
}
|
||||||
"Refused" => storage_enums::AttemptStatus::Failure,
|
"Refused" => storage_enums::AttemptStatus::Failure,
|
||||||
_ => storage_enums::AttemptStatus::Pending,
|
_ => storage_enums::AttemptStatus::Pending,
|
||||||
};
|
};
|
||||||
@ -522,15 +548,24 @@ pub fn get_redirection_response(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F, Req>
|
impl<F, Req>
|
||||||
TryFrom<types::ResponseRouterData<F, AdyenPaymentResponse, Req, types::PaymentsResponseData>>
|
TryFrom<(
|
||||||
for types::RouterData<F, Req, types::PaymentsResponseData>
|
types::ResponseRouterData<F, AdyenPaymentResponse, Req, types::PaymentsResponseData>,
|
||||||
|
bool,
|
||||||
|
)> for types::RouterData<F, Req, types::PaymentsResponseData>
|
||||||
{
|
{
|
||||||
type Error = error_stack::Report<errors::ParsingError>;
|
type Error = error_stack::Report<errors::ParsingError>;
|
||||||
fn try_from(
|
fn try_from(
|
||||||
item: types::ResponseRouterData<F, AdyenPaymentResponse, Req, types::PaymentsResponseData>,
|
items: (
|
||||||
|
types::ResponseRouterData<F, AdyenPaymentResponse, Req, types::PaymentsResponseData>,
|
||||||
|
bool,
|
||||||
|
),
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
|
let item = items.0;
|
||||||
|
let is_manual_capture = items.1;
|
||||||
let (status, error, payment_response_data) = match item.response {
|
let (status, error, payment_response_data) = match item.response {
|
||||||
AdyenPaymentResponse::AdyenResponse(response) => get_adyen_response(response)?,
|
AdyenPaymentResponse::AdyenResponse(response) => {
|
||||||
|
get_adyen_response(response, is_manual_capture)?
|
||||||
|
}
|
||||||
AdyenPaymentResponse::AdyenRedirectResponse(response) => {
|
AdyenPaymentResponse::AdyenRedirectResponse(response) => {
|
||||||
get_redirection_response(response)?
|
get_redirection_response(response)?
|
||||||
}
|
}
|
||||||
@ -539,7 +574,70 @@ impl<F, Req>
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
status,
|
status,
|
||||||
response: error.map_or_else(|| Ok(payment_response_data), Err),
|
response: error.map_or_else(|| Ok(payment_response_data), Err),
|
||||||
|
..item.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Default, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AdyenCaptureRequest {
|
||||||
|
merchant_account: String,
|
||||||
|
amount: Amount,
|
||||||
|
reference: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&types::PaymentsCaptureRouterData> for AdyenCaptureRequest {
|
||||||
|
type Error = error_stack::Report<errors::ConnectorError>;
|
||||||
|
fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
|
||||||
|
let auth_type = AdyenAuthType::try_from(&item.connector_auth_type)?;
|
||||||
|
Ok(Self {
|
||||||
|
merchant_account: auth_type.merchant_account,
|
||||||
|
reference: item.payment_id.to_string(),
|
||||||
|
amount: Amount {
|
||||||
|
currency: item.request.currency.to_string(),
|
||||||
|
value: item
|
||||||
|
.request
|
||||||
|
.amount_to_capture
|
||||||
|
.unwrap_or(item.request.amount),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AdyenCaptureResponse {
|
||||||
|
merchant_account: String,
|
||||||
|
payment_psp_reference: String,
|
||||||
|
psp_reference: String,
|
||||||
|
reference: String,
|
||||||
|
status: String,
|
||||||
|
amount: Amount,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<types::PaymentsCaptureResponseRouterData<AdyenCaptureResponse>>
|
||||||
|
for types::PaymentsCaptureRouterData
|
||||||
|
{
|
||||||
|
type Error = error_stack::Report<errors::ParsingError>;
|
||||||
|
fn try_from(
|
||||||
|
item: types::PaymentsCaptureResponseRouterData<AdyenCaptureResponse>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let (status, amount_captured) = match item.response.status.as_str() {
|
||||||
|
"received" => (
|
||||||
|
storage_enums::AttemptStatus::Charged,
|
||||||
|
Some(item.response.amount.value),
|
||||||
|
),
|
||||||
|
_ => (storage_enums::AttemptStatus::Pending, None),
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
status,
|
||||||
|
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||||
|
resource_id: types::ResponseId::ConnectorTransactionId(item.response.psp_reference),
|
||||||
|
redirect: false,
|
||||||
|
redirection_data: None,
|
||||||
|
mandate_reference: None,
|
||||||
|
}),
|
||||||
|
amount_captured,
|
||||||
..item.data
|
..item.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,6 +87,97 @@ impl
|
|||||||
types::PaymentsResponseData,
|
types::PaymentsResponseData,
|
||||||
> for Checkout
|
> for Checkout
|
||||||
{
|
{
|
||||||
|
fn get_headers(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsCaptureRouterData,
|
||||||
|
_connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||||
|
let mut header = vec![
|
||||||
|
(
|
||||||
|
headers::CONTENT_TYPE.to_string(),
|
||||||
|
self.common_get_content_type().to_string(),
|
||||||
|
),
|
||||||
|
(headers::X_ROUTER.to_string(), "test".to_string()),
|
||||||
|
];
|
||||||
|
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
|
||||||
|
header.append(&mut api_key);
|
||||||
|
Ok(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_url(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsCaptureRouterData,
|
||||||
|
connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<String, errors::ConnectorError> {
|
||||||
|
let id = req.request.connector_transaction_id.as_str();
|
||||||
|
Ok(format!(
|
||||||
|
"{}payments/{id}/captures",
|
||||||
|
self.base_url(connectors)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
fn get_request_body(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsCaptureRouterData,
|
||||||
|
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
||||||
|
let checkout_req =
|
||||||
|
utils::Encode::<checkout::PaymentCaptureRequest>::convert_and_encode(req)
|
||||||
|
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||||
|
Ok(Some(checkout_req))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_request(
|
||||||
|
&self,
|
||||||
|
req: &types::PaymentsCaptureRouterData,
|
||||||
|
connectors: &settings::Connectors,
|
||||||
|
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||||
|
Ok(Some(
|
||||||
|
services::RequestBuilder::new()
|
||||||
|
.method(services::Method::Post)
|
||||||
|
.url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
|
||||||
|
.headers(types::PaymentsCaptureType::get_headers(
|
||||||
|
self, req, connectors,
|
||||||
|
)?)
|
||||||
|
.body(types::PaymentsCaptureType::get_request_body(self, req)?)
|
||||||
|
.build(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_response(
|
||||||
|
&self,
|
||||||
|
data: &types::PaymentsCaptureRouterData,
|
||||||
|
res: types::Response,
|
||||||
|
) -> CustomResult<types::PaymentsCaptureRouterData, errors::ConnectorError> {
|
||||||
|
let response: checkout::PaymentCaptureResponse = res
|
||||||
|
.response
|
||||||
|
.parse_struct("CaptureResponse")
|
||||||
|
.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<types::ErrorResponse, errors::ConnectorError> {
|
||||||
|
let response: checkout::ErrorResponse = res
|
||||||
|
.parse_struct("ErrorResponse")
|
||||||
|
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||||
|
Ok(types::ErrorResponse {
|
||||||
|
code: response
|
||||||
|
.error_codes
|
||||||
|
.unwrap_or_else(|| vec![consts::NO_ERROR_CODE.to_string()])
|
||||||
|
.join(" & "),
|
||||||
|
message: response
|
||||||
|
.error_type
|
||||||
|
.unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
|
||||||
|
reason: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl
|
impl
|
||||||
|
|||||||
@ -276,6 +276,7 @@ pub struct PaymentVoidResponse {
|
|||||||
action_id: String,
|
action_id: String,
|
||||||
reference: String,
|
reference: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&PaymentVoidResponse> for enums::AttemptStatus {
|
impl From<&PaymentVoidResponse> for enums::AttemptStatus {
|
||||||
fn from(item: &PaymentVoidResponse) -> Self {
|
fn from(item: &PaymentVoidResponse) -> Self {
|
||||||
if item.status == 202 {
|
if item.status == 202 {
|
||||||
@ -316,6 +317,69 @@ impl TryFrom<&types::PaymentsCancelRouterData> for PaymentVoidRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub enum CaptureType {
|
||||||
|
Final,
|
||||||
|
NonFinal,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct PaymentCaptureRequest {
|
||||||
|
pub amount: Option<i64>,
|
||||||
|
pub capture_type: Option<CaptureType>,
|
||||||
|
pub processing_channel_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&types::PaymentsCaptureRouterData> for PaymentCaptureRequest {
|
||||||
|
type Error = error_stack::Report<errors::ConnectorError>;
|
||||||
|
fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
|
||||||
|
let connector_auth = &item.connector_auth_type;
|
||||||
|
let auth_type: CheckoutAuthType = connector_auth.try_into()?;
|
||||||
|
let processing_channel_id = auth_type.processing_channel_id;
|
||||||
|
Ok(Self {
|
||||||
|
amount: item.request.amount_to_capture,
|
||||||
|
capture_type: Some(CaptureType::Final),
|
||||||
|
processing_channel_id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct PaymentCaptureResponse {
|
||||||
|
pub action_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<types::PaymentsCaptureResponseRouterData<PaymentCaptureResponse>>
|
||||||
|
for types::PaymentsCaptureRouterData
|
||||||
|
{
|
||||||
|
type Error = error_stack::Report<errors::ParsingError>;
|
||||||
|
fn try_from(
|
||||||
|
item: types::PaymentsCaptureResponseRouterData<PaymentCaptureResponse>,
|
||||||
|
) -> Result<Self, Self::Error> {
|
||||||
|
let (status, amount_captured) = if item.http_code == 202 {
|
||||||
|
(
|
||||||
|
enums::AttemptStatus::Charged,
|
||||||
|
item.data.request.amount_to_capture,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(enums::AttemptStatus::Pending, None)
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||||
|
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||||
|
item.data.request.connector_transaction_id.to_owned(),
|
||||||
|
),
|
||||||
|
redirect: false,
|
||||||
|
redirection_data: None,
|
||||||
|
mandate_reference: None,
|
||||||
|
}),
|
||||||
|
status,
|
||||||
|
amount_captured,
|
||||||
|
..item.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct RefundRequest {
|
pub struct RefundRequest {
|
||||||
amount: Option<i64>,
|
amount: Option<i64>,
|
||||||
|
|||||||
@ -463,6 +463,8 @@ impl<F: Clone> TryFrom<PaymentData<F>> for types::PaymentsCaptureData {
|
|||||||
.payment_attempt
|
.payment_attempt
|
||||||
.connector_transaction_id
|
.connector_transaction_id
|
||||||
.ok_or(errors::ApiErrorResponse::MerchantConnectorAccountNotFound)?,
|
.ok_or(errors::ApiErrorResponse::MerchantConnectorAccountNotFound)?,
|
||||||
|
currency: payment_data.currency,
|
||||||
|
amount: payment_data.amount.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,8 @@ pub type PaymentsSyncResponseRouterData<R> =
|
|||||||
ResponseRouterData<api::PSync, R, PaymentsSyncData, PaymentsResponseData>;
|
ResponseRouterData<api::PSync, R, PaymentsSyncData, PaymentsResponseData>;
|
||||||
pub type PaymentsSessionResponseRouterData<R> =
|
pub type PaymentsSessionResponseRouterData<R> =
|
||||||
ResponseRouterData<api::Session, R, PaymentsSessionData, PaymentsResponseData>;
|
ResponseRouterData<api::Session, R, PaymentsSessionData, PaymentsResponseData>;
|
||||||
|
pub type PaymentsCaptureResponseRouterData<R> =
|
||||||
|
ResponseRouterData<api::Capture, R, PaymentsCaptureData, PaymentsResponseData>;
|
||||||
|
|
||||||
pub type RefundsResponseRouterData<F, R> =
|
pub type RefundsResponseRouterData<F, R> =
|
||||||
ResponseRouterData<F, R, RefundsData, RefundsResponseData>;
|
ResponseRouterData<F, R, RefundsData, RefundsResponseData>;
|
||||||
@ -112,6 +114,8 @@ pub struct PaymentsAuthorizeData {
|
|||||||
pub struct PaymentsCaptureData {
|
pub struct PaymentsCaptureData {
|
||||||
pub amount_to_capture: Option<i64>,
|
pub amount_to_capture: Option<i64>,
|
||||||
pub connector_transaction_id: String,
|
pub connector_transaction_id: String,
|
||||||
|
pub currency: storage_enums::Currency,
|
||||||
|
pub amount: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@ -56,6 +56,8 @@ pub trait ConnectorActions: Connector {
|
|||||||
payment_data.unwrap_or(types::PaymentsCaptureData {
|
payment_data.unwrap_or(types::PaymentsCaptureData {
|
||||||
amount_to_capture: Some(100),
|
amount_to_capture: Some(100),
|
||||||
connector_transaction_id: transaction_id,
|
connector_transaction_id: transaction_id,
|
||||||
|
currency: enums::Currency::USD,
|
||||||
|
amount: 100,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
call_connector(request, integration).await
|
call_connector(request, integration).await
|
||||||
|
|||||||
Reference in New Issue
Block a user