Monetisasi (Stripe Integration)

Serial Bagian 10: Mengubah aplikasi menjadi mesin uang. User membayar -> Stripe Notifikasi -> Kuota Bertambah Otomatis.

33. Setup Stripe & Endpoint Checkout

Anda wajib memiliki akun Stripe.com dan mengambil Secret Key (Mode Test).

Update: requirements.txt
stripe==7.8.0
File: /www/wwwroot/app-collection/ao/app/api/v1/endpoints/stripe.py
import stripe
from fastapi import APIRouter, HTTPException
from sqlalchemy.orm import Session
import secrets

from core.db import get_db
import core.models as models

router = APIRouter()

# Masukkan Secret Key dari Dashboard Stripe
stripe.api_key = "sk_test_..." 

@router.post("/create-checkout-session")
def create_checkout_session(api_key: str, db: Session = Depends(get_db)):
    # 1. Validasi User
    user = db.query(models.User).filter(models.User.api_key == api_key).first()
    if not user:
        raise HTTPException(status_code=403, detail="Invalid API Key")

    # 2. Buat Stripe Session
    try:
        checkout_session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            line_items=[{
                'price_data': {
                    'currency': 'usd',
                    'product_data': {
                        'name': 'AI SaaS Premium Quota',
                    },
                    'unit_amount': 1000, # $10.00
                },
                'quantity': 1,
            }],
            mode='payment',
            success_url='https://ao.baktimakmur.com/success?session_id={CHECKOUT_SESSION_ID}',
            cancel_url='https://ao.baktimakmur.com/cancel',
            metadata={
                'user_email': user.email # Simpan email user di metadata Stripe agar bisa diambil saat Webhook
            }
        )
        return {"url": checkout_session.url}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))

34. Webhook Endpoint (Crucial)

Ini adalah bagian terpenting. Setelah user bayar, Stripe akan mengirim data ke endpoint ini. Di sinilah kita menambah kuota user secara otomatis.

PENTING: Anda harus masuk ke Dashboard Stripe -> Developers -> Webhooks -> Add Endpoint -> Masukkan URL https://ao.baktimakmur.com/api/v1/stripe/webhook -> Pilih Event checkout.session.completed.
Update: /www/wwwroot/app-collection/ao/app/api/v1/endpoints/stripe.py (Tambah fungsi ini)
from fastapi import Request, Header

@router.post("/webhook")
async def stripe_webhook(request: Request, stripe_signature: str = Header(None), db: Session = Depends(get_db)):
    payload = await request.body()
    endpoint_secret = "whsec_..." # Webhook Signing Key dari Stripe

    try:
        event = stripe.Webhook.construct_event(
            payload, stripe_signature, endpoint_secret
        )
    except ValueError as e:
        raise HTTPException(status_code=400, detail="Invalid payload")
    except stripe.error.SignatureVerificationError as e:
        raise HTTPException(status_code=400, detail="Invalid signature")

    # 3. Handle Pembayaran Sukses
    if event['type'] == 'checkout.session.completed':
        session = event['data']['object']
        
        # Ambil email yang kita simpan di metadata checkout
        user_email = session['metadata']['user_email']
        
        # Cari user di DB
        user = db.query(models.User).filter(models.User.email == user_email).first()
        
        if user:
            # TAMBAH KUOTA MISAL: +1000 REQUEST
            user.quota_limit += 1000
            db.commit()
            print(f"Updated quota for {user_email}")
        else:
            print("User not found for email: " + user_email)

    return {"status": "success"}

35. UI Tombol Upgrade

Update dashboard.html agar ada tombol ke halaman pembayaran.

Update: /www/wwwroot/ao.baktimakmur.com/static/js/dashboard.js
// ... kode loadUsers() yang sudah ada

// Tambahkan fungsi Upgrade
async function upgradePlan() {
    const apiKey = localStorage.getItem('saas_api_key');
    if(!apiKey) return alert("Silakan Login terlebih dahulu");

    try {
        const res = await fetch('/api/v1/stripe/create-checkout-session', {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: `api_key=${apiKey}`
        });
        const data = await res.json();
        if(data.url) {
            // Redirect ke halaman pembayaran Stripe
            window.location.href = data.url;
        }
    } catch (error) {
        alert("Gagal membuat sesi pembayaran.");
    }
}

// Panggil fungsi ini saat tombol upgrade diklik
// document.getElementById('upgradeBtn').addEventListener('click', upgradePlan);

Status SaaS Anda (After Part 10)

Sistem Anda sekarang memiliki:

  • User Flow Lengkap: Sign Up -> Login -> Dashboard -> Use App.
  • Monetisasi Aktif: User bisa upgrade paket sendiri via kartu kredit.
  • Automatisasi: Kuota bertambah otomatis tanpa Admin.
  • Keamanan: Password di-hash, Token JWT, API Key privasi.

Aplikasi ini sudah setara dengan MVP SaaS komersial yang dijual di marketplace.