구독 웹훅
Aghanim의 구독 웹훅은 구독 주기 이벤트를 통해 여러분의 게임에 알림을 제공하여 구독 기반 콘텐츠 및 서비스에 대한 플레이어 접근 권한을 관리할 수 있게 해줍니다.
웹훅 이벤트
이 웹훅 이벤트를 사용하여 구독 접근 권한을 부여, 확장 또는 취소할 수 있습니다.
| 이벤트 | 발생 시기 | 해야 할 일 |
|---|---|---|
subscription.activated | 구독이 활성화됩니다. | 플레이어에게 구독 혜택을 제공합니다. |
subscription.updated | 구독 속성이 변경됩니다 (상태, 플랜 또는 청 구 날짜). | 업데이트된 구독 데이터와 내부 상태를 동기화하십시오. |
subscription.renewed | 정기 결제가 성공적으로 이루어집니다. | effective_until을 업데이트하여 접근을 확장합니다. (선택 사항) 각 성공적인 갱신 시 보상을 제공하십시오 (적용되는 경우). |
subscription.deactivated | 구독이 비활성화되었습니다 | 구독 혜택을 즉시 취소합니다. |
Idempotency의 중요성
웹훅 이벤트는 여러 번 전송될 수 있으므로 핸들러가 idempotent를 유지해야 합니다.
구독 상태
상태는 구독의 현재 상태를 추적하는 데 사용됩니다.
| 상태 | 설명 |
|---|---|
trial | 구독이 시험 기간에 있습니다. |
active | 구독이 결제 완료되었고 정상 상태입니다. |
canceled | 구독이 갱신되지 않을 것입니다. effective_until까지 활성 상태로 유지되며, 그 후 expired로 전환됩니다. |
expired | 구독이 더 이상 활성 상태가 아닙니다. |
전방 호환성
향후 새 구독 상태가 추가될 수 있습니다.
통합이 앞으로도 호환되도록 하려면, 혜택을 부여하거나 회수하는 데 구독 상태만 단독으로 의존하지 마세요.
구독 액세스를 활성화 및 비활성화하기 위한 단일 진실 공급원(source of truth)으로는 항상 event_type 및 effective_until에 의존하세요.
코드에서 status를 엄격한 enum으로 모델링하지 마세요 — 새 값이 도입될 때 깨지는 것을 방지하기 위해 문자열로 취급하세요.
공통 시나리오
다음 예는 일반적인 구독 흐름 및 각 단계에서 발생하는 이벤트를 보여줍니다:
트라이얼 → 결제 완료
subscription.activatedstatus=trial→ 접근 권한 부여subscription.updatedstatus=active→ 시험이 결제로 전환됨 (첫 번째 성공적인 결제),effective_until확장
정기 결제
subscription.renewedstatus=active→ 접근 확장 (effective_until업데이트)- (선택 사항) 각 성공적인 갱신 시 보상을 제공하십시오 (적용되는 경우).
취소
subscription.updatedstatus=canceled→effective_until까지 접근 유지subscription.deactivated→ 접근 취소
만료
subscription.deactivated상태=expired→ 접근 취소- (선택 사항) 웹훅을 받지 못한 경우
now >= effective_until일 때 접근을 취소하십시오.
요구 사항
Aghanim의 구독 웹훅을 사용하려면 웹훅 서버를 다음과 같이 구성해야 합니다:
- POST 웹훅 요청을 수락하는 HTTPS 엔드포인트.
- Aghanim이 생성하고 서명한 이벤트를 수신합니다.
- 중복 웹훅 처리를 방지하기 위해 웹훅 페이로드에 포함된
idempotency_key를 처리합니다. - 구독 이벤트가 성공적으로 처리된 경우 2xx 상태 코드로 응답하고, 오류가 발생하면 4xx 또는 5xx로 응답합니다.
구성
- 구독 웹훅 처리를 위한 함수를 개발합니다.
- 엔드포인트를 사용 가능하게 설정하세요.
- Aghanim 계정에서 → 게임 → 웹훅 → 새 웹훅에서 처리하고자 하는 구독 이벤트 유형을 선택하여 엔드포인트를 등록하세요.
대안으로, 웹후크 생성 API 방법을 사용하여 Aghanim 내에서 엔드포인트를 등록할 수 있습니다.
요청 스키마
아래는 예시입니다 subscription.activated 웹훅 요청:
- HTTP
- cURL
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": "Battle Pass",
"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": "Battle Pass Monthly",
"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": "XP 부스트",
"description": "구독 기간 동안 활성화된 25% XP 부스트",
"sku": "xp_boost_25",
"quantity": 1,
"type": "item"
}
]
},
"effective_until": 1705276800,
"trial_due_at": 1705276800,
"paid_due_at": 1704067200,
"updated_at": 1704067200,
"metadata": {
"tier": "premium",
"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"
}
curl "https://your-webhook-endpoint.com/your/webhook/uri" \
-X POST \
-H "Content-Type: application/json" \
-H "User-Agent: Aghanim/0.1.0" \
-H "X-Aghanim-Signature: 2e45ed4dede5e09506717490655d2f78e96d4261040ef48cc623a780bda38812" \
-H "X-Aghanim-Signature-Timestamp: 1725548450" \
-d '{
"event_type": "subscription.activated",
"event_data": {
"id": "sub_kMnoPqRsTuV",
"sku": "battle_pass",
"name": "Battle Pass",
"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": "Battle Pass Monthly",
"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": "XP 부스트",
"description": "구독 기간 동안 활성화된 25% XP 부스트",
"sku": "xp_boost_25",
"quantity": 1,
"type": "item"
}
]
},
"effective_until": 1705276800,
"trial_due_at": 1705276800,
"paid_due_at": 1704067200,
"updated_at": 1704067200,
"metadata": {
"tier": "premium",
"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"
}'
이벤트 스키마
| Key | 유형 | 설명 |
|---|---|---|
event_id | string | Aghanim에 의해 생성된 고유 이벤트 ID. |
game_id | string | Aghanim 시스템에서의 귀하의 게임 ID. |
event_type | string | 이벤트의 유형, subscription.activated 이럴 경우. |
event_time | number | 유닉스 에포크 시간으로 된 이벤트 날짜. |
event_data | EventData | 이벤트 특정 데이터가 포함되어 있으며, 상속된 객체에 대한 가능한 키가 포함됩니다. |
idempotency_key | string | 웹훅 작업이 재시도되어도 한 번만 실행되도록 보장합니다. |
request_id | string|null | 이벤트가 API 요청에 의해 트리거된 경우, 요청 ID가 포함됩니다. |
sandbox | boolean | 이 이벤트가 샌드박스 게임 환경에서 전송되었는지를 표시합니다. |
trigger | string|null | 이벤트가 전송된 원인이 된 트리거입니다. |
transaction_id | string | Aghanim이 생성한 거래 ID입니다. 이 ID는 동일한 거래 내에서 발생한 여러 이벤트에서 동일할 수 있습니다. |
context | EventContext|null | 이벤트에 대한 컨텍스트 정보. |
EventContext 스키마
| Key | 유형 | 설명 |
|---|---|---|
order | OrderContext|null | 해당되는 경우 이벤트와 관련된 주문 정보입니다. |
player | PlayerContext|null | 플레이어 정보를 추가하려면 웹훅 설정에서 "플레이어 컨텍스트 추가"를 활성화하세요. |
EventData 스키마
| Key | 유형 | 설명 |
|---|---|---|
id | string | 이 구독 인스턴스의 고유 식별자입니다. 이 ID를 사용하여 구독의 전체 수명 주기 동안 구독을 추적하고 관리하세요. |
sku | string | 구독의 고유 SKU입니다. |
name | string | 구독 표시 이름입니다. |
nested_items | NestedItem[] | 이 구독에 포함된 아이템입니다. |
order_id | string | 구독이 최초로 활성화된 주문 ID입니다. 주문 웹훅과 연관 짓는 데 사용하세요. |
user_id | string | Aghanim 시스템에서 게임 허브 유저 ID. |
player_id | string | 고유한 플레이어 인증에 선택된 플레이어 ID. |
amount | number | 구독 금액. 소수 통화 단위. |
amount_decimal | number | 구독 금액. 주요 통화 단위. |
currency | string | 구독 통화. |
payment_method | string | 사용된 결제 방법입니다 (cards, apple_pay, google_pay, paypal 등). |
status | string | 구독 상태입니다. 위의 구독 상태를 참조하세요. |
due_at | number | 다음 결제 예정일(Unix epoch 시간, 초)입니다. 체험 구독의 경우 첫 청구가 발생하는 시점입니다. |
created_at | number | 구독 생성일(Unix epoch 시간, 초)입니다. |
plan | Plan | 구독과 연관된 플랜입니다. |
effective_until | number | 구독이 유효한 종료일(Unix epoch 시간, 초)입니다. 이는 trial_due_at와 paid_due_at 중 더 큰 값이며, 구독 혜택에 계속 접근할 수 있어야 하는 시점을 나타냅니다. |
trial_due_at | number|null | 체험 종료일(Unix epoch 시간, 초)입니다. 구독에 체험이 없는 경우 null입니다. |
paid_due_at | number|null | 구독이 결제된 종료일(paid-through 날짜, Unix epoch 시간, 초)입니다. 이 날짜 이후에는 구독을 갱신해야 하며, 그렇지 않으면 만료됩니다. 체험 기간 중이거나 첫 결제 전에는 null입니다. |
updated_at | number|null | 구독 최종 업데이트일(Unix epoch 시간, 초)입니다. 구독이 업데이트되지 않은 경우 null입니다. |
metadata | object|null | 구독에 첨부된 사용자 지정 키-값 쌍입니다. 설정된 메타데이터가 없는 경우 null입니다. |
Plan 스키마
| Key | 유형 | 설명 |
|---|---|---|
key | string | 구독 내 플랜의 고유 키입니다. |
name | string | 플랜 표시 이름입니다. |
amount | number | 플랜 금액. 소수 통화 단위. |
amount_decimal | number | 플랜 금액. 주요 통화 단위. |
currency | string | 플랜 통화. |
offer | Offer|null | 플랜에 적용된 오퍼입니다. 적용된 오퍼가 없는 경우 null입니다. |
cycle_period | number|null | 정기 청구 주기(일 단위)입니다 (예: 월간은 30, 연간은 365). |
grace_period | number|null | 결제 실패 후 재시도가 진행되는 동안 구독이 활성 상태로 유지되는 일수입니다. 유예 기간이 설정되지 않은 경우 null입니다. |
trial_period | number|null | 체험 기간(일 단위)입니다. 플랜에 체험이 없는 경우 null입니다. |
nested_items | NestedItem[] | 이 플랜에 포함된 아이템입니다. |
Offer 스키마
| Key | 유형 | 설명 |
|---|---|---|
key | string | 오퍼의 고유 키입니다. |
name | string|null | 오퍼 표시 이름입니다. |
description | string|null | 오퍼 설명입니다. |
discount_percent | number|null | 할인율(퍼센트)입니다. |
grace_extension | number|null | 유예 기간 연장(일 단위)입니다. |
trial_extension | number|null | 체험 기간 연장(일 단위)입니다. |
NestedItem 스키마
| Key | 유형 | 설명 |
|---|---|---|
id | string | Aghanim에 의해 생성된 아이템 ID. |
name | string | 아이템 이름. |
description | string|null | 아이템 설명. |
sku | string | 게임과 Aghanim 측 모두에서 일치하는 아이템 SKU. |
quantity | number | 아이템 수량. |
fallback_item | Item|null | 주 아이템을 플레이어에게 제공할 수 없을 경우 백업으로 제공할 수 있는 아이템입니다. |
metadata | object|null | 귀하 측의 추가 로직을 지원하기 위한 아이템의 사용자 지정 키-값 쌍입니다. |
도움이 필요하세요?
통합팀에 문의하십시오 [email protected]