Zum Inhalt springen
WebViewGold Vibe Coding in den App Store
Deutsch
WebViewGold holen

ChatGPT & Codex

In-App-Käufe für eine Codex-Web-App: RevenueCat, WebViewGold und ein Pull Request, dem du vertrauen kannst

Bei Zahlungen kann dich ein Agent eine Ablehnung oder echtes Geld kosten, also behandle diese Aufgabe als Cloud-Aufgabe mit strengem Review. Codex findet jede Stelle, an der du digitale Güter verkaufst, leitet sie über RevenueCat, wenn die Seite in der App läuft, und schreibt den Webhook, der auf deinem Server den Zugang freischaltet. Die Produkte, die Keys und den Merge-Button behältst du.

Ab $109 einmalig pro Plattform, oder unser Team erledigt alles ab $698.

  • Genehmigungsgarantie – oder Geld zurück innerhalb von 14 Tagen
  • Kein Programmieren nötig
  • Einmalzahlung, kostenlose Updates
  • 24/7 Support von echten Menschen
  • Made in Germany seit 2014 · ISO 27001

Ziel und Blick des Reviewers

Das Ziel: In den iOS- und Android-Apps wird jedes digitale Produkt (Abos, Credits, Premium-Features, freischaltbare Inhalte) über den Store gekauft; im Browser funktioniert Stripe weiter; und beide Wege schreiben denselben Entitlement-Eintrag auf deinem Server.

Der Reviewer prüft drei Dinge. Ein Kaufen-Button, der für digitale Güter ein Kartenformular oder einen externen Checkout öffnet, führt zur Ablehnung nach Richtlinie 3.1.1. Eine Abo-Paywall ohne Preis, Abrechnungszeitraum, Verlängerungsbedingungen und Links zu AGB und Datenschutz führt zur Ablehnung nach 3.1.2. Ein fehlendes "Käufe wiederherstellen" wird ebenfalls beanstandet. Physische Waren und reale Dienstleistungen sind eine andere Kategorie und dürfen in der App bei Stripe bleiben (so unterscheidest du sie).

Die Regeln für Links zu externen Käufen haben sich in einigen Regionen verschoben, etwa im US-Storefront nach dem Epic-Urteil von 2025 und in der EU unter dem DMA. Wenn du diese Optionen nutzen willst, lies zuerst den aktuellen Richtlinientext in App Store Connect und lass sie aus deiner ersten Einreichung heraus. Der Rest dieser Seite geht vom Standardweg aus, den auch der Codex-Release-Workflow empfiehlt. Alle Kaufoptionen, die WebViewGold bietet, sind im Hub zu In-App-Käufen zusammengefasst.

Jeder Geldfluss im Überblick

SituationWas die Web-App machtHinweise
Browser-Nutzer kauftBestehender Stripe Checkout, unverändertDer Stripe-Webhook schreibt das Entitlement
App-Nutzer kauft ein Produktrevenuecat://purchase?external_id=UID&product=PRODUCT_IDiOS und Android; UID ist deine stabile User-ID, PRODUCT_ID wie in RevenueCat angezeigt
App-Nutzer öffnet eine PaywalliOS: revenuecat://launchPaywall?external_id=UID&offering=OFFERING (iOS 15 oder neuer). Android: deine eigene Paywall-Seite, die purchase aufruftDie Docs beschreiben launchPaywall nur für iOS
Wiederherstellenrestoreinapppurchases://Ein sichtbares Bedienelement, erwartet bei Abos und nicht verbrauchbaren Käufen
Verwalten oder kündigencancelinapppurchase://Öffnet den Abo-Screen des Stores
Frühere Käufe anzeigengetpurchasehistory:// füllt window.purchaseHistoryPro Gerät; die Feldnamen unterscheiden sich zwischen iOS und Android
Zugang freischaltenNichts im ClientDer RevenueCat-Webhook an Express schreibt das Entitlement

WebViewGold hat uns die kürzeste und effizienteste Time-to-Market ermöglicht, die jemals möglich war, verglichen mit allen anderen App-Plattformen, die wir in den letzten 5 Jahren ausprobiert haben. Ich weiß nicht, warum ich euch nicht schon früher entdeckt habe, aber ich bin wirklich, wirklich froh, dass ich es getan habe. Wir nähern uns derzeit fast 6000 App-Downloads im iOS App Store & Google Play Store ohne Probleme!

