sepa 0.1.0

SEPA payment utilities: IBAN validation (ISO 13616), BIC validation (ISO 9362), pain.008 direct-debit XML builder, pain.001 credit-transfer XML builder, and CAMT.054 notification types (ISO 20022). Zero I/O. No async. No domain assumptions.
Documentation

sepa

Crates.io Docs.rs CI License MSRV

Pure SEPA payment utilities for Rust.
Zero I/O. No async. No domain assumptions. No f64 in monetary arithmetic.


Features

Module What it provides
iban IBAN validation — ISO 13616 mod-97 algorithm
bic BIC validation — ISO 9362 format rules
pain008 pain.008.003.02 XML builder — SEPA Core Direct Debit (Lastschrift)
pain001 pain.001.003.03 XML builder — SEPA Credit Transfer (Überweisung)
camt054 Typed CAMT.054 entry — Bank-to-Customer Notification (ISO 20022)
ct_to_eur_str Integer-safe i64 ct → "1234.56" formatter, no f64

Quick start

[dependencies]
sepa = "0.1"
use sepa::{validate_iban, validate_bic, Pain008Builder, Pain001Builder};
use sepa::{DirectDebitEntry, CreditTransferEntry, SequenceType};

let iban = validate_iban("DE89 3704 0044 0532 0130 00").unwrap();
assert_eq!(iban.as_str(), "DE89370400440532013000");

// pain.008 — Direct Debit (Lastschrift)
let dd_xml = Pain008Builder::new("Creditor GmbH", &iban)
    .msg_id("DD-2026-07-001")
    .add_entry(DirectDebitEntry {
        mandate_ref: "MND-001".to_owned(),
        mandate_signed_at: "2024-06-01".to_owned(),
        sequence_type: SequenceType::Rcur,
        debtor_name: "Max Mustermann".to_owned(),
        debtor_iban: validate_iban("NL91ABNA0417164300").unwrap(),
        debtor_bic: None,
        amount_ct: 7_500,           // 75.00 EUR
        end_to_end_id: "E2E-001".to_owned(),
        description: Some("Abschlag Juli 2026".to_owned()),
    })
    .build_xml();

// pain.001 — Credit Transfer (Überweisung)
let ct_xml = Pain001Builder::new("Debtor GmbH", &iban)
    .msg_id("CT-2026-07-001")
    .add_entry(CreditTransferEntry {
        creditor_name: "Supplier AG".to_owned(),
        creditor_iban: validate_iban("NL91ABNA0417164300").unwrap(),
        creditor_bic: None,
        amount_ct: 12_000,          // 120.00 EUR
        end_to_end_id: "REFUND-001".to_owned(),
        description: Some("Erstattung 2025".to_owned()),
    })
    .build_xml();

CAMT.054 (json feature)

sepa = { version = "0.1", features = ["json"] }
use sepa::camt054::parse_simple_json;

let raw = serde_json::json!({
    "iban": "DE89370400440532013000",
    "amount_eur": "155.42",
    "reference": "Invoice-001",
    "date": "2026-07-10"
});

let entry = parse_simple_json(&raw).unwrap();
assert_eq!(entry.amount_ct, 15_542);
assert_eq!(entry.to_ledger_ct(), -15_542); // credit → negative in open-items

Standards

Standard Module
ISO 13616-1 iban
ISO 9362 bic
ISO 20022 pain.001.003.03 pain001
ISO 20022 pain.008.003.02 pain008
ISO 20022 camt.054 camt054
EPC SEPA Core Rulebook all

License

Licensed under either of MIT or Apache-2.0, at your option.