server/laf-cloud/signInActivity.API.md

11 KiB
Raw Blame History

七日签到后端接口文档

1. 基本约定

  • 基础地址:https://<APPID>.laf.run
  • 数据格式:application/json
  • 时区:UTC+8
  • 活动周期:触发当天为第 1 个自然日,第 15 天 00:00 结束
  • 签到规则:14 个自然日内累计领取 7 次,允许断签,每个自然日最多领取一次
  • 适用用户库:仅主游戏 users;gameName: "iaa" 不支持签到活动
  • 身份校验:请求携带登录接口返回的 uid 和 token
  • 通用成功码:code: 1
  • 通用失败码:code: 0

签到奖励由后端校验并记录,实际金币、道具、无限体力和猫皮肤仍由前端根据领取接口返回的 rewards 发放。前端必须使用 claimId 做发奖幂等。

2. 推荐调用流程

  1. 玩家进入主界面后调用 signInActivityInfo。
  2. 如果返回 data: false,表示玩家尚未达到目标关卡,不展示活动。
  3. 符合领取条件时,服务端保存领取前的展示快照,再异步执行并等待领取落库。
  4. 如果 data.todayClaim 非空,前端检查其 claimId 是否已处理,未处理才发放 todayClaim.rewards 并保存处理标记。
  5. 按照领取前的 status、canClaim、todayClaimed 和 rewards 渲染活动。本次请求触发自动领取时 canClaim: true,当档奖励的 claimed: false,便于播放领取展示;前端完成发奖后更新本地状态,不再需要调用 signInClaim。当天再次请求会返回已领取状态。

当天重复请求会返回同一个 todayClaim,用于首次响应丢失后的重试;它不表示本次新增领取。必须按 claimId 去重,不能每次收到就发奖。此接口具有写入行为,不应被预加载或轮询当作纯查询使用。todayClaim 只返回当天记录,不包含跨日未处理奖励的补领机制。

活动只在 users.levelAmount 达到目标关卡且没有活动状态的用户首次调用 signInActivityInfo 时创建。login 和 setUserLevel 均不读取签到配置、不判断签到资格,也不创建签到活动。

3. 查询签到活动信息

POST /signInActivityInfo

云函数同时配置了 GET 和 POST;客户端统一使用 POST。

请求参数

interface SignInActivityInfoRequest {
  uid: string;
  token: string;
  gameName?: string;
}
字段 类型 必填 说明
uid string 是 用户 _id
token string 是 登录令牌
gameName string 否 不传表示主游戏;传 iaa 会被拒绝

未达到目标关卡

{
  "code": 1,
  "data": false,
  "msg": "未达到签到活动开启关卡"
}

达到目标关卡

用户没有活动状态时,本次请求会创建活动;已有活动状态时不会重置开始和结束时间。

活动进行中且当天未领取时,本次请求会自动领取下一档奖励。当天已领、活动完成或过期时不新增领取记录。status、claimedCount、todayClaimed、canClaim、nextRewardDay 和 rewards[].claimed 均为本次自动领取前的快照;todayClaim 为落库后的当天领取凭据。数据库写入失败时返回失败或抛出服务端错误,不返回虚假的领取成功。

例如已有 Day 1、2 记录,本次自动领取 Day 3:返回 claimedCount: 2、todayClaimed: false、canClaim: true、nextRewardDay: 3,Day 1、2 的 claimed 为 true,Day 3~7 为 false,同时 todayClaim.rewardDay: 3。当天再次请求则返回 claimedCount: 3、todayClaimed: true、canClaim: false 和 Day 3 的 claimed: true。第 7 次领取的首次响应同样保留 status: active,再次请求才显示 completed。并发请求可能均读到领取前快照,前端发奖始终按 claimId 去重,不能只依赖 canClaim。

{
  "code": 1,
  "data": {
    "serverNow": 1788310800000,
    "activityId": "seven_day_sign_in_v1",
    "status": "active",
    "triggerLevel": 23,
    "triggerReached": true,
    "startAt": 1788278400000,
    "endAt": 1789488000000,
    "claimedCount": 0,
    "todayClaimed": false,
    "todayClaim": {
      "claimId": "71b4...9a2f",
      "rewardDay": 1,
      "rewards": [{ "type": "infinite_health", "count": 900 }]
    },
    "canClaim": true,
    "nextRewardDay": 1,
    "rewards": [
      {
        "day": 1,
        "items": [
          { "type": "infinite_health", "count": 900 }
        ],
        "claimed": false
      }
    ]
  },
  "msg": "成功"
}

返回字段

字段 类型 说明
serverNow number 服务器当前毫秒时间戳
activityId string 用户参与的活动配置 ID
status string active、completed 或 expired
triggerLevel number 活动开启目标关卡,当前配置为 23
triggerReached boolean 服务端根据 users.levelAmount 确认的关卡是否达标
startAt number 活动第 1 天 UTC+8 零点时间戳
endAt number 活动结束时间戳,不包含该时刻
claimedCount number 本次自动领取前的已领取奖励天数,范围 0~7
todayClaimed boolean 本次自动领取前,当前 UTC+8 自然日是否已经领取
todayClaim object | null 当天领取凭据:claimId: string、rewardDay: number、rewards: RewardItem[];当天无记录为 null,重复请求返回相同凭据
canClaim boolean 本次自动领取前是否可领,用于展示领取过程,不代表响应后还能再次领取
nextRewardDay number | null 下一档奖励序号;当前不可领取时为 null
rewards RewardDay[] 完整七天奖励及每档领取状态