Antonio Davila · CodeCanyon

Eine verschachtelte AGENTS.md für den Billing-Code

Codex kombiniert AGENTS.md-Dateien vom Root des Repositorys bis hinunter zu dem Ordner, in dem es gerade arbeitet, und die Datei, die dem Code am nächsten liegt, gewinnt. Eine kleine server/billing/AGENTS.md hält die Zahlungsregeln direkt neben dem Zahlungscode, zusätzlich zu deiner AGENTS.md im Root, und ihr Abschnitt Review guidelines sagt dem Codex Code Review, was es bei jedem Pull Request melden soll, der Billing berührt. Das Codex Review auf GitHub meldet Befunde der Stufen P0 und P1, deshalb nutzen die Regeln diese Stufen.

markdown
# server/billing/AGENTS.md

## Invariants
- Entitlements live in Firestore at entitlements/{uid} and are written ONLY by
  webhooks: /webhooks/stripe (source "stripe") and /webhooks/revenuecat
  (source "revenuecat"). No client code, callable function or admin page sets premium.
- Every access check reads entitlements/{uid} on the server. Never trust a flag,
  cookie or localStorage value from the device.
- The RevenueCat app user ID is the Firebase uid, passed as external_id in
  revenuecat://purchase?external_id=...&product=... (never the email address).
- Webhooks: compare the Authorization header with REVENUECAT_WEBHOOK_AUTH, dedupe by
  event.id in billingEvents/{eventId}, answer 200 quickly. Tests use fixtures in
  server/billing/__fixtures__, never live RevenueCat or Stripe APIs.
- Inside the native app (isNativeApp()), digital goods use the bridge only:
  revenuecat://purchase, revenuecat://launchPaywall (iOS only),
  restoreinapppurchases://, cancelinapppurchase://.
  No Stripe links, no card forms, no "cheaper on the web" copy.
- Product IDs come from src/config/products.ts, never hardcoded in components.

## Review guidelines
- P0: any code path that grants or extends premium outside the two webhooks.
- P0: a webhook handler that does not check the Authorization header.
- P1: a Stripe checkout, price link or external payment URL for a digital product
  that is reachable when isNativeApp() is true.
- P1: a paywall without price, billing period, renewal terms, Terms and Privacy
  links, or without a Restore Purchases control.

Die Cloud-Aufgabe

Führe das als Cloud-Aufgabe aus, damit das Ergebnis als Diff ankommt, aus dem du einen Pull Request machen kannst, und nicht als Änderungen in deiner Arbeitskopie. Starte sie von der Codex-Seite in ChatGPT, aus der IDE-Erweiterung oder mit codex cloud im Terminal. Die Umgebung braucht das Repository und ein Setup-Skript, das die Abhängigkeiten installiert (zum Beispiel npm ci). Sie braucht keinen Netzwerkzugriff auf RevenueCat oder Stripe und sollte niemals Produktions-Keys enthalten.

In eine Codex-Cloud-Aufgabe einfügen (oder in die CLI)
Lies AGENTS.md und server/billing/AGENTS.md. Ziel: In den nativen iOS- und Android-Apps (isNativeApp() ist true) wird jedes digitale Produkt per In-App-Kauf über die RevenueCat-Bridge von WebViewGold verkauft. Browser behalten Stripe. Stack: React-Frontend, Express-API, Firebase Auth, Firestore.

