fix(connector): fix for sending refund_amount in connectors refund request (#1278)

Co-authored-by: Narayan Bhat <48803246+Narayanbhat166@users.noreply.github.com>
This commit is contained in:
Arjun Karthik
2023-06-15 14:06:27 +05:30
committed by GitHub
parent 1e5d2a28f6
commit 016857fff0
15 changed files with 94 additions and 82 deletions

View File

@ -480,7 +480,7 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for BamboraRefundRequest {
type Error = error_stack::Report<errors::ParsingError>;
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
Ok(Self {
amount: item.request.amount,
amount: item.request.refund_amount,
})
}
}

View File

@ -463,7 +463,7 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for ForteRefundRequest {
utils::to_connector_meta(item.request.connector_metadata.clone())?;
let auth_code = connector_auth_id.auth_id;
let authorization_amount =
utils::to_currency_base_unit_asf64(item.request.amount, item.request.currency)?;
utils::to_currency_base_unit_asf64(item.request.refund_amount, item.request.currency)?;
Ok(Self {
action: "reverse".to_string(),
authorization_amount,

View File

@ -352,7 +352,7 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for MollieRefundRequest {
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
let amount = Amount {
currency: item.request.currency,
value: utils::to_currency_base_unit(item.request.amount, item.request.currency)?,
value: utils::to_currency_base_unit(item.request.refund_amount, item.request.currency)?,
};
Ok(Self {
amount,

View File

@ -508,7 +508,7 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for MultisafepayRefundRequest {
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
Ok(Self {
currency: item.request.currency,
amount: item.request.amount,
amount: item.request.refund_amount,
description: item.description.clone(),
refund_order_id: Some(item.request.refund_id.clone()),
checkout_data: None,

View File

@ -1009,7 +1009,7 @@ impl TryFrom<&types::RefundExecuteRouterData> for NuveiPaymentFlowRequest {
Self::try_from(NuveiPaymentRequestData {
client_request_id: item.attempt_id.clone(),
connector_auth_type: item.connector_auth_type.clone(),
amount: item.request.amount.to_string(),
amount: item.request.refund_amount.to_string(),
currency: item.request.currency,
related_transaction_id: Some(item.request.connector_transaction_id.clone()),
..Default::default()

View File

@ -145,7 +145,7 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for OpennodeRefundRequest {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
Ok(Self {
amount: item.request.amount,
amount: item.request.refund_amount,
})
}
}

View File

@ -257,7 +257,7 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for RapydRefundRequest {
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
Ok(Self {
payment: item.request.connector_transaction_id.to_string(),
amount: Some(item.request.amount),
amount: Some(item.request.refund_amount),
currency: Some(item.request.currency),
})
}

View File

@ -885,7 +885,7 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for TrustpayRefundRequest {
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
let amount = format!(
"{:.2}",
utils::to_currency_base_unit(item.request.amount, item.request.currency)?
utils::to_currency_base_unit(item.request.refund_amount, item.request.currency)?
.parse::<f64>()
.into_report()
.change_context(errors::ConnectorError::RequestEncodingFailed)?

View File

@ -171,7 +171,7 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for WorldpayRefundRequest {
Ok(Self {
reference: item.request.connector_transaction_id.clone(),
value: PaymentValue {
amount: item.request.amount,
amount: item.request.refund_amount,
currency: item.request.currency.to_string(),
},
})

View File

@ -52,7 +52,7 @@ pub async fn construct_refund_router_data<'a, F>(
let status = payment_attempt.status;
let (amount, currency) = money;
let (payment_amount, currency) = money;
let payment_method_type = payment_attempt
.payment_method
@ -87,7 +87,7 @@ pub async fn construct_refund_router_data<'a, F>(
connector_transaction_id: refund.connector_transaction_id.clone(),
refund_amount: refund.refund_amount,
currency,
amount,
payment_amount,
webhook_url,
connector_metadata: payment_attempt.connector_metadata.clone(),
reason: refund.refund_reason.clone(),

View File

@ -461,7 +461,7 @@ pub struct RefundsData {
pub connector_refund_id: Option<String>,
pub currency: storage_enums::Currency,
/// Amount for the payment against which this refund is issued
pub amount: i64,
pub payment_amount: i64,
pub reason: Option<String>,
pub webhook_url: Option<String>,
/// Amount to be refunded

View File

@ -98,7 +98,7 @@ fn construct_refund_router_data<F>() -> types::RefundsRouterData<F> {
description: Some("This is a test".to_string()),
return_url: None,
request: types::RefundsData {
amount: 1000,
payment_amount: 1000,
currency: enums::Currency::USD,
refund_id: uuid::Uuid::new_v4().to_string(),

View File

@ -454,28 +454,6 @@ async fn should_sync_refund() {
}
// Cards Negative scenerios
// Creates a payment with incorrect card number.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_card_number() {
let response = CONNECTOR
.make_payment(
Some(types::PaymentsAuthorizeData {
payment_method_data: types::api::PaymentMethodData::Card(api::Card {
card_number: CardNumber::from_str("4111111111111100").unwrap(),
..utils::CCardType::default().0
}),
..utils::PaymentAuthorizeType::default().0
}),
get_default_payment_info(),
)
.await
.unwrap();
assert_eq!(
response.response.unwrap_err().message,
"INVALID CREDIT CARD NUMBER".to_string(),
);
}
// Creates a payment with incorrect CVC.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {

View File

@ -1,11 +1,10 @@
use std::str::FromStr;
use api_models::payments::{Address, AddressDetails};
use masking::Secret;
use router::types::{self, api, storage::enums};
use router::types::{self, api, storage::enums, PaymentAddress};
use crate::{
connector_auth,
utils::{self, ConnectorActions},
utils::{self, ConnectorActions, PaymentInfo},
};
#[derive(Clone, Copy)]
@ -36,28 +35,55 @@ impl utils::Connector for MultisafepayTest {
static CONNECTOR: MultisafepayTest = MultisafepayTest {};
fn get_default_payment_info() -> Option<PaymentInfo> {
let address = Some(PaymentAddress {
shipping: None,
billing: Some(Address {
address: Some(AddressDetails {
first_name: Some(Secret::new("John".to_string())),
last_name: Some(Secret::new("Doe".to_string())),
line1: Some(Secret::new("Kraanspoor".to_string())),
line2: Some(Secret::new("line2".to_string())),
line3: Some(Secret::new("line3".to_string())),
city: Some("Amsterdam".to_string()),
zip: Some(Secret::new("1033SC".to_string())),
country: Some(api_models::enums::CountryAlpha2::NL),
state: Some(Secret::new("Amsterdam".to_string())),
}),
phone: None,
}),
});
Some(PaymentInfo {
address,
..utils::PaymentInfo::default()
})
}
// Cards Positive Tests
// Creates a payment using the manual capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_only_authorize_payment() {
let response = CONNECTOR
.authorize_payment(None, None)
.authorize_payment(None, get_default_payment_info())
.await
.expect("Authorize payment response");
assert_eq!(response.status, enums::AttemptStatus::Authorized);
}
// Captures a payment using the manual capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_capture_authorized_payment() {
let response = CONNECTOR
.authorize_and_capture_payment(None, None, None)
.authorize_and_capture_payment(None, None, get_default_payment_info())
.await
.expect("Capture payment response");
assert_eq!(response.status, enums::AttemptStatus::Charged);
}
// Partially captures a payment using the manual capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_partially_capture_authorized_payment() {
let response = CONNECTOR
@ -67,7 +93,7 @@ async fn should_partially_capture_authorized_payment() {
amount_to_capture: 50,
..utils::PaymentCaptureType::default().0
}),
None,
get_default_payment_info(),
)
.await
.expect("Capture payment response");
@ -75,12 +101,17 @@ async fn should_partially_capture_authorized_payment() {
}
// Synchronizes a payment using the manual capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_sync_authorized_payment() {
let authorize_response = CONNECTOR
.authorize_payment(None, None)
.authorize_payment(None, get_default_payment_info())
.await
.expect("Authorize payment response");
assert_eq!(
authorize_response.status,
enums::AttemptStatus::AuthenticationPending,
);
let txn_id = utils::get_connector_transaction_id(authorize_response.response);
let response = CONNECTOR
.psync_retry_till_status_matches(
@ -99,6 +130,7 @@ async fn should_sync_authorized_payment() {
}
// Voids a payment using the manual capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_void_authorized_payment() {
let response = CONNECTOR
@ -109,7 +141,7 @@ async fn should_void_authorized_payment() {
cancellation_reason: Some("requested_by_customer".to_string()),
..Default::default()
}),
None,
get_default_payment_info(),
)
.await
.expect("Void payment response");
@ -117,10 +149,11 @@ async fn should_void_authorized_payment() {
}
// Refunds a payment using the manual capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_refund_manually_captured_payment() {
let response = CONNECTOR
.capture_payment_and_refund(None, None, None, None)
.capture_payment_and_refund(None, None, None, get_default_payment_info())
.await
.unwrap();
assert_eq!(
@ -130,6 +163,7 @@ async fn should_refund_manually_captured_payment() {
}
// Partially refunds a payment using the manual capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_partially_refund_manually_captured_payment() {
let response = CONNECTOR
@ -140,7 +174,7 @@ async fn should_partially_refund_manually_captured_payment() {
refund_amount: 50,
..utils::PaymentRefundType::default().0
}),
None,
get_default_payment_info(),
)
.await
.unwrap();
@ -151,10 +185,11 @@ async fn should_partially_refund_manually_captured_payment() {
}
// Synchronizes a refund using the manual capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_sync_manually_captured_refund() {
let refund_response = CONNECTOR
.capture_payment_and_refund(None, None, None, None)
.capture_payment_and_refund(None, None, None, get_default_payment_info())
.await
.unwrap();
let response = CONNECTOR
@ -173,16 +208,24 @@ async fn should_sync_manually_captured_refund() {
}
// Creates a payment using the automatic capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_make_payment() {
let authorize_response = CONNECTOR.make_payment(None, None).await.unwrap();
let authorize_response = CONNECTOR
.make_payment(None, get_default_payment_info())
.await
.unwrap();
assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
}
// Synchronizes a payment using the automatic capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_sync_auto_captured_payment() {
let authorize_response = CONNECTOR.make_payment(None, None).await.unwrap();
let authorize_response = CONNECTOR
.make_payment(None, get_default_payment_info())
.await
.unwrap();
assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
let txn_id = utils::get_connector_transaction_id(authorize_response.response);
assert_ne!(txn_id, None, "Empty connector transaction id");
@ -203,10 +246,11 @@ async fn should_sync_auto_captured_payment() {
}
// Refunds a payment using the automatic capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_refund_auto_captured_payment() {
let response = CONNECTOR
.make_payment_and_refund(None, None, None)
.make_payment_and_refund(None, None, get_default_payment_info())
.await
.unwrap();
assert_eq!(
@ -216,6 +260,7 @@ async fn should_refund_auto_captured_payment() {
}
// Partially refunds a payment using the automatic capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_partially_refund_succeeded_payment() {
let refund_response = CONNECTOR
@ -225,7 +270,7 @@ async fn should_partially_refund_succeeded_payment() {
refund_amount: 50,
..utils::PaymentRefundType::default().0
}),
None,
get_default_payment_info(),
)
.await
.unwrap();
@ -236,6 +281,7 @@ async fn should_partially_refund_succeeded_payment() {
}
// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_refund_succeeded_payment_multiple_times() {
CONNECTOR
@ -245,16 +291,17 @@ async fn should_refund_succeeded_payment_multiple_times() {
refund_amount: 50,
..utils::PaymentRefundType::default().0
}),
None,
get_default_payment_info(),
)
.await;
}
// Synchronizes a refund using the automatic capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_sync_refund() {
let refund_response = CONNECTOR
.make_payment_and_refund(None, None, None)
.make_payment_and_refund(None, None, get_default_payment_info())
.await
.unwrap();
let response = CONNECTOR
@ -273,38 +320,20 @@ async fn should_sync_refund() {
}
// Cards Negative scenerios
// Creates a payment with incorrect card number.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_card_number() {
let response = CONNECTOR
.make_payment(
Some(types::PaymentsAuthorizeData {
payment_method_data: types::api::PaymentMethodData::Card(api::Card {
card_number: cards::CardNumber::from_str("37450000000001").unwrap(),
..utils::CCardType::default().0
}),
..utils::PaymentAuthorizeType::default().0
}),
None,
)
.await
.unwrap();
assert!(response.response.is_err());
}
// Creates a payment with incorrect CVC.
#[ignore = "Connector doesn't fail invalid cvv scenario"]
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {
let response = CONNECTOR
.make_payment(
Some(types::PaymentsAuthorizeData {
payment_method_data: types::api::PaymentMethodData::Card(api::Card {
card_cvc: Secret::new("12345".to_string()),
card_cvc: Secret::new("123498765".to_string()),
..utils::CCardType::default().0
}),
..utils::PaymentAuthorizeType::default().0
}),
None,
get_default_payment_info(),
)
.await
.unwrap();
@ -323,7 +352,7 @@ async fn should_fail_payment_for_invalid_exp_month() {
}),
..utils::PaymentAuthorizeType::default().0
}),
None,
get_default_payment_info(),
)
.await
.unwrap();
@ -342,7 +371,7 @@ async fn should_fail_payment_for_incorrect_expiry_year() {
}),
..utils::PaymentAuthorizeType::default().0
}),
None,
get_default_payment_info(),
)
.await
.unwrap();
@ -350,9 +379,13 @@ async fn should_fail_payment_for_incorrect_expiry_year() {
}
// Voids a payment using automatic capture flow (Non 3DS).
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_fail_void_payment_for_auto_capture() {
let authorize_response = CONNECTOR.make_payment(None, None).await.unwrap();
let authorize_response = CONNECTOR
.make_payment(None, get_default_payment_info())
.await
.unwrap();
assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
let txn_id = utils::get_connector_transaction_id(authorize_response.response);
assert_ne!(txn_id, None, "Empty connector transaction id");
@ -370,16 +403,17 @@ async fn should_fail_void_payment_for_auto_capture() {
#[actix_web::test]
async fn should_fail_capture_for_invalid_payment() {
let capture_response = CONNECTOR
.capture_payment("123456789".to_string(), None, None)
.capture_payment("123456789".to_string(), None, get_default_payment_info())
.await
.unwrap();
assert_eq!(
capture_response.response.unwrap_err().message,
String::from("No such payment_intent: '123456789'")
String::from("Something went wrong")
);
}
// Refunds a payment with refund amount higher than payment amount.
#[ignore = "Connector supports only 3ds flow"]
#[actix_web::test]
async fn should_fail_for_refund_amount_higher_than_payment_amount() {
let response = CONNECTOR
@ -389,7 +423,7 @@ async fn should_fail_for_refund_amount_higher_than_payment_amount() {
refund_amount: 150,
..utils::PaymentRefundType::default().0
}),
None,
get_default_payment_info(),
)
.await
.unwrap();

View File

@ -319,7 +319,7 @@ pub trait ConnectorActions: Connector {
let integration = self.get_data().connector.get_connector_integration();
let request = self.generate_data(
payment_data.unwrap_or_else(|| types::RefundsData {
amount: 1000,
payment_amount: 1000,
currency: enums::Currency::USD,
refund_id: uuid::Uuid::new_v4().to_string(),
connector_transaction_id: "".to_string(),
@ -582,7 +582,7 @@ impl Default for PaymentSyncType {
impl Default for PaymentRefundType {
fn default() -> Self {
let data = types::RefundsData {
amount: 100,
payment_amount: 100,
currency: enums::Currency::USD,
refund_id: uuid::Uuid::new_v4().to_string(),
connector_transaction_id: String::new(),