From 4acec068aad885a17bf4f09d759884e1ce4bfea2 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 8 Sep 2022 05:32:46 -0400 Subject: [PATCH] asdhfahsdf --- .../http_endpoints/stripe_webhook_handler.rs | 72 ++++++++++++++++--- .../customer/customer_created_handler.rs | 22 ++++++ .../customer/customer_deleted_handler.rs | 22 ++++++ .../customer/customer_updated_handler.rs | 22 ++++++ .../webhook_event_handlers/customer/mod.rs | 3 + .../{ => invoice}/invoice_paid_handler.rs | 4 +- .../invoice/invoice_payment_failed.rs | 26 +++++++ .../invoice_payment_succeeded_handler.rs | 26 +++++++ .../webhook_event_handlers/invoice/mod.rs | 3 + .../src/stripe/webhook_event_handlers/mod.rs | 3 +- 10 files changed, 190 insertions(+), 13 deletions(-) create mode 100644 crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_created_handler.rs create mode 100644 crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_deleted_handler.rs create mode 100644 crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_updated_handler.rs create mode 100644 crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/mod.rs rename crates/component_subsystem/billing/src/stripe/webhook_event_handlers/{ => invoice}/invoice_paid_handler.rs (94%) create mode 100644 crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_payment_failed.rs create mode 100644 crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_payment_succeeded_handler.rs create mode 100644 crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/mod.rs diff --git a/crates/component_subsystem/billing/src/stripe/http_endpoints/stripe_webhook_handler.rs b/crates/component_subsystem/billing/src/stripe/http_endpoints/stripe_webhook_handler.rs index 6679074330..efce4d72d3 100644 --- a/crates/component_subsystem/billing/src/stripe/http_endpoints/stripe_webhook_handler.rs +++ b/crates/component_subsystem/billing/src/stripe/http_endpoints/stripe_webhook_handler.rs @@ -6,9 +6,14 @@ use actix_web::{web, HttpResponse, HttpRequest}; use chrono::{DateTime, Utc}; use crate::stripe::stripe_config::StripeConfig; use crate::stripe::webhook_event_handlers::checkout_session_completed_handler::checkout_session_completed_handler; +use crate::stripe::webhook_event_handlers::customer::customer_created_handler::customer_created_handler; +use crate::stripe::webhook_event_handlers::customer::customer_updated_handler::customer_updated_handler; use crate::stripe::webhook_event_handlers::customer_subscription::customer_subscription_created_handler::customer_subscription_created_handler; +use crate::stripe::webhook_event_handlers::customer_subscription::customer_subscription_deleted_handler::customer_subscription_deleted_handler; use crate::stripe::webhook_event_handlers::customer_subscription::customer_subscription_updated_handler::customer_subscription_updated_handler; -use crate::stripe::webhook_event_handlers::invoice_paid_handler::invoice_paid_handler; +use crate::stripe::webhook_event_handlers::invoice::invoice_paid_handler::invoice_paid_handler; +use crate::stripe::webhook_event_handlers::invoice::invoice_payment_failed::invoice_payment_failed_handler; +use crate::stripe::webhook_event_handlers::invoice::invoice_payment_succeeded_handler::invoice_payment_succeeded_handler; use crate::stripe::webhook_event_handlers::stripe_webhook_error::StripeWebhookError; use http_server_common::request::get_request_header_optional::get_request_header_optional; use http_server_common::response::serialize_as_json_error::serialize_as_json_error; @@ -18,7 +23,7 @@ use sqlx::MySqlPool; use std::collections::HashMap; use std::fmt; use stripe::{EventObject, EventType, PaymentIntentStatus, Webhook}; -use crate::stripe::webhook_event_handlers::customer_subscription::customer_subscription_deleted_handler::customer_subscription_deleted_handler; +use crate::stripe::webhook_event_handlers::customer::customer_deleted_handler::customer_deleted_handler; #[derive(Serialize)] pub struct StripeWebhookSuccessResponse { @@ -58,18 +63,18 @@ pub async fn stripe_webhook_handler( // // CustomerSubscriptionCreated ------ // CustomerSubscriptionUpdated ------- + // InvoicePaymentSucceeded + // CustomerCreated + // CustomerUpdated // // Events seen (not yet handled): // // CheckoutSessionCompleted // ChargeSucceeded // PaymentMethodAttached - // CustomerCreated - // CustomerUpdated // InvoiceCreated // InvoiceFinalized // InvoiceUpdated - // InvoicePaymentSucceeded // PaymentIntentSucceeded // PaymentIntentCreated @@ -99,6 +104,28 @@ pub async fn stripe_webhook_handler( } } + // EventType::CheckoutSessionExpired + // EventType::CheckoutSessionAsyncPaymentFailed + // EventType::CheckoutSessionAsyncPaymentSucceeded + + // =============== CUSTOMERS =============== + + EventType::CustomerCreated => { + if let EventObject::Customer(customer) = webhook_payload.data.object { + let _r = customer_created_handler(&customer)?; + } + } + EventType::CustomerUpdated => { + if let EventObject::Customer(customer) = webhook_payload.data.object { + let _r = customer_updated_handler(&customer)?; + } + } + EventType::CustomerDeleted => { + if let EventObject::Customer(customer) = webhook_payload.data.object { + let _r = customer_deleted_handler(&customer)?; + } + } + // =============== CUSTOMER SUBSCRIPTIONS =============== EventType::CustomerSubscriptionCreated => { @@ -116,10 +143,9 @@ pub async fn stripe_webhook_handler( let _r = customer_subscription_deleted_handler(&subscription)?; } } - EventType::CustomerSubscriptionPendingUpdateApplied => { - } - EventType::CustomerSubscriptionPendingUpdateExpired => { - } + // EventType::CustomerSubscriptionPendingUpdateApplied + // EventType::CustomerSubscriptionPendingUpdateExpired + // EventType::CustomerSubscriptionTrialWillEnd // =============== INVOICES =============== @@ -127,17 +153,41 @@ pub async fn stripe_webhook_handler( // TODO: We need to respond to this so we don't hold payments up by 72 hours! // See: https://stripe.com/docs/billing/subscriptions/webhooks } + EventType::InvoicePaymentSucceeded => { + if let EventObject::Invoice(invoice) = webhook_payload.data.object { + let _r = invoice_payment_succeeded_handler(&invoice)?; + } + } EventType::InvoicePaid => { if let EventObject::Invoice(invoice) = webhook_payload.data.object { let _r = invoice_paid_handler(&invoice)?; } } + EventType::InvoicePaymentFailed => { + if let EventObject::Invoice(invoice) = webhook_payload.data.object { + let _r = invoice_payment_failed_handler(&invoice)?; + } + } + + // EventType::InvoiceDeleted + // EventType::InvoiceFinalizationFailed + // EventType::InvoiceFinalized + // EventType::InvoiceItemCreated + // EventType::InvoiceItemDeleted + // EventType::InvoiceItemUpdated + // EventType::InvoiceMarkedUncollectible + // EventType::InvoicePaymentActionRequired + // EventType::InvoiceSent + // EventType::InvoiceUpcoming + // EventType::InvoiceUpdated + // EventType::InvoiceVoided + + // =============== PAYMENT INTENTS =============== + EventType::PaymentIntentSucceeded => { if let EventObject::PaymentIntent(payment_intent) = webhook_payload.data.object { } } - EventType::InvoicePaymentFailed => { - } _ => {}, } diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_created_handler.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_created_handler.rs new file mode 100644 index 0000000000..8465b5223e --- /dev/null +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_created_handler.rs @@ -0,0 +1,22 @@ +use container_common::anyhow_result::AnyhowResult; +use crate::stripe::helpers::common_metadata_keys::METADATA_USER_TOKEN; +use crate::stripe::helpers::expand_customer_id::expand_customer_id; +use crate::stripe::webhook_event_handlers::stripe_webhook_error::StripeWebhookError; +use log::warn; +use stripe::Customer; + +// Handle event type: 'customer.created' +pub fn customer_created_handler(customer: &Customer) -> Result<(), StripeWebhookError> { + + // NB: We'll need this to send them to the "customer portal", which is how they can modify + // or cancel their subscriptions. + let customer_id = customer.id.to_string(); + + // NB: Our internal user token. + let maybe_user_token = customer.metadata.get(METADATA_USER_TOKEN) + .map(|t| t.to_string()); + + warn!(">>> customer.created: {:?}, {:?}", customer_id, maybe_user_token); + + Ok(()) +} diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_deleted_handler.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_deleted_handler.rs new file mode 100644 index 0000000000..ec56b16603 --- /dev/null +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_deleted_handler.rs @@ -0,0 +1,22 @@ +use container_common::anyhow_result::AnyhowResult; +use crate::stripe::helpers::common_metadata_keys::METADATA_USER_TOKEN; +use crate::stripe::helpers::expand_customer_id::expand_customer_id; +use crate::stripe::webhook_event_handlers::stripe_webhook_error::StripeWebhookError; +use log::warn; +use stripe::Customer; + +// Handle event type: 'customer.deleted' +pub fn customer_deleted_handler(customer: &Customer) -> Result<(), StripeWebhookError> { + + // NB: We'll need this to send them to the "customer portal", which is how they can modify + // or cancel their subscriptions. + let customer_id = customer.id.to_string(); + + // NB: Our internal user token. + let maybe_user_token = customer.metadata.get(METADATA_USER_TOKEN) + .map(|t| t.to_string()); + + warn!(">>> customer.deleted : {:?}, {:?}", customer_id, maybe_user_token); + + Ok(()) +} diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_updated_handler.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_updated_handler.rs new file mode 100644 index 0000000000..775b118f2b --- /dev/null +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/customer_updated_handler.rs @@ -0,0 +1,22 @@ +use container_common::anyhow_result::AnyhowResult; +use crate::stripe::helpers::common_metadata_keys::METADATA_USER_TOKEN; +use crate::stripe::helpers::expand_customer_id::expand_customer_id; +use crate::stripe::webhook_event_handlers::stripe_webhook_error::StripeWebhookError; +use log::warn; +use stripe::Customer; + +// Handle event type: 'customer.updated' +pub fn customer_updated_handler(customer: &Customer) -> Result<(), StripeWebhookError> { + + // NB: We'll need this to send them to the "customer portal", which is how they can modify + // or cancel their subscriptions. + let customer_id = customer.id.to_string(); + + // NB: Our internal user token. + let maybe_user_token = customer.metadata.get(METADATA_USER_TOKEN) + .map(|t| t.to_string()); + + warn!(">>> customer.updated: {:?}, {:?}", customer_id, maybe_user_token); + + Ok(()) +} diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/mod.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/mod.rs new file mode 100644 index 0000000000..a052e3fd17 --- /dev/null +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/customer/mod.rs @@ -0,0 +1,3 @@ +pub (crate) mod customer_created_handler; +pub (crate) mod customer_deleted_handler; +pub (crate) mod customer_updated_handler; diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice_paid_handler.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_paid_handler.rs similarity index 94% rename from crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice_paid_handler.rs rename to crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_paid_handler.rs index d0306a3570..bb0e1f5b2a 100644 --- a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice_paid_handler.rs +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_paid_handler.rs @@ -5,10 +5,12 @@ use stripe::Invoice; use crate::stripe::helpers::common_metadata_keys::METADATA_USER_TOKEN; use crate::stripe::webhook_event_handlers::stripe_webhook_error::StripeWebhookError; +// Handle event type: 'invoice.paid' +// // https://stripe.com/docs/billing/subscriptions/webhooks : // // Sent when the invoice is successfully paid. You can provision access to your product when you -// receive this event and the subscription status is active. +// receive this event and the subscription `status` is `active`. // // https://stripe.com/docs/billing/subscriptions/webhooks#active-subscriptions : // diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_payment_failed.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_payment_failed.rs new file mode 100644 index 0000000000..f5a3a48960 --- /dev/null +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_payment_failed.rs @@ -0,0 +1,26 @@ +use container_common::anyhow_result::AnyhowResult; +use crate::stripe::helpers::common_metadata_keys::METADATA_USER_TOKEN; +use crate::stripe::helpers::expand_customer_id::expand_customer_id; +use crate::stripe::webhook_event_handlers::stripe_webhook_error::StripeWebhookError; +use log::warn; +use stripe::Invoice; + +// Handle event type: 'invoice.payment_failed' +pub fn invoice_payment_failed_handler(invoice: &Invoice) -> Result<(), StripeWebhookError> { + + let paid_status = invoice.status; + + // NB: We'll need this to send them to the "customer portal", which is how they can modify + // or cancel their subscriptions. + let maybe_stripe_customer_id = invoice.customer + .as_ref() + .map(|c| expand_customer_id(c)); + + // NB: Our internal user token. + let maybe_user_token = invoice.metadata.get(METADATA_USER_TOKEN) + .map(|t| t.to_string()); + + warn!(">>> invoice.payment_failed: {:?}, {:?}, {:?}", paid_status, maybe_stripe_customer_id, maybe_user_token); + + Ok(()) +} diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_payment_succeeded_handler.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_payment_succeeded_handler.rs new file mode 100644 index 0000000000..6946985f49 --- /dev/null +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/invoice_payment_succeeded_handler.rs @@ -0,0 +1,26 @@ +use container_common::anyhow_result::AnyhowResult; +use crate::stripe::helpers::common_metadata_keys::METADATA_USER_TOKEN; +use crate::stripe::helpers::expand_customer_id::expand_customer_id; +use crate::stripe::webhook_event_handlers::stripe_webhook_error::StripeWebhookError; +use log::warn; +use stripe::Invoice; + +// Handle event type: 'invoice.payment_succeeded' +pub fn invoice_payment_succeeded_handler(invoice: &Invoice) -> Result<(), StripeWebhookError> { + + let paid_status = invoice.status; + + // NB: We'll need this to send them to the "customer portal", which is how they can modify + // or cancel their subscriptions. + let maybe_stripe_customer_id = invoice.customer + .as_ref() + .map(|c| expand_customer_id(c)); + + // NB: Our internal user token. + let maybe_user_token = invoice.metadata.get(METADATA_USER_TOKEN) + .map(|t| t.to_string()); + + warn!(">>> invoice.payment_succeeded: {:?}, {:?}, {:?}", paid_status, maybe_stripe_customer_id, maybe_user_token); + + Ok(()) +} diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/mod.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/mod.rs new file mode 100644 index 0000000000..ad4a1eb7eb --- /dev/null +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/invoice/mod.rs @@ -0,0 +1,3 @@ +pub (crate) mod invoice_paid_handler; +pub (crate) mod invoice_payment_failed; +pub (crate) mod invoice_payment_succeeded_handler; diff --git a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/mod.rs b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/mod.rs index 072d6819cb..d444a3ffaa 100644 --- a/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/mod.rs +++ b/crates/component_subsystem/billing/src/stripe/webhook_event_handlers/mod.rs @@ -1,5 +1,6 @@ pub mod stripe_webhook_error; pub (crate) mod checkout_session_completed_handler; +pub (crate) mod customer; pub (crate) mod customer_subscription; -pub (crate) mod invoice_paid_handler; +pub (crate) mod invoice;