mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 02:01:10 +02:00
💳 feat(stripe): add SEPA Direct Debit payment option
- Add sepa_debit to payment_method_types for credit purchases - Add sepa_debit to subscription checkout sessions - Handle payment_intent.processing webhook for SEPA status tracking - Add blueprint article analyzing payment options (Stripe vs LSV+/FinTS) SEPA offers lower fees (0.8% vs 1.5%+€0.25) for DACH customers. Payments are confirmed 3-14 days after checkout (bank processing).
This commit is contained in:
parent
0e8f6f134e
commit
b5d7524c77
4 changed files with 543 additions and 3 deletions
|
|
@ -0,0 +1,527 @@
|
|||
---
|
||||
title: 'Stripe vs. Direkter Bankeinzug: Payment-Optionen für SaaS'
|
||||
description: 'Analyse der Payment-Möglichkeiten für europäische SaaS-Produkte: Stripe-Integration, Schweizer LSV+, deutsches FinTS/HBCI und SEPA-Lastschrift im Vergleich'
|
||||
date: 2026-02-16
|
||||
author: 'Till Schneider'
|
||||
category: 'business-model'
|
||||
status: 'accepted'
|
||||
tags:
|
||||
[
|
||||
'payments',
|
||||
'stripe',
|
||||
'sepa',
|
||||
'lastschrift',
|
||||
'lsv',
|
||||
'fints',
|
||||
'hbci',
|
||||
'schweiz',
|
||||
'deutschland',
|
||||
'monetarisierung',
|
||||
'saas',
|
||||
'subscriptions',
|
||||
]
|
||||
featured: true
|
||||
readTime: 15
|
||||
decisionDate: 2026-02-16
|
||||
---
|
||||
|
||||
# Stripe vs. Direkter Bankeinzug: Payment-Optionen für SaaS
|
||||
|
||||
Als europäisches SaaS-Unternehmen stellt sich früher oder später die Frage: **Kann man Zahlungen auch ohne Payment-Provider wie Stripe direkt über die Hausbank abwickeln?** Dieser Artikel analysiert die technischen Möglichkeiten, Kosten und Vor-/Nachteile.
|
||||
|
||||
---
|
||||
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
1. [Ausgangssituation](#ausgangssituation)
|
||||
2. [Option 1: Stripe (Status Quo)](#option-1-stripe-status-quo)
|
||||
3. [Option 2: Schweizer Bankeinzug (LSV+)](#option-2-schweizer-bankeinzug-lsv)
|
||||
4. [Option 3: Deutscher Bankeinzug (FinTS/HBCI)](#option-3-deutscher-bankeinzug-fintshbci)
|
||||
5. [Option 4: Stripe SEPA-Lastschrift (Kompromiss)](#option-4-stripe-sepa-lastschrift-kompromiss)
|
||||
6. [Vergleichsmatrix](#vergleichsmatrix)
|
||||
7. [Entscheidung & Empfehlung](#entscheidung--empfehlung)
|
||||
8. [Quellen](#quellen)
|
||||
|
||||
---
|
||||
|
||||
## Ausgangssituation
|
||||
|
||||
ManaCore verwendet aktuell eine umfangreiche **Stripe-Integration** für Monetarisierung:
|
||||
|
||||
### Aktuelles Zwei-Säulen-Modell
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ ManaCore Monetarisierung │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Säule 1: Subscriptions Säule 2: Credits │
|
||||
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
|
||||
│ │ Free €0/Monat │ │ 100 Credits €0.99 │ │
|
||||
│ │ Plus €4.99/Monat │ │ 500 Credits €4.99 │ │
|
||||
│ │ Pro €11.99/Monat │ │ 1000 Credits €8.99 │ │
|
||||
│ │ Ultra €24.99/Monat │ │ 5000 Credits €39.99 │ │
|
||||
│ └─────────────────────────┘ └─────────────────────────┘ │
|
||||
│ │
|
||||
│ + Jahresabos mit ~17% Rabatt + Gift Codes für Gutscheine │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Stripe-Gebühren (aktuell)
|
||||
|
||||
| Zahlungsart | Gebühr | Beispiel €10 |
|
||||
|-------------|--------|--------------|
|
||||
| Kreditkarte (EU) | 1.5% + €0.25 | €0.40 |
|
||||
| Kreditkarte (Non-EU) | 2.9% + €0.25 | €0.54 |
|
||||
| SEPA-Lastschrift | 0.8% (max €5) | €0.08 |
|
||||
|
||||
**Frage:** Können wir diese Gebühren eliminieren, indem wir direkt mit der Hausbank arbeiten?
|
||||
|
||||
---
|
||||
|
||||
## Option 1: Stripe (Status Quo)
|
||||
|
||||
### Vorteile
|
||||
|
||||
| Aspekt | Bewertung |
|
||||
|--------|-----------|
|
||||
| **API-Qualität** | Erstklassige REST-API, SDKs für alle Sprachen |
|
||||
| **Integration** | ~2 Tage für Grundintegration |
|
||||
| **Dokumentation** | Branchenführend, mit Code-Beispielen |
|
||||
| **Compliance** | PCI DSS Level 1, DSGVO-konform |
|
||||
| **Features** | Subscriptions, Invoices, Customer Portal, Webhooks |
|
||||
| **Support** | 24/7, mehrsprachig |
|
||||
|
||||
### Nachteile
|
||||
|
||||
| Aspekt | Bewertung |
|
||||
|--------|-----------|
|
||||
| **Gebühren** | 1.5-2.9% + €0.25 pro Transaktion |
|
||||
| **Abhängigkeit** | Vendor Lock-in (Stripe-spezifische APIs) |
|
||||
| **Kontosperre** | Risiko bei "High-Risk" Kategorien |
|
||||
| **Auszahlung** | 2-7 Tage Verzögerung |
|
||||
|
||||
### Aktuelle Implementation
|
||||
|
||||
```typescript
|
||||
// services/mana-core-auth/src/stripe/stripe.service.ts
|
||||
@Injectable()
|
||||
export class StripeService {
|
||||
private stripe: Stripe;
|
||||
|
||||
constructor(private configService: ConfigService) {
|
||||
this.stripe = new Stripe(configService.get('STRIPE_SECRET_KEY'), {
|
||||
apiVersion: '2025-02-24.acacia',
|
||||
});
|
||||
}
|
||||
|
||||
async createPaymentIntent(customerId: string, amountCents: number) {
|
||||
return this.stripe.paymentIntents.create({
|
||||
amount: amountCents,
|
||||
currency: 'eur',
|
||||
customer: customerId,
|
||||
automatic_payment_methods: { enabled: true },
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Option 2: Schweizer Bankeinzug (LSV+)
|
||||
|
||||
### Was ist LSV+?
|
||||
|
||||
**LSV+ (Lastschriftverfahren)** ist das Schweizer Pendant zur SEPA-Lastschrift. Es ermöglicht Unternehmen, Beträge direkt von Kundenkonten einzuziehen.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ LSV+ Ablauf │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. Kunde unterschreibt 2. Unternehmen erstellt │
|
||||
│ LSV-Mandat (Papier!) XML-Datei (pain.008) │
|
||||
│ │
|
||||
│ 3. Upload via E-Banking 4. SIX Interbank Clearing │
|
||||
│ oder payCOMweb verarbeitet Lastschrift │
|
||||
│ │
|
||||
│ 5. Geld wird eingezogen 6. Kunde kann 30 Tage │
|
||||
│ (T+2 Werktage) widersprechen (LSV+) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Raiffeisen Schweiz: Technische Möglichkeiten
|
||||
|
||||
| Aspekt | Bewertung |
|
||||
|--------|-----------|
|
||||
| **API-Zugang** | Keine moderne REST-API verfügbar |
|
||||
| **Automatisierung** | Nur via ISO-20022 XML-Dateien |
|
||||
| **Schnittstellen** | E-Banking Upload, payCOMweb, Dateitransfer |
|
||||
| **Mandatserteilung** | Handschriftliche Unterschrift erforderlich |
|
||||
| **Gebühren** | ~CHF 0.10-0.50 pro Transaktion |
|
||||
|
||||
### Kritische Einschränkung: Einstellung 2028
|
||||
|
||||
> **LSV+ und Business Direct Debit (BDD) werden am 30. September 2028 eingestellt.**
|
||||
> Ab 2026 werden keine neuen Biller mehr für LSV+/BDD aktiviert.
|
||||
|
||||
Die Schweizer Banken führen stattdessen **eBill Debit Direct** ein (Sommer 2025).
|
||||
|
||||
### Technische Implementation (theoretisch)
|
||||
|
||||
```typescript
|
||||
// ISO-20022 pain.008 XML Generierung
|
||||
function generateSepaDirectDebit(mandate: Mandate, amount: number): string {
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02">
|
||||
<CstmrDrctDbtInitn>
|
||||
<GrpHdr>
|
||||
<MsgId>${generateMessageId()}</MsgId>
|
||||
<CreDtTm>${new Date().toISOString()}</CreDtTm>
|
||||
<NbOfTxs>1</NbOfTxs>
|
||||
<CtrlSum>${amount}</CtrlSum>
|
||||
</GrpHdr>
|
||||
<PmtInf>
|
||||
<PmtInfId>${mandate.id}</PmtInfId>
|
||||
<PmtMtd>DD</PmtMtd>
|
||||
<NbOfTxs>1</NbOfTxs>
|
||||
<CtrlSum>${amount}</CtrlSum>
|
||||
<!-- ... weitere 200+ Zeilen XML ... -->
|
||||
</PmtInf>
|
||||
</CstmrDrctDbtInitn>
|
||||
</Document>`;
|
||||
}
|
||||
|
||||
// Upload zu Bank (manuell oder via SFTP)
|
||||
async function uploadToBank(xmlContent: string) {
|
||||
// Keine API - manueller Upload oder SFTP-Batch
|
||||
throw new Error('Keine automatisierte API verfügbar');
|
||||
}
|
||||
```
|
||||
|
||||
### Fazit Schweiz
|
||||
|
||||
| Pro | Contra |
|
||||
|-----|--------|
|
||||
| Niedrige Transaktionsgebühren | Keine moderne API |
|
||||
| Direkte Bankbeziehung | Papier-Mandate erforderlich |
|
||||
| Keine Drittanbieter-Abhängigkeit | System wird 2028 eingestellt |
|
||||
| | Hoher manueller Aufwand |
|
||||
| | Keine Echtzeit-Webhooks |
|
||||
|
||||
---
|
||||
|
||||
## Option 3: Deutscher Bankeinzug (FinTS/HBCI)
|
||||
|
||||
### Was ist FinTS/HBCI?
|
||||
|
||||
**FinTS (Financial Transaction Services)**, früher HBCI, ist ein bankenübergreifendes Protokoll für Online-Banking in Deutschland. Es wurde von den deutschen Bankenverbänden entwickelt und wird von ~3000 Kreditinstituten unterstützt.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ FinTS/HBCI Architektur │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Deine App FinTS-Library Sparkasse/Bank │
|
||||
│ ┌─────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ NestJS │───────>│ libfintx │──────>│ FinTS 3.0 │ │
|
||||
│ │ Backend │ │ python-fints │ │ Server │ │
|
||||
│ │ │<───────│ Subsembly │<──────│ │ │
|
||||
│ └─────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
│ Authentifizierung: PIN/TAN (chipTAN, smsTAN, pushTAN) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Sparkasse: Technische Möglichkeiten
|
||||
|
||||
| Aspekt | Bewertung |
|
||||
|--------|-----------|
|
||||
| **API-Zugang** | FinTS 3.0 Protokoll (kein REST) |
|
||||
| **Libraries** | libfintx (.NET), python-fints, Subsembly |
|
||||
| **SEPA-Support** | Basislastschrift und Firmenlastschrift |
|
||||
| **TAN-Verfahren** | chipTAN, smsTAN, pushTAN |
|
||||
| **Gebühren** | Je nach Kontomodell, oft ~€0.10-0.30 |
|
||||
|
||||
### Verfügbare Open-Source-Libraries
|
||||
|
||||
```typescript
|
||||
// Option 1: libfintx (.NET)
|
||||
// https://github.com/libfintx/libfintx
|
||||
const client = new FinTsClient({
|
||||
blz: '12345678',
|
||||
userId: 'username',
|
||||
pin: 'pin',
|
||||
url: 'https://banking.sparkasse.de/fints'
|
||||
});
|
||||
|
||||
await client.sepaDirectDebit({
|
||||
iban: 'DE89370400440532013000',
|
||||
bic: 'COBADEFFXXX',
|
||||
amount: 9.99,
|
||||
mandate: mandateReference,
|
||||
});
|
||||
|
||||
// Option 2: python-fints
|
||||
// https://github.com/raphaelm/python-fints
|
||||
```
|
||||
|
||||
### SEPA-Firmenlastschrift vs. Basislastschrift
|
||||
|
||||
| Merkmal | Basislastschrift | Firmenlastschrift |
|
||||
|---------|------------------|-------------------|
|
||||
| **Zielgruppe** | Privatkunden | Firmenkunden |
|
||||
| **Widerspruchsrecht** | 8 Wochen | Keines |
|
||||
| **Vorab-Anzeige** | Nein | Ja (beide Banken) |
|
||||
| **Einsatz** | B2C | B2B |
|
||||
|
||||
### Herausforderungen
|
||||
|
||||
1. **TAN-Pflicht:** Jede Transaktion erfordert TAN-Bestätigung
|
||||
2. **Keine Webhooks:** Polling für Statusupdates erforderlich
|
||||
3. **Komplexes Protokoll:** FinTS ist deutlich komplexer als REST
|
||||
4. **Mandate-Management:** Selbst zu implementieren
|
||||
5. **PSD2-Einschränkungen:** Zugang über Drittanbieter reguliert
|
||||
|
||||
### Drittanbieter: finAPI
|
||||
|
||||
Für eine modernere API gibt es Anbieter wie **finAPI**, die als Middleware zwischen App und Bank fungieren:
|
||||
|
||||
```typescript
|
||||
// finAPI Direct Debit API
|
||||
const response = await fetch('https://api.finapi.io/v1/payments/directDebit', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
accountId: customerAccountId,
|
||||
amount: 9.99,
|
||||
currency: 'EUR',
|
||||
mandateId: mandateReference,
|
||||
executionDate: '2026-02-20',
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
**Aber:** finAPI hat eigene Gebühren und ist selbst ein Payment-Provider.
|
||||
|
||||
### Fazit Deutschland
|
||||
|
||||
| Pro | Contra |
|
||||
|-----|--------|
|
||||
| Etablierter Standard (3000+ Banken) | Komplexes Protokoll |
|
||||
| Open-Source-Libraries verfügbar | TAN für jede Transaktion |
|
||||
| Niedrige Bankgebühren | Kein Echtzeit-Feedback |
|
||||
| Keine Drittanbieter nötig (theoretisch) | PSD2-Regulierung |
|
||||
| | MT-940 wird ab 11/2025 eingestellt |
|
||||
|
||||
---
|
||||
|
||||
## Option 4: Stripe SEPA-Lastschrift (Kompromiss)
|
||||
|
||||
### Der beste beider Welten
|
||||
|
||||
Stripe bietet **SEPA Direct Debit** als Zahlungsmethode an - mit den Vorteilen beider Ansätze:
|
||||
|
||||
```typescript
|
||||
// Minimale Code-Änderung in bestehender Integration
|
||||
const paymentIntent = await stripe.paymentIntents.create({
|
||||
amount: 1199, // €11.99
|
||||
currency: 'eur',
|
||||
payment_method_types: ['sepa_debit'], // Statt 'card'
|
||||
customer: stripeCustomerId,
|
||||
mandate_data: {
|
||||
customer_acceptance: {
|
||||
type: 'online',
|
||||
online: {
|
||||
ip_address: req.ip,
|
||||
user_agent: req.headers['user-agent'],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Gebührenvergleich
|
||||
|
||||
| Zahlungsmethode | Stripe-Gebühr | Bei €10 |
|
||||
|-----------------|---------------|---------|
|
||||
| Kreditkarte (EU) | 1.5% + €0.25 | €0.40 |
|
||||
| SEPA-Lastschrift | 0.8% (max €5) | €0.08 |
|
||||
| **Ersparnis** | | **€0.32 pro Transaktion** |
|
||||
|
||||
Bei 1000 Transaktionen/Monat: **€320 Ersparnis**
|
||||
|
||||
### Vorteile gegenüber direktem Bankeinzug
|
||||
|
||||
| Aspekt | Stripe SEPA | Direkt (LSV+/FinTS) |
|
||||
|--------|-------------|---------------------|
|
||||
| **API** | REST, moderne SDKs | XML/FinTS, komplex |
|
||||
| **Mandate** | Digital, sofort | Papier, manuell |
|
||||
| **Webhooks** | Echtzeit | Keine / Polling |
|
||||
| **Rückbuchungen** | Automatisch verwaltet | Manuell |
|
||||
| **Compliance** | Stripe übernimmt | Selbst verantwortlich |
|
||||
| **Setup** | Minuten | Wochen/Monate |
|
||||
|
||||
### Implementation
|
||||
|
||||
```typescript
|
||||
// Frontend: SEPA-Mandat einholen
|
||||
const { error } = await stripe.confirmSepaDebitPayment(clientSecret, {
|
||||
payment_method: {
|
||||
sepa_debit: {
|
||||
iban: 'DE89370400440532013000',
|
||||
},
|
||||
billing_details: {
|
||||
name: 'Max Mustermann',
|
||||
email: 'max@example.com',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Backend: Webhook wie gehabt
|
||||
@Post('webhook')
|
||||
async handleWebhook(@Req() req: Request) {
|
||||
const event = this.stripe.webhooks.constructEvent(/*...*/);
|
||||
|
||||
switch (event.type) {
|
||||
case 'payment_intent.succeeded':
|
||||
// Funktioniert identisch wie bei Kreditkarten
|
||||
await this.handlePaymentSuccess(event.data.object);
|
||||
break;
|
||||
case 'payment_intent.payment_failed':
|
||||
// SEPA kann auch fehlschlagen (Kontodeckung, etc.)
|
||||
await this.handlePaymentFailure(event.data.object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Vergleichsmatrix
|
||||
|
||||
| Kriterium | Stripe Karte | Stripe SEPA | LSV+ (CH) | FinTS (DE) |
|
||||
|-----------|--------------|-------------|-----------|------------|
|
||||
| **Gebühren** | 1.5-2.9% | 0.8% | ~0.1-0.5 CHF | ~0.1-0.3 € |
|
||||
| **API-Qualität** | Excellent | Excellent | Keine | Komplex |
|
||||
| **Setup-Zeit** | Stunden | Stunden | Wochen | Wochen |
|
||||
| **Mandate** | Digital | Digital | Papier | Papier |
|
||||
| **Webhooks** | Ja | Ja | Nein | Nein |
|
||||
| **Compliance** | Stripe | Stripe | Selbst | Selbst |
|
||||
| **Vendor Lock-in** | Ja | Ja | Nein | Nein |
|
||||
| **Zukunftssicher** | Ja | Ja | Nein (2028) | Eingeschränkt |
|
||||
| **Empfohlen** | Standard | **Beste Wahl** | Nein | Nein |
|
||||
|
||||
---
|
||||
|
||||
## Entscheidung & Empfehlung
|
||||
|
||||
### Entscheidung: Stripe SEPA-Lastschrift aktivieren
|
||||
|
||||
Nach Analyse aller Optionen ist die Empfehlung:
|
||||
|
||||
1. **Stripe SEPA-Lastschrift** als primäre Zahlungsmethode für DACH-Kunden
|
||||
2. **Kreditkarte** als Fallback für internationale Kunden
|
||||
3. **Kein direkter Bankeinzug** - Aufwand/Nutzen-Verhältnis nicht gegeben
|
||||
|
||||
### Begründung
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Kosten-Nutzen-Analyse │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Direkter Bankeinzug: │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ Entwicklungsaufwand: ~80-160 Stunden │ │
|
||||
│ │ Wartungsaufwand: ~10 Stunden/Monat │ │
|
||||
│ │ Ersparnis pro Transaktion: €0.05-0.10 │ │
|
||||
│ │ Break-Even bei: >10.000 Transaktionen/Monat │ │
|
||||
│ │ Risiko: Hoch (Compliance, Edge Cases) │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Stripe SEPA-Lastschrift: │
|
||||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||
│ │ Entwicklungsaufwand: ~2-4 Stunden │ │
|
||||
│ │ Wartungsaufwand: ~0 Stunden/Monat │ │
|
||||
│ │ Ersparnis pro Transaktion: €0.32 vs. Kreditkarte │ │
|
||||
│ │ Break-Even bei: Sofort │ │
|
||||
│ │ Risiko: Niedrig (Stripe übernimmt) │ │
|
||||
│ └─────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Nächste Schritte
|
||||
|
||||
#### Bereits erledigt (Code)
|
||||
|
||||
- [x] `stripe.service.ts` - SEPA zu Checkout Sessions hinzugefügt
|
||||
- [x] `subscriptions.service.ts` - SEPA für Subscriptions aktiviert
|
||||
- [x] `stripe-webhook.controller.ts` - SEPA-Dokumentation und `processing` Event
|
||||
|
||||
#### Manuell im Stripe Dashboard
|
||||
|
||||
1. **SEPA-Lastschrift aktivieren:**
|
||||
- Öffne: https://dashboard.stripe.com/settings/payment_methods
|
||||
- Finde "SEPA Direct Debit" → Klicke "Turn on"
|
||||
- Akzeptiere die SEPA-Bedingungen
|
||||
|
||||
2. **Webhook-Event hinzufügen:**
|
||||
- Öffne: https://dashboard.stripe.com/webhooks
|
||||
- Klicke auf deinen Webhook (Endpoint: `/webhooks/stripe`)
|
||||
- Klicke "Update details" → Events
|
||||
- Füge hinzu: `payment_intent.processing`
|
||||
- Speichern
|
||||
|
||||
3. **Deployment:**
|
||||
```bash
|
||||
# Auf dem Server
|
||||
ssh mana-server
|
||||
cd ~/projects/manacore-monorepo
|
||||
git pull
|
||||
./scripts/mac-mini/deploy.sh
|
||||
```
|
||||
|
||||
### Langfristige Option
|
||||
|
||||
Falls das Transaktionsvolumen >10.000/Monat erreicht, kann eine direkte Bank-Integration erneut evaluiert werden - dann aber mit **eBill Debit Direct** (Schweiz, ab 2025) oder einem **PSD2-konformen Aggregator** (EU).
|
||||
|
||||
---
|
||||
|
||||
## Quellen
|
||||
|
||||
### Schweiz
|
||||
|
||||
- [Raiffeisen LSV+](https://www.raiffeisen.ch/rch/de/privatkunden/konten-und-bezahlen/lsv-plus.html)
|
||||
- [SIX Direct Debits](https://www.six-group.com/en/products-services/banking-services/billing-and-payments/direct-debits.html)
|
||||
- [Moneyland Direct Debit FAQ](https://www.moneyland.ch/en/direct-debits-switzerland-faq)
|
||||
- [Guide to Swiss Payments (Atlar)](https://www.atlar.com/blog/guide-to-swiss-payments)
|
||||
|
||||
### Deutschland
|
||||
|
||||
- [Sparkasse SEPA-Lastschrift](https://www.sparkasse.de/unsere-loesungen/firmenkunden/konten-karten/sepa-lastschrift.html)
|
||||
- [FinTS Wikipedia](https://en.wikipedia.org/wiki/FinTS)
|
||||
- [libfintx GitHub](https://github.com/libfintx/libfintx)
|
||||
- [python-fints GitHub](https://github.com/raphaelm/python-fints)
|
||||
- [Subsembly FinTS API](https://subsembly.com/fints-api.html)
|
||||
- [finAPI](https://www.finapi.io/en/home/)
|
||||
|
||||
### Stripe
|
||||
|
||||
- [Stripe SEPA Direct Debit](https://stripe.com/docs/payments/sepa-debit)
|
||||
- [Stripe Pricing](https://stripe.com/de/pricing)
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
| Datum | Änderung |
|
||||
|-------|----------|
|
||||
| 2026-02-16 | Initial version, Entscheidung für Stripe SEPA |
|
||||
|
|
@ -69,13 +69,26 @@ export class StripeWebhookController {
|
|||
});
|
||||
|
||||
// Handle relevant events
|
||||
// Note: SEPA Direct Debit payments are not instant - they go through:
|
||||
// 1. checkout.session.completed (payment_status may be 'unpaid' for SEPA)
|
||||
// 2. payment_intent.processing (SEPA is being processed by banks)
|
||||
// 3. payment_intent.succeeded (3-14 days later when bank confirms)
|
||||
// Credits are only added on payment_intent.succeeded for safety.
|
||||
switch (event.type) {
|
||||
// Credit purchases via Checkout Session
|
||||
case 'checkout.session.completed':
|
||||
await this.handleCheckoutSessionCompleted(event.data.object as Stripe.Checkout.Session);
|
||||
break;
|
||||
|
||||
// Credit purchases
|
||||
// Payment processing (SEPA: bank is processing the debit)
|
||||
case 'payment_intent.processing':
|
||||
this.logger.log('Payment processing (SEPA in progress)', {
|
||||
paymentIntentId: (event.data.object as Stripe.PaymentIntent).id,
|
||||
});
|
||||
// Purchase stays in 'pending' status until succeeded
|
||||
break;
|
||||
|
||||
// Credit purchases - payment confirmed
|
||||
case 'payment_intent.succeeded':
|
||||
await this.handlePaymentSucceeded(event.data.object as Stripe.PaymentIntent);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ export class StripeService {
|
|||
const session = await stripe.checkout.sessions.create({
|
||||
customer: options.customerId,
|
||||
mode: 'payment',
|
||||
payment_method_types: ['card'],
|
||||
payment_method_types: ['card', 'sepa_debit'],
|
||||
line_items: [
|
||||
{
|
||||
price_data: {
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ export class SubscriptionsService {
|
|||
const session = await this.stripe.checkout.sessions.create({
|
||||
customer: stripeCustomerId,
|
||||
mode: 'subscription',
|
||||
payment_method_types: ['card'],
|
||||
payment_method_types: ['card', 'sepa_debit'],
|
||||
line_items: [
|
||||
{
|
||||
price: stripePriceId,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue