Skip to content

Commit 91ff74e

Browse files
tsdk02claudehyperswitch-bot[bot]Gnanasundari24
authored
feat(platform): support platform-aware outgoing webhook delivery (#11643)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: Gnanasundari24 <118818938+Gnanasundari24@users.noreply.github.com>
1 parent df822c3 commit 91ff74e

39 files changed

Lines changed: 1923 additions & 431 deletions

File tree

api-reference/v1/openapi_spec_v1.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20324,6 +20324,12 @@
2032420324
"example": "evt_018e31720d1b7a2b82677d3032cab959",
2032520325
"maxLength": 64
2032620326
},
20327+
"processor_merchant_id": {
20328+
"type": "string",
20329+
"description": "The identifier for the Processor Merchant Account.",
20330+
"nullable": true,
20331+
"maxLength": 64
20332+
},
2032720333
"created": {
2032820334
"type": "string",
2032920335
"format": "date-time",
@@ -26754,7 +26760,7 @@
2675426760
"properties": {
2675526761
"merchant_id": {
2675626762
"type": "string",
26757-
"description": "The merchant id of the merchant"
26763+
"description": "The provider merchant id (platform/business owner)"
2675826764
},
2675926765
"event_id": {
2676026766
"type": "string",
@@ -26770,6 +26776,11 @@
2677026776
"type": "string",
2677126777
"format": "date-time",
2677226778
"description": "The time at which webhook was sent"
26779+
},
26780+
"processor_merchant_id": {
26781+
"type": "string",
26782+
"description": "The merchant id of the merchant account whose connector credentials are used for payment processing",
26783+
"nullable": true
2677326784
}
2677426785
}
2677526786
},

api-reference/v2/openapi_spec_v2.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13948,6 +13948,12 @@
1394813948
"example": "evt_018e31720d1b7a2b82677d3032cab959",
1394913949
"maxLength": 64
1395013950
},
13951+
"processor_merchant_id": {
13952+
"type": "string",
13953+
"description": "The identifier for the Processor Merchant Account.",
13954+
"nullable": true,
13955+
"maxLength": 64
13956+
},
1395113957
"created": {
1395213958
"type": "string",
1395313959
"format": "date-time",
@@ -19784,7 +19790,7 @@
1978419790
"properties": {
1978519791
"merchant_id": {
1978619792
"type": "string",
19787-
"description": "The merchant id of the merchant"
19793+
"description": "The provider merchant id (platform/business owner)"
1978819794
},
1978919795
"event_id": {
1979019796
"type": "string",
@@ -19800,6 +19806,11 @@
1980019806
"type": "string",
1980119807
"format": "date-time",
1980219808
"description": "The time at which webhook was sent"
19809+
},
19810+
"processor_merchant_id": {
19811+
"type": "string",
19812+
"description": "The merchant id of the merchant account whose connector credentials are used for payment processing",
19813+
"nullable": true
1980319814
}
1980419815
}
1980519816
},

crates/analytics/docs/clickhouse/scripts/outgoing_webhook_events.sql

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ CREATE TABLE outgoing_webhook_events_queue (
1616
`initial_attempt_id` Nullable(String),
1717
`status_code` Nullable(UInt16),
1818
`delivery_attempt` LowCardinality(String),
19-
`created_at_timestamp` DateTime64(3)
19+
`created_at_timestamp` DateTime64(3),
20+
`processor_merchant_id` Nullable(String),
21+
`initiator_merchant_id` Nullable(String)
2022
) ENGINE = Kafka SETTINGS kafka_broker_list = 'kafka0:29092',
2123
kafka_topic_list = 'hyperswitch-outgoing-webhook-events',
2224
kafka_group_name = 'hyper',
@@ -43,6 +45,8 @@ CREATE TABLE outgoing_webhook_events (
4345
`delivery_attempt` LowCardinality(String),
4446
`created_at` DateTime64(3),
4547
`inserted_at` DateTime DEFAULT now() CODEC(T64, LZ4),
48+
`processor_merchant_id` Nullable(String),
49+
`initiator_merchant_id` Nullable(String),
4650
INDEX eventIndex event_type TYPE bloom_filter GRANULARITY 1,
4751
INDEX webhookeventIndex outgoing_webhook_event_type TYPE bloom_filter GRANULARITY 1
4852
) ENGINE = MergeTree PARTITION BY toStartOfDay(created_at)
@@ -73,7 +77,9 @@ CREATE TABLE outgoing_webhook_events_audit (
7377
`status_code` Nullable(UInt16),
7478
`delivery_attempt` LowCardinality(String),
7579
`created_at` DateTime64(3),
76-
`inserted_at` DateTime DEFAULT now() CODEC(T64, LZ4)
80+
`inserted_at` DateTime DEFAULT now() CODEC(T64, LZ4),
81+
`processor_merchant_id` Nullable(String),
82+
`initiator_merchant_id` Nullable(String)
7783
) ENGINE = MergeTree PARTITION BY merchant_id
7884
ORDER BY
7985
(merchant_id, payment_id) TTL inserted_at + toIntervalMonth(18) SETTINGS index_granularity = 8192;
@@ -118,7 +124,9 @@ CREATE MATERIALIZED VIEW outgoing_webhook_events_mv TO outgoing_webhook_events (
118124
`status_code` Nullable(UInt16),
119125
`delivery_attempt` LowCardinality(String),
120126
`created_at` DateTime64(3),
121-
`inserted_at` DateTime DEFAULT now() CODEC(T64, LZ4)
127+
`inserted_at` DateTime DEFAULT now() CODEC(T64, LZ4),
128+
`processor_merchant_id` Nullable(String),
129+
`initiator_merchant_id` Nullable(String)
122130
) AS
123131
SELECT
124132
merchant_id,
@@ -139,7 +147,9 @@ SELECT
139147
status_code,
140148
delivery_attempt,
141149
created_at_timestamp AS created_at,
142-
now() AS inserted_at
150+
now() AS inserted_at,
151+
processor_merchant_id,
152+
initiator_merchant_id
143153
FROM
144154
outgoing_webhook_events_queue
145155
WHERE
@@ -163,7 +173,9 @@ CREATE MATERIALIZED VIEW outgoing_webhook_events_audit_mv TO outgoing_webhook_ev
163173
`status_code` Nullable(UInt16),
164174
`delivery_attempt` LowCardinality(String),
165175
`created_at` DateTime64(3),
166-
`inserted_at` DateTime DEFAULT now() CODEC(T64, LZ4)
176+
`inserted_at` DateTime DEFAULT now() CODEC(T64, LZ4),
177+
`processor_merchant_id` Nullable(String),
178+
`initiator_merchant_id` Nullable(String)
167179
) AS
168180
SELECT
169181
merchant_id,
@@ -183,7 +195,9 @@ SELECT
183195
status_code,
184196
delivery_attempt,
185197
created_at_timestamp AS created_at,
186-
now() AS inserted_at
198+
now() AS inserted_at,
199+
processor_merchant_id,
200+
initiator_merchant_id
187201
FROM
188202
outgoing_webhook_events_queue
189203
WHERE
@@ -249,4 +263,4 @@ SELECT
249263
FROM
250264
outgoing_webhook_events_queue
251265
WHERE
252-
length(_error) > 0;
266+
length(_error) > 0;

