TuBrief
Subscribed Channels
Videos
Community

Warum in 30 Minuten bereitgestellte Apps bei echten Zahlungen versagen und die Lösungen

TuBrief Editorial
August 10, 2026
0
Computing/Software

Written with AI assistance from the source video. The video is the authority.

Deutsch한국어English中文العربيةहिन्दीEspañolFrançaisPortuguêsРусскийBahasa Indonesia日本語

Related Video

Ship 26 NYC - Workshop - Von Init bis Deploy in 30 Minuten11:26

Ship 26 NYC - Workshop - Von Init bis Deploy in 30 Minuten

Vercel

More from the community

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

September 13, 2026

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

September 13, 2026

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

September 13, 2026

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

September 13, 2026

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

September 12, 2026

Apple Won the AI Race

September 12, 2026

Comments (0)

Log in to leave a comment

No posts yet

© 2026 . All rights reserved.

TuBrief
Subscribed Channels
Videos
Community
Log in

Warum in 30 Minuten bereitgestellte Apps bei echten Zahlungen versagen und die Lösungen

Das Dopamin, das man spürt, wenn man einen Dienst in nur 30 Minuten über die CLI online bringt und den ersten Zahlungsbutton einbindet, hält nicht lange an. Das echte Problem tritt auf, wenn ein echter Nutzer das Zahlungsfenster schließt, wenn es zu Verzögerungen bei der Kommunikation mit dem Kreditkartenunternehmen kommt oder wenn ein internationaler Nutzer versucht zu bezahlen. Eine Architektur, die sich nur auf die Weiterleitung durch den Client verlässt, bricht bei einem einzigen Network-Timeout sofort zusammen. Es entsteht eine Situation, in der das Geld abgebucht wurde, aber der Zugang oder das Guthaben nicht gutgeschrieben wird.

Um solche Pannen zu verhindern, muss der Erfolg einer Zahlung nicht vom Client, sondern über asynchrone Server-zu-Server-Ereignisse (Webhooks) empfangen werden.

1. Lokales Debuggen von Zahlungs-Webhooks mit der Stripe CLI

In einer lokalen Entwicklungsumgebung kann der Stripe-Server keine Anfragen an Ihren Computer (localhost) senden. Sie sollten den Gedanken verwerfen, erst nach dem Deployment zu debuggen. Mit der Stripe CLI können Sie Ereignisse direkt über ein Tunneling empfangen.

Laut Berichten von GitGuardian stammen über 40 % der Zahlungsausfälle aus Fehlern bei der Verarbeitung asynchroner Ereignisse. Man muss Fehlerszenarien lokal selbst durchspielen.

Öffnen Sie zuerst das Tunneling.

`bash
stripe listen --events payment_intent.succeeded,payment_intent.payment_failed,checkout.session.completed --forward-to localhost:4242/webhook

`

Nach Ausführung des Befehls wird im Terminal ein Webhook-Secret ausgegeben, das mit whsec_ beginnt. Fügen Sie diesen Wert in Ihre Umgebungsvariablen ein und lösen Sie in einem anderen Terminalfenster das Ereignis manuell aus.

`bash
stripe trigger payment_intent.succeeded
stripe trigger payment_intent.payment_failed

`

Auf dem Server müssen die Signatur des Ereignisses überprüft und die Idempotenz sichergestellt werden. Wenn Stripe dasselbe Ereignis aufgrund von Netzwerkinstabilität zweimal sendet, darf der Nutzer die Ware schließlich nicht zweimal erhalten. Hier ist ein Express-Beispiel, das event.id in Redis speichert, um eine doppelte Ausführung zu verhindern.

`javascript
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const Redis = require('ioredis');

const app = express();
const redis = new Redis(process.env.REDIS_URL);

app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
const sig = req.headers['stripe-signature'];
let event;

try {
event = stripe.webhooks.constructEvent(
req.body,
sig,
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
return res.status(400).send(Webhook Error: ${err.message});
}

const eventId = event.id;
const isProcessed = await redis.get(webhook:processed:${eventId});

if (isProcessed) {
return res.status(200).json({ received: true, status: 'already_processed' });
}

try {
switch (event.type) {
case 'payment_intent.succeeded':
await handlePaymentSuccess(event.data.object);
break;
case 'payment_intent.payment_failed':
await handlePaymentFailure(event.data.object);
break;
}

await redis.set(`webhook:processed:${eventId}`, 'true', 'EX', 604800);
return res.status(200).json({ received: true });

} catch (dbError) {
return res.status(500).send('Internal Server Error');
}
});

async function handlePaymentSuccess(paymentIntent) {}
async function handlePaymentFailure(paymentIntent) {}

app.listen(4242, () => console.log('Stripe Webhook Monitoring gestartet'));

`

