125 lines
3.6 KiB
Markdown
125 lines
3.6 KiB
Markdown
# 注册奖励 Flutter 对接
|
||
|
||
## 边界
|
||
|
||
注册奖励由服务端在三方注册成功后自动发放。Flutter 端不需要、也不能主动发放奖励,只需要在登录态下查询当前用户是否仍满足领取条件,用于展示入口、提示或埋点。
|
||
|
||
服务端判断条件:
|
||
|
||
- 用户没有成功领取过注册奖励。
|
||
- 注册奖励配置已开启且奖励配置有效。
|
||
- UTC 当天每日限制份数未用完;`daily_limit=0` 表示不限量。
|
||
|
||
## 查询接口
|
||
|
||
`GET /api/v1/activities/registration-reward/eligibility`
|
||
|
||
请求头:
|
||
|
||
```http
|
||
Authorization: Bearer <access_token>
|
||
X-App-Code: lalu
|
||
```
|
||
|
||
响应仍使用 gateway 统一 envelope:
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "ok",
|
||
"request_id": "req_xxx",
|
||
"data": {
|
||
"can_receive": false,
|
||
"reason": "already_claimed",
|
||
"enabled": true,
|
||
"reward_type": "coin",
|
||
"coin_amount": 100,
|
||
"resource_group_id": 0,
|
||
"daily_limit": 1000,
|
||
"daily_used": 328,
|
||
"daily_remaining": 672,
|
||
"reward_day": "2026-05-12",
|
||
"server_time_ms": 1778563200000
|
||
}
|
||
}
|
||
```
|
||
|
||
`reason` 取值:
|
||
|
||
- `eligible`: 当前用户符合条件。
|
||
- `already_claimed`: 用户已经领取或正在发放中。
|
||
- `daily_limit_reached`: UTC 当天份数已用完。
|
||
- `disabled`: 后台关闭注册奖励。
|
||
- `not_configured`: 后台还没有配置注册奖励。
|
||
- `invalid_config`: 后台配置不完整,例如金币数量为 0 或资源组为空。
|
||
|
||
## Dart DTO
|
||
|
||
```dart
|
||
class RegistrationRewardEligibility {
|
||
const RegistrationRewardEligibility({
|
||
required this.canReceive,
|
||
required this.reason,
|
||
required this.enabled,
|
||
required this.rewardType,
|
||
required this.coinAmount,
|
||
required this.resourceGroupId,
|
||
required this.dailyLimit,
|
||
required this.dailyUsed,
|
||
required this.dailyRemaining,
|
||
required this.rewardDay,
|
||
required this.serverTimeMs,
|
||
});
|
||
|
||
final bool canReceive;
|
||
final String reason;
|
||
final bool enabled;
|
||
final String rewardType;
|
||
final int coinAmount;
|
||
final int resourceGroupId;
|
||
final int dailyLimit;
|
||
final int dailyUsed;
|
||
final int dailyRemaining;
|
||
final String rewardDay;
|
||
final int serverTimeMs;
|
||
|
||
factory RegistrationRewardEligibility.fromJson(Map<String, dynamic> json) {
|
||
return RegistrationRewardEligibility(
|
||
canReceive: json['can_receive'] == true,
|
||
reason: json['reason'] as String? ?? '',
|
||
enabled: json['enabled'] == true,
|
||
rewardType: json['reward_type'] as String? ?? '',
|
||
coinAmount: (json['coin_amount'] as num? ?? 0).toInt(),
|
||
resourceGroupId: (json['resource_group_id'] as num? ?? 0).toInt(),
|
||
dailyLimit: (json['daily_limit'] as num? ?? 0).toInt(),
|
||
dailyUsed: (json['daily_used'] as num? ?? 0).toInt(),
|
||
dailyRemaining: (json['daily_remaining'] as num? ?? 0).toInt(),
|
||
rewardDay: json['reward_day'] as String? ?? '',
|
||
serverTimeMs: (json['server_time_ms'] as num? ?? 0).toInt(),
|
||
);
|
||
}
|
||
}
|
||
```
|
||
|
||
## 调用示例
|
||
|
||
```dart
|
||
Future<RegistrationRewardEligibility> fetchRegistrationRewardEligibility(
|
||
ApiClient api,
|
||
) async {
|
||
final envelope = await api.get('/api/v1/activities/registration-reward/eligibility');
|
||
if (envelope.code != 0) {
|
||
throw ApiException(envelope.code, envelope.message);
|
||
}
|
||
return RegistrationRewardEligibility.fromJson(
|
||
envelope.data as Map<String, dynamic>,
|
||
);
|
||
}
|
||
```
|
||
|
||
## 客户端使用建议
|
||
|
||
新用户登录成功后可以调用一次该接口刷新展示状态;如果 `can_receive=false` 且 `reason=already_claimed`,说明服务端已经成功发放或发放中,不要重复提示用户手动领取。
|
||
|
||
`reward_day` 按 UTC 日期返回,不使用设备时区;客户端只做展示,不要用本地日期自行判断每日份数。
|