snippe 0.1.0

Async Rust client for the Snippe payments API (Tanzania) — collections, hosted checkout sessions, disbursements, and verified webhooks.
Documentation
//! Hosted checkout sessions — `/api/v1/sessions`.

use crate::client::{encode_path_segment, Client};
use crate::idempotency::IdempotencyKey;
use crate::models::common::ListParams;
use crate::models::session::{CreateSessionRequest, Session};

/// Handle returned by [`Client::sessions`](crate::Client::sessions).
#[derive(Debug, Clone, Copy)]
pub struct Sessions<'c> {
    client: &'c Client,
}

impl<'c> Sessions<'c> {
    pub(crate) fn new(client: &'c Client) -> Self {
        Self { client }
    }

    /// Create a hosted-checkout session — `POST /api/v1/sessions`.
    ///
    /// The response includes both `checkout_url` (for embedding / WebView)
    /// and `payment_link_url` (short vanity URL for SMS / WhatsApp). Prefer
    /// `payment_link_url` for any URL the customer will see or read aloud.
    pub async fn create(
        &self,
        request: &CreateSessionRequest,
        idempotency_key: Option<&IdempotencyKey>,
    ) -> crate::Result<Session> {
        let mut req = self.client.post("/api/v1/sessions").json(request);
        if let Some(k) = idempotency_key {
            req = req.idempotency_key(k);
        }
        req.send().await
    }

    /// Retrieve a session by reference — `GET /api/v1/sessions/{reference}`.
    pub async fn get(&self, reference: &str) -> crate::Result<Session> {
        self.client
            .get(&format!(
                "/api/v1/sessions/{}",
                encode_path_segment(reference)
            ))
            .send()
            .await
    }

    /// List sessions — `GET /api/v1/sessions`.
    pub async fn list(&self, params: &ListParams) -> crate::Result<Vec<Session>> {
        self.client
            .get("/api/v1/sessions")
            .query(params)
            .send()
            .await
    }

    /// Cancel a session — `POST /api/v1/sessions/{reference}/cancel`.
    ///
    /// Only valid for sessions in `pending` or `active` status. Cancelling an
    /// already-`completed` session returns a state-conflict error.
    pub async fn cancel(&self, reference: &str) -> crate::Result<Session> {
        self.client
            .post(&format!(
                "/api/v1/sessions/{}/cancel",
                encode_path_segment(reference)
            ))
            .send()
            .await
    }
}