1. Bestandsaufnahme: Liste jede Stelle auf, an der ein Abo, ein Credit-Paket oder ein Premium-Feature verkauft oder mit Preis beworben wird (Komponenten, Routen, E-Mails oder Banner, die zum Checkout verlinken). Schreib die Liste mit der jeweiligen Datei in die Beschreibung des Pull Requests.
2. Client: Lege src/lib/purchase.ts mit buy(productKey), openPaywall(), restorePurchases() und manageSubscription() an. In der App navigiert buy zu revenuecat://purchase?external_id=UID&product=PRODUCT_ID, mit UID = der Firebase-uid (URL-kodiert) und PRODUCT_ID aus src/config/products.ts. restorePurchases navigiert zu restoreinapppurchases://, manageSubscription zu cancelinapppurchase://. Im Browser behält buy den bestehenden Stripe Checkout.
3. Paywall: Auf iOS darf openPaywall revenuecat://launchPaywall?external_id=UID&offering=default verwenden (nur für iOS 15 oder neuer dokumentiert). Behalte unsere eigene Paywall-Komponente für Android und als Fallback, hinter einem Flag in src/config/products.ts. Unsere Paywall zeigt Preis, Abrechnungszeitraum, Verlängerungsbedingungen und Links zu /terms und /privacy.
4. Entferne in der App Stripe-Buttons, Links zu Web-Preisen und Texte wie "im Web günstiger" für digitale Güter. Physische Waren und Dienstleistungen bleiben bei Stripe.
5. Server: POST /webhooks/revenuecat in server/billing/. Gib 401 zurück, außer der Authorization-Header entspricht REVENUECAT_WEBHOOK_AUTH. Dedupliziere nach event.id in billingEvents. Schreibe entitlements/{uid} mit premium, source, store, productId, expiresAt und sandbox. Der Stripe-Webhook schreibt dasselbe Dokument mit source "stripe". Jede Premium-Prüfung auf dem Server liest nur dieses Dokument.
6. Nachdem sich das native Kauf-Sheet geschlossen hat, schaltet der Client nichts frei. Er pollt GET /api/entitlements bis zu 20 Sekunden lang und zeigt währenddessen "Dein Kauf wird verarbeitet".
7. Einstellungen: Zeilen für "Käufe wiederherstellen" und "Abo verwalten", nur in der nativen App.
8. Tests mit Fixture-Events (INITIAL_PURCHASE, RENEWAL, CANCELLATION, EXPIRATION, TEST, eine doppelte Event-ID) und ein Request mit falschem Authorization-Header. Keine Aufrufe der echten RevenueCat- oder Stripe-APIs.
9. Beschreibung des Pull Requests: die Bestandsaufnahme, die Umgebungsvariablen, die ich setzen muss, die verbleibenden Schritte im RevenueCat-Dashboard und ein Sandbox-Testplan für iOS und Android.

Der Webhook, den du im Pull Request finden solltest

Vereinfacht, aber mit den Teilen, die im Review zählen: Autorisierung, Idempotenz, die User-ID aus app_user_id (das ist deine external_id) und keine Beteiligung des Clients. Erstattungen, Transfers und Lifetime-Produkte brauchen in einer echten App zusätzliche Behandlung.

javascript
// server/billing/revenuecat.js (Express + firebase-admin)
import express from "express";
import { getFirestore, FieldValue } from "firebase-admin/firestore";

const db = getFirestore();
export const revenuecatRouter = express.Router();
const GRANT = new Set(["INITIAL_PURCHASE", "RENEWAL", "UNCANCELLATION",
  "PRODUCT_CHANGE", "NON_RENEWING_PURCHASE", "SUBSCRIPTION_EXTENDED"]);

revenuecatRouter.post("/webhooks/revenuecat", express.json(), async (req, res) => {
  if (req.get("Authorization") !== process.env.REVENUECAT_WEBHOOK_AUTH) {
    return res.status(401).end();
  }
  const event = req.body && req.body.event;
  if (!event || !event.id) return res.status(400).end();
  if (event.type === "TEST") return res.status(200).end();

  const seen = db.collection("billingEvents").doc(event.id);
  if ((await seen.get()).exists) return res.status(200).end(); // duplicate delivery

  const uid = event.app_user_id; // = external_id from revenuecat://purchase
  if (uid) {
    const expiresAt = event.expiration_at_ms ? new Date(event.expiration_at_ms) : null;
    const ref = db.collection("entitlements").doc(uid);
    if (GRANT.has(event.type)) {
      await ref.set({ premium: true, source: "revenuecat", store: event.store,
        productId: event.product_id, expiresAt, sandbox: event.environment === "SANDBOX",
        updatedAt: FieldValue.serverTimestamp() }, { merge: true });
    } else if (event.type === "EXPIRATION") {
      await ref.set({ premium: false, expiresAt, updatedAt: FieldValue.serverTimestamp() }, { merge: true });
    }
    // CANCELLATION and BILLING_ISSUE: access usually runs until EXPIRATION.
  }
  await seen.set({ type: event.type, uid: uid || null, at: FieldValue.serverTimestamp() });
  res.status(200).end();
});

