Skip to main content

rustlavel_payment/
lib.rs

1//! rustlavel-payment: payment gateways behind one trait.
2//!
3//! An application takes money through a *gateway* — a company that presents a
4//! virtual account number, a QR code or an e-wallet screen to the customer,
5//! collects the payment, and tells the application by webhook. Every gateway
6//! does the same five things and describes them differently, so this crate
7//! holds the description and a driver holds the difference.
8//!
9//! # What crosses the trait
10//!
11//! - [`Money`] — an amount in minor units and a currency. An integer, never a
12//!   float: money that is rounded is money that goes missing.
13//! - [`Channel`] — how the customer pays: a bank's virtual account, QRIS, an
14//!   e-wallet, or a retail counter. The Indonesian set, because that is where
15//!   the first driver lives; the enum is not closed.
16//! - [`Charge`] — a request for payment and its state, with what the customer
17//!   needs to pay it (a VA number, a QR string, a deeplink).
18//! - [`Transfer`] — money out, to a bank account or an e-wallet.
19//! - [`WebhookEvent`] — what a gateway says happened, after its signature has
20//!   been checked.
21//!
22//! # The receiver, and why it deduplicates on disk
23//!
24//! A gateway retries a webhook until it is acknowledged, and a network that
25//! drops the acknowledgement delivers the same payment twice. [`Receiver`]
26//! verifies the signature (each driver knows its own scheme), records the
27//! event by the *gateway's* id, and hands a duplicate straight back as already
28//! handled. That record must survive a restart: a duplicate that arrives after
29//! a deploy is still a duplicate, and crediting it twice is a refund
30//! conversation. So the log is a trait with a table-backed implementation
31//! behind the `db` feature, and the in-memory one is for tests.
32//!
33//! # No driver is invented
34//!
35//! [`FakeGateway`] is the only driver here today. A driver for a real gateway
36//! is written against that gateway's published specification, not from what
37//! its competitors do — an adapter written from guesses is code that looks
38//! finished and fails on the first real callback.
39
40pub mod channel;
41pub mod charge;
42#[cfg(feature = "db")]
43pub mod database;
44pub mod fake;
45pub mod gateway;
46pub mod money;
47pub mod receiver;
48pub mod signature;
49pub mod transfer;
50pub mod webhook;
51
52pub use channel::{Bank, Channel, Retail, Wallet};
53pub use charge::{Charge, ChargeRequest, ChargeStatus, Customer, Instructions};
54pub use fake::FakeGateway;
55pub use gateway::{Gateway, GatewayFuture};
56pub use money::Money;
57pub use receiver::{Handled, Receiver};
58pub use transfer::{Account, Transfer, TransferRequest, TransferStatus};
59pub use webhook::{EventKind, MemoryWebhookLog, WebhookEvent, WebhookLog};
60
61pub use rustlavel_core::{Error, Result};