Subscriptions: monthly + yearly billing cycles #2

Closed
opened 2026-07-29 22:32:34 +00:00 by Cordy · 1 comment
Owner

Offer both monthly and yearly per-seat billing (currently yearly-only).

Scope

  • Paddle catalog: add a monthly recurring price alongside the existing yearly one (sandbox first; both under the existing "Cairn Commercial License" product). Price points are Nikola's call — current yearly is the $48/seat placeholder.
  • Webhook: derive license validity from the billing period of the transaction (monthly txn → ~1 month + grace margin, yearly → 1 year + margin) instead of the hardcoded 1 year. Store the billing cycle on the record.
  • Buy flow (cairn-site account.html): billing-cycle toggle (Monthly / Yearly) selecting the right priceId; show effective per-seat price for each cycle.

Depends on the renewal-refresh issue — monthly subscriptions make "new key every month" absurd, so refresh-in-place must land with or before this.

Decision needed at greenlight (Nikola): monthly and yearly price points.

Acceptance: sandbox checkout in both cycles → license issued with correct expiry; renewal simulation extends it (see refresh issue); UI shows both options.

Offer both monthly and yearly per-seat billing (currently yearly-only). **Scope** - Paddle catalog: add a monthly recurring price alongside the existing yearly one (sandbox first; both under the existing "Cairn Commercial License" product). Price points are Nikola's call — current yearly is the $48/seat placeholder. - Webhook: derive license validity from the billing period of the transaction (monthly txn → ~1 month + grace margin, yearly → 1 year + margin) instead of the hardcoded 1 year. Store the billing cycle on the record. - Buy flow (cairn-site `account.html`): billing-cycle toggle (Monthly / Yearly) selecting the right `priceId`; show effective per-seat price for each cycle. **Depends on** the renewal-refresh issue — monthly subscriptions make "new key every month" absurd, so refresh-in-place must land with or before this. **Decision needed at greenlight (Nikola):** monthly and yearly price points. **Acceptance:** sandbox checkout in both cycles → license issued with correct expiry; renewal simulation extends it (see refresh issue); UI shows both options.
Author
Owner

Shipped and deployed to license.swisscairn.ch.

  • Paddle sandbox catalog: monthly price pri_01kyr0wc5ppy74jatv29cq2tyz at $3.00/seat/mo and yearly pri_01kyfy4xqf5mf8mggspfty7903 repriced to $32.40/seat/yr ($2.70/seat/mo billed yearly), both qty 51–10000.
  • Webhook reads billing_cycle.interval from the txn line items; issueFor mints monthly licenses valid 1 month + 3-day margin, yearly 1 year + 3 days.
  • Site buy flow now has a Monthly/Yearly toggle with a live per-cycle price calculation.

Renewals extend the license in place — see #3. Covered by TestIssueForIntervals.

Shipped and deployed to license.swisscairn.ch. - Paddle sandbox catalog: monthly price `pri_01kyr0wc5ppy74jatv29cq2tyz` at **$3.00/seat/mo** and yearly `pri_01kyfy4xqf5mf8mggspfty7903` repriced to **$32.40/seat/yr** ($2.70/seat/mo billed yearly), both qty 51–10000. - Webhook reads `billing_cycle.interval` from the txn line items; `issueFor` mints monthly licenses valid 1 month + 3-day margin, yearly 1 year + 3 days. - Site buy flow now has a Monthly/Yearly toggle with a live per-cycle price calculation. Renewals extend the license in place — see #3. Covered by `TestIssueForIntervals`.
Cordy closed this issue 2026-07-29 23:17:07 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/cairn-license-server#2
No description provided.