2. Vorab-Prüfskript zur Verhinderung von API-Schlüssel-Leaks in der Build-Phase

Laut dem Secret State Report 2025 von GitGuardian wurden im Laufe des Jahres 2024 insgesamt 28,6 Millionen geheime Schlüssel in öffentlichen GitHub-Repositories geleakt. Scann-Bots greifen Schlüssel innerhalb von 5 Minuten nach Veröffentlichung eines Repositories ab.

Bei der Nutzung von KI-Coding-Tools rutschen einem oft unbemerkt .env-Inhalte in den Code oder man vergisst .gitignore. Es ist am sichersten, die Validierung direkt als Skript beim Ausführen des Build-Befehls (npm run build) einzubinden.

Erstellen Sie die Datei scripts/preflight-security.js mit folgender Logik:

`javascript
const fs = require('fs');
const path = require('path');

const rootDir = path.resolve(__dirname, '..');
const gitignorePath = path.join(rootDir, '.gitignore');

if (!fs.existsSync(gitignorePath)) {
console.error('.gitignore-Datei nicht gefunden.');
process.exit(1);
}

const gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');
if (!gitignoreContent.split('\n').map(l => l.trim()).includes('.env')) {
console.error('.env in .gitignore vergessen.');
process.exit(1);
}

const secretPatterns = [
/sk_live_[0-9a-zA-Z]{24,}/g,
/sk_test_[0-9a-zA-Z]{24,}/g
];

function scanDirectory(dir) {
const files = fs.readdirSync(dir);
for (const file of files) {
const fullPath = path.join(dir, file);
if (['node_modules', '.git', '.next', 'build'].includes(file)) continue;

const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
  scanDirectory(fullPath);
} else if (stat.isFile() && (file.endsWith('.js') || file.endsWith('.ts'))) {
  const content = fs.readFileSync(fullPath, 'utf8');
  secretPatterns.forEach(pattern => {
    if (pattern.test(content)) {
      console.error(`Hardcodierter API-Schlüssel gefunden: ${fullPath}`);
      process.exit(1);
    }
  });
}

}
}

scanDirectory(rootDir);
console.log('Sicherheitsprüfung abgeschlossen.');

`

Fügen Sie dies in Ihre package.json ein.

`json
"scripts": {
"prebuild": "node scripts/preflight-security.js",
"build": "next build"
}

`

Echte Secrets werden nun direkt in den Umgebungsvariablen-Einstellungen von Vercel oder AWS hinterlegt. Sollte ein Schlüssel geleakt worden sein, zögern Sie nicht, den vorherigen Schlüssel im Stripe-Dashboard über 'Roll Key' sofort zu invalidieren.

3. Automatisierung der länderbezogenen Steuerberechnung mit Stripe Tax

Sobald Sie beginnen, SaaS an internationale Nutzer zu verkaufen, tauchen Probleme mit indirekten Steuern wie der EU-Umsatzsteuer oder den Sales Taxes der US-Bundesstaaten auf. Anfangs mag das unbemerkt bleiben, aber mit steigendem Umsatz melden sich das Finanzamt oder internationale Steuerbehörden.

Mit Stripe Tax wird der Standort des Kunden zum Zeitpunkt der Zahlung ermittelt und die Steuer automatisch hinzugefügt.

  1. Registrieren Sie Ihre Geschäftsadresse im Stripe-Dashboard unter Settings > Tax.
  2. Legen Sie im Product Catalog den Steuercode für das Produkt auf den SaaS-Standard txcd_10000000 fest.
  3. Aktivieren Sie die Option für automatische Steuern in der Session-Erstellungs-API.

`javascript
const express = require('express');
const app = express();
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post('/create-checkout-session', async (req, res) => {
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
payment_method_types: ['card'],
line_items: [{ price: 'price_1NXXXXXXXXXXXXXX', quantity: 1 }],
automatic_tax: { enabled: true },
customer_update: { address: 'auto', name: 'auto' },
billing_address_collection: 'required',
success_url: 'https://yourdomain.com/success?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'https://yourdomain.com/cancel',
});

res.redirect(333, session.url);
});

`

Durch das Hinzufügen von nur zwei Zeilen – automatic_tax: { enabled: true } und billing_address_collection: 'required' – werden die Erfassung von Adressen nach Ländern und die Mehrwertsteuerberechnung abgedeckt. Steuerrelevante Daten können monatlich als CSV über das Reports-Menü exportiert und für die Buchhaltung verwendet werden.