# 广告先发奖、异步验真与火花人工核查(0.4.2) 此文是当前广告接入规则,替代0.3.0的“验真后发奖”。账号注销、禁用、会话和公共权益消费协议继续沿用。 ## 前后端分工 前端仍集成渠道广告SDK。App后端认证用户、创建广告上下文并转发SDK完成通知;公共服务掌管奖励字段配置、余额及一次性发奖。渠道服务端回调只补验真事实,不触发第二次发奖,不自动追回、不自动封禁。 1. App后端POST /v1/apps/{appId}/ads/contexts,{appUserId,placement,idempotencyKey}。奖励场景/字段/数量来自受控配置,前端不能传任意奖励数值。使用响应contextId作为穿山甲extra,公共用户ID作为user_id。上下文30分钟有效。 2. SDK看完广告的完成回调给到前端,前端请求自己的App后端。后端根据当前认证用户和服务端保存的context映射调用POST /ads/contexts/{contextId}/complete,{appUserId,transactionId}。transactionId可选;SDK当时已提供则传真实渠道交易号,尚未拿到就省略,不自行生成、不等待验真才发奖。防重复以contextId为准,渠道回调后补齐交易事实。展示回调不能冒充完成。 3. 公共服务原子记录完成、奖励流水、余额及广告上报快照。返回state=rewarded、rewarded=true;verification可以仍是pending。重复同context和交易号不重复发奖;相同context换交易号冲突409。前端读取公共余额刷新,不再本地加一次。 4. 渠道公网回调入口确认来源后,用独立管理令牌POST /ads/callbacks/{placement},{rawQuery:原始查询字符串}。穿山甲验证SecurityKey:trans_id签名、用户与context映射。回调可以先于SDK完成:先存valid,仍等完成通知才发奖;晚到回调更新验真,不再次发奖。 5. GET /ads/contexts/{contextId}返回独立的state/verification/rewarded。POST /display仅展示留痕,没有发奖能力。开屏可匿名,没有完成发奖流程。 路径均相对/v1/apps/{appId},普通接口使用运行Bearer;/ads/callbacks和/management使用独立管理Bearer。SDK完成通知代表客户端完成报告,不能写成服务端已证明真实观看。穿山甲签名只覆盖交易号,公网入口仍须可靠校验来源并保护回调原文,不把签名或服务凭据交前端。 ## 异步验证与人工处理 验证状态:pending待验证、valid有效、invalid异常、timeout超时。完成后24小时仍待验证转timeout;晚到有效回调可以纠正为valid。无效签名记录“回调签名无效,不能据此认定用户作弊”,不自动扣回已发奖励。格式无法解析或无法匹配上下文的请求被拒绝,不能随意算到某个用户头上。已验证有效不会被后来的无效签名降级。 后台没有可凭普通用户输入任意指定无效结论的公开接口。验真异常不改变公共余额或账号状态;人工需要采取外部措施时,使用独立授权流程,广告处理表单仅记录已人工采取的方式。 ## 全量同步火花 公共服务在每次创建、展示、完成发奖和验真变化时,以contextId+单调version持久保存快照。正常、待验证、异常、超时都上报;没有填写礼包码也上报,匿名开屏保留匿名遥测。回调重试不制造重复发奖,版本快照重试不重复新增广告记录。 目标POST /api/bounty/app/advertisements,使用既有每App平台签名身份,JSON包括contextId/version/appUserId/provider/placement/adType/state/verification/reason/transactionId/rewardField/rewardAmount/rewarded/createdAt/completedAt/rewardedAt/verifiedAt/observedAt。字段以最新平台控制OpenAPI附录为准。密钥、签名原文、心理测评内容不进入上报正文。 接收回执为{accepted:true,contextId,version};公共服务只在确认上下文及版本后标记送达,超时/错误持久退避重试,进程重启后恢复。较新版本先到时旧版本不能覆盖它,同版本不同正文409。同App上下文的用户、渠道、广告位和创建时间不可换绑。 这些广告事实单独保存,不通过赏金玩家进度API提交,不自动发火花赏金,也不把“已发App权益”当作“广告验真有效”。只有经审核批准的任务口径才可另行采集进度。 ## 火花后台 入口“广告数据核查” /ad-reviews。默认全部广告,可切异常记录,按应用ID、App用户ID、推广人ID、邀请人ID、验真及人工处理状态筛选。 邀请来源由火花自己的BountyGiftRedemption关联:App用户→最早礼包填写对应推广人→该推广人在火花的邀请人。App上报不接受promoterId或inviterId指定归因。暂未关联也保存广告数据;后续出现礼包记录时可查到来源。存在多个来源时明确提示需要核对,不能自动判定某个邀请人有问题。 详情显示奖励字段和数量、完成/发奖/验真时间、异常原因、推广人及邀请人。人工表单填写核查结论、处理方式和备注,保存操作人、时间与记录版本;重复提交有幂等操作ID。新证据更新后,旧版本处理不能覆盖新版本,历史处理记录保留,异常新版本重新待核查。 ## 部署、升级和支持范围 App数据库版本4,新增广告完成/发奖时间、独立验真状态、交易号、上报版本及ad_reports持久队列;双向迁移和备份包含它们。旧0.3.0已发奖励记录迁为valid,不重新发奖;后台生成初始快照等待上报。升级前停写备份,不用旧程序直接降级打开新库。 火花数据库新增迁移20261023120000_app_ad_review,需先执行迁移并部署接收API/后台,再升级公共服务;未部署接收API时快照保留重试,不假报已送达。接入AI不得直接操作生产库。 穿山甲与腾讯优量汇直连验真已适配;腾讯使用官方transid:secret顺序,不使用旧工程的双算法猜测。真实SDK完成交易号、广告位及回调网络仍需实际渠道联调;本地测试不代表真实平台验收。 ## 同步状态查询 0.4.1增加GET /ads/contexts/{contextId}/report-status,返回最新快照version、state(pending/sending/delivered)、attempts及lastError。只有delivered说明火花接收回执已核对;rewarded只表示App权益已发放。GET /sync-status同时返回advertisements各投递状态数量。没有平台配置时队列保留,不假报已送达。 历史0.3.0没有采集SDK完成时间,升级兼容记录的完成/发奖时间使用旧记录创建时间占位,不能据此还原旧SDK精确回调时刻;0.4起的新记录使用各阶段真实服务端时间。 0.4.2兼容SDK完成时暂无交易号的场景;complete正文只要求appUserId,transactionId可选。签名验真仍要求真实渠道交易号,不能把未取得交易号当作已验真。