Skip to content

Commit 285bf8e

Browse files
committed
Merge remote-tracking branch 'origin/main' into 7852-chore-remove-billing-details-are-required-fields-from-worldpay
2 parents 3a0fa2c + eabef32 commit 285bf8e

File tree

51 files changed

+5091
-14726
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+5091
-14726
lines changed

Cargo.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api-reference-v2/openapi_spec.json

Lines changed: 12 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -20357,82 +20357,6 @@
2035720357
}
2035820358
}
2035920359
},
20360-
"RefundRequest": {
20361-
"type": "object",
20362-
"required": [
20363-
"payment_id"
20364-
],
20365-
"properties": {
20366-
"payment_id": {
20367-
"type": "string",
20368-
"description": "The payment id against which refund is to be initiated",
20369-
"example": "pay_mbabizu24mvu3mela5njyhpit4",
20370-
"maxLength": 30,
20371-
"minLength": 30
20372-
},
20373-
"refund_id": {
20374-
"type": "string",
20375-
"description": "Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment. If this is not passed by the merchant, this field shall be auto generated and provided in the API response. It is recommended to generate uuid(v4) as the refund_id.",
20376-
"example": "ref_mbabizu24mvu3mela5njyhpit4",
20377-
"nullable": true,
20378-
"maxLength": 30,
20379-
"minLength": 30
20380-
},
20381-
"merchant_id": {
20382-
"type": "string",
20383-
"description": "The identifier for the Merchant Account",
20384-
"example": "y3oqhf46pyzuxjbcn2giaqnb44",
20385-
"nullable": true,
20386-
"maxLength": 255
20387-
},
20388-
"amount": {
20389-
"type": "integer",
20390-
"format": "int64",
20391-
"description": "Total amount for which the refund is to be initiated. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, this will default to the full payment amount",
20392-
"example": 6540,
20393-
"nullable": true,
20394-
"minimum": 100
20395-
},
20396-
"reason": {
20397-
"type": "string",
20398-
"description": "Reason for the refund. Often useful for displaying to users and your customer support executive. In case the payment went through Stripe, this field needs to be passed with one of these enums: `duplicate`, `fraudulent`, or `requested_by_customer`",
20399-
"example": "Customer returned the product",
20400-
"nullable": true,
20401-
"maxLength": 255
20402-
},
20403-
"refund_type": {
20404-
"allOf": [
20405-
{
20406-
"$ref": "#/components/schemas/RefundType"
20407-
}
20408-
],
20409-
"default": "Instant",
20410-
"nullable": true
20411-
},
20412-
"metadata": {
20413-
"type": "object",
20414-
"description": "You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.",
20415-
"nullable": true
20416-
},
20417-
"merchant_connector_details": {
20418-
"allOf": [
20419-
{
20420-
"$ref": "#/components/schemas/MerchantConnectorDetailsWrap"
20421-
}
20422-
],
20423-
"nullable": true
20424-
},
20425-
"split_refunds": {
20426-
"allOf": [
20427-
{
20428-
"$ref": "#/components/schemas/SplitRefund"
20429-
}
20430-
],
20431-
"nullable": true
20432-
}
20433-
},
20434-
"additionalProperties": false
20435-
},
2043620360
"RefundResponse": {
2043720361
"type": "object",
2043820362
"required": [
@@ -20535,7 +20459,7 @@
2053520459
},
2053620460
"RefundType": {
2053720461
"type": "string",
20538-
"description": "To indicate whether to refund needs to be instant or scheduled",
20462+
"description": "To indicate whether the refund needs to be instant or scheduled",
2053920463
"enum": [
2054020464
"scheduled",
2054120465
"instant"
@@ -20562,7 +20486,8 @@
2056220486
"RefundsCreateRequest": {
2056320487
"type": "object",
2056420488
"required": [
20565-
"payment_id"
20489+
"payment_id",
20490+
"merchant_reference_id"
2056620491
],
2056720492
"properties": {
2056820493
"payment_id": {
@@ -20574,11 +20499,17 @@
2057420499
},
2057520500
"merchant_reference_id": {
2057620501
"type": "string",
20577-
"description": "Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment.",
20502+
"description": "Unique Identifier for the Refund given by the Merchant.",
2057820503
"example": "ref_mbabizu24mvu3mela5njyhpit4",
20504+
"maxLength": 64,
20505+
"minLength": 1
20506+
},
20507+
"merchant_id": {
20508+
"type": "string",
20509+
"description": "The identifier for the Merchant Account",
20510+
"example": "y3oqhf46pyzuxjbcn2giaqnb44",
2057920511
"nullable": true,
20580-
"maxLength": 30,
20581-
"minLength": 30
20512+
"maxLength": 255
2058220513
},
2058320514
"amount": {
2058420515
"type": "integer",
Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::time;
2-
31
#[inline]
42
pub async fn record_operation_time<F, R, T>(
53
future: F,
@@ -11,7 +9,7 @@ where
119
F: futures::Future<Output = R>,
1210
T: ToString,
1311
{
14-
let (result, time) = time_future(future).await;
12+
let (result, time) = common_utils::metrics::utils::time_future(future).await;
1513
let attributes = router_env::metric_attributes!(
1614
("metric_name", metric_name.to_string()),
1715
("source", source.to_string()),
@@ -22,14 +20,3 @@ where
2220
router_env::logger::debug!("Attributes: {:?}, Time: {}", attributes, value);
2321
result
2422
}
25-
26-
#[inline]
27-
pub async fn time_future<F, R>(future: F) -> (R, time::Duration)
28-
where
29-
F: futures::Future<Output = R>,
30-
{
31-
let start = time::Instant::now();
32-
let result = future.await;
33-
let time_spent = start.elapsed();
34-
(result, time_spent)
35-
}

crates/api_models/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ olap = []
1717
openapi = ["common_enums/openapi", "olap", "recon", "dummy_connector", "olap"]
1818
recon = []
1919
v1 = ["common_utils/v1"]
20-
v2 = ["common_types/v2", "common_utils/v2", "customer_v2"]
20+
v2 = ["common_types/v2", "common_utils/v2", "customer_v2", "refunds_v2"]
2121
customer_v2 = ["common_utils/customer_v2"]
2222
payment_methods_v2 = ["common_utils/payment_methods_v2"]
23+
refunds_v2 = []
2324
dynamic_routing = []
2425
control_center_theme = ["dep:actix-web", "dep:actix-multipart"]
2526
revenue_recovery = []

crates/api_models/src/events/refund.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use common_utils::events::{ApiEventMetric, ApiEventsType};
22

3+
#[cfg(feature = "v1")]
4+
use crate::refunds::RefundRequest;
5+
#[cfg(feature = "v2")]
6+
use crate::refunds::RefundsCreateRequest;
37
use crate::refunds::{
48
RefundAggregateResponse, RefundListFilters, RefundListMetaData, RefundListRequest,
5-
RefundListResponse, RefundManualUpdateRequest, RefundRequest, RefundResponse,
6-
RefundUpdateRequest, RefundsRetrieveRequest,
9+
RefundListResponse, RefundManualUpdateRequest, RefundResponse, RefundUpdateRequest,
10+
RefundsRetrieveRequest,
711
};
812

913
#[cfg(feature = "v1")]
@@ -19,6 +23,13 @@ impl ApiEventMetric for RefundRequest {
1923
}
2024
}
2125

26+
#[cfg(feature = "v2")]
27+
impl ApiEventMetric for RefundsCreateRequest {
28+
fn get_api_event_type(&self) -> Option<ApiEventsType> {
29+
None
30+
}
31+
}
32+
2233
#[cfg(feature = "v1")]
2334
impl ApiEventMetric for RefundResponse {
2435
fn get_api_event_type(&self) -> Option<ApiEventsType> {

crates/api_models/src/refunds.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
enums,
1313
};
1414

15+
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "refunds_v2")))]
1516
#[derive(Default, Debug, ToSchema, Clone, Deserialize, Serialize)]
1617
#[serde(deny_unknown_fields)]
1718
pub struct RefundRequest {
@@ -61,7 +62,7 @@ pub struct RefundRequest {
6162
pub split_refunds: Option<common_types::refunds::SplitRefund>,
6263
}
6364

64-
#[cfg(feature = "v2")]
65+
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
6566
#[derive(Debug, ToSchema, Clone, Deserialize, Serialize)]
6667
#[serde(deny_unknown_fields)]
6768
pub struct RefundsCreateRequest {
@@ -74,14 +75,18 @@ pub struct RefundsCreateRequest {
7475
)]
7576
pub payment_id: common_utils::id_type::GlobalPaymentId,
7677

77-
/// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment.
78+
/// Unique Identifier for the Refund given by the Merchant.
7879
#[schema(
79-
max_length = 30,
80-
min_length = 30,
80+
max_length = 64,
81+
min_length = 1,
8182
example = "ref_mbabizu24mvu3mela5njyhpit4",
82-
value_type = Option<String>,
83+
value_type = String,
8384
)]
84-
pub merchant_reference_id: Option<common_utils::id_type::RefundReferenceId>,
85+
pub merchant_reference_id: common_utils::id_type::RefundReferenceId,
86+
87+
/// The identifier for the Merchant Account
88+
#[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = Option<String>)]
89+
pub merchant_id: Option<common_utils::id_type::MerchantId>,
8590

8691
/// Total amount for which the refund is to be initiated. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., If not provided, this will default to the amount_captured of the payment
8792
#[schema(value_type = Option<i64> , minimum = 100, example = 6540)]
@@ -153,6 +158,7 @@ pub struct RefundManualUpdateRequest {
153158
pub error_message: Option<String>,
154159
}
155160

161+
#[cfg(feature = "v1")]
156162
/// To indicate whether to refund needs to be instant or scheduled
157163
#[derive(
158164
Default, Debug, Clone, Copy, ToSchema, Deserialize, Serialize, Eq, PartialEq, strum::Display,
@@ -164,6 +170,18 @@ pub enum RefundType {
164170
Instant,
165171
}
166172

173+
#[cfg(feature = "v2")]
174+
/// To indicate whether the refund needs to be instant or scheduled
175+
#[derive(
176+
Default, Debug, Clone, Copy, ToSchema, Deserialize, Serialize, Eq, PartialEq, strum::Display,
177+
)]
178+
#[serde(rename_all = "snake_case")]
179+
pub enum RefundType {
180+
Scheduled,
181+
#[default]
182+
Instant,
183+
}
184+
167185
#[cfg(feature = "v1")]
168186
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
169187
pub struct RefundResponse {

crates/common_utils/src/types.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,6 +1204,14 @@ impl ConnectorTransactionId {
12041204
}
12051205
}
12061206

1207+
/// Implementation for extracting hashed data
1208+
pub fn extract_hashed_data(&self) -> Option<String> {
1209+
match self {
1210+
Self::TxnId(_) => None,
1211+
Self::HashedData(src) => Some(src.clone()),
1212+
}
1213+
}
1214+
12071215
/// Implementation for retrieving
12081216
pub fn get_txn_id<'a>(
12091217
&'a self,

crates/diesel_models/src/business_profile.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,25 @@ pub struct CardTestingGuardConfig {
641641

642642
common_utils::impl_to_sql_from_sql_json!(CardTestingGuardConfig);
643643

644+
impl Default for CardTestingGuardConfig {
645+
fn default() -> Self {
646+
Self {
647+
is_card_ip_blocking_enabled: common_utils::consts::DEFAULT_CARD_IP_BLOCKING_STATUS,
648+
card_ip_blocking_threshold: common_utils::consts::DEFAULT_CARD_IP_BLOCKING_THRESHOLD,
649+
is_guest_user_card_blocking_enabled:
650+
common_utils::consts::DEFAULT_GUEST_USER_CARD_BLOCKING_STATUS,
651+
guest_user_card_blocking_threshold:
652+
common_utils::consts::DEFAULT_GUEST_USER_CARD_BLOCKING_THRESHOLD,
653+
is_customer_id_blocking_enabled:
654+
common_utils::consts::DEFAULT_CUSTOMER_ID_BLOCKING_STATUS,
655+
customer_id_blocking_threshold:
656+
common_utils::consts::DEFAULT_CUSTOMER_ID_BLOCKING_THRESHOLD,
657+
card_testing_guard_expiry:
658+
common_utils::consts::DEFAULT_CARD_TESTING_GUARD_EXPIRY_IN_SECS,
659+
}
660+
}
661+
}
662+
644663
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression)]
645664
#[diesel(sql_type = diesel::sql_types::Json)]
646665
pub struct WebhookDetails {

crates/diesel_models/src/query/payment_attempt.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,29 @@ impl PaymentAttempt {
161161
.ok_or(report!(DatabaseError::NotFound))
162162
}
163163

164+
#[cfg(feature = "v2")]
165+
pub async fn find_last_successful_or_partially_captured_attempt_by_payment_id(
166+
conn: &PgPooledConn,
167+
payment_id: &common_utils::id_type::GlobalPaymentId,
168+
) -> StorageResult<Self> {
169+
// perform ordering on the application level instead of database level
170+
generics::generic_filter::<<Self as HasTable>::Table, _, _, Self>(
171+
conn,
172+
dsl::payment_id.eq(payment_id.to_owned()).and(
173+
dsl::status
174+
.eq(enums::AttemptStatus::Charged)
175+
.or(dsl::status.eq(enums::AttemptStatus::PartialCharged)),
176+
),
177+
Some(1),
178+
None,
179+
Some(dsl::modified_at.desc()),
180+
)
181+
.await?
182+
.into_iter()
183+
.nth(0)
184+
.ok_or(report!(DatabaseError::NotFound))
185+
}
186+
164187
#[cfg(feature = "v1")]
165188
pub async fn find_by_merchant_id_connector_txn_id(
166189
conn: &PgPooledConn,

crates/diesel_models/src/query/refund.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,26 @@ impl Refund {
170170
)
171171
.await
172172
}
173+
174+
pub async fn find_by_merchant_id_connector_transaction_id(
175+
conn: &PgPooledConn,
176+
merchant_id: &common_utils::id_type::MerchantId,
177+
connector_transaction_id: &str,
178+
) -> StorageResult<Vec<Self>> {
179+
generics::generic_filter::<
180+
<Self as HasTable>::Table,
181+
_,
182+
<<Self as HasTable>::Table as Table>::PrimaryKey,
183+
_,
184+
>(
185+
conn,
186+
dsl::merchant_id
187+
.eq(merchant_id.to_owned())
188+
.and(dsl::connector_transaction_id.eq(connector_transaction_id.to_owned())),
189+
None,
190+
None,
191+
None,
192+
)
193+
.await
194+
}
173195
}

0 commit comments

Comments
 (0)