Documentation

Paiements (Polar)

Facturation Polar dans Motoko Base — configuration, checkout, portail, webhooks et entitlements.

Ouvrir dansChatGPT (s’ouvre dans un nouvel onglet)Claude (s’ouvre dans un nouvel onglet)Cursor (s’ouvre dans un nouvel onglet)Facturation Polar dans Motoko Base — configuration, checkout, portail, webhooks et entitlements.

Motoko Base utilise Polar pour les abonnements en v1. La facturation est encapsulée dans une API indépendante du fournisseur — le code de feature n'importe jamais Polar directement.

Official docs: Polar documentation

Architecture

Polar (source of truth)
   ↓
polar.customers.getStateExternal(userId)
   ↓
BillingSummary (plan, status, period end)
   ↓
Dashboard UI + hasPlan() / canAccess()

Polar est la source de vérité. Motoko Base ne reflète pas les abonnements dans Postgres. L'état du plan est récupéré depuis Polar Customer State et mis en cache brièvement (60s). Les webhooks invalident le cache lorsque les abonnements changent.

Better Auth user id = Polar externalId. Un client Polar est créé à l'inscription lorsque la facturation est configurée.

Setup

  1. Créez une organisation Polar — commencez en sandbox
  2. Créez un produit d'abonnement Pro → copiez le product ID
  3. Créez un Organization Access Token
  4. Ajoutez un webhook → {APP_URL}/api/billing/webhooks/polar
  5. Définissez les variables d'environnement dans .env :
VariablePurpose
BILLING_PROVIDERpolar (default)
POLAR_ACCESS_TOKENOrganization access token
POLAR_WEBHOOK_SECRETWebhook signing secret
POLAR_PRO_MONTHLY_PRODUCT_IDPro monthly product ID
POLAR_PRO_YEARLY_PRODUCT_IDPro yearly product ID (optional)
POLAR_SERVERsandbox or production

Sans les variables Polar, l'app reste sur Free — pas de crash, checkout désactivé.

Checkout & portal

ActionAPIUI
Upgrade to Procheckout(userId, "pro")Billing page → Upgrade
Manage subscriptionopenPortal(userId)Billing page → Manage billing

Le checkout redirige vers Polar Checkout. Le portail ouvre Polar Customer Portal (annuler, mettre à jour le moyen de paiement, factures).

Webhooks

Route : src/app/api/billing/webhooks/polar/

Polar envoie des événements d'abonnement → signature vérifiée → cache billing invalidé → événement analytics capturé. Pas de ledger local d'abonnements.

Abonnez-vous aux événements d'abonnement + customer.state_changed dans le dashboard Polar. Les types d'événements non gérés sont ignorés en toute sécurité.

Entitlements

import { hasPlan, canAccess } from "@/lib/billing";

await hasPlan(userId, "pro");
await canAccess(userId, "ai"); // feature → plan map in billingConfig

Le mapping feature→plan se trouve dans src/lib/billing/config.ts. Les features demo ne sont pas gated en v1 — appelez canAccess lorsque vous ajoutez des portes payantes.

Libellés de plan dans l'UI : src/lib/billing/config/plans.ts.

Sandbox testing

  1. Définissez POLAR_SERVER=sandbox et le token/product ID sandbox
  2. Utilisez les cartes de test Polar au checkout — voir Polar sandbox docs
  3. Confirmez la livraison des webhooks dans le dashboard Polar (utilisez ngrok en local si besoin)
  4. Après le checkout, ouvrez /dashboard/settings/administration/billing?checkout=success — le plan devrait se mettre à jour

Passez à POLAR_SERVER=production avec des credentials de production pour la facturation live.

Where to change this

WhatWhere
Public billing APIsrc/lib/billing/index.ts
Plans & feature gatessrc/lib/billing/config.ts
Polar providersrc/lib/billing/providers/polar/
Webhook handlersrc/lib/billing/providers/polar/webhooks.ts
Billing UI & actionssrc/features/dashboard/actions/billing.ts, src/features/dashboard/components/settings/billing-*

N'importez pas @polar-sh/* depuis les features ou l'UI — utilisez uniquement @/lib/billing.


Environment Variables — toutes les variables Polar.