Skip to content

Commit

Permalink
Added support for the remaining BTCPay web hook events
Browse files Browse the repository at this point in the history
  • Loading branch information
blakejakopovic committed May 11, 2023
1 parent bf5bb8d commit d5eeb9e
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 48 deletions.
35 changes: 31 additions & 4 deletions examples/btcpay/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ use serde_json::Value;
async fn webhook_handler(pg_pool: &PGPool, payload: WebhookPayload) -> Result<()> {
match payload {

// Triggers when an invoice is considered settled and the merchant can proceed with the order's delivery. The
// invoice now has enough confirmations on the blockchain (if paid on-chain) according to your store's configuration.
// Triggers when an invoice is considered settled and the merchant can proceed with the order's
// delivery. The invoice now has enough confirmations on the blockchain (if paid on-chain) according
// to your store's configuration.
WebhookPayload::InvoiceSettled(event) => {
debug!("InvoiceSettled Event: {event:?}");

Expand Down Expand Up @@ -67,8 +68,8 @@ async fn webhook_handler(pg_pool: &PGPool, payload: WebhookPayload) -> Result<()
// .map_err(|_| ServiceError::InternalError)?;

// // Extract what we need to update the database
// // Note: Since we are populating the posData values in BTCPay server, we can skip validation here - unless
// // you are risk adverse.
// // Note: Since we are populating the posData values in BTCPay server, we can skip validation
// // here - unless you are risk adverse.
// let pubkey = pos_data.get("pubkey").ok_or(ServiceError::InternalError)?.to_string();
// let content_id = pos_data.get("content_id").ok_or(ServiceError::InternalError)?.to_string();

Expand Down Expand Up @@ -147,6 +148,32 @@ async fn webhook_handler(pg_pool: &PGPool, payload: WebhookPayload) -> Result<()
Ok(())
},

// An invoice expired
WebhookPayload::InvoiceExpired(event) => {
debug!("InvoiceExpired Event: {event:?}");
Ok(())
},

// An invoice became invalid
WebhookPayload::InvoiceInvalid(event) => {
debug!("InvoiceInvalid Event: {event:?}");
Ok(())
},

// Triggers when an invoice is fully paid, but doesn't have the required amount of confirmations
// on the blockchain yet according to your store's settings.
WebhookPayload::InvoiceProcessing(event) => {
debug!("InvoiceProcessing Event: {event:?}");
Ok(())
},

// A new invoice has been created
WebhookPayload::InvoiceCreated(event) => {
debug!("InvoiceCreated Event: {event:?}");
Ok(())
},

// Any unhandled webhook events - return ok, as we don't have any logic for them yet
WebhookPayload::Unsupported => {
debug!("Unsupported Event");
Ok(())
Expand Down
70 changes: 29 additions & 41 deletions src/btcpay/btcpay_models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,6 @@ pub struct WebhookInvoiceSettledEvent {
pub over_paid: Option<bool>,
}

impl WebhookInvoiceSettledEvent {
/// Callback sent if the `type` is `InvoiceSettled`
pub fn new() -> WebhookInvoiceSettledEvent {
WebhookInvoiceSettledEvent {
delivery_id: None,
webhook_id: None,
original_delivery_id: None,
is_redelivery: None,
_type: None,
timestamp: None,
store_id: None,
invoice_id: None,
metadata: None,
manually_marked: None,
over_paid: None,
}
}
}

#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
pub struct InvoiceMetadata {
/// You can use this property to store the ID of an external system. We allow you to search in the invoice list based on this ID.
Expand Down Expand Up @@ -97,26 +78,33 @@ pub struct InvoiceMetadata {
pub tax_included: Option<f32>,
}

impl InvoiceMetadata {
/// Additional information around the invoice that can be supplied. The mentioned properties are all optional and you can introduce any json format you wish.
pub fn new() -> InvoiceMetadata {
InvoiceMetadata {
order_id: None,
order_url: None,
pos_data: None,
buyer_name: None,
buyer_email: None,
buyer_country: None,
buyer_zip: None,
buyer_state: None,
buyer_city: None,
buyer_address1: None,
buyer_address2: None,
buyer_phone: None,
item_desc: None,
item_code: None,
physical: None,
tax_included: None,
}
}
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
pub struct WebhookInvoiceCreatedEvent {
/// The delivery id of the webhook
#[serde(rename = "deliveryId", skip_serializing_if = "Option::is_none")]
pub delivery_id: Option<String>,
/// The id of the webhook
#[serde(rename = "webhookId", skip_serializing_if = "Option::is_none")]
pub webhook_id: Option<String>,
/// If this delivery is a redelivery, the is the delivery id of the original delivery.
#[serde(rename = "originalDeliveryId", skip_serializing_if = "Option::is_none")]
pub original_delivery_id: Option<String>,
/// True if this delivery is a redelivery
#[serde(rename = "isRedelivery", skip_serializing_if = "Option::is_none")]
pub is_redelivery: Option<bool>,
/// The type of this event, which is always "InvoiceCreated" for this struct
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub _type: Option<String>,
/// The timestamp when this delivery has been created
#[serde(rename = "timestamp", skip_serializing_if = "Option::is_none")]
pub timestamp: Option<i64>,
/// The store id of the invoice's event
#[serde(rename = "storeId", skip_serializing_if = "Option::is_none")]
pub store_id: Option<String>,
/// The invoice id of the invoice's event
#[serde(rename = "invoiceId", skip_serializing_if = "Option::is_none")]
pub invoice_id: Option<String>,
/// The invoice metadata
#[serde(rename = "metadata", skip_serializing_if = "Option::is_none")]
pub metadata: Option<Box<InvoiceMetadata>>,
}
20 changes: 17 additions & 3 deletions src/btcpay/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@ use serde::{Serialize, Deserialize};
pub mod btcpay_middleware;
pub mod btcpay_models;

// Use our custom type here to support the metadata key and fix physical being a bool, instead of a string
pub use btcpay_models::WebhookInvoiceSettledEvent;
pub use btcpay_client::models::{WebhookInvoicePaymentSettledEvent,WebhookInvoiceReceivedPaymentEvent, InvoiceData};
// Use our custom types here to support the metadata key and fix physical being a bool, instead of a string
pub use btcpay_models::{
WebhookInvoiceSettledEvent,
WebhookInvoiceCreatedEvent
};
pub use btcpay_client::models::{
WebhookInvoicePaymentSettledEvent,
WebhookInvoiceReceivedPaymentEvent,
WebhookInvoiceExpiredEvent,
WebhookInvoiceInvalidEvent,
WebhookInvoiceProcessingEvent,
InvoiceData
};


lazy_static! {
Expand All @@ -23,6 +33,10 @@ pub enum WebhookPayload {
InvoiceSettled(WebhookInvoiceSettledEvent),
InvoicePaymentSettled(WebhookInvoicePaymentSettledEvent),
InvoiceReceivedPayment(WebhookInvoiceReceivedPaymentEvent),
InvoiceExpired(WebhookInvoiceExpiredEvent),
InvoiceInvalid(WebhookInvoiceInvalidEvent),
InvoiceProcessing(WebhookInvoiceProcessingEvent),
InvoiceCreated(WebhookInvoiceCreatedEvent), // Note: Not yet part of btcpay-client crate
Unsupported
}

Expand Down

0 comments on commit d5eeb9e

Please sign in to comment.