Skip to content

Stripe Integration

Erstelle automatisch EU-konforme E-Rechnungen wenn eine Stripe-Zahlung eingeht. Stripe Webhook → thelawin.dev → ZUGFeRD-PDF.

Voraussetzungen

  • Stripe Account mit Webhook-Zugriff
  • thelawin.dev API Key (zum Testen: env_sandbox_demo)
  • Server fuer Webhook-Empfang (Node.js, Python, Ruby, etc.)

Architektur

Stripe Payment → Webhook (payment_intent.succeeded)
    → Dein Server (extrahiert Kundendaten + Betrag)
    → POST api.thelawin.dev/v1/generate
    → PDF per Email an Kunden senden

Webhook-Handler (Node.js)

javascript
import Stripe from 'stripe';
import { ThelawinClient } from '@thelawin/sdk';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const thelawin = new ThelawinClient(process.env.THELAWIN_API_KEY);

app.post('/webhooks/stripe', async (req, res) => {
  const event = stripe.webhooks.constructEvent(
    req.body, req.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET
  );

  if (event.type === 'payment_intent.succeeded') {
    const payment = event.data.object;
    const customer = await stripe.customers.retrieve(payment.customer);

    const result = await thelawin.invoice()
      .number(`RE-${Date.now()}`)
      .date(new Date().toISOString().split('T')[0])
      .format('zugferd')
      .seller({
        name: 'Your Company GmbH',
        vatId: 'DE123456789',
        city: 'Berlin',
        country: 'DE'
      })
      .buyer({
        name: customer.name,
        email: customer.email,
        city: customer.address?.city,
        country: customer.address?.country || 'DE'
      })
      .addItem({
        description: payment.description || 'Service',
        quantity: 1,
        unitPrice: payment.amount / 100,
      })
      .generate();

    if (result.success) {
      // PDF per Email senden, in S3 speichern, etc.
      console.log(`Invoice generated: ${result.filename}`);
    }
  }

  res.json({ received: true });
});

Webhook-Handler (Python)

python
import stripe
from thelawin import ThelawinClient

stripe.api_key = os.environ["STRIPE_SECRET_KEY"]
client = ThelawinClient(os.environ["THELAWIN_API_KEY"])

@app.route("/webhooks/stripe", methods=["POST"])
def stripe_webhook():
    event = stripe.Webhook.construct_event(
        request.data, request.headers["Stripe-Signature"],
        os.environ["STRIPE_WEBHOOK_SECRET"]
    )

    if event["type"] == "payment_intent.succeeded":
        payment = event["data"]["object"]
        customer = stripe.Customer.retrieve(payment["customer"])

        result = (
            client.invoice()
            .number(f"RE-{int(time.time())}")
            .date(datetime.now().strftime("%Y-%m-%d"))
            .format("zugferd")
            .seller("Your Company GmbH", vat_id="DE123456789", city="Berlin", country="DE")
            .buyer(customer["name"], email=customer["email"], country="DE")
            .add_item(payment.get("description", "Service"), quantity=1, unit_price=payment["amount"] / 100)
            .generate()
        )

        if result.success:
            result.save_pdf(f"invoices/{result.filename}")

    return jsonify(received=True)

Stripe Checkout → Rechnung

Fuer Stripe Checkout Sessions nutze den checkout.session.completed Event:

javascript
if (event.type === 'checkout.session.completed') {
  const session = event.data.object;
  const lineItems = await stripe.checkout.sessions.listLineItems(session.id);
  // Baue Invoice-Items aus lineItems.data
}

Naechste Schritte

ZUGFeRD 2.4 & Factur-X 1.0.8 compliant