---
title: "Совершение покупок в мобильном приложении в iOS SDK"
description: "Гайд по обработке встроенных покупок и подписок с помощью Adapty."
---

Отображение пейволов в мобильном приложении — обязательный шаг для предоставления пользователям доступа к премиум-контенту или сервисам. Однако просто показать пейвол достаточно для поддержки покупок только в том случае, если вы используете [Paywall Builder](adapty-paywall-builder) для их кастомизации.

Если вы не используете Paywall Builder, для совершения покупки и открытия доступа к нужному контенту необходимо вызывать отдельный метод `.makePurchase()`. Именно через него пользователи взаимодействуют с пейволами и проводят нужные транзакции.

Если на пейволе активирован promotional offer для продукта, который пользователь пытается купить, Adapty автоматически применит его в момент покупки.

:::warning
Обратите внимание: introductory offer применяется автоматически только в том случае, если пейволы настроены через Paywall Builder.

В остальных случаях нужно самостоятельно [проверить eligibility пользователя на introductory offer в iOS](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios). Пропуск этого шага может привести к отказу в публикации приложения. Кроме того, пользователи, которым положен introductory offer, могут быть списаны по полной цене.
:::

Убедитесь, что вы [выполнили начальную настройку](quickstart), не пропустив ни одного шага. Без неё проверка покупок невозможна.

## Совершение покупки \{#make-purchase\}

:::note
**Используете [Paywall Builder](adapty-paywall-builder)?** Покупки обрабатываются автоматически — этот шаг можно пропустить.

**Нужны пошаговые инструкции?** Ознакомьтесь с [quickstart-гайдом](ios-implement-paywalls-manually) — там описан полный процесс реализации с подробным контекстом.
:::

<Tabs groupId="current-os" queryString>
<TabItem value="swift" label="Swift" default>

```swift showLineNumbers
do {
    let purchaseResult = try await Adapty.makePurchase(product: product)

    switch purchaseResult {
        case .userCancelled:
            // Handle the case where the user canceled the purchase
        case .pending:
            // Handle deferred purchases (e.g., the user will pay offline with cash)
        case let .success(profile, transaction):
            if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
            // Grant access to the paid features
            }
    }
} catch {
    // Handle the error
}
```

</TabItem>
<TabItem value="swift-callback" label="Swift-Callback" default>

```swift showLineNumbers
Adapty.makePurchase(product: product) { result in
    switch result {
    case let .success(purchaseResult):
        switch purchaseResult {
            case .userCancelled:
                // Handle the case where the user canceled the purchase
            case .pending:
                // Handle deferred purchases (e.g., the user will pay offline with cash)
            case let .success(profile, transaction):
                if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false {
                    // Grant access to the paid features
                }
        }
    case let .failure(error):
        // Handle the error
    }
}
```

</TabItem>

</Tabs>

Параметры запроса:

| Параметр    | Обязательность | Описание                                                                                            |
| :---------- | :------------- | :-------------------------------------------------------------------------------------------------- |
| **Product** | обязательный   | Объект [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct), полученный из пейвола. |

Параметры ответа:

| Параметр    | Описание                                                                                                                                                                                                                                                                                                                                                               |
|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Profile** | <p>При успешном запросе ответ содержит этот объект. Объект [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) предоставляет исчерпывающую информацию об уровнях доступа пользователя, подписках и разовых покупках в приложении.</p><p>Проверьте статус уровня доступа, чтобы убедиться, что пользователь имеет необходимый доступ к приложению.</p> |

