|
|
|
|
@ -37,13 +37,18 @@ public class StripeController : Controller
@@ -37,13 +37,18 @@ public class StripeController : Controller
|
|
|
|
|
{ |
|
|
|
|
if (!CoreHelpers.FixedTimeEquals(key, _billingSettings.StripeWebhookKey)) |
|
|
|
|
{ |
|
|
|
|
_logger.LogError("Stripe webhook key does not match configured webhook key"); |
|
|
|
|
return new BadRequestResult(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var parsedEvent = await TryParseEventFromRequestBodyAsync(); |
|
|
|
|
if (parsedEvent is null) |
|
|
|
|
{ |
|
|
|
|
return Ok(); |
|
|
|
|
return Ok(new |
|
|
|
|
{ |
|
|
|
|
Processed = false, |
|
|
|
|
Message = "Could not find a configured webhook secret to process this event with" |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (StripeConfiguration.ApiVersion != parsedEvent.ApiVersion) |
|
|
|
|
@ -54,7 +59,11 @@ public class StripeController : Controller
@@ -54,7 +59,11 @@ public class StripeController : Controller
|
|
|
|
|
parsedEvent.ApiVersion, |
|
|
|
|
StripeConfiguration.ApiVersion); |
|
|
|
|
|
|
|
|
|
return new OkResult(); |
|
|
|
|
return Ok(new |
|
|
|
|
{ |
|
|
|
|
Processed = false, |
|
|
|
|
Message = "SDK API version does not match the event's API version" |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(parsedEvent?.Id)) |
|
|
|
|
@ -72,11 +81,19 @@ public class StripeController : Controller
@@ -72,11 +81,19 @@ public class StripeController : Controller
|
|
|
|
|
// If the customer and server cloud regions don't match, early return 200 to avoid unnecessary errors |
|
|
|
|
if (!await _stripeEventService.ValidateCloudRegion(parsedEvent)) |
|
|
|
|
{ |
|
|
|
|
return new OkResult(); |
|
|
|
|
return Ok(new |
|
|
|
|
{ |
|
|
|
|
Processed = false, |
|
|
|
|
Message = "Event is not for this cloud region" |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
await _stripeEventProcessor.ProcessEventAsync(parsedEvent); |
|
|
|
|
return Ok(); |
|
|
|
|
return Ok(new |
|
|
|
|
{ |
|
|
|
|
Processed = true, |
|
|
|
|
Message = "Processed" |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
@ -89,19 +106,49 @@ public class StripeController : Controller
@@ -89,19 +106,49 @@ public class StripeController : Controller
|
|
|
|
|
/// </returns> |
|
|
|
|
private string PickStripeWebhookSecret(string webhookBody) |
|
|
|
|
{ |
|
|
|
|
var versionContainer = JsonSerializer.Deserialize<StripeWebhookVersionContainer>(webhookBody); |
|
|
|
|
var deliveryContainer = JsonSerializer.Deserialize<StripeWebhookDeliveryContainer>(webhookBody); |
|
|
|
|
|
|
|
|
|
_logger.LogInformation( |
|
|
|
|
"Picking secret for Stripe webhook | {EventID}: {EventType} | Version: {APIVersion} | Initiating Request ID: {RequestID}", |
|
|
|
|
deliveryContainer.Id, |
|
|
|
|
deliveryContainer.Type, |
|
|
|
|
deliveryContainer.ApiVersion, |
|
|
|
|
deliveryContainer.Request?.Id); |
|
|
|
|
|
|
|
|
|
return versionContainer.ApiVersion switch |
|
|
|
|
return deliveryContainer.ApiVersion switch |
|
|
|
|
{ |
|
|
|
|
"2023-10-16" => _billingSettings.StripeWebhookSecret20231016, |
|
|
|
|
"2022-08-01" => _billingSettings.StripeWebhookSecret, |
|
|
|
|
_ => HandleDefault(versionContainer.ApiVersion) |
|
|
|
|
"2024-06-20" => HandleVersionWith(_billingSettings.StripeWebhookSecret20240620), |
|
|
|
|
"2023-10-16" => HandleVersionWith(_billingSettings.StripeWebhookSecret20231016), |
|
|
|
|
"2022-08-01" => HandleVersionWith(_billingSettings.StripeWebhookSecret), |
|
|
|
|
_ => HandleDefault(deliveryContainer.ApiVersion) |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
string HandleVersionWith(string secret) |
|
|
|
|
{ |
|
|
|
|
if (string.IsNullOrEmpty(secret)) |
|
|
|
|
{ |
|
|
|
|
_logger.LogError("No webhook secret is configured for API version {APIVersion}", deliveryContainer.ApiVersion); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!secret.StartsWith("whsec_")) |
|
|
|
|
{ |
|
|
|
|
_logger.LogError("Webhook secret configured for API version {APIVersion} does not start with whsec_", |
|
|
|
|
deliveryContainer.ApiVersion); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var truncatedSecret = secret[..10]; |
|
|
|
|
|
|
|
|
|
_logger.LogInformation("Picked webhook secret {TruncatedSecret}... for API version {APIVersion}", truncatedSecret, deliveryContainer.ApiVersion); |
|
|
|
|
|
|
|
|
|
return secret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string HandleDefault(string version) |
|
|
|
|
{ |
|
|
|
|
_logger.LogWarning( |
|
|
|
|
"Stripe webhook contained an recognized 'api_version': {ApiVersion}", |
|
|
|
|
"Stripe webhook contained an API version ({APIVersion}) we do not process", |
|
|
|
|
version); |
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
@ -121,22 +168,13 @@ public class StripeController : Controller
@@ -121,22 +168,13 @@ public class StripeController : Controller
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(webhookSecret)) |
|
|
|
|
{ |
|
|
|
|
_logger.LogDebug("Unable to parse event. No webhook secret."); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var parsedEvent = EventUtility.ConstructEvent( |
|
|
|
|
return EventUtility.ConstructEvent( |
|
|
|
|
json, |
|
|
|
|
Request.Headers["Stripe-Signature"], |
|
|
|
|
webhookSecret, |
|
|
|
|
throwOnApiVersionMismatch: false); |
|
|
|
|
|
|
|
|
|
if (parsedEvent is not null) |
|
|
|
|
{ |
|
|
|
|
return parsedEvent; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_logger.LogDebug("Stripe-Signature request header doesn't match configured Stripe webhook secret"); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|