Restore to commit 74e578279624c6045ca440a3459ebfa1f8d54191

This commit is contained in:
southseact-3d
2026-02-07 20:32:41 +00:00
commit ed67b7741b
252 changed files with 99814 additions and 0 deletions

157
DODO_PLAN_CHANGE_FIX.md Normal file
View File

@@ -0,0 +1,157 @@
# Dodo Payments Plan Change & Cancellation Fix
## Summary
Fixed the subscription management system to properly handle plan changes and cancellations using the correct Dodo Payments API endpoints.
## Issues Fixed
### 1. **Paid-to-Paid Plan Changes**
- **Problem**: When users switched between paid plans (e.g., Starter → Professional), the app was creating a new checkout session instead of using Dodo's Change Plan API
- **Solution**: Implemented `changeDodoSubscriptionPlan()` function that uses `POST /subscriptions/{subscription_id}/change-plan` with `difference_immediately` proration mode
- **Behavior**:
- Upgrades: Charges the price difference for the current billing period
- Downgrades: Applies remaining value as credit to future renewals
- No service interruption during the change
### 2. **Paid-to-Free Downgrades**
- **Problem**: Downgrading to the free "Hobby" plan wasn't properly cancelling the Dodo subscription
- **Solution**: Enhanced the logic to call `cancelDodoSubscription()` when switching from a paid plan to hobby
- **Behavior**: Subscription is cancelled with Dodo, user downgraded to free tier immediately
### 3. **Cancel Button**
- **Problem**: Cancel button was calling general account update endpoint which may not have properly cancelled the Dodo subscription
- **Solution**: Already uses dedicated `/api/subscription/cancel` endpoint which properly calls `cancelDodoSubscription()`
- **Behavior**: Cancels subscription at Dodo and marks billing status as cancelled
## Technical Implementation
### Server-Side Changes (`server.js`)
#### 1. New Function: `changeDodoSubscriptionPlan()`
```javascript
async function changeDodoSubscriptionPlan(user, newPlan, billingCycle, currency)
```
- Uses Dodo's official Change Plan API endpoint
- Handles proration automatically
- Proper error handling and logging
- Updates subscription product while maintaining continuity
#### 2. Updated: `handleAccountSettingsUpdate()`
Enhanced to handle three scenarios:
- **Paid → Paid**: Calls `changeDodoSubscriptionPlan()` with Dodo API
- **Paid → Free**: Calls `cancelDodoSubscription()` and downgrades to hobby
- **Free → Paid**: Returns error requiring checkout flow (correct behavior)
### Frontend Changes (`settings.html`)
#### Updated: `saveAccount()` Function
Completely restructured to handle different plan change scenarios:
1. **Paid-to-Paid Changes**:
- Calls `/api/account` which uses Change Plan API
- Shows appropriate confirmation with proration explanation
- Immediate update without checkout
2. **Paid-to-Free Downgrades**:
- Warns user about feature loss
- Cancels subscription via `/api/account`
- Immediate downgrade
3. **Free-to-Paid Upgrades**:
- Redirects to checkout flow (correct)
- Uses `/api/subscription/checkout`
4. **Other Settings**:
- Simple account updates (email, currency)
## Dodo Payments API Integration
### Change Plan API
**Endpoint**: `POST /subscriptions/{subscription_id}/change-plan`
**Request Body**:
```json
{
"product_id": "prod_xxx",
"quantity": 1,
"proration_billing_mode": "difference_immediately"
}
```
**Proration Mode**: `difference_immediately`
- **Upgrades**: Immediate charge for price difference
- **Downgrades**: Credit applied to subscription for future renewals
- **Benefits**: Simple, fair billing without complex proration calculations
### Cancel Subscription API
**Endpoints Used**:
1. `DELETE /subscriptions/{subscription_id}` (immediate cancellation)
2. `PATCH /subscriptions/{subscription_id}` with `cancel_at_next_billing_date: true` (fallback)
The implementation tries immediate cancellation first, then falls back to end-of-period cancellation if needed.
## User Experience Improvements
### Clear Messaging
- Upgrade messages explain immediate charges
- Downgrade messages explain credit application
- Free plan changes warn about feature loss
### Seamless Transitions
- Paid-to-paid changes happen instantly without checkout
- No service interruption during plan changes
- Proper proration handled by Dodo
### Confirmation Dialogs
- All plan changes require explicit confirmation
- Different messages for upgrades vs downgrades
- Warning icons for cancellations and downgrades
## Testing Checklist
- [ ] **Upgrade** (Starter → Professional): Verify immediate charge for difference
- [ ] **Downgrade** (Professional → Starter): Verify credit applied to account
- [ ] **Cancel** (any paid → hobby): Verify Dodo subscription cancelled
- [ ] **Free to Paid** (hobby → starter): Verify checkout flow triggered
- [ ] **Cancel Button**: Verify subscription cancelled at Dodo
- [ ] **Webhook Handling**: Verify `subscription.plan_changed` webhook updates user plan
## Environment Variables Required
All existing Dodo environment variables remain the same:
- `DODO_PAYMENTS_API_KEY`
- `DODO_PAYMENTS_ENV` (test/live)
- Subscription product IDs for each plan/cycle/currency combination
## API Endpoints Modified
### `POST /api/account`
Now handles three plan change scenarios differently:
1. Paid→Paid: Uses Change Plan API
2. Paid→Free: Cancels subscription
3. Free→Paid: Returns error requiring checkout
### `POST /api/subscription/cancel`
Already working correctly - cancels Dodo subscription properly
## Webhook Events
The system now properly responds to:
- `subscription.plan_changed`: Confirms plan change succeeded
- `subscription.canceled`: Confirms cancellation
- `payment.succeeded`: Confirms upgrade payment
- `subscription.on_hold`: Handles failed plan change payments
## Documentation References
- [Dodo Subscription Upgrade & Downgrade Guide](https://docs.dodopayments.com/developer-resources/subscription-upgrade-downgrade)
- [Change Plan API Reference](https://docs.dodopayments.com/api-reference/subscriptions/change-plan)
- [Update Subscription API](https://docs.dodopayments.com/api-reference/subscriptions/patch-subscriptions)
## Notes
- The `difference_immediately` proration mode is ideal for most SaaS applications
- Credits from downgrades are automatically applied by Dodo to future renewals
- The Change Plan API uses existing payment method - no new payment collection needed
- All plan changes are logged for audit purposes