Обработка ошибок в Capacitor SDK
Каждая ошибка, возвращаемая SDK, является экземпляром AdaptyError. Пример:
try {
const result = await adapty.makePurchase({ product });
// Handle purchase result
if (result.type === 'success') {
console.log('Purchase successful:', result.profile);
} else if (result.type === 'user_cancelled') {
console.log('User cancelled the purchase');
} else if (result.type === 'pending') {
console.log('Purchase is pending');
}
} catch (error) {
if (error instanceof AdaptyError) {
console.error('Adapty error:', error.adaptyCode, error.localizedDescription);
// Handle specific error codes
switch (error.adaptyCode) {
case ErrorCodeName.cantMakePayments:
console.log('In-app purchases are not allowed on this device');
break;
case ErrorCodeName.notActivated:
console.log('Adapty SDK is not activated');
break;
case ErrorCodeName.productPurchaseFailed:
console.log('Purchase failed:', error.detail);
break;
default:
console.log('Other error occurred:', error.detail);
}
} else {
console.error('Non-Adapty error:', error);
}
}
Свойства ошибки
Класс AdaptyError предоставляет следующие свойства:
| Свойство | Тип | Описание |
|---|---|---|
adaptyCode | number | Числовой код ошибки (например, 1003 для cantMakePayments) |
localizedDescription | string | Понятное пользователю сообщение об ошибке |
detail | string | undefined | Дополнительная информация об ошибке (необязательно) |
message | string | Полное сообщение об ошибке с кодом и описанием |
Коды ошибок
SDK экспортирует константы и утилиты для работы с кодами ошибок:
Константа ErrorCodeName
Сопоставляет строковые идентификаторы с числовыми кодами:
ErrorCodeName.cantMakePayments // 1003
ErrorCodeName.notActivated // 2002
ErrorCodeName.networkFailed // 2005
Константа ErrorCode
Сопоставляет числовые коды со строковыми идентификаторами:
ErrorCode[1003] // 'cantMakePayments'
ErrorCode[2002] // 'notActivated'
ErrorCode[2005] // 'networkFailed'
Вспомогательные функции
// Get numeric code from string name:
getErrorCode('cantMakePayments') // 1003
// Get string name from numeric code:
getErrorPrompt(1003) // 'cantMakePayments'
Сравнение кодов ошибок
Важно: error.adaptyCode — это число, поэтому сравнивайте его напрямую с числовыми кодами:
// Option 1: Use ErrorCodeName constant (recommended) ✅
if (error.adaptyCode === ErrorCodeName.cantMakePayments) {
console.log('Cannot make payments');
}
// Option 2: Compare with numeric literal ✅
if (error.adaptyCode === 1003) {
console.log('Cannot make payments');
}
// NOT like this ❌ - compares number to string and will never match
if (error.adaptyCode === ErrorCode[1003]) {
}
Глобальный обработчик ошибок
Вы можете настроить глобальный обработчик для перехвата всех ошибок Adapty:
// Set up global error handler
AdaptyError.onError = (error: AdaptyError) => {
console.error('Global Adapty error:', {
code: error.adaptyCode,
message: error.localizedDescription,
detail: error.detail
});
// Handle specific error types globally
if (error.adaptyCode === ErrorCodeName.notActivated) {
// SDK not activated - maybe retry activation
console.log('SDK not activated, attempting to reactivate...');
}
};
Типовые паттерны обработки ошибок
Обработка ошибок покупки
async function handlePurchase(product: AdaptyPaywallProduct) {
try {
const result = await adapty.makePurchase({ product });
if (result.type === 'success') {
console.log('Purchase successful:', result.profile);
} else if (result.type === 'user_cancelled') {
console.log('User cancelled the purchase');
} else if (result.type === 'pending') {
console.log('Purchase is pending');
}
} catch (error) {
if (error instanceof AdaptyError) {
switch (error.adaptyCode) {
case ErrorCodeName.cantMakePayments:
console.log('In-app purchases not allowed');
break;
case ErrorCodeName.productPurchaseFailed:
console.log('Purchase failed:', error.detail);
break;
default:
console.error('Purchase error:', error.localizedDescription);
}
}
}
}
Обработка сетевых ошибок
async function fetchPaywall(placementId: string) {
try {
const paywall = await adapty.getPaywall({ placementId });
return paywall;
} catch (error) {
if (error instanceof AdaptyError) {
switch (error.adaptyCode) {
case ErrorCodeName.networkFailed:
console.log('Network error, retrying...');
// Implement retry logic
break;
case ErrorCodeName.serverError:
console.log('Server error:', error.detail);
break;
case ErrorCodeName.notActivated:
console.log('SDK not activated');
break;
default:
console.error('Paywall fetch error:', error.localizedDescription);
}
}
throw error;
}
}
Системные коды StoreKit
| Ошибка | Код | Описание |
|---|---|---|
| unknown | 0 | Неизвестная или непредвиденная ошибка. |
| clientInvalid | 1 | Клиенту не разрешено выполнять это действие. |
| paymentCancelled | 2 | Пользователь отменил запрос на оплату. Никаких действий не требуется, однако с точки зрения бизнес-логики вы можете предложить пользователю скидку или напомнить о покупке позже. |
| paymentInvalid | 3 | Один из параметров платежа не был распознан стором. |
| paymentNotAllowed | 4 | Пользователю не разрешено выполнять платежи. Возможные причины: - Платежи не поддерживаются в стране пользователя. - Пользователь является несовершеннолетним. |
| storeProductNotAvailable | 5 | Запрошенный продукт отсутствует в App Store. Убедитесь, что продукт доступен для используемой страны. |
| cloudServicePermissionDenied | 6 | Пользователь не разрешил доступ к информации об облачном сервисе. |
| cloudServiceNetworkConnectionFailed | 7 | Устройству не удалось подключиться к сети. |
| cloudServiceRevoked | 8 | Пользователь отозвал разрешение на использование этого облачного сервиса. |
| privacyAcknowledgementRequired | 9 | Пользователь ещё не принял политику конфиденциальности стора. |
| unauthorizedRequestData | 10 | Запрос сформирован некорректно. |
| invalidOfferIdentifier | 11 | Идентификатор оффера недействителен. Возможные причины: - Оффер с таким идентификатором не настроен в App Store. - Оффер был отозван. - Идентификатор оффера указан с опечаткой. |
| invalidSignature | 12 | Подпись в платёжной скидке недействительна. Убедитесь, что заполнено поле In-app purchase Key ID и загружен файл In-App Purchase Private Key. Подробнее см. в разделе Настройка интеграции с App Store. |
| missingOfferParams | 13 | Проблема с интеграцией Adapty или с офферами. Подробнее об их настройке см. в разделах Настройка интеграции с App Store и Офферы. |
| invalidOfferPrice | 14 | Указанная в сторе цена больше не действительна. Офферы всегда должны предоставлять скидку относительно базовой цены. |
Кастомные коды Android
| Ошибка | Код | Описание |
|---|---|---|
| adaptyNotInitialized | 20 | Необходимо правильно настроить Adapty SDK с помощью метода Adapty.activate. Узнайте, как это сделать для React Native. |
| productNotFound | 22 | Запрошенный для покупки продукт недоступен в сторе. |
| invalidJson | 23 | JSON пейвола недействителен. Исправьте его в дашборде Adapty. Подробнее см. в разделе Кастомизация пейвола с помощью Remote Config. |
| currentSubscriptionToUpdateNotFoundInHistory | 24 | Исходная подписка, которую необходимо продлить, не найдена. |
| pendingPurchase | 25 | Статус покупки — ожидание, а не выполнена. Подробнее см. на странице Обработка отложенных транзакций в документации Android Developer. |
| billingServiceTimeout | 97 | Запрос достиг максимального таймаута до того, как Google Play успел ответить. Это может быть вызвано, например, задержкой при выполнении действия, запрошенного вызовом Play Billing Library. |
| featureNotSupported | 98 | Запрошенная функция не поддерживается Play Store на данном устройстве. |
| billingServiceDisconnected | 99 | Критическая ошибка: соединение клиентского приложения со службой Google Play Store через BillingClient было разорвано. |
| billingServiceUnavailable | 102 | Временная ошибка: служба Google Play Billing в данный момент недоступна. В большинстве случаев это означает проблему с сетевым соединением между клиентским устройством и серверами Google Play Billing. |
| billingUnavailable | 103 | Ошибка выставления счёта на стороне пользователя в процессе покупки. Примеры ситуаций, когда это может произойти: 1. Приложение Play Store на устройстве пользователя устарело. 2. Пользователь находится в неподдерживаемой стране. 3. Пользователь является корпоративным клиентом, и администратор заблокировал для него возможность совершать покупки. 4. Google Play не может списать средства с платёжного метода пользователя. Например, срок действия кредитной карты истёк. 5. Пользователь не авторизован в приложении Play Store. |
| developerError | 105 | Критическая ошибка: некорректное использование API. |
| billingError | 106 | Критическая ошибка: внутренняя проблема на стороне Google Play. |
| itemAlreadyOwned | 107 | Расходуемая покупка уже была приобретена. |
| itemNotOwned | 108 | Запрошенное действие над товаром не выполнено, так как он не принадлежит пользователю. |
Кастомные коды StoreKit
| Ошибка | Код | Описание |
|---|---|---|
| noProductIDsFound | 1000 | Ни один из продуктов пейвола недоступен в сторе. Если вы столкнулись с этой ошибкой, выполните следующие шаги для её устранения: 1. Убедитесь, что все продукты добавлены в дашборд Adapty. 2. Убедитесь, что Bundle ID приложения совпадает с указанным в Apple Connect. 3. Проверьте, что идентификаторы продуктов из сторов совпадают с теми, что добавлены в дашборд. Обратите внимание: идентификаторы не должны содержать Bundle ID, если он не включён в идентификатор самого стора. 4. Убедитесь, что статус оплаты приложения активен в настройках налогов Apple. Убедитесь, что налоговые данные актуальны, а сертификаты действительны. 5. Проверьте, привязан ли банковский счёт к приложению — это необходимо для возможности монетизации. 6. Проверьте доступность продуктов во всех регионах. Также убедитесь, что ваши продукты находятся в статусе “Ready to Submit”. |
| productRequestFailed | 1002 | Не удалось получить список доступных продуктов. Возможная причина: - Кэш ещё не создан, и при этом отсутствует подключение к интернету. |
| cantMakePayments | 1003 | Встроенные покупки не разрешены на этом устройстве. |
| noPurchasesToRestore | 1004 | Google Play не нашёл покупки для восстановления. |
| cantReadReceipt | 1005 | На устройстве нет действительного чека. Это может возникать при тестировании в песочнице. Никаких действий не требуется, однако с точки зрения бизнес-логики вы можете предложить пользователю скидку или напомнить о покупке позже. |
| productPurchaseFailed | 1006 | Покупка продукта не выполнена. |
| refreshReceiptFailed | 1010 | Чек не был получен. Применимо только к StoreKit 1. |
| receiveRestoredTransactionsFailed | 1011 | Восстановление покупок завершилось ошибкой. |
Кастомные сетевые коды
| Ошибка | Код | Описание |
|---|---|---|
| notActivated | 2002 | Необходимо правильно настроить Adapty SDK с помощью метода Adapty.activate. Узнайте, как это сделать для React Native. |
| badRequest | 2003 | Некорректный запрос. |
| serverError | 2004 | Ошибка сервера. |
| networkFailed | 2005 | Сетевой запрос завершился ошибкой. |
| decodingFailed | 2006 | Ошибка декодирования ответа. |
| encodingFailed | 2009 | Ошибка кодирования запроса. |
| analyticsDisabled | 3000 | Обработка аналитических событий невозможна, так как вы отключили эту функцию. Подробнее см. в разделе Интеграция аналитики. |
| wrongParam | 3001 | Один или несколько параметров указаны некорректно: пустое значение там, где оно не допускается, неверный тип и т. д. |
| activateOnceError | 3005 | Метод .activate нельзя вызывать более одного раза. |
| profileWasChanged | 3006 | Профиль пользователя был изменён в ходе операции. |
| fetchTimeoutError | 3101 | Пейвол не удалось загрузить в отведённое время. Чтобы избежать этой ситуации, настройте локальные резервные пейволы. |
| operationInterrupted | 9000 | Операция была прервана системой. |