К основному содержанию
скилл CX Codex

rc-cancellations-pauses-winback — скилл для Claude Code: отмены

Показывает в Android-приложении отмену подписки, паузу и возврат клиента. Помогает не гадать, что происходит с доступом.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add RevenueCat/ai-toolkit --skill rc-cancellations-pauses-winback -a claude-code
Открыть на GitHub

Что делает rc-cancellations-pauses-winback

Скилл разбирает состояния подписки, которые приходят в CustomerInfo от RevenueCat. Отмену с остатком доступа видно по unsubscribeDetectedAt и isActive == true, проблему с оплатой — по billingIssuesDetectedAt, паузу — когда продукт ещё принадлежит пользователю, а isActive уже false. Дальше агент подсказывает, что показать в интерфейсе.

Внутри четыре фазы: определить нужное состояние, проверить готовые данные, написать код на Kotlin и протестировать. Отдельно разобрана кнопка управления подпиской: managementURL уже имеет тип Uri?, его передают в Intent напрямую, а обёртка Uri.parse(url.toString()) тут лишняя и легко ломается. Дату возобновления после паузы в SDK не найти — её берут из REST-эндпоинта /v1/subscribers/{app_user_id} по полю paused_expiration_time_ms, причём с бэкенда, потому что нужен секретный ключ RC_SECRET_API_KEY.

Есть нюансы, о которые спотыкаются. Не считайте доступ вручную по expirationDate — читайте isActive и willRenew. Возврат до истечения срока сбрасывает unsubscribeDetectedAt сам, а вот возврат после истечения приходит как RENEWAL, и в обработчике на бэкенде доступ надо выдавать и на это событие. Отдельного вебхука про паузу RevenueCat не шлёт, состояние появляется в CustomerInfo после обработки RTDN от Google Play.

Какие задачи решает

  • показать баннер «подписка закончится такого-то числа» после отмены
  • открыть экран управления подпиской в Google Play по тапу
  • отличить паузу от полного окончания доступа
  • вытащить дату возобновления после паузы через REST API
  • выдать доступ при возврате клиента после истечения срока

Примеры запросов агенту

  • Добавь в экран подписки баннер об отмене, если unsubscribeDetectedAt не null, а isActive true
  • Сделай кнопку «Управлять подпиской», которая открывает managementURL
  • Напиши на бэкенде запрос к /v1/subscribers/{app_user_id} и верни paused_expiration_time_ms на клиент

Как установить rc-cancellations-pauses-winback

1Через Skills CLI (Vercel)

npx skills add RevenueCat/ai-toolkit --skill rc-cancellations-pauses-winback -a claude-code

2Вручную: положить файлы

~/.claude/skills/rc-cancellations-pauses-winback/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/rc-cancellations-pauses-winback/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора25

rc-error-handling Разбирает ошибки RevenueCat Android SDK: какой код что значит и что показать пользователю. Пригодится, когда платёжный флоу ломается на проде. CX Codex +1 627установок rc-revenuecat-api-quick-reference Справочник по Android SDK 10.x и REST API RevenueCat прямо в редакторе: сигнатуры вызовов, структура Offerings, поля CustomerInfo. CX Codex +1 624установок rc-price-changes Помогает провести новую цену подписки в Google Play через RevenueCat, не трогая код приложения. CX Codex +1 618установок rc-understanding-revenuecat Объясняет агенту, как устроен RevenueCat Android SDK 10.x, до того как он напишет хоть строчку кода. Пригодится, если вы переходите с чистого Play Billing. CX Codex +1 617установок rc-revenuecat-vs-raw-billing Скилл помогает решить, брать RevenueCat или писать Google Play Billing напрямую: показывает, что уходит на сторону SDK, а что остаётся вашей команде. CX Codex +1 601установок rc-alternative-billing Скилл помогает разобраться, какие программы альтернативного биллинга Google Play закрывает RevenueCat Android SDK, а какие придётся делать самому. CX Codex +1 603установок revenuecat-sdk-compatibility Скилл проверяет, поддерживает ли версия RevenueCat SDK нужную функцию, и считает, сколько подписчиков сидит на устаревших версиях. CX Codex +1 491установок revenuecat-cli Скилл учит агента работать с официальным CLI rc: проекты, продукты, пейволлы, загрузка картинок и шрифтов. Пригодится, когда MCP-сервер не умеет нужную операцию. CX Codex +1 403установок

