跳转到内容

事件类型

无论来自哪个渠道,每个事件的顶层字段都相同。

{
"id": "evt_3f0c...",
"type": "subscription.renewed",
"created_at": "2026-11-01T12:00:03.000Z",
"app_user_id": "6f1c2a3b-4d5e-4f60-8a71-92b3c4d5e6f7",
"platform": "ios",
"environment": "production",
"product_id": "pro_monthly",
"transaction_id": "2000000789",
"original_transaction_id": "2000000123",
"purchased_at": "2026-11-01T12:00:00.000Z",
"expires_at": "2026-12-01T12:00:00.000Z",
"price_micros": 9990000,
"currency": "USD",
"ownership": "purchased",
"data": { "store": "app_store", "notification_type": "DID_RENEW", "transaction_reason": "RENEWAL", "status": "active", "will_renew": true }
}
字段 含义
id 稳定的事件 id,用来去重
type 下表中的一种类型
platform ios、android、web 或 test
environment production、sandbox 或 test。见环境
price_micros 价格乘以 1,000,000,币种为原始 currency;9.99 USD 即 9990000
ownership purchased 或 family_shared
data 渠道详情。data.store 为 app_store、google_play、stripe、ccbill 或 test_store
类型 触发时机
purchase 记录了一笔一次性商品购买(消耗型、非消耗型、非续期订阅)
subscription.started 新订阅,或到期后重新订阅
subscription.renewed 续订成功,包括扣款失败后的恢复(data.recovered)
subscription.product_changed 升级(立即生效,产生新交易)或降级(data.change:downgrade 或 downgrade_canceled,data.effective:next_renewal,data.new_product_id)
subscription.canceled 关闭了自动续订。权限保留到 expires_at
subscription.uncanceled 重新打开了自动续订
subscription.billing_issue 扣款失败。data.in_grace_period 表示权限是否继续
subscription.grace_period_expired 宽限期结束,仍未扣款成功
subscription.expired 订阅结束。data.expiration_reason:VOLUNTARY、BILLING_RETRY、PRICE_INCREASE、PRODUCT_NOT_FOR_SALE,其他渠道还有 DEVELOPER 或 DISPUTE
subscription.paused 仅 Android。带 data.auto_resume_time
refund 已退款。请收回权限
refund.reversed Apple 撤销了退款。请恢复权限
refund.consumption_requested Apple 索要消费信息(data.deadline_at、data.default_refund_preference)
revoked 家人共享的权限被撤销
chargeback Stripe 发起拒付。不会收回权限,由你自行决定
chargeback.closed 拒付结案,data.outcome 为 won 或 lost。结果为 lost 时随后会有一条 data.reason: "chargeback_lost" 的 refund
ad.reward 一个激励广告被完整观看。见广告奖励
test 只由测试回调接口发送。校验签名、返回 2xx,其他什么都不做

只有 Kasskeep 知道对应用户时才会产生事件。不带 appAccountToken 的交易(比如在 App 外兑换的优惠码)会被静默保存,等有用户提交它时再发出事件。

并非每个渠道都会产生所有类型。

类型 App Store Google Play Stripe 测试商店
subscription.paused ✓
refund.reversed ✓ ✓
refund.consumption_requested ✓
revoked ✓ ✓
chargeback、chargeback.closed ✓

在 Android 上,data 还带有 purchase_token、subscription_state、base_plan_id、offer_id 和 notification_type(RTDN 名称)。在 Stripe 上,视情况带有 notification_type、notification_id、subscription_id、invoice_id、stripe_status 和 checkout_session_id。

  1. 校验签名。
  2. 保存事件 id。如果已经处理过,返回 2xx 并结束。
  3. 不要依赖顺序。依据 created_at 和事件里的字段,或者用私钥从 GET /v1/customers/:app_user_id 读取当前状态。
  4. sandbox 和 test 事件不算收入。
  5. 在 10 秒内返回 2xx。耗时的工作放到响应之后做。