Vom Pull Request zum Sandbox-Kauf

  1. Den Pull Request wie ein Auditor prüfen

    Lies zuerst die Bestandsaufnahme: Jede Verkaufsstelle sollte aufgeführt sein, und jede sollte entweder bei Stripe (Browser) oder in der Bridge (App) enden. Kommentiere dann @codex review for payment bypasses im Pull Request, um eine fokussierte Zweitmeinung zu bekommen, die die verschachtelten Review-Richtlinien anwendet. Merge erst, wenn du jeden Pfad erklären kannst.

  2. Den Webhook konfigurieren

    Füge in RevenueCat einen Webhook hinzu, der auf https://api.example.com/webhooks/revenuecat zeigt, und setze einen Wert für den Authorization-Header; denselben Wert trägst du auf deinem Server in REVENUECAT_WEBHOOK_AUTH ein. Sende das Test-Event von RevenueCat und prüfe, dass eine 200-Antwort zurückkommt.

  3. Die nativen Keys setzen

    iOS, Config.swift: kRevenueCatEnable auf true, revenueCatAPIKey, revenueCatProjectID; lass kRevenueCatShowDefaultOfferingPaywall auf false, außer die Paywall soll bei jedem Start erscheinen. Android, Config.java: REVENUECAT_API_KEY und REVENUECAT_PROJECT_ID. Bundle-ID und Paketname müssen exakt zu den Apps in RevenueCat passen (iOS-IAP-Docs, Android-IAP-Docs).

  4. In der Sandbox testen

    iOS: ein TestFlight-Build und ein Sandbox-Apple-Account. Android: Lizenztester und ein interner Test-Track. Kaufe, stelle auf einem zweiten Gerät wieder her, lass ein Sandbox-Abo ablaufen und beobachte, dass sich das Entitlement erst ändert, wenn der Webhook ankommt.

  5. Mit angehängten Produkten einreichen

    Hänge die ersten In-App-Käufe in App Store Connect an die App-Version an und sag dem Reviewer, wo die Paywall ist und welchen Demo-Account er nutzen soll (Template für Review-Notizen).

Test-Checkliste

  • Desktop-Browser: Stripe funktioniert genau wie vorher, und kein revenuecat://-Link ist erreichbar.
  • App: Kein Screen zeigt einen Stripe-Button, ein Kartenformular oder einen Link zu Web-Preisen für digitale Güter.
  • Ein Kauf auf iOS und auf Android schaltet Premium innerhalb von Sekunden frei, und zwar erst, nachdem der Webhook das Entitlement geschrieben hat.
  • Wird die App bei offenem Kauf-Sheet beendet, bleibt kein halber Zustand zurück; der Webhook schaltet den Zugang trotzdem frei.
  • Wiederherstellen auf einem zweiten Gerät (gleiches Store-Konto, gleicher Login) bringt Premium zurück.
  • "Abo verwalten" öffnet den Store-Screen; ein gekündigtes Sandbox-Abo bleibt aktiv, bis es abläuft.
  • Die Paywall zeigt Preis, Zeitraum, Verlängerungsbedingungen und Links zu AGB und Datenschutz.
  • Ein Webhook-Request mit falschem Authorization-Header bekommt eine 401.

Stolperfallen

  • Die E-Mail-Adresse als external_id verwenden. E-Mail-Adressen ändern sich, und der RevenueCat-Kunde zerfällt in zwei. Nimm die uid.
  • Vor dem Login verkaufen. Ohne stabile ID landet der Kauf bei einem Kunden, den du später nicht zuordnen kannst. Verlange zuerst den Login oder nutze eine Geräte-ID aus get-uuid:// und führe die Konten bewusst zusammen.
  • Premium im Client freischalten, sobald sich das Kauf-Sheet schließt. Das ist ein Gratis-Unlock für jeden, der einen Request manipuliert; polle stattdessen deinen Server.
  • Auf die Reihenfolge der Events vertrauen. Webhooks können verspätet oder doppelt ankommen. Dedupliziere nach Event-ID; für einen robusteren Zustand lässt du den Handler bei jedem Event den Kunden über die REST-API von RevenueCat neu laden, statt jeden Event-Typ einzeln zu interpretieren.
  • Cookies bei jedem Start löschen (deletecache auf iOS, CLEAR_CACHE_ON_STARTUP auf Android). Die WebViewGold-Docs empfehlen, das ausgeschaltet zu lassen, wenn der Kaufablauf von der Session abhängt.
  • Annehmen, dass window.purchaseHistory überall gleich aussieht: iOS liefert purchaseDateMs als String, Android purchaseTime und orderId. Lass Codex einen einzigen Normalizer schreiben.