Похожие

capacitor-in-app-purchases capawesome-team Скилл ведёт агента по шагам: настройка товаров в App Store Connect и Google Play Console, выбор плагина, покупки, валидация чеков и тесты в песочнице. CX Codex +1 728установок asc-revenuecat-catalog-sync rorkai Сверяет каталог подписок и встроенных покупок App Store Connect с продуктами RevenueCat. Нужен перед запуском или при устранении расхождений между каталогами. CX Codex +1 6 100установок paywall-optimization appeeky Скилл для аудита и A/B-тестов пейвола в подписочных приложениях. Помогает найти слабую ступень воронки и починить её. CX Codex +1 1 900установок convex-billing convex Подключает подписки Stripe к приложению на Convex через компонент @convex-dev/stripe: настраивает сессии оплаты, вебхуки и серверную проверку статуса. CX Codex +1 35 800установок clerk-billing clerk Скилл для работы с Clerk Billing: тарифы, чекаут, ограничение функций по плану и вебхуки подписок. CX Codex +1 16 900установок billing-automation Seth Hobson Скилл помогает проектировать подписочный биллинг, счета и возврат неуспешных платежей. Подойдёт для SaaS и сервисов с регулярными списаниями. CX Codex 11 245установок

Рядом в теме «Мобильная разработка»

Всё по теме «Мобильная разработка» →

Вопросы о rc-cancellations-pauses-winback

Как установить rc-cancellations-pauses-winback в Claude?

Выполните npx skills add RevenueCat/ai-toolkit --skill rc-cancellations-pauses-winback -a claude-code. Скилл окажется в ~/.claude/skills/rc-cancellations-pauses-winback/SKILL.md.

Что делает rc-cancellations-pauses-winback?

Помогает агенту разобрать состояния отмены, паузы и возврата клиента в Android-приложении на RevenueCat: какие поля CustomerInfo читать, как открыть экран управления подпиской и откуда взять дату возобновления.

Нужен ли секретный ключ RevenueCat?

Да, для даты возобновления после паузы. Её запрашивают с бэкенда через /v1/subscribers/{app_user_id} с заголовком Authorization: Bearer $RC_SECRET_API_KEY — в SDK этого значения нет.

Исходный текст

SKILL.md · MIT
---
name: rc-cancellations-pauses-winback
description: Use this skill when surfacing cancellation, pause, and winback state on Android with RevenueCat. Covers reading unsubscribeDetectedAt, billingIssuesDetectedAt, pause state via periodType, managementURL for deep link, and pause resume date lookup via the REST API.
license: Apache-2.0; see LICENSE
metadata:
  author: RevenueCat
  source: revenuecat-handbook chapter 13
  keywords:
  - android
  - revenuecat
  - cancellation
  - pause
  - winback
  - management-url
---

# Cancellations, Pauses, and Winback

Detect cancellation, pause, and winback states on Android by reading `CustomerInfo`. Most of these events are passive: your app observes them rather than initiates them. Open Google Play's manage screen with `managementURL`. Look up the pause resume date from the REST API.

## Phase 1: Scope

Decide what state you need to surface to the user.

| State | Signal in CustomerInfo | Notes |
|---|---|---|
| Canceled, still has access | `entitlement.unsubscribeDetectedAt != null` and `isActive == true` | Show "ends on [expirationDate]" |
| Billing issue (grace or hold) | `entitlement.billingIssuesDetectedAt != null` | Payment failed, recovery in progress |
| Paused | `entitlement.isActive == false` while product is still owned | Resume date requires REST API |
| Active and renewing | `entitlement.willRenew == true` | Normal state |

