升级建议配置
config/upgrade.ts 中的 OAuth 授权范围升级规则、套餐信息和默认行为。
config/upgrade.ts 导出 websiteScopeUpgradePolicies,服务端通过 getServerConfig().upgrade 读取。它用于 OAuth 授权页在特定角色或权益条件下展示套餐升级建议。
默认配置
import type { OAuthUpgradeRule } from '@/core/services/oauth2-server/types';
import type { Scope } from './scopes';
export const websiteScopeUpgradePolicies = {
} as const satisfies Partial<Record<Scope, OAuthUpgradeRule[]>>;当前生效值是空对象。源文件中的注释只是示意,不是已经启用的产品或升级规则,不应直接取消注释使用。
对象的键对应 config/scopes.ts 中的 Scope,每个键的值是一组规则。可以不为某个 Scope 配置规则,但配置后规则数组不能是空数组,每条规则的 upgradePlans 也至少要有一项。
规则字段
| 字段 | 类型 | 说明 |
|---|---|---|
id | string,可选 | 规则标识,填写时不能为空 |
description | LocalizedText,可选 | 规则说明 |
trigger | Condition | 匹配用户当前有效角色或权益的条件 |
upgradePlans | OAuthUpgradePlan[] | 条件匹配时展示的套餐 |
trigger 支持以下条件:
| 形式 | 含义 |
|---|---|
{ type: 'role', operator: 'in', values: [...] } | 用户拥有列出的任意一个角色 |
{ type: 'role', operator: 'not_in', values: [...] } | 用户不拥有列出的任何角色 |
{ type: 'entitlement', operator: 'has', values: [...] } | 用户拥有列出的任意一个权益 |
{ type: 'entitlement', operator: 'not_has', values: [...] } | 用户不拥有列出的任何权益 |
{ anyOf: [...] } | 至少一个子条件成立 |
{ allOf: [...] } | 全部子条件成立 |
{ noneOf: [...] } | 全部子条件都不成立 |
条件数组不能留空。条件描述的是“什么时候提示升级”,例如为尚未拥有某项权益的用户显示升级建议,应使用 not_has。
套餐字段
| 字段 | 类型 | 说明 |
|---|---|---|
productId | ProductId | 产品 ID,引用 products.ts |
planId | 对应产品的套餐 ID | 必须属于该产品 |
title、description | LocalizedText | 套餐标题和介绍 |
salePrice | string | 展示价格,例如 $9.99 |
listPrice | string,可选 | 展示原价 |
discountLabel | string,可选 | 折扣文案 |
billingLabel | string,可选 | 计费周期文案 |
recommended | boolean,可选 | 推荐标记 |
priority | 整数,可选 | 展示优先级 |
platforms | readonly string[],可选 | 平台标签 |
价格字符串只控制展示,不会创建或修改 Stripe Price,也不会改变 Checkout 实际收费。产品、套餐、支付价格和展示文案需要一起检查。
授权页如何使用
授权页逐项读取请求的 Scope。如果没有配置升级规则,该 Scope 进入可授权列表。如果规则匹配并返回套餐,该 Scope 会进入需要升级的列表,同时展示套餐信息。没有匹配套餐时,该 Scope 仍可进入可授权列表。
同一 Scope 中,多条规则匹配到同一个产品和套餐时,匹配函数按产品和套餐组合去重,保留先出现的套餐信息。
这份配置负责授权页的升级引导,不会自动授予角色或权益。业务 API 仍需检查登录状态、授权范围和业务权限,购买后的权益由支付流程处理。
修改后运行 npm run typecheck,并分别用满足条件和不满足条件的账号检查授权页。改名或删除 Scope、角色、权益、产品、套餐时,也要更新这里的引用。