Search the site
BACKEND
Sell subscriptions, charge with tax and promotions, and cap usage per customer, with every grant checked on the server.
Stripe, Paddle and the store paths are tested against fakes. None has been run against the live service yet.
ON THIS PAGE
Sell a plan through Stripe or Paddle
Check app store purchases on your server
Charge with tax and promotions, and refund cleanly
Meter usage and cap it per tenant
Checkout reads the plan's price from the provider first and refuses when it differs from your plan, so a page cannot show one price and charge another.
Webhooks grant and revoke entitlements from subscription status, and each is believed only when its signature matches within five minutes.
Trials and usage meters are passed through to the provider.
// What you sell, and what each plan turns on. The price is the number the
// application is held to: checkout reads the provider's own price first and
// refuses when the two disagree, so a page cannot show one price and charge
// another.
const BillingPlan team = BillingPlan(
id: 'team',
displayName: 'Team',
priceMinorUnits: 4900,
currency: 'USD',
trialDays: 14,
);
const Entitlement reports = Entitlement('reports');Copy code to clipboard
void useStripe() {
DV.Billing.useProvider(DVStripeBillingProvider(
secretKey: DV.Secrets.get('STRIPE_SECRET_KEY'),
webhookSecret: DV.Secrets.get('STRIPE_WEBHOOK_SECRET'),
// Your plan id on the left, the provider's price on the right.
prices: const <String, String>{'team': 'price_1234'},
// What each plan grants once the subscription is live.
entitlements: const <String, Set<Entitlement>>{
'team': <Entitlement>{reports},
},
successUrl: Uri.parse('https://example.com/billing/done'),
cancelUrl: Uri.parse('https://example.com/pricing'),
));
}Copy code to clipboard
Future<Uri?> subscribe(Workspace workspace) async {
final DVBillingCheckoutSession session =
await DV.Billing.checkout(plan: team, customer: workspace);
// Null when the provider gave back no hosted page. Send the customer
// nowhere; a blank tab is worse.
return session.checkoutUrl;
}Copy code to clipboard
// Asked on the server, never read off the client: the page that shows a
// feature and the code that allows it must not be two different answers.
Future<bool> mayExport(Workspace workspace) =>
DV.Billing.hasEntitlement(workspace, reports);Copy code to clipboard
Partial
Spec section: Billing
Planned work and implementation limits
Neither provider has been exercised against the live service.
Stripe and Paddle keep webhook grants in memory, so a refund revokes a grant only with the local provider.
DVPurchases writes a grant only from the store's own answer about a receipt, and refuses one bought under another account.
Store notifications are signature-checked, applied once and in order, and access ends when the paid period and grace end.
A refund or chargeback is told apart from a lapse, so DVCommerce can reverse the sale.
Partial
Spec section: Purchases and Entitlements
Planned work and implementation limits
No real App Store or Play adapters yet, and no StoreKit or Play Billing binding, so DV.Purchases.buy does not exist.
Products are not generated from models.
DVTax asks your tax provider and refuses the sale when the answer does not add up. Nothing is ever taxed at zero by accident.
Promotions stack by group, respect global and per-customer limits under load, and are checked on the server.
DVCommerce.charge captures last, so a failure at any step leaves nothing behind. A refund reverses tax and revokes what the sale granted.
Partial
Spec section: Commerce: Tax, Promotions, Disputes and Payouts
Planned work and implementation limits
Tested against fakes only. No live tax, payment or payout provider has been run.
DVTaxTable ships no rates. It is the offline fallback and the reference for rounding.
Count or gauge anything per tenant, in memory or in your database. Each record needs an idempotency key, so a retry is not counted twice.
Limits can block, throttle or allow and bill, with thresholds announced once.
Each period's usage is reported to your billing provider, with a retry queue and a reconcile that is safe to run again.
Partial
Spec section: Usage Metering and Quotas
Planned work and implementation limits
No @DVMeter annotations, so meters are not generated or counted for you.
No dartvel meters commands, no Studio view, and no scheduled period close.
FSL-1.1-MIT licensed. Built with Dartvel.
Dartvel is made by
To the bottom