feat(server): 免费版账户级分钟卡控 + 累加式看广告加时(#21 后端)
免费版此前形同虚设:ConnectNode 每次连接发固定 daily_minutes×1min TTL、
从不扣减已用,重连即崭新 10 分钟,日额度从未强制。改为账户级(全设备共享)
真卡控 + 累加式看广告加时:
- migration 000020: usage_daily 加 ad_bonus_minutes(sqlite+mysql)。
当日额度 = plans.daily_minutes + ad_bonus_minutes;剩余 = 额度 − minutes_used。
- usage.store.AddAdBonusMinutes: 事务内累加封顶(替代布尔 MarkAdUnlocked),
返回新总额+本次实际加时;GetDay/GetUsageRange 补读 ad_bonus_minutes。
- usage.service.UnlockAd: verify+nonce 后 +adBonusPerAd(10) 封顶 adDailyBonusCeiling(120),
返回 granted+remaining;TodaySummary 加 MinutesCap/AdBonusMinutes。
- usage.ads DevVerifier: 放行式占位校验(nonce 防重放仍生效),接真 AdMob 前
让看广告加时流程可端到端跑通;main.go 按 ADS_DEV_MODE/默认装配。
- ads/unlock: 204 → 200 返回 {granted_minutes, minutes_remaining}。
- ConnectNode 免费门: 读 AccountDayMinutes(used,bonus) → remaining≤0 拒 QUOTA_EXHAUSTED,
否则 TTL=remaining(凭证到点硬切断兜底)。nodes.store 加 AccountDayMinutes。
- /me: 补 ad_bonus_minutes,quota_today_min 分母改 daily+bonus,加 quota_cap_min。
- quota.CheckFreeConnect 同步累加语义(免费基础 10 分钟不再需先看广告)。
- openapi + 契约/迁移版本/集成测试同步;新增 SQLite AddAdBonusMinutes 单测。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+28
-6
@@ -294,10 +294,11 @@ paths:
|
||||
/ads/unlock:
|
||||
post:
|
||||
operationId: adsUnlock
|
||||
summary: 激励视频广告解锁当日时长
|
||||
summary: 激励视频广告加时(累加式)
|
||||
description: |
|
||||
免费版用户完成激励视频广告后调用。服务端向广告平台(AdMob/Unity)校验 ad_token 真伪,
|
||||
通过后记录 `usage_daily.ad_unlocked_at`,当日 connect 接口方可放行。
|
||||
通过后向 `usage_daily.ad_bonus_minutes` 累加固定分钟(每日封顶),当日免费额度随之上浮。
|
||||
额度为**全账户共享**(非每设备)。响应返回本次实际加时与最新剩余分钟。
|
||||
tags: [Commerce]
|
||||
requestBody:
|
||||
required: true
|
||||
@@ -315,8 +316,20 @@ paths:
|
||||
type: string
|
||||
description: 广告 SDK 签发的服务端回执 token
|
||||
responses:
|
||||
"204":
|
||||
description: 广告解锁成功(无响应体)
|
||||
"200":
|
||||
description: 广告加时成功
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [granted_minutes, minutes_remaining]
|
||||
properties:
|
||||
granted_minutes:
|
||||
type: integer
|
||||
description: 本次广告实际加时分钟(已达每日封顶时为 0)
|
||||
minutes_remaining:
|
||||
type: integer
|
||||
description: 加时后账户当日剩余分钟(全账户共享)
|
||||
"400":
|
||||
$ref: "#/components/responses/BadRequest"
|
||||
"401":
|
||||
@@ -715,14 +728,23 @@ components:
|
||||
type: integer
|
||||
description: 今日已使用分钟数
|
||||
example: 3
|
||||
minutes_cap:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: 今日额度 = 套餐每日分钟 + 看广告累加分钟;付费无限制时为 null
|
||||
example: 20
|
||||
minutes_remaining:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: 今日剩余分钟数,付费无限制时为 null
|
||||
description: 今日剩余分钟数(全账户共享),付费无限制时为 null
|
||||
example: 7
|
||||
ad_bonus_minutes:
|
||||
type: integer
|
||||
description: 今日已通过看广告累加的分钟数
|
||||
example: 10
|
||||
ad_unlocked:
|
||||
type: boolean
|
||||
description: 免费版今日是否已完成激励广告解锁
|
||||
description: 免费版今日是否已通过看广告加过时(ad_bonus_minutes > 0,历史字段)
|
||||
example: false
|
||||
|
||||
Device:
|
||||
|
||||
Reference in New Issue
Block a user