:::warning
**Примечание:** если вы ещё используете StoreKit версии ниже 2.0 и Adapty SDK версии ниже 2.9.0, вместо этого необходимо указать [общий секрет Apple App Store](app-store-connection-configuration#step-5-enter-app-store-shared-secret). Этот метод в настоящее время признан устаревшим компанией Apple.
:::

## Встроенные покупки из App Store \{#in-app-purchases-from-the-app-store\}

Когда пользователь инициирует покупку в App Store и транзакция переходит в ваше приложение, у вас есть два варианта:

- **Обработать транзакцию немедленно:** верните `true` в `shouldAddStorePayment`. Это сразу вызовет экран покупки Apple.
- **Сохранить объект продукта для последующей обработки:** верните `false` в `shouldAddStorePayment`, а затем вызовите `makePurchase` с сохранённым продуктом позже. Это может быть полезно, если перед инициированием покупки нужно показать пользователю что-то кастомное.

Вот полный пример кода:

```swift showLineNumbers title="Swift"
final class YourAdaptyDelegateImplementation: AdaptyDelegate {
    nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool {
        // 1a.
        // Return `true` to continue the transaction in your app. The Apple purchase system screen will show automatically.

        // 1b.
        // Store the product object and return `false` to defer or cancel the transaction.
        false
    }
    
    // 2. Continue the deferred purchase later on by passing the product to `makePurchase` when the timing is appropriate
    func continueDeferredPurchase() async {
        let storedProduct: AdaptyDeferredProduct = // get the product object from 1b.
        do {
            try await Adapty.makePurchase(product: storedProduct)
        } catch {
            // handle the error
        }
    }
}
```

## Активация промокодов в iOS \{#redeem-offer-codes-in-ios\}

---
no_index: true
---
import Callout from '../../../components/Callout.astro';

<Details>
<summary>Об офферных кодах</summary>

Офферные коды позволяют предоставлять скидки или бесплатные пробные периоды конкретным пользователям. В отличие от обычных офферов, которые применяются автоматически, офферные коды распространяются за пределами приложения — через email-рассылки, социальные сети или печатные материалы. Пользователи активируют их, вводя код в App Store, переходя по ссылке для активации или через диалог внутри приложения.

Чтобы настроить офферные коды, откройте подписку в App Store Connect и перейдите в раздел **Offer Codes**. Вы можете создать [три вида](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes) офферных кодов:

- **Free** — подписка бесплатна на заданный период, следующее продление — по полной цене.
- **Pay as you go** — пользователь платит сниженную цену в каждом расчётном периоде на протяжении заданного срока, после чего подписка продлевается по полной цене.
- **Pay up front** — пользователь единовременно платит сниженную цену за весь срок оффера, после чего подписка продлевается по полной цене.

Добавлять офферные коды в Adapty не нужно. Apple помечает каждую транзакцию в период действия оффера категорией офферного кода. Это касается как первоначальной активации, так и всех последующих продлений со скидкой. Adapty обнаруживает метку и записывает каждую транзакцию с категорией оффера `offer_code`. Как только период оффера заканчивается и подписка продлевается по полной цене, метка исчезает. Вы можете фильтровать аналитику по типу оффера **Offer Code** в [дашборде Adapty](controls-filters-grouping-compare-proceeds).

#### Устранение расхождений в выручке \{#revenue-discrepancy-troubleshooting\}

Если транзакция по офферному коду отображается в Adapty по полной цене продукта вместо сниженной цены оффера, проверьте следующее в App Store Connect:

- Для офферного кода настроены корректные цены для всех регионов, где пользователи могут его активировать.
- Цена оффера задана для конкретной страны или региона пользователя. Apple передаёт региональную цену в транзакции. Если для оффера не настроена региональная цена, Apple может передать полную цену продукта.

Вы можете фильтровать и проверять транзакции по офферным кодам в [дашборде Adapty](controls-filters-grouping-compare-proceeds) по фильтрам типа оффера **Offer Code** и **Offer Discount Type**.

#### Устаревшие промокоды (deprecated) \{#legacy-promo-codes-deprecated\}

<Callout type="warning">
Apple прекратила поддержку промокодов для встроенных покупок в марте 2026 года. Офферные коды заменяют их с расширенными возможностями: настраиваемые условия применения, сроки действия и до 1 миллиона кодов в квартал. Если вы ранее использовали промокоды для встроенных покупок, перейдите на офферные коды в App Store Connect.
</Callout>

Устаревшие промокоды (не более 100 на приложение на версию) предоставляли бесплатный доступ к подписке. В отличие от офферных кодов, Apple не включала информацию о скидке в транзакции по промокодам — в чеке указывалась полная цена продукта. В результате Adapty записывал эти транзакции по полной цене, что приводило к расхождениям в выручке между аналитикой Adapty и App Store Connect.

Если вы видите исторические транзакции по полной цене, которые должны были быть бесплатными, скорее всего, они связаны с устаревшими промокодами. Поскольку эти коды больше не поддерживаются, перейдите на офферные коды для точного учёта выручки.

</Details>

Чтобы отобразить экран активации промокода в вашем приложении:

```swift showLineNumbers
Adapty.presentCodeRedemptionSheet()
```

:::danger
По нашим наблюдениям, экран активации промокода (Offer Code Redemption) в некоторых приложениях работает ненадёжно. Мы рекомендуем перенаправлять пользователя напрямую в App Store.

Для этого откройте URL в следующем формате:
`https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}`
:::