跳至主要内容

订阅 Webhooks

Aghanim 的订阅 webhooks 通知您的游戏关于订阅生命周期事件,使您能够管理玩家对基于订阅的内容和服务的访问。

Webhook 事件

使用这些 Webhook 事件来授予、延长或撤销订阅访问权限。

事件触发时间你应该做的事情
subscription.activated订阅变为活跃状态授予玩家订阅福利
subscription.updated订阅属性更改(状态、计划或账单日期)用更新的订阅数据同步内部状态
subscription.renewed经常性付款成功通过更新 effective_until 延长访问权限。 (可选)在每次成功续订时授予奖励(如果适用)
subscription.deactivated订阅被停用立即撤销订阅福利
幂等性很重要

Webhook 事件可能会多次传递,因此处理程序必须是幂等的

订阅状态

状态用于跟踪订阅的当前状态。

状态描述
trial订阅处于试用期。
active订阅已付费且状态良好。
canceled订阅不会续订。 它保持活跃状态直到 effective_until,然后过渡到 expired
expired订阅不再活跃。
向前兼容性

未来可能会添加新的订阅状态。

为了保持你的集成具备向前兼容性,不要仅依赖订阅状态来授予或撤销权益。 始终依赖 event_typeeffective_until 作为激活和停用订阅访问权限的真实来源。

不要在你的代码中将 status 建模为严格的枚举 — 将其视为字符串,以避免在引入新值时发生破坏。

常见场景

以下示例展示了典型的订阅流程以及每个阶段触发的事件:

试用期 → 付费

  1. subscription.activated 状态=trial → 授权访问
  2. subscription.updated 状态=active → 试用期转换为付费(首次成功付款),延长 effective_until

