dramaling-app/docs/04_technical/api/subscription.md

14 KiB
Raw Blame History

訂閱系統 API

📋 概述

Drama Ling 的訂閱會員系統支援iOS/Android原生內購提供對話訓練功能解鎖和進階學習體驗。

💳 訂閱特色

訂閱方案

  • 月費會員: NT$600/月 (測試期2折優惠 NT$120)
  • 支援平台: iOS App Store、Google Play 原生內購
  • 訪客訂閱: 支援透過裝置ID的訪客用戶訂閱
  • 權限管理: 基於訂閱狀態的功能權限控制

解鎖功能

  • 對話訓練: 無限制對話練習
  • 進階場景: 專業場景和挑戰模式
  • 詳細分析: 完整學習報告和建議
  • 語言評估: Microsoft API 驅動的專業評估
  • 優先支援: 專屬客服通道

📌 API 端點

1. 獲取訂閱方案

GET /api/v1/subscriptions/plans
Authorization: Bearer <access_token> // 訪客用戶可選

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "available_plans": [
      {
        "plan_id": "PLAN_MONTHLY_TWD",
        "product_id": "dramaling.subscription.monthly",
        "name": "月費會員",
        "description": "解鎖對話訓練功能,享受完整學習體驗",
        "pricing": {
          "regular_price": {
            "amount": 600,
            "currency": "TWD",
            "display": "NT$600"
          },
          "test_period_discount": {
            "percentage": 80,
            "discounted_amount": 120,
            "currency": "TWD",
            "display": "NT$120",
            "description": "內部測試期間限時2折優惠",
            "valid_until": "2025-03-31T23:59:59Z"
          }
        },
        "billing_cycle": "monthly",
        "trial_period": {
          "duration_days": 7,
          "available": true
        },
        "features": [
          {
            "feature_id": "unlimited_dialogue",
            "name": "無限制對話練習",
            "description": "解鎖所有對話訓練場景,無每日次數限制"
          },
          {
            "feature_id": "advanced_scenarios",
            "name": "進階情境練習",
            "description": "商務、醫療、學術等專業場景"
          },
          {
            "feature_id": "detailed_analysis",
            "name": "詳細學習分析",
            "description": "Microsoft AI 驅動的語言評估和建議"
          },
          {
            "feature_id": "priority_support",
            "name": "優先客服支援",
            "description": "專屬客服通道,優先處理問題"
          }
        ],
        "platform_config": {
          "ios": {
            "product_id": "dramaling.subscription.monthly",
            "app_store_id": "6451234567"
          },
          "android": {
            "sku": "dramaling_monthly_subscription",
            "billing_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOC..."
          }
        }
      }
    ],
    "current_user_status": {
      "is_subscribed": false,
      "user_type": "guest", // guest, registered
      "device_id": "DEV_iOS_12345",
      "eligible_for_trial": true,
      "subscription_triggers": [
        {
          "trigger_id": "first_dialogue_attempt",
          "description": "首次嘗試對話訓練時",
          "timing": "immediate"
        },
        {
          "trigger_id": "vocabulary_completion",
          "description": "完成詞彙練習後",
          "timing": "after_completion"
        }
      ]
    }
  }
}

2. 驗證內購收據

POST /api/v1/subscriptions/verify-receipt
Authorization: Bearer <access_token> // 訪客用戶可選
Content-Type: application/json

{
  "platform": "ios", // ios, android
  "receipt_data": "base64_encoded_receipt",
  "transaction_id": "1000000123456789",
  "product_id": "dramaling.subscription.monthly",
  "user_context": {
    "user_type": "guest", // guest, registered
    "device_id": "DEV_iOS_12345",
    "subscription_trigger": "dialogue_access_blocked"
  }
}

iOS 收據驗證範例

Response 200 OK
{
  "success": true,
  "data": {
    "subscription_created": {
      "subscription_id": "SUB_20240907_001",
      "plan_id": "PLAN_MONTHLY_TWD",
      "user_id": "USR_12345", // null for guest users
      "device_id": "DEV_iOS_12345",
      "status": "active"
    },
    "receipt_validation": {
      "is_valid": true,
      "platform": "ios",
      "original_transaction_id": "1000000123456789",
      "purchase_date": "2024-09-07T12:00:00Z",
      "expires_date": "2024-10-07T12:00:00Z",
      "product_id": "dramaling.subscription.monthly",
      "auto_renew_status": true
    },
    "subscription_details": {
      "activated_at": "2024-09-07T12:00:00Z",
      "expires_at": "2024-10-07T12:00:00Z",
      "auto_renewal": true,
      "billing_cycle": "monthly",
      "is_trial_period": false,
      "price_paid": {
        "amount": 120,
        "currency": "TWD",
        "was_discounted": true
      }
    },
    "unlocked_features": [
      "unlimited_dialogue",
      "advanced_scenarios", 
      "detailed_analysis",
      "priority_support"
    ]
  },
  "message": "Subscription activated successfully"
}