Backend win back campaign segmentation uses the `CANCELLATION` webhook `cancel_reason` field (`UNSUBSCRIBE`, `BILLING_ERROR`, `DEVELOPER_INITIATED`, `PRICE_INCREASE`).

## Phase 2: Prepare

Confirm you already have a fetched `CustomerInfo` from `Purchases.sharedInstance.getCustomerInfo(...)` or a listener. You do not need to call `BillingClient.queryPurchasesAsync` with `setIncludeSuspendedSubscriptions(true)`. RevenueCat resolves pause state from the server side subscription state.

Rules:

- `managementURL` is already `Uri?`. Pass it straight to the Intent. Do not call `Uri.parse(url.toString())`.
- Do not compute access manually from `expirationDate`. Read `isActive` and `willRenew`.
- Pause resume date is not in the SDK. Fetch it from `/v1/subscribers/{app_user_id}` in your backend.

## Phase 3: Execute

### Detect cancellation with remaining access

```kotlin
val entitlement = customerInfo.entitlements["pro_access"]
if (entitlement?.unsubscribeDetectedAt != null && entitlement.isActive) {
    entitlement.expirationDate?.let { expiry ->
        showCancellationBanner(expiry)
    }
}
```

`unsubscribeDetectedAt` is set when RevenueCat receives the `SUBSCRIPTION_CANCELED` RTDN. `isActive` stays `true` until the billing period ends.

### Detect pause

```kotlin
val entitlement = customerInfo.entitlements["pro_access"]
val hasAccess = entitlement?.isActive == true
// When paused, isActive == false. Pause resume date is not in the SDK.
```

### Open the subscription management screen

```kotlin
customerInfo.managementURL?.let { url ->
    startActivity(Intent(Intent.ACTION_VIEW, url))
}
```

`managementURL` is typed as `Uri?`. Use it directly. Wrapping it with `Uri.parse(url.toString())` is redundant and error prone.

### Look up pause resume date via REST

From your backend, call the subscribers endpoint and read `paused_expiration_time_ms` on the subscription:

```bash
curl -H "Authorization: Bearer $RC_SECRET_API_KEY" \
  https://api.revenuecat.com/v1/subscribers/$APP_USER_ID
```

The subscription object contains `paused_expiration_time_ms` when paused. Expose this to your client through your own endpoint.

### Resubscribe before expiry

Google's resubscribe before expiry flow fires `SUBSCRIPTION_RESTARTED`. RevenueCat clears `unsubscribeDetectedAt` and sets `willRenew = true`. No extra code required, just re-read `customerInfo`.

### Resubscribe after expiry

A resubscribe after expiry fires a `RENEWAL` webhook, not `INITIAL_PURCHASE`. Grant entitlement access on both events in your backend handler.

## Phase 4: Verify

| Check | How |
|---|---|
| Cancellation banner shows | Cancel in Play Store, pull fresh `CustomerInfo`, confirm `unsubscribeDetectedAt != null` and `isActive == true` |
| Management deep link opens | Tap the link, verify Play subscriptions screen opens for the correct product |
| Pause is reflected | Pause in Play Store sandbox, confirm `entitlement.isActive == false` |
| Pause resume date | Call `/v1/subscribers/{id}`, confirm `paused_expiration_time_ms` is present |
| Win back accepted | Accept a Play configured win back offer, confirm the purchase surfaces as a normal subscription in `CustomerInfo` |

## Notes

- Deferral and revocation are done through the Google Play Developer API (`purchases.subscriptionsv2.defer`, `purchases.subscriptionsv2.revoke`) from your backend. RevenueCat processes the resulting RTDN and updates `CustomerInfo` automatically.
- Win back campaigns need no SDK code. They are configured in Play Console or the RevenueCat dashboard.
- RevenueCat does not currently emit a dedicated pause webhook. Pause state appears in `CustomerInfo` once the Google Play RTDN is processed.

## References

- [Full chapter](https://www.revenuecat.com/guides/revenuecat-android-sdk/cancellations-pauses-and-winback)

© RevenueCat · MIT · RevenueCat/ai-toolkit

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой