Skip to content

Commit 06dc66c

Browse files
feat(core): Adding integration for webhooks through UCS (#8814)
1 parent ef27ac5 commit 06dc66c

File tree

5 files changed

+898
-321
lines changed

5 files changed

+898
-321
lines changed

crates/external_services/src/grpc_client/unified_connector_service.rs

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use tonic::{
99
};
1010
use unified_connector_service_client::payments::{
1111
self as payments_grpc, payment_service_client::PaymentServiceClient,
12-
PaymentServiceAuthorizeResponse,
12+
PaymentServiceAuthorizeResponse, PaymentServiceTransformRequest,
13+
PaymentServiceTransformResponse,
1314
};
1415

1516
use crate::{
@@ -96,6 +97,10 @@ pub enum UnifiedConnectorServiceError {
9697
/// Failed to perform Payment Repeat Payment from gRPC Server
9798
#[error("Failed to perform Repeat Payment from gRPC Server")]
9899
PaymentRepeatEverythingFailure,
100+
101+
/// Failed to transform incoming webhook from gRPC Server
102+
#[error("Failed to transform incoming webhook from gRPC Server")]
103+
WebhookTransformFailure,
99104
}
100105

101106
/// Result type for Dynamic Routing
@@ -194,6 +199,7 @@ impl UnifiedConnectorServiceClient {
194199
) -> UnifiedConnectorServiceResult<tonic::Response<PaymentServiceAuthorizeResponse>> {
195200
let mut request = tonic::Request::new(payment_authorize_request);
196201

202+
let connector_name = connector_auth_metadata.connector_name.clone();
197203
let metadata =
198204
build_unified_connector_service_grpc_headers(connector_auth_metadata, grpc_headers)?;
199205
*request.metadata_mut() = metadata;
@@ -203,7 +209,14 @@ impl UnifiedConnectorServiceClient {
203209
.authorize(request)
204210
.await
205211
.change_context(UnifiedConnectorServiceError::PaymentAuthorizeFailure)
206-
.inspect_err(|error| logger::error!(?error))
212+
.inspect_err(|error| {
213+
logger::error!(
214+
grpc_error=?error,
215+
method="payment_authorize",
216+
connector_name=?connector_name,
217+
"UCS payment authorize gRPC call failed"
218+
)
219+
})
207220
}
208221

209222
/// Performs Payment Sync/Get
@@ -216,6 +229,7 @@ impl UnifiedConnectorServiceClient {
216229
{
217230
let mut request = tonic::Request::new(payment_get_request);
218231

232+
let connector_name = connector_auth_metadata.connector_name.clone();
219233
let metadata =
220234
build_unified_connector_service_grpc_headers(connector_auth_metadata, grpc_headers)?;
221235
*request.metadata_mut() = metadata;
@@ -225,7 +239,14 @@ impl UnifiedConnectorServiceClient {
225239
.get(request)
226240
.await
227241
.change_context(UnifiedConnectorServiceError::PaymentGetFailure)
228-
.inspect_err(|error| logger::error!(?error))
242+
.inspect_err(|error| {
243+
logger::error!(
244+
grpc_error=?error,
245+
method="payment_get",
246+
connector_name=?connector_name,
247+
"UCS payment get/sync gRPC call failed"
248+
)
249+
})
229250
}
230251

231252
/// Performs Payment Setup Mandate
@@ -238,6 +259,7 @@ impl UnifiedConnectorServiceClient {
238259
{
239260
let mut request = tonic::Request::new(payment_register_request);
240261

262+
let connector_name = connector_auth_metadata.connector_name.clone();
241263
let metadata =
242264
build_unified_connector_service_grpc_headers(connector_auth_metadata, grpc_headers)?;
243265
*request.metadata_mut() = metadata;
@@ -247,7 +269,14 @@ impl UnifiedConnectorServiceClient {
247269
.register(request)
248270
.await
249271
.change_context(UnifiedConnectorServiceError::PaymentRegisterFailure)
250-
.inspect_err(|error| logger::error!(?error))
272+
.inspect_err(|error| {
273+
logger::error!(
274+
grpc_error=?error,
275+
method="payment_setup_mandate",
276+
connector_name=?connector_name,
277+
"UCS payment setup mandate gRPC call failed"
278+
)
279+
})
251280
}
252281

253282
/// Performs Payment repeat (MIT - Merchant Initiated Transaction).
@@ -261,6 +290,7 @@ impl UnifiedConnectorServiceClient {
261290
> {
262291
let mut request = tonic::Request::new(payment_repeat_request);
263292

293+
let connector_name = connector_auth_metadata.connector_name.clone();
264294
let metadata =
265295
build_unified_connector_service_grpc_headers(connector_auth_metadata, grpc_headers)?;
266296
*request.metadata_mut() = metadata;
@@ -270,7 +300,43 @@ impl UnifiedConnectorServiceClient {
270300
.repeat_everything(request)
271301
.await
272302
.change_context(UnifiedConnectorServiceError::PaymentRepeatEverythingFailure)
273-
.inspect_err(|error| logger::error!(?error))
303+
.inspect_err(|error| {
304+
logger::error!(
305+
grpc_error=?error,
306+
method="payment_repeat",
307+
connector_name=?connector_name,
308+
"UCS payment repeat gRPC call failed"
309+
)
310+
})
311+
}
312+
313+
/// Transforms incoming webhook through UCS
314+
pub async fn transform_incoming_webhook(
315+
&self,
316+
webhook_transform_request: PaymentServiceTransformRequest,
317+
connector_auth_metadata: ConnectorAuthMetadata,
318+
grpc_headers: GrpcHeaders,
319+
) -> UnifiedConnectorServiceResult<tonic::Response<PaymentServiceTransformResponse>> {
320+
let mut request = tonic::Request::new(webhook_transform_request);
321+
322+
let connector_name = connector_auth_metadata.connector_name.clone();
323+
let metadata =
324+
build_unified_connector_service_grpc_headers(connector_auth_metadata, grpc_headers)?;
325+
*request.metadata_mut() = metadata;
326+
327+
self.client
328+
.clone()
329+
.transform(request)
330+
.await
331+
.change_context(UnifiedConnectorServiceError::WebhookTransformFailure)
332+
.inspect_err(|error| {
333+
logger::error!(
334+
grpc_error=?error,
335+
method="transform_incoming_webhook",
336+
connector_name=?connector_name,
337+
"UCS webhook transform gRPC call failed"
338+
)
339+
})
274340
}
275341
}
276342

@@ -318,17 +384,18 @@ pub fn build_unified_connector_service_grpc_headers(
318384
parse(common_utils_consts::X_MERCHANT_ID, meta.merchant_id.peek())?,
319385
);
320386

321-
grpc_headers.tenant_id
322-
.parse()
323-
.map(|tenant_id| {
324-
metadata.append(
325-
common_utils_consts::TENANT_HEADER,
326-
tenant_id)
327-
})
328-
.inspect_err(
329-
|err| logger::warn!(header_parse_error=?err,"invalid {} received",common_utils_consts::TENANT_HEADER),
330-
)
331-
.ok();
387+
if let Err(err) = grpc_headers
388+
.tenant_id
389+
.parse()
390+
.map(|tenant_id| metadata.append(common_utils_consts::TENANT_HEADER, tenant_id))
391+
{
392+
logger::error!(
393+
header_parse_error=?err,
394+
tenant_id=?grpc_headers.tenant_id,
395+
"Failed to parse tenant_id header for UCS gRPC request: {}",
396+
common_utils_consts::TENANT_HEADER
397+
);
398+
}
332399

333400
Ok(metadata)
334401
}

crates/router/src/core/payments/helpers.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4188,6 +4188,15 @@ impl MerchantConnectorAccountType {
41884188
Self::CacheVal(_) => None,
41894189
}
41904190
}
4191+
4192+
pub fn get_webhook_details(
4193+
&self,
4194+
) -> CustomResult<Option<&masking::Secret<serde_json::Value>>, errors::ApiErrorResponse> {
4195+
match self {
4196+
Self::DbVal(db_val) => Ok(db_val.connector_webhook_details.as_ref()),
4197+
Self::CacheVal(_) => Ok(None),
4198+
}
4199+
}
41914200
}
41924201

41934202
/// Query for merchant connector account either by business label or profile id

0 commit comments

Comments
 (0)