3. 檢查訂閱狀態

GET /api/v1/subscriptions/status
Authorization: Bearer <access_token> // 訪客用戶可選

查詢參數

  • include_features: 是否包含功能權限詳情 (true/false)
  • check_renewal: 是否檢查自動續訂狀態 (true/false)

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "subscription_status": {
      "is_active": true,
      "subscription_id": "SUB_20240907_001",
      "plan_id": "PLAN_MONTHLY_TWD",
      "status": "active", // active, expired, cancelled, pending
      "activated_at": "2024-09-07T12:00:00Z",
      "expires_at": "2024-10-07T12:00:00Z",
      "days_remaining": 30,
      "auto_renewal": true,
      "billing_cycle": "monthly"
    },
    "user_context": {
      "user_type": "registered", // guest, registered
      "device_id": "DEV_iOS_12345",
      "platform": "ios"
    },
    "access_permissions": {
      "dialogue_training": {
        "has_access": true,
        "access_type": "unlimited",
        "restrictions": []
      },
      "advanced_features": {
        "detailed_analysis": true,
        "progress_reports": true,
        "priority_support": true,
        "offline_content": false // 未來功能
      }
    },
    "usage_statistics": {
      "dialogues_this_month": 45,
      "analysis_requests": 23,
      "last_activity": "2024-09-07T11:30:00Z"
    }
  }
}

4. 取消訂閱

POST /api/v1/subscriptions/cancel
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "cancellation_reason": "too_expensive", // too_expensive, not_using, technical_issues, other
  "feedback": "價格對學生來說太高了",
  "immediate_cancellation": false // true: 立即取消, false: 期滿後取消
}

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "cancellation_processed": {
      "subscription_id": "SUB_20240907_001",
      "cancellation_effective_date": "2024-10-07T12:00:00Z",
      "immediate_cancellation": false,
      "remaining_access_days": 30
    },
    "retention_offer": {
      "offer_id": "RETENTION_STUDENT_50",
      "discount_percentage": 50,
      "offer_description": "學生專屬50%折扣",
      "valid_until": "2024-09-14T12:00:00Z",
      "reactivation_url": "/subscriptions/reactivate?offer=RETENTION_STUDENT_50"
    },
    "feature_impact": {
      "features_will_be_disabled": [
        "unlimited_dialogue",
        "detailed_analysis"
      ],
      "features_remain_accessible": [
        "basic_vocabulary",
        "spaced_repetition"
      ]
    }
  },
  "message": "Subscription will be cancelled at the end of current billing period"
}

5. 重新啟用訂閱

POST /api/v1/subscriptions/reactivate
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "offer_id": "RETENTION_STUDENT_50", // 可選,使用挽留優惠
  "payment_method_update": {
    "platform": "ios",
    "new_receipt_data": "base64_receipt_data"
  }
}

6. 訂閱歷史記錄

GET /api/v1/subscriptions/history
Authorization: Bearer <access_token>

查詢參數

  • start_date: 開始日期
  • end_date: 結束日期
  • status: 訂閱狀態篩選
  • page: 頁碼
  • limit: 每頁筆數

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "subscription_history": [
      {
        "subscription_id": "SUB_20240907_001",
        "plan_name": "月費會員",
        "status": "active",
        "activated_at": "2024-09-07T12:00:00Z",
        "expires_at": "2024-10-07T12:00:00Z",
        "platform": "ios",
        "amount_paid": 120,
        "currency": "TWD",
        "transaction_id": "1000000123456789"
      }
    ],
    "summary": {
      "total_subscriptions": 1,
      "total_amount_paid": 120,
      "currency": "TWD",
      "average_subscription_length": 30, // days
      "most_recent_status": "active"
    },
    "pagination": {
      "current_page": 1,
      "total_pages": 1,
      "total_items": 1
    }
  }
}

7. 訂閱優惠和促銷