状态说明:

状态 说明
active 活动期内且尚未领取满 7 天
completed 已领取全部 7 天奖励
expired 已到第 15 天 00:00 且未领取满 7 天

4. 领取签到奖励

POST /signInClaim

保留兼容旧客户端,与活动信息接口复用同一领取实现。新流程无需额外调用;活动信息接口自动领取后,当天调用此接口会返回“今天已经领取”。

客户端不能指定领取第几天。后端按照当前累计领取次数自动发放下一档配置,并使用用户、活动和自然日生成唯一 claimId。

请求参数

interface SignInClaimRequest {
  uid: string;
  token: string;
  gameName?: string;
}

成功响应

{
  "code": 1,
  "data": {
    "claimId": "71b4...9a2f",
    "rewardDay": 1,
    "rewards": [
      { "type": "infinite_health", "count": 900 }
    ],
    "claimedCount": 1,
    "todayClaimed": true,
    "completed": false
  },
  "msg": "领取成功"
}

返回字段

字段 类型 说明
claimId string 本次领取唯一标识,前端发奖幂等键
rewardDay number 本次领取的奖励序号,范围 1~7
rewards RewardItem[] 本次需要由前端发放的奖励
claimedCount number 领取成功后的累计领取天数
todayClaimed boolean 成功时固定为 true
completed boolean 本次领取后是否已经领满 7 天

5. 奖励数据结构

interface RewardDay {
  day: number;
  items: RewardItem[];
  claimed: boolean;
}

interface RewardItem {
  type: "coin" | "freeze" | "hammer" | "magic_wand" | "infinite_health" | "cat_skin";
  count: number;
  itemId?: number;
}
type 含义 count 单位 额外字段
coin 金币 个 无
hammer 锤子 个 无
freeze 冻结道具 个 无
magic_wand 魔法棒 个 无
infinite_health 无限体力 秒 无
cat_skin 猫皮肤 个 必须提供正整数 itemId

当前七天配置:

Day 奖励数据 展示含义
1 infinite_health: 900 无限体力 15 分钟
2 hammer: 1 锤子 ×1
3 infinite_health: 1800 无限体力 30 分钟
4 freeze: 1、magic_wand: 1 冻结 ×1、魔法棒 ×1
5 coin: 600 金币 ×600
6 hammer: 1、freeze: 1、magic_wand: 1 三种道具各 ×1
7 infinite_health: 3600、cat_skin: 1, itemId: 12 无限体力 1 小时、专属猫 12

6. 错误响应

两个签到接口共用的错误:

code data msg 触发条件
0 null 未获取到uid 未传 uid
0 null 七日签到仅支持主游戏 gameName 为 iaa
0 null 未获取到用户信息 用户不存在
0 null token校验失败 token 不匹配
0 null 签到活动配置不存在或配置无效 找不到配置、配置非法或同时启用多条配置

signInActivityInfo 特有错误:

code data msg
0 null 签到活动开启失败

signInClaim 特有错误:

code data msg
0 null 签到活动尚未开启
0 null 七日签到奖励已全部领取
0 null 七日签到活动已结束
0 null 今天已经领取
0 null 签到奖励配置异常

7. 数据库配置

配置集合:sign_in_activity_config

  • 必须且只能存在一条 enabled: true 的有效配置。
  • 当前可导入配置文件:laf-cloud/sign-in-activity-config.json。
  • 用户开始活动后通过 activityId 继续读取配置,因此旧配置可以禁用,但在参与用户全部结束前不能删除。

用户活动状态写入 users.signInActivity。数据库中使用 JSON 字符串保存,读取时由服务端解析为下述结构;这样可以兼容字段原值为 null 的用户,并避免 Laf 将对象更新展开成点路径后触发 MongoDB 错误:

interface SignInActivityState {
  activityId: string;
  startAt: number;
  endAt: number;
  activatedAt: number;
  completedAt: number | null;
}

领取记录集合:sign_in_activity_claims

  • 每次领取保存奖励序号、奖励快照和领取时间。
  • 记录 _id 与 claimId 相同,由 uid + activityId + UTC+8自然日 计算 SHA-256。
  • 同一用户、同一活动、同一自然日的并发请求只能成功写入一条记录。

8. 前端接入注意事项

  • 不要根据客户端本地关卡自行判定资格;服务端使用 users.levelAmount 判断,以 signInActivityInfo 返回值为准。
  • data: false 是正常成功响应,不应作为网络或服务器错误处理。
  • 领取成功不代表后端已经增加资产;前端负责发奖。
  • 前端必须保存已处理的 claimId,避免重复回调造成重复发奖。
  • infinite_health.count 单位是秒。
  • Day 7 的 cat_skin.itemId 当前为 12,客户端必须先支持猫 12 的资源、展示和幂等写入 catArr。
  • 倒计时使用 serverNow 和 endAt,不要完全依赖客户端本地时间。

9. 单账号测试接口

测试环境可发布 POST /signInTestAdmin,用一个账号快速准备未达标、待领取 Day 1~7、当天已领、过期和完成状态。该接口的密钥配置、参数和测试顺序见 laf-cloud/signInActivity.TESTING.md;禁止在正式环境发布。