经常性付款

  1. subscription.renewed 状态=active → 延长访问权限(更新 effective_until
  2. (可选)在每次成功续订时授予奖励(如果适用)

取消

  1. subscription.updated 状态=canceled → 访问权限保持活跃直到 effective_until
  2. subscription.deactivated → 撤销访问权限

过期

  1. subscription.deactivated status=expired → 撤销访问权限
  2. (可选)如果未收到 Webhook,当 now >= effective_until 时撤销访问

要求

如需使用 Aghanim 的订阅 Webhook,您应该将 Webhook 服务器配置如下:

  • HTTPS 端点,可接收 POST Webhook 请求。
  • 监听由 Aghanim 生成并签名的事件。
  • 实现幂等性机制,利用请求中的 idempotency_key 确保即使收到重复事件通知也只处理一次。
  • 如果成功处理了订阅事件,则响应 2xx 状态码;如有错误,则用 4xx 或 5xx 状态码。

配置步骤

  1. 为订阅 Webhook 处理开发一个函数。
  2. 部署您的端点使其可访问。
  3. 在 Aghanim 帐户中选择您要处理的订阅事件类型以注册您的端点 → 游戏Webhooks新 Webhook

或者,您也可以使用 Create Webhook API 方法在 Aghanim 中注册您的端点。

请求模式

下面是一个 subscription.activated Webhook 请求示例:

POST /your/webhook/uri HTTP/1.1
Content-Type: application/json
Host: your-webhook-endpoint.com
User-Agent: Aghanim/0.1.0
X-Aghanim-Signature: 2e45ed4dede5e09506717490655d2f78e96d4261040ef48cc623a780bda38812
X-Aghanim-Signature-Timestamp: 1725548450

{
"event_type": "subscription.activated",
"event_data": {
"id": "sub_kMnoPqRsTuV",
"sku": "battle_pass",
"name": "战斗通行证",
"nested_items": [
{
"id": "itm_zzzzzzz",
"name": "独占皮肤",
"description": "限量版订阅者皮肤",
"sku": "exclusive_skin_001",
"quantity": 1,
"type": "item"
}
],
"order_id": "ord_eCacpFwavzi",
"user_id": "usr_eymySUreClx",
"player_id": "2D2R-OP3C",
"amount": 999,
"amount_decimal": 9.99,
"currency": "USD",
"payment_method": "cards",
"status": "active",
"due_at": 1706745600,
"created_at": 1704067200,
"plan": {
"key": "battle_pass_monthly",
"name": "战斗通行证每月",
"amount": 999,
"amount_decimal": 9.99,
"currency": "USD",
"offer": {
"key": "season_launch",
"name": "季节启动奖励",
"description": "季节启动的特别折扣",
"discount_percent": 20,
"grace_extension": 3,
"trial_extension": 7
},
"cycle_period": 30,
"grace_period": 3,
"trial_period": 7,
"nested_items": [
{
"id": "itm_xxxxxxx",
"name": "500金币奖励",
"description": "订阅者的每月金币奖励",
"sku": "bonus_gold_500",
"quantity": 1,
"type": "item"
},
{
"id": "itm_yyyyyyy",
"name": "经验值提升",
"description": "订阅期间激活的25%经验值提升",
"sku": "xp_boost_25",
"quantity": 1,
"type": "item"
}
]
},
"effective_until": 1705276800,
"trial_due_at": 1705276800,
"paid_due_at": 1704067200,
"updated_at": 1704067200,
"metadata": {
"tier": "高级",
"referral_code": "SUMMER2024"
}
},
"event_time": 1725548450,
"event_id": "whevt_eCacGbJVbvToOgzjXUgOCitkQE",
"idempotency_key": "idmpt_aXRlb...JkX2VFS",
"request_id": "d1593e9c-c291-4004-8846-6679c2e5810b",
"sandbox": false,
"trigger": "subscription.activated",
"transaction_id": "whtx_eCacGbJVbvT",
"context": null,
"game_id": "gm_exTAyxPsVwh"
}

事件 Schema

键名类型描述
event_idstring阿哈利姆生成的唯一事件标识符。
game_idstring您的游戏在阿哈利姆中的唯一标识符。
event_typestring事件的类型, subscription.activated 在此情境下。
event_timenumber以 Unix 时间戳表示的事件发生日期。
event_dataEventData包含事件特定数据的字段,其中可能包含用于继承对象的各种键值。
idempotency_keystring即使出现重试情况,也能确保 Webhook 操作只执行一次。
request_idstring|null如果事件是通过 API 请求触发的,此字段将包含对应的请求 ID。
sandboxboolean标识事件是否来自沙盒测试环境的指示器。
triggerstring|null触发该事件发送的触发器。
transaction_idstring阿哈利姆生成的交易标识符。在同一交易过程中触发的多个事件可能共享相同的交易 ID。
contextEventContext|null事件的相关上下文信息。

EventContext Schema

键名类型描述
orderOrderContext|null与事件相关的订单信息(如果适用)。
playerPlayerContext|null(可选)玩家信息。如需启用,请在webhook设置中选择“添加玩家上下文”。

EventData Schema

键名类型描述
idstring此订阅实例的唯一标识符。使用此 ID 可在整个生命周期内跟踪和管理该订阅。
skustring订阅的唯一 SKU。
namestring订阅的显示名称。
nested_itemsNestedItem[]此订阅中包含的商品。
order_idstring最初激活该订阅的订单 ID。可用于与订单 Webhook 进行关联。
user_idstring用户在阿哈利姆游戏枢纽中的唯一标识符。
player_idstring唯一的 用于玩家身份验证的玩家标识符.
amountnumber订阅金额使用 最小货币单位.
amount_decimalnumber订阅金额使用 主要货币单位.
currencystring订阅 货币单位.
payment_methodstring使用的支付方式(cards、apple_pay、google_pay、paypal 等)。
statusstring订阅状态。请参阅上文的订阅状态。
due_atnumber以 Unix 时间戳(秒)表示的下次付款到期日期。对于试用订阅,这是首次扣款发生的时间。
created_atnumber以 Unix 时间戳(秒)表示的订阅创建日期。
planPlan与该订阅关联的计划。
effective_untilnumber以 Unix 时间戳(秒)表示的订阅有效截止日期。此值为 trial_due_at 和 paid_due_at 中的较大者,代表订阅福利应保持可用的时间。
trial_due_atnumber|null以 Unix 时间戳(秒)表示的试用期结束日期。若订阅没有试用期,则为 null。
paid_due_atnumber|null以 Unix 时间戳(秒)表示的订阅已付费截止日期(paid-through 日期)。在此日期之后,订阅必须续订,否则将过期。在试用期内或首次付款之前为 null。
updated_atnumber|null以 Unix 时间戳(秒)表示的订阅最后更新日期。若订阅从未更新过,则为 null。
metadataobject|null附加到该订阅的自定义键值对。若未设置任何元数据,则为 null。

Plan Schema

键名类型描述
keystring订阅内计划的唯一键。
namestring计划的显示名称。
amountnumber计划金额使用 最小货币单位.
amount_decimalnumber计划金额使用 主要货币单位.
currencystring计划 货币单位.
offerOffer|null应用于该计划的优惠。若未应用任何优惠,则为 null。
cycle_periodnumber|null以天为单位的定期计费周期(例如,30 表示每月,365 表示每年)。
grace_periodnumber|null付款失败后订阅仍保持活跃并进行重试尝试的天数。若未配置宽限期,则为 null。
trial_periodnumber|null以天为单位的试用期时长。若计划没有试用期,则为 null。
nested_itemsNestedItem[]此计划中包含的商品。

Offer Schema

键名类型描述
keystring优惠的唯一键。
namestring|null优惠的显示名称。
descriptionstring|null优惠的描述。
discount_percentnumber|null折扣百分比。
grace_extensionnumber|null以天为单位的宽限期延长时长。
trial_extensionnumber|null以天为单位的试用期延长时长。

NestedItem Schema

键名类型描述
idstring阿哈利姆生成的商品唯一标识符。
namestring商品名称。
descriptionstring|null商品描述。
skustring商品的 SKU 标识符,必须确保在游戏系统和阿哈利姆上保持一致。
quantitynumber商品数量。
fallback_itemItem|null如果无法向玩家发放主要商品,系统将提供的备选商品。
metadataobject|null该商品的自定义键值对,用于支持您端的额外逻辑。

需要技术支持?
联系我们的集成技术团队: [email protected]