lnbits_rs/api/
webhook.rs

1//! Webhook
2
3use axum::extract::State;
4use axum::http::StatusCode;
5use axum::routing::post;
6use axum::{Json, Router};
7use serde_json::Value;
8
9use crate::api::invoice::FindInvoiceResponse;
10use crate::LNBitsClient;
11
12/// Webhook state
13#[derive(Debug, Clone)]
14pub struct WebhookState {
15    /// Sender
16    pub sender: tokio::sync::mpsc::Sender<String>,
17}
18
19impl LNBitsClient {
20    /// Create invoice webhook
21    pub async fn create_invoice_webhook_router(
22        &self,
23        webhook_endpoint: &str,
24        sender: tokio::sync::mpsc::Sender<String>,
25    ) -> anyhow::Result<Router> {
26        let state = WebhookState { sender };
27
28        let router = Router::new()
29            .route(webhook_endpoint, post(handle_invoice))
30            .with_state(state);
31
32        Ok(router)
33    }
34}
35
36async fn handle_invoice(
37    State(state): State<WebhookState>,
38    Json(payload): Json<Value>,
39) -> Result<StatusCode, StatusCode> {
40    let webhook_response: FindInvoiceResponse =
41        serde_json::from_value(payload.clone()).map_err(|_err| {
42            log::warn!("Got an invalid payload on webhook");
43            log::debug!("Value: {}", payload);
44
45            StatusCode::UNPROCESSABLE_ENTITY
46        })?;
47
48    log::debug!(
49        "Received webhook update for: {}",
50        webhook_response.checking_id
51    );
52
53    if let Err(err) = state.sender.send(webhook_response.checking_id).await {
54        log::warn!("Could not send on channel: {}", err);
55    }
56
57    Ok(StatusCode::OK)
58}