GET /api/v1/subscriptions/offers
Authorization: Bearer <access_token> // 可選

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "active_offers": [
      {
        "offer_id": "NEW_USER_TRIAL",
        "name": "新用戶免費試用",
        "description": "7天免費試用隨時可取消",
        "discount_type": "free_trial",
        "trial_duration_days": 7,
        "applicable_plans": ["PLAN_MONTHLY_TWD"],
        "eligibility": {
          "new_users_only": true,
          "device_restriction": false,
          "geographic_restriction": ["TW"]
        },
        "valid_until": "2024-12-31T23:59:59Z"
      },
      {
        "offer_id": "STUDENT_DISCOUNT",
        "name": "學生專屬折扣",
        "description": "學生身分驗證後享50%折扣",
        "discount_type": "percentage",
        "discount_percentage": 50,
        "verification_required": "student_email",
        "valid_until": "2024-12-31T23:59:59Z"
      }
    ],
    "user_eligibility": {
      "eligible_offers": ["NEW_USER_TRIAL"],
      "ineligible_offers": [
        {
          "offer_id": "STUDENT_DISCOUNT",
          "reason": "verification_required"
        }
      ]
    }
  }
}

🔐 權限控制系統

功能權限矩陣

功能 免費用戶 訂閱用戶 備註
基礎詞彙練習 完全開放
間隔複習 完全開放
對話訓練 需訂閱解鎖
進階場景 需訂閱解鎖
詳細分析報告 需訂閱解鎖
語言程度評估 需訂閱解鎖

權限檢查 API

GET /api/v1/subscriptions/check-access/{feature_id}
Authorization: Bearer <access_token>

回應範例

Response 200 OK
{
  "success": true,
  "data": {
    "feature_id": "dialogue_training",
    "has_access": false,
    "access_reason": "subscription_required",
    "subscription_info": {
      "required_plan": "PLAN_MONTHLY_TWD",
      "upgrade_url": "/subscriptions/plans",
      "current_status": "expired"
    },
    "alternative_actions": [
      "subscribe_now",
      "start_free_trial",
      "use_basic_features"
    ]
  }
}

🔧 錯誤處理

訂閱相關錯誤

錯誤碼 HTTP狀態 描述 處理建議
SUBSCRIPTION_NOT_FOUND 404 訂閱記錄不存在 檢查訂閱狀態或重新訂閱
SUBSCRIPTION_EXPIRED 403 訂閱已過期 引導用戶續訂
SUBSCRIPTION_CANCELLED 403 訂閱已取消 提供重新訂閱選項
RECEIPT_VERIFICATION_FAILED 400 收據驗證失敗 檢查收據格式或重新購買
RECEIPT_INVALID 400 收據無效 聯繫App Store/Google Play
SUBSCRIPTION_ALREADY_ACTIVE 409 訂閱已啟用 提示用戶當前訂閱狀態
PLATFORM_VERIFICATION_ERROR 502 平台驗證服務錯誤 稍後重試
REFUND_PROCESSING_ERROR 400 退款處理失敗 聯繫客服

錯誤回應範例

Response 403 Forbidden
{
  "success": false,
  "error": {
    "code": "SUBSCRIPTION_EXPIRED",
    "message": "訂閱已過期,無法存取此功能",
    "details": {
      "expired_at": "2024-09-01T12:00:00Z",
      "days_since_expiration": 6,
      "grace_period_remaining": 1,
      "renewal_options": [
        {
          "plan_id": "PLAN_MONTHLY_TWD",
          "price": 600,
          "currency": "TWD"
        }
      ]
    }
  }
}

🧪 測試範例

檢查訂閱狀態

curl -X GET "https://api.dramaling.com/api/v1/subscriptions/status" \
  -H "Authorization: Bearer <access_token>"

驗證iOS收據

curl -X POST "https://api.dramaling.com/api/v1/subscriptions/verify-receipt" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "ios",
    "receipt_data": "base64_receipt_here",
    "transaction_id": "1000000123456789",
    "product_id": "dramaling.subscription.monthly"
  }'

取消訂閱

curl -X POST "https://api.dramaling.com/api/v1/subscriptions/cancel" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "cancellation_reason": "not_using",
    "feedback": "暫時不需要進階功能",
    "immediate_cancellation": false
  }'

📊 收據驗證流程

iOS App Store 驗證

  1. 客戶端完成內購後取得收據
  2. 將收據傳送到後端 API
  3. 後端調用 Apple App Store API 驗證
  4. 驗證成功後啟用訂閱

Google Play 驗證

  1. 客戶端完成內購後取得購買token
  2. 將token傳送到後端 API
  3. 後端調用 Google Play Developer API 驗證
  4. 驗證成功後啟用訂閱

模組負責人: 後端團隊 + 金流團隊
最後更新: 2024年9月7日
相關文檔: 用戶管理API, 錯誤處理