1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! One payment API over any payment provider.
//!
//! Write against [`Provider`] and which provider takes the money becomes a
//! deployment decision rather than a rewrite. Five ship with this workspace —
//! Stripe, iyzico, PayTR, Mollie and PayPal — and a provider that lives
//! elsewhere is a first-class one: implement [`Provider`], name it with
//! [`ProviderId::new`]. Everything a caller needs is re-exported here; the
//! bundled adapters are behind features, one each.
//!
//! ```toml
//! kasapay = { version = "0.0.5", features = ["stripe", "iyzico"] }
//! ```
//!
//! # The one thing to understand first
//!
//! [`Provider::charge`] does not mean the money moved. It returns a [`Charge`]
//! whose [`Status`] is often [`Status::RequiresAction`], with a [`NextAction`]
//! saying what the payer must do — confirm in the browser for Stripe, follow a
//! deep link into iyzico's app for iyzico. Treating a returned `Charge` as a
//! completed payment is the mistake this crate is shaped to prevent.
//!
//! # What the trait answers
//!
//! [`Provider`] is `charge`, `charge_status`, `capture`, `cancel`, `refund`,
//! `lookup` and `instruments`, and [`Capabilities`] says which of them a given
//! provider actually does — before there is a payment to ask about. A
//! capability that says yes and a call that then fails is a bug in the
//! adapter.
//!
//! **Giving money back is [`Provider::refund`]**, which answers a [`Refund`]
//! with its own life: its own identifier where the provider issues one, its
//! own [`RefundStatus`], and at iyzico's counter its own [`NextAction`],
//! because there the payer approves the refund in an app. [`Status`] has no
//! `Refunded` and will not grow one — no provider reports a refund as a
//! payment's status.
//!
//! **The call whose answer never arrived is [`Provider::lookup`]**, keyed by
//! [`OrderRef`] — the caller's own reference, which they had before they sent
//! anything. `Ok(None)` means the provider has no record and the charge can
//! safely be sent again. Two of the five can answer it; the rest say what to
//! do instead.
//!
//! # What arrives without being asked for
//!
//! [`Webhook`] is the second trait: it takes the headers and bytes of a
//! [`Delivery`], shows they are the provider's, and says what they mean as an
//! [`Event`].
//!
//! ```no_run
//! use kasapay::{Delivery, EventKind, Webhook};
//!
//! # async fn handle(verifier: &dyn Webhook, headers: &[(&str, &str)], body: &[u8]) -> &'static str {
//! match verifier.verify(&Delivery::new(headers, body)).await {
//! // The identifier goes into a unique index before anything ships: the
//! // second delivery of an event must collide rather than ship twice.
//! Ok(event) if event.kind == EventKind::Captured => "ship it",
//! // Not an error. A provider adding an event type is normal, and
//! // refusing one earns days of redeliveries for something nobody wanted.
//! Ok(_) => "acknowledged",
//! // Do not act on it — and still answer the provider what the provider
//! // documents. Those are two different questions.
//! Err(_) => "acknowledged",
//! }
//! # }
//! ```
//!
//! # Choosing a provider at runtime
//!
//! ```no_run
//! use std::sync::Arc;
//! use kasapay::{Provider, ProviderId};
//!
//! # #[cfg(all(feature = "stripe", feature = "iyzico"))]
//! # fn pick(
//! # id: ProviderId,
//! # stripe: kasapay::stripe::Stripe,
//! # iyzico: kasapay::iyzico::in_store::Client,
//! # )
//! # -> Option<Arc<dyn Provider>> {
//! match id {
//! ProviderId::STRIPE => Some(Arc::new(stripe)),
//! ProviderId::IYZICO => Some(Arc::new(iyzico)),
//! _ => None,
//! }
//! # }
//! ```
pub use ;
pub use kasapay_iyzico as iyzico;
pub use kasapay_mollie as mollie;
pub use kasapay_paypal as paypal;
pub use kasapay_paytr as paytr;
pub use kasapay_stripe as stripe;