# Dewemoji Billing Integration Plan (QRIS + PayPal) This document outlines a proper, production-grade billing flow for Dewemoji using **QRIS (Pakasir)** and **PayPal Subscriptions**, including webhooks, retries, and license activation. --- ## 1) Goals - Replace primitive payment links with real provider integrations. - Support **subscription** billing (monthly/annual) and **one-time lifetime**. - Activate or revoke licenses based on webhook-confirmed payments. - Log all webhook events and payment activity for audit. --- ## 2) Data Model ### `orders` (new) Acts as the primary record of what the user is buying. Payments link back to orders. - `id` - `user_id` - `plan_code` - `type` (`one_time`, `subscription`) - `currency` (`IDR`, `USD`) - `amount` - `status` (`pending`, `paid`, `failed`, `expired`, `refunded`) - `provider` (`qris`, `paypal`) - `provider_ref` - `created_at`, `updated_at` ### `payments` (new) - `id` - `user_id` - `order_id` - `provider` (`qris`, `paypal`) - `type` (`one_time`, `subscription`) - `plan_code` (`personal_monthly`, `personal_annual`, `personal_lifetime`) - `currency` (`IDR`, `USD`) - `amount` - `status` (`pending`, `paid`, `failed`, `expired`, `refunded`) - `provider_ref` (invoice_id / order_id / subscription_id) - `raw_payload` (json) - `created_at`, `updated_at` ### `subscriptions` (existing) Extend with: - `provider` - `provider_ref` - `status` (`active`, `pending`, `canceled`, `expired`) - `started_at`, `expires_at`, `canceled_at` - `next_renewal_at` (optional) ### `webhook_events` (existing) Continue to log inbound payloads and processing status: - `provider`, `event_type`, `status`, `payload`, `received_at`, `processed_at`, `error_message` --- ## 3) Payment Flow (User Journey) ### Pricing Page (Frontend) Each plan shows: - **Primary currency** (based on geo + user toggle) - **Two payment buttons** (real provider flow): - **QRIS (IDR)** → subscription or one-time - **PayPal (USD)** → subscription or one-time ### Backend Endpoints #### QRIS (Pakasir) - `POST /billing/qris/create` - Creates invoice via Pakasir API - Stores `payments` with `pending` - Returns QR payment URL or QR code data - `GET /billing/qris/return` (optional) - Shows “pending / processing” state #### PayPal Subscriptions - `POST /billing/paypal/create` - Creates PayPal subscription - Stores `payments` with `pending` - Returns approval URL - `GET /billing/paypal/return` - Shows “pending / processing” state --- ## 4) Webhook Processing (Critical) Webhook endpoint: ``` POST /webhooks/{provider} ``` Store inbound payloads in `webhook_events`, then process async (queue). ### PayPal Events - `BILLING.SUBSCRIPTION.ACTIVATED` → mark subscription active, set `users.tier = personal` - `BILLING.SUBSCRIPTION.CANCELLED` → mark subscription canceled - `PAYMENT.SALE.COMPLETED` → mark payment paid - `PAYMENT.SALE.DENIED` → mark payment failed ### Pakasir / QRIS Events - `payment.paid` → mark payment paid, grant access - `payment.expired` → mark payment failed/expired --- ## 5) License Activation Rules When a payment or subscription is confirmed: - Create or update a `subscriptions` record - Set `users.tier = personal` - Store provider refs (`provider_ref`) - Log admin audit record When revoked/expired: - Update `subscriptions.status` - Downgrade user if no active subscription remains ### Renewal Logic (QRIS manual renew) - **If still active:** extend from current `expires_at` - `expires_at = expires_at + duration` - **If expired:** start from now - `expires_at = now + duration` --- ## 6) Admin Dashboard Enhancements Add or extend: - **Payments list** (new screen) - filter by provider/status/currency - show raw provider ref - **Subscriptions list** (already exists) - show provider + status - **Webhook events** (already exists) - replay capability --- ## 7) Security & Reliability - Validate webhook signatures (PayPal + Pakasir) - Reject duplicate events (idempotency) - Use queues for webhook processing - Log all webhook failures --- ## 8) Required Inputs (From Owner) Before implementation: 1. **Pakasir API docs** (create invoice, webhook payload format) 2. **PayPal API credentials** (client_id, secret, webhook signing key) 3. Confirm **plans & pricing**: - Monthly - Annual - Lifetime --- ## 9) Implementation Phases **Phase 1 — Schema + Core Models** - Add `orders` table - Add `payments` table (link to orders) - Extend `subscriptions` - Update webhook model if needed **Phase 2 — Provider APIs** - Pakasir invoice create - PayPal subscription create **Phase 3 — Webhooks** - Save raw events - Process via queue + idempotency **Phase 4 — UI** - Pricing page buttons → real flows - Admin payment + subscription tools --- ## 10) Notes - This plan assumes **proper subscription lifecycle** with webhooks. - PayPal.me / static links are **not sufficient** for subscriptions. - All access control must be tied to **confirmed payment status**.