---
title: "iOS SDKでモバイルアプリの購入を行う"
description: "Adaptyを使用したアプリ内課金とサブスクリプションの処理に関するガイド。"
---

モバイルアプリ内でペイウォールを表示することは、ユーザーにプレミアムコンテンツやサービスへのアクセスを提供するための重要なステップです。ただし、[ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしている場合に限り、ペイウォールを表示するだけで購入処理が完結します。

ペイウォールビルダーを使用しない場合は、購入を完了してコンテンツをアンロックするために `.makePurchase()` という別のメソッドを使用する必要があります。このメソッドは、ユーザーがペイウォールで操作を行い、目的のトランザクションを進めるための窓口となります。

ペイウォールにユーザーが購入しようとしているプロダクトに対して有効なプロモーションオファーがある場合、Adaptyは購入時に自動的にそれを適用します。

:::warning
初回オファーが自動的に適用されるのは、ペイウォールビルダーで設定されたペイウォールを使用している場合のみです。

それ以外の場合は、[iOS での初回オファーの利用資格を確認](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)する必要があります。この手順を省略すると、リリース時にアプリが審査で却下される可能性があります。また、初回オファーの対象ユーザーに通常価格が請求される可能性もあります。
:::

一つのステップも省略せずに[初期設定](quickstart)を完了していることを確認してください。設定が完了していないと、購入の検証ができません。

## 購入を行う \{#make-purchase\}

:::note
**[ペイウォールビルダー](adapty-paywall-builder)を使用していますか？** 購入は自動的に処理されます。このステップはスキップできます。

**ステップバイステップのガイドが必要ですか？** 完全なコンテキストとエンドツーエンドの実装手順については、[クイックスタートガイド](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
**注意：** Apple の StoreKit バージョンが v2.0 未満、かつ Adapty SDK バージョンが v2.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 で購入を開始し、トランザクションがアプリに引き継がれる場合、2つの選択肢があります：

- **トランザクションを即座に処理する：** `shouldAddStorePayment` で `true` を返します。これにより、Apple の購入システム画面がすぐに表示されます。
- **後処理のためにプロダクトオブジェクトを保存する：** `shouldAddStorePayment` で `false` を返し、後で保存したプロダクトを使って `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>

オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動的に適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物など、アプリの外で配布します。ユーザーはApp Storeでコードを入力するか、引き換えURLを使うか、アプリ内ダイアログから利用できます。

オファーコードを設定するには、App Store Connectでサブスクリプションを開き、**Offer Codes** セクションに移動してください。オファーコードは[3種類](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` として記録します。オファー期間が終了してサブスクリプションが通常価格で更新されると、タグは付与されなくなります。[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)のアナリティクスで **Offer Code** オファータイプによるフィルタリングが可能です。

#### 収益の差異が生じた場合のトラブルシューティング \{#revenue-discrepancy-troubleshooting\}

オファーコードのトランザクションが、割引価格ではなく通常価格でAdaptyに記録されている場合は、App Store Connectで以下を確認してください。

- オファーコードに、ユーザーが引き換え可能なすべての地域に対して正しい価格が設定されているか。
- ユーザーの特定の国や地域に対してオファー価格が設定されているか。Appleはトランザクションに地域価格を含めて送信します。その地域のオファー価格が設定されていない場合、Appleは通常価格を送信することがあります。

[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)で、**Offer Code** オファータイプと **Offer Discount Type** フィルターを使ってオファーコードのトランザクションをフィルタリング・確認できます。

#### レガシープロモコード（非推奨） \{#legacy-promo-codes-deprecated\}

<Callout type="warning">
Appleは2026年3月にアプリ内課金向けのプロモコードを廃止しました。オファーコードはより多くの機能（適格性の設定、有効期限、四半期あたり最大100万コード）を備えた後継機能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。
</Callout>

レガシープロモコード（アプリのバージョンごとに最大100件）は、サブスクリプションへの無料アクセスを付与していました。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには通常価格が記載されていました。そのため、Adaptyはこれらのトランザクションを通常価格で記録し、Adaptyアナリティクスとレポートの間に収益の差異が生じていました。

本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。

</Details>

アプリ内でコード引き換えシートを表示するには：

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

:::danger
確認された問題として、一部のアプリでオファーコード引き換えシートが正常に動作しない場合があります。ユーザーを直接 App Store にリダイレクトすることをお勧めします。

そのためには、以下の形式の URL を開く必要があります：
`https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}`
:::