Häufig gestellte Fragen

Muss die Paywall nativ sein?

Nein. Eine Paywall-Seite in deiner Web-App, die revenuecat://purchase aufruft, funktioniert auf beiden Plattformen, solange sie Preis, Zeitraum, Verlängerungsbedingungen und die rechtlichen Links zeigt. Auf iOS kannst du mit revenuecat://launchPaywall (iOS 15 oder neuer) auch eine in RevenueCat gestaltete Paywall öffnen.

Soll die Cloud-Aufgabe meine RevenueCat- oder Stripe-Keys bekommen?

Nein. Die Aufgabe schreibt Code und Tests gegen Fixtures. Keys gehören in die Umgebung deines Servers und werden nach dem Merge von dir gesetzt. Produktions-Secrets aus Agenten-Umgebungen herauszuhalten ist die günstigste Risikominderung, die du hast.

Können Web-Abonnenten Premium in der App nutzen?

Meistens ja. Apples Multiplattform-Regel (Richtlinie 3.1.3(b)) erlaubt Nutzern den Zugriff auf das, was sie auf deiner Website gekauft haben, sofern dieselben Artikel in der App auch als In-App-Käufe verfügbar sind. Weil beide Webhooks dasselbe Entitlement schreiben, ist ein Stripe-Abonnent nach dem Login auch in der App Premium.

Wie viel behalten Apple und Google ein?

Die Standardprovision beträgt 30 Prozent. Apples Small Business Program und Googles reduzierte Stufe für die erste Million US-Dollar Jahreseinnahmen senken sie auf 15 Prozent, und RevenueCat berechnet oberhalb seiner kostenlosen Schwelle einen Anteil am Umsatz.

Brauche ich die WebViewGold Extended License?

Ja. Die WebViewGold-Dokumentation zu In-App-Käufen setzt die Extended License voraus, wenn du In-App-Käufe in einem Endprodukt nutzt. Mach das Upgrade, bevor du den Build mit Käufen einreichst.

Drei Wege, deine App in die Stores zu bringen

Gleiches Ergebnis, unterschiedlich viel Arbeit auf deiner Seite. Alle drei kommen mit Genehmigungsgarantie und 24/7 Support von echten Menschen.

Selbst machen

$109 pro Plattform, einmalig

Die WebViewGold-Lizenz: ein fertiges Xcode- oder Android-Studio-Projekt. URL einfügen, Name und Icon setzen, Features einschalten, bauen und einreichen. Kostenlose Updates für immer.

Pakete auf der Hauptseite ansehen

Full Service

$698 pro Plattform $798

Schick uns deine URL und dein Icon. Unser Team konfiguriert, baut und liefert deine App innerhalb von 72 Stunden, White-Label, inklusive Quellprojekten. Beide Plattformen für $1,158.

Full-Service-Details Powered by WeSetupYourWebViewApp

Winter-Sale-Preise gültig bis 31. Dezember 2026.

Bereit, deine App zu veröffentlichen?

App Store & Google Play Genehmigungsgarantie – oder Geld zurück innerhalb von 14 Tagen

Lieber abgeben? Full Service: Wir konfigurieren, bauen und liefern innerhalb von 72 Stunden, ab $698 pro Plattform. Fragen? Chatte mit uns – 24/7.

Erstattungen erfolgen zu den in unseren FAQ genannten Bedingungen: eine nicht inhaltsbedingte Ablehnung durch Apple und/oder Google, geltend gemacht innerhalb von 14 Tagen nach dem Kauf.