跳至主要内容

订阅 Webhooks

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

Webhook 事件

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

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

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

订阅状态

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

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

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

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

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

常见场景

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

试用期 → 付费

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

经常性付款

  1. subscription.renewed 状态=进行中 → 延长访问权限(更新 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|nullThe trigger that caused the event to be sent.
transaction_idstring阿哈利姆生成的交易标识符。在同一交易过程中触发的多个事件可能共享相同的交易 ID。
contextEventContext|null事件的相关上下文信息。

EventContext Schema

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

The EventData schema

idstringUnique identifier for this subscription instance. Use this ID to track and manage the subscription throughout its lifecycle.
键名类型描述
skustringSubscription unique SKU.
namestringSubscription display name.
nested_itemsNestedItem[]Items included in this subscription.
order_idstringOrder ID where the subscription was originally activated. Use this to correlate with order webhooks.
user_idstring用户在阿哈利姆游戏枢纽中的唯一标识符。
player_idstring唯一的 用于玩家身份验证的玩家标识符.
amountnumberSubscription amount in 最小货币单位.
amount_decimalnumberSubscription amount in major currency units.
currencystringSubscription 货币单位.
payment_methodstringPayment method used (cards, apple_pay, google_pay, paypal, etc.).
statusstringSubscription status. See Subscription statuses above.
due_atnumberNext payment due date in Unix epoch time (seconds). For trial subscriptions, this is when the first charge will occur.
created_atnumberSubscription creation date in Unix epoch time (seconds).
planPlanPlan associated with the subscription.
effective_untilnumberThe date until which the subscription is effective in Unix epoch time (seconds). This is the higher value between trial_due_at and paid_due_at, representing when the subscription benefits should remain accessible.
trial_due_atnumber|nullTrial end date in Unix epoch time (seconds). Null if subscription has no trial.
paid_due_atnumber|nullDate through which the subscription is paid (paid-through date) in Unix epoch time (seconds). After this date, the subscription must be renewed or it will become expired. Null during trial or before first payment.
updated_atnumber|nullSubscription last update date in Unix epoch time (seconds). Null if the subscription has not been updated.
metadataobject|nullCustom key-value pairs attached to the subscription. Null if no metadata is set.

The Plan schema

键名类型描述
keystringPlan unique key within subscription.
namestringPlan display name.
amountnumberPlan amount in 最小货币单位.
amount_decimalnumberPlan amount in major currency units.
currencystringPlan 货币单位.
offerOffer|nullOffer applied to the plan. Null if no offer is applied.
cycle_periodnumber|nullRecurring billing interval in days (e.g., 30 for monthly, 365 for yearly).
grace_periodnumber|nullNumber of days after a failed payment during which the subscription remains active while retry attempts are made. Null if no grace period is configured.
trial_periodnumber|nullTrial period duration in days. Null if plan has no trial.
nested_itemsNestedItem[]Items included in this plan.

The Offer schema

键名类型描述
keystringOffer unique key.
namestring|nullOffer display name.
descriptionstring|nullOffer description.
discount_percentnumber|nullDiscount percentage.
grace_extensionnumber|nullGrace period extension in days.
trial_extensionnumber|nullTrial period extension in days.

NestedItem Schema

键名类型描述
idstring阿哈利姆生成的商品唯一标识符。
namestring商品名称。
descriptionstring|null商品描述。
skustring商品的 SKU 标识符,必须确保在游戏系统和阿哈利姆上保持一致。
quantitynumber商品数量。
fallback_itemItem|null如果无法向玩家发放主要商品,系统将提供的备选商品。
metadataobject|nullCustom key-value pairs for the item to support additional logic on your end.

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