crates/analytics/src/outgoing_webhook_event/events.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub struct OutgoingWebhookLogsResult {
9797
pub content: Option<String>,
9898
pub is_error: bool,
9999
pub error: Option<String>,
100+
pub initiator_merchant_id: Option<common_utils::id_type::MerchantId>,
100101
#[serde(with = "common_utils::custom_serde::iso8601")]
101102
pub created_at: PrimitiveDateTime,
102103
}

crates/api_models/src/webhook_events.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ pub struct EventListItemResponse {
9595
#[schema(max_length = 64, example = "evt_018e31720d1b7a2b82677d3032cab959")]
9696
pub initial_attempt_id: String,
9797

98+
/// The identifier for the Processor Merchant Account.
99+
#[schema(max_length = 64, value_type = Option<String>)]
100+
pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
101+
98102
/// Time at which the event was created.
99103
#[schema(example = "2022-09-10T10:11:12Z")]
100104
#[serde(with = "common_utils::custom_serde::iso8601")]

crates/api_models/src/webhooks.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ pub struct PayoutWebhookUpdate {
443443

444444
#[derive(Debug, Serialize, ToSchema)]
445445
pub struct OutgoingWebhook {
446-
/// The merchant id of the merchant
446+
/// The provider merchant id (platform/business owner)
447447
#[schema(value_type = String)]
448448
pub merchant_id: common_utils::id_type::MerchantId,
449449

@@ -460,6 +460,10 @@ pub struct OutgoingWebhook {
460460
/// The time at which webhook was sent
461461
#[serde(default, with = "custom_serde::iso8601")]
462462
pub timestamp: PrimitiveDateTime,
463+
464+
/// The merchant id of the merchant account whose connector credentials are used for payment processing
465+
#[schema(value_type = Option<String>)]
466+
pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
463467
}
464468

465469
#[derive(Debug, Clone, Serialize, ToSchema)]

crates/common_utils/src/types.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,19 @@ impl_enum_str!(
14591459
}
14601460
);
14611461

1462+
impl CreatedBy {
1463+
/// Returns `true` if the creator is the provider (platform) merchant, i.e. an API-triggered
1464+
/// creation whose `merchant_id` matches `provider_merchant_id`.
1465+
pub fn is_provider_initiated(&self, provider_merchant_id: &id_type::MerchantId) -> bool {
1466+
match self {
1467+
Self::Api { merchant_id } => id_type::MerchantId::wrap(merchant_id.clone())
1468+
.map(|parsed_merchant_id| parsed_merchant_id == *provider_merchant_id)
1469+
.unwrap_or_default(),
1470+
Self::Jwt { .. } | Self::Invalid | Self::EmbeddedToken { .. } => false,
1471+
}
1472+
}
1473+
}
1474+
14621475
/// Trait for enums created with `impl_enum_str!` macro that have an `Invalid` variant.
14631476
/// This trait allows generic functions to check if a parsed enum value is invalid.
14641477
pub trait HasInvalidVariant {

crates/diesel_models/src/events.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ pub struct EventNew {
2727
pub delivery_attempt: Option<storage_enums::WebhookDeliveryAttempt>,
2828
pub metadata: Option<EventMetadata>,
2929
pub is_overall_delivery_successful: Option<bool>,
30+
pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
31+
pub initiator_merchant_id: Option<common_utils::id_type::MerchantId>,
3032
}
3133

3234
#[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)]
@@ -60,6 +62,8 @@ pub struct Event {
6062
pub delivery_attempt: Option<storage_enums::WebhookDeliveryAttempt>,
6163
pub metadata: Option<EventMetadata>,
6264
pub is_overall_delivery_successful: Option<bool>,
65+
pub processor_merchant_id: Option<common_utils::id_type::MerchantId>,
66+
pub initiator_merchant_id: Option<common_utils::id_type::MerchantId>,
6367
}
6468

6569
#[derive(Clone, Debug, Deserialize, Serialize, AsExpression, diesel::FromSqlRow)]

0 commit comments

Comments
 (0)