> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/classic-push-provisioning/ja/ysuksu/xpayworettohenopusshupurobijoningu/ios/pusshupurobijoningu-1.md).

# プッシュプロビジョニング拡張機能

アプリケーション拡張により、イシュアアプリケーションの範囲を超えてカスタム機能やコンテンツを公開できます。これにより、エンドユーザは他のアプリやiOSとやり取りしている際にもそれらにアクセスできます。詳しくは、 [Appleの拡張ドキュメント](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html).

Apple Wallet拡張を使用すると、対応するiPhoneおよびApple Watchデバイス上のApple Walletアプリからトークンを直接プロビジョニングできます。

Apple Walletアプリでカードをプロビジョニングすると、アプリ内の体験が向上します。エンドユーザが支払いカードの詳細を手動で入力する必要がなくなります。

> <i class="fa-info-circle">:info-circle:</i>
>
> #### 注意 <a href="#note" id="note"></a>
>
> Apple Wallet拡張はエンドユーザがイシュアアプリケーションをインストールするとインストールされます。Apple Walletが利用可能な `パス` を検出して拡張を表示するには、エンドユーザが少なくとも一度イシュアアプリケーションを起動する必要があります。

## 概要 <a href="#overview" id="overview"></a>

<figure><img src="/files/b99dd8b75b81a2a992da64caeda8954bc5f404a7" alt=""><figcaption></figcaption></figure>

エンドユーザがApple Walletアプリを起動したとき：

1. Appleはカードの利用可否を確認するためにイシュアアプリケーションに問い合わせを行い、 [status](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571367-status) APIを呼び出します。
2. エンドユーザがイシュアアプリケーションを選択すると、イシュアは [UI拡張](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionauthorizationproviding).
3. を使用してユーザ認証を要求します。Appleはイシュアアプリケーションに対して利用可能なカードを確認し、カードをエンドユーザに表示します。Appleは [passEntries](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571366-passentries) APIをiPhone向けに、またWatch向けには [remotePassEntries](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3606586-remotepassentries) を呼び出します。
4. エンドユーザは1つ以上のカードを選択します。選択された各カードについて、Appleはイシュアアプリケーションからプロビジョニングペイロードを要求します。Appleはその後、 [generateAddPaymentPassRequest](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571365-generateaddpaymentpassrequestfor) APIを呼び出します。

> <i class="fa-info-circle">:info-circle:</i>
>
> #### 注意 <a href="#note-1" id="note-1"></a>
>
> * を呼び出してプロビジョニングフローを続行します。 `Push Provisioning SDKは、` generateAddPaymentPassRequestForInput
> * APIを使用してステップ4のプロビジョニングペイロードを取得します。

ステップ2の認証データをステップ3および4でカード詳細を取得するために使用する場合は、有効期限を十分な値に設定してください。例えば5分などです。

* Apple Wallet拡張はイシュアアプリケーションに2つの拡張を必要とします： [拡張のステータスとイシュアアプリケーション内でのカード検出可能性を報告する非UI拡張。これはステップ1、3、および4をカバーします。これを実装するには、](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler) PKIssuerProvisioningExtensionHandler
* のスーパークラスを拡張してください。 [ステップ2でエンドユーザを認証するためのUI拡張。これは同じイシュアアプリケーションのログイン資格情報を使用する別画面です。これを実装するには、](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionauthorizationproviding) PKIssuerProvisioningExtensionAuthorizationProviding

## プロトコルに準拠してください。 <a href="#integrating-apple-wallet-via-push-provisioning-sdk" id="integrating-apple-wallet-via-push-provisioning-sdk"></a>

### Push Provisioning SDKを介したApple Walletの統合 <a href="#app-configuration" id="app-configuration"></a>

アプリ構成

Push Provisioning SDKに特別な追加構成は必要ありません。ただし、イシュアアプリケーションにApp Group IDを設定する必要があります。これをイシュアアプリケーションとその拡張間の共有コンテナの構成に使用します。

その後、イシュアアプリケーションはこのコンテナを使用してカードの詳細（PANの下4桁やカードデザインなど）や認証データを保存でき、拡張は同じデータを取得できます。 [Appleの拡張ドキュメント](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionOverview.html).

デフォルトでは、イシュアアプリケーションは拡張とストレージを共有しません。イシュアアプリケーションとその拡張の両方がApp Groupを使用してストレージを共有する必要があります。詳しくは、 [Xcodeで、CapabilitiesタブにApp Group IDを追加します。以下のように。詳しくは、](https://developer.apple.com/documentation/xcode/configuring-app-groups).

<figure><img src="/files/c4ee95e060774e32614e7b8c8dbf9e8e7eff7e8d" alt=""><figcaption></figcaption></figure>

AppleのApp Groupsドキュメント

```swift
XcodeでApp Group IDを追加した後、イシュアアプリケーションはキーチェーンアクセスグループにデータを保存できます。
// ユーザ認証データとカードのlast4（および他の静的な
// 情報、例：カード所有者名など）をキーチェーンに保存
// これによりWallet拡張からアクセス可能にする
// 例: カードのlast4を保存
saveToKeychain(key: "cardID1_Last4", value: "1234")

saveToKeychain(key: "cardID2_Last4", value: "5678")
    func saveToKeychain(key: String, value: String) {
        guard let valueData = value.data(using: .utf8) else {
    }
    return
        let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
        kSecAttrService as String: "BankServiceKechain",
        kSecAttrAccessGroup as String: "group.com.thalesgroup.gemalto.tpcsdk.app",
    kSecAttrAccount as String: key]
    var addQuery = query
    addQuery[kSecValueData as String] = valueData

    let status = SecItemAdd(addQuery as CFDictionary, nil)
        if status == errSecDuplicateItem  {
        let updatedData: [String: Any] = [kSecValueData as String: valueData]
    }
}
```

### let status = SecItemUpdate(query as CFDictionary, updatedData as CFDictionary) <a href="#apple-pay-entitlement" id="apple-pay-entitlement"></a>

Apple Payのエンタイトルメント `Apple Payのプロビジョニングフローと同様に、アプリ開発者はUIおよび非UI拡張ターゲットの両方に` com.apple.developer.payment-pass-provisioning [エンタイトルメントを追加する必要があります。詳しくは、](/classic-push-provisioning/ja/gaido/sdkno/ios.md).

### SDKの構成 <a href="#ui-extension" id="ui-extension"></a>

UI拡張

#### **UI拡張はユーザ認証を行うために使用されます。SDKはその機能を提供しないため、イシュアアプリケーションはこの拡張内に独自の認証UIを実装する必要があります。**

1. UI拡張を作成する **Xcodeで、タイプが**.
2. Intents UI Extension

<figure><img src="/files/99ed7be1366202cb97b5eb6b90e93409128fc72d" alt=""><figcaption></figcaption></figure>

の新しいターゲットを追加します。

```xml
新しく作成したターゲットにエンタイトルメントと（オプションで）App Group IDを追加します。これらの値はイシュアアプリケーションで定義したものと同じです。
WalletExtensionsUI.entitlementsの例：
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
	<plist version="1.0">
	<dict>
	<key>com.apple.developer.payment-pass-provisioning</key>
	<true/>
		<key>com.apple.security.application-groups</key>
	<array>
<string>group.com.example.IssuerApp</string>
</array>
```

3. \</dict> `</plist>` Info.plistの値を次の値に置き換えてください：

| KEY                        | VALUE                                                                                      |
| -------------------------- | ------------------------------------------------------------------------------------------ |
| NSExtensionPointIdentifier | com.apple.PassKit.issuer-provisioning.authorization                                        |
| NSExtensionPrincipalClass  | このクラスは次に準拠します： `ステップ2でエンドユーザを認証するためのUI拡張。これは同じイシュアアプリケーションのログイン資格情報を使用する別画面です。これを実装するには、`. |

Wallet UI ExtensionのInfo.plistの例：

```xml
新しく作成したターゲットにエンタイトルメントと（オプションで）App Group IDを追加します。これらの値はイシュアアプリケーションで定義したものと同じです。
WalletExtensionsUI.entitlementsの例：
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
	<key>NSExtension</key>
	<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
		<key>NSExtensionPointIdentifier</key>
		<string>com.apple.PassKit.issuer-provisioning.authorization</string>
		<key>NSExtensionPrincipalClass</key>
		<string>$(PRODUCT_MODULE_NAME).IntentViewController</string>
	<string>group.com.example.IssuerApp</string>
<string>group.com.example.IssuerApp</string>
</array>
```

**UI拡張を実装する `ステップ2でエンドユーザを認証するためのUI拡張。これは同じイシュアアプリケーションのログイン資格情報を使用する別画面です。これを実装するには、` プロトコル**

Apple Wallet拡張でのエンドユーザ認証は、プロトコル [ステップ2でエンドユーザを認証するためのUI拡張。これは同じイシュアアプリケーションのログイン資格情報を使用する別画面です。これを実装するには、](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionauthorizationproviding).

に準拠することで実装されます。

Appleはこれをオプショナルとしていますが、プロビジョニング前にエンドユーザを認証することを推奨します。

```swift
Wallet UI拡張の実装例：
import UIKit

import PassKit
// 参照: https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionauthorizationproviding
    class IntentViewController: UIViewController, PKIssuerProvisioningExtensionAuthorizationProviding {
    var completionHandler: ((PKIssuerProvisioningExtensionAuthorizationResult) -> Void)?
    
    private let authButton = UIButton(type: .system)
        override func viewDidLoad() {
        super.viewDidLoad()

        // ビュー読み込み後の追加セットアップを行います。
        /* UIレイアウトを構成 */
    }

    authButton.addTarget(self, action: #selector(authButtonTouched), for: .touchUpInside)
        @objc func authButtonTouched() {
        // ...

        // Appleの機能要件に基づき、手動ログインと生体認証の両方を提供してください
        // 認証に基づいて
        // 成功した場合は .authorized 結果を返す
        self.completionHandler?(.authorized)
        // それ以外の場合は .canceled 結果を返す
    }
}
```

### //self.completionHandler?(.canceled) <a href="#non-ui-extension" id="non-ui-extension"></a>

非UI拡張 `Push Provisioning SDKは、`.

**非UI拡張はカードの利用可否とカード詳細を報告します。また、プロビジョニングペイロードを取得するために**

1. UI拡張を作成する **を呼び出します。**&#x975E;UI拡張を作成する **Intents Extension** 。
2. 前節でUI拡張を作成したため、

<figure><img src="/files/79020f87950d6dc9fbb687f16783c56289c44566" alt=""><figcaption></figcaption></figure>

Include UI Extension

```xml
新しく作成したターゲットにエンタイトルメントと（オプションで）App Group IDを追加します。これらの値はイシュアアプリケーションで定義したものと同じです。
WalletExtensionsUI.entitlementsの例：
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
	<plist version="1.0">
	<dict>
	<key>com.apple.developer.payment-pass-provisioning</key>
	<true/>
		<key>com.apple.security.application-groups</key>
	<array>
<string>group.com.example.IssuerApp</string>
</array>
```

3. \</dict> `</plist>` Info.plistの値を次の値に置き換えてください：

| KEY                        | VALUE                                                                                                                                                             |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| NSExtensionPointIdentifier | チェックボックスはオフにしてください。                                                                                                                                               |
| NSExtensionPrincipalClass  | 新しく作成したターゲットにエンタイトルメントと（オプションで）App Group IDを追加します。これらの値はイシュアアプリケーションで定義したものと同じです。 `拡張のステータスとイシュアアプリケーション内でのカード検出可能性を報告する非UI拡張。これはステップ1、3、および4をカバーします。これを実装するには、`. |

WalletExtensions.entitlementsの例：

```xml
新しく作成したターゲットにエンタイトルメントと（オプションで）App Group IDを追加します。これらの値はイシュアアプリケーションで定義したものと同じです。
WalletExtensionsUI.entitlementsの例：
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
	<key>NSExtension</key>
	<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
		<key>NSExtensionPointIdentifier</key>
		com.apple.PassKit.issuer-provisioning
		<key>NSExtensionPrincipalClass</key>
		このクラスは次に準拠します：
	<string>group.com.example.IssuerApp</string>
<string>group.com.example.IssuerApp</string>
</array>
```

**WalletのNon-UI拡張Info.plistの例： `拡張のステータスとイシュアアプリケーション内でのカード検出可能性を報告する非UI拡張。これはステップ1、3、および4をカバーします。これを実装するには、` \<string>com.apple.PassKit.issuer-provisioning\</string>**

\<string>$(PRODUCT\_MODULE\_NAME).IntentHandler\</string> [拡張のステータスとイシュアアプリケーション内でのカード検出可能性を報告する非UI拡張。これはステップ1、3、および4をカバーします。これを実装するには、](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler) 非UI拡張を実装する

* [status](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571367-status)
* [passEntries](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571366-passentries)
* [remotePassEntries](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3606586-remotepassentries)
* [generateAddPaymentPassRequest](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571365-generateaddpaymentpassrequestfor)

スーパークラス

```swift
Appleはイシュアアプリケーションに
スーパークラスを拡張してApple Wallet拡張を実装することを要求します。以下のセクションでは使用される各APIについて説明します：

    WalletのNon-UI拡張実装例：
        // 参照: https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler
    }

    class IntentHandler: PKIssuerProvisioningExtensionHandler {
        override func status(completion: @escaping (PKIssuerProvisioningExtensionStatus) -> Void) {
    }

    // 以下のセクションを参照：3. Non-UI拡張API `status` を実装。
    override func passEntries(completion: @escaping ([PKIssuerProvisioningExtensionPassEntry]) -> Void) {
    // 以下のセクションを参照：4. Non-UI拡張API `passEntries` を実装。
    // 参照：
        // https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3606586-remotepassentries
    }

    // 以下のセクションを参照：3. Non-UI拡張API `status` を実装。
    // 時間制約：20秒
    // 以下のセクションを参照：4. Non-UI拡張API `passEntries` を実装。
    override func remotePassEntries(completion: @escaping ([PKIssuerProvisioningExtensionPassEntry]) -> Void) {
            // 以下のセクションを参照：5. Non-UI拡張API `remotePassEntries` を実装。
            // https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571365-generateaddpaymentpassrequestfor
            override open func generateAddPaymentPassRequestForPassEntryWithIdentifier(
            _ identifier: String,
            configuration: PKAddPaymentPassRequestConfiguration,
            certificateChain certificates: [Data],
    ) {
        nonce: Data,
    }

    nonceSignature: Data,
        completionHandler completion: @escaping (PKAddPaymentPassRequest?) -> Void
            let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
            kSecAttrService as String: "BankServiceKechain",
            // 以下のセクションを参照：6. Non-UI拡張API `generateAddPaymentPassRequest` を実装。
            func loadFromKeychain(key: String) -> String? {
        let getQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: key,
        kSecReturnData as String: true]
            var item: AnyObject?
            let status = SecItemCopyMatching(getQuery as CFDictionary, &item)
        }
        if status == errSecSuccess,
    }
}
```

**WalletのNon-UI拡張Info.plistの例： `status` let data = item as? Data {**

return String(data: data, encoding: .utf8) [status](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571367-status) return nil

API `Appleは利用可能なカードがあるかをイシュアアプリケーションに確認するために` APIを呼び出します。

Appleはハンドラからの戻りに対して100msの時間制限を課します。これを超えると、Apple Walletアプリがイシュアアプリケーションを表示しない可能性があります。ローカルのキーチェーングループからカード情報を取得することを推奨します。その後、Push Provisioning SDKの `Appleは利用可能なカードがあるかをイシュアアプリケーションに確認するために`getToken `APIを使用してカードがデジタル化されているかを確認します。`.

を呼び出す前に、Push Provisioning SDKを `configure`

```swift
スーパークラスを拡張してApple Wallet拡張を実装することを要求します。以下のセクションでは使用される各APIについて説明します：
    // 以下のセクションを参照：3. Non-UI拡張API `status` を実装。
    を呼んで構成してください。
    WalletのNon-UI拡張API実装の例
    WalletのNon-UI拡張実装例：
        status:
        // https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571367-status
        // 時間制約：100ms
        let status = PKIssuerProvisioningExtensionStatus()

        status.requiresAuthentication = true
        status.passEntriesAvailable = false
            status.remotePassEntriesAvailable = false
        // 例: PPROD環境向けにTPCSDKを構成
            do {
            try TPCSDK.configure(url: "https://hapi.dbp-stg.thalescloud.io/mg/tpc", issuerId: "<issuerId>")
        }

        } catch {
        // エラー処理
        completion(status)
            // 共有キーチェーンからカード情報を読み込む
            // 前のステップの `loadFromKeychain` のサンプルコードを参照
        let last4Array = [

        loadFromKeychain(key: "cardID1_Last4"),
        loadFromKeychain(key: "cardID2_Last4")
        ].compactMap { $0 }
            let semaphore = DispatchSemaphore(value: 0)
            // 各カードについて、それが利用可能か（デジタル化されていないか）を確認する
                for last4 in last4Array {
                    do {
                // デジタル化状態を確認するためにTPC SDKのgetTokenを呼び出す
                    TPCSDK.getToken(input: GetTokenInput(last4: last4)) { local, remote, error in
                        if let error = error {
                        } else {
                        if local == nil {
                    }

                    // もしiPhone上で少なくとも1枚がデジタル化されていなければ、
                        // デジタル化可能なカードがあることになる
                        } else {
                        status.passEntriesAvailable = true
                    }
                }

                if remote == nil {
            }
            // もしWatch上で少なくとも1枚がデジタル化されていなければ、

            status.remotePassEntriesAvailable = true
            semaphore.signal()
                semaphore.wait()
            }
        }

        try TPCSDK.configure(url: "https://hapi.dbp-stg.thalescloud.io/mg/tpc", issuerId: "<issuerId>")
    }
}
```

**WalletのNon-UI拡張Info.plistの例： `passEntries` let data = item as? Data {**

return String(data: data, encoding: .utf8) [passEntries](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571366-passentries) // pass と remotePass の両方が利用可能であれば、これ以上繰り返す必要はありません。

if status.passEntriesAvailable && status.remotePassEntriesAvailable {

* break
* APIはiPhoneに追加してエンドユーザに表示するためのカード詳細を要求するためのものです。
* カードを正しく表示するために次の情報を提供する必要があります：
* カードデザイン
* カード所有者名
* PANの下4桁 `generateAddPaymentPassRequest` let data = item as? Data {

カードスキーム

を呼び出す前に、Push Provisioning SDKを `カード製品のタイトル`

```swift
スーパークラスを拡張してApple Wallet拡張を実装することを要求します。以下のセクションでは使用される各APIについて説明します：
    カード識別子（後で
    // 以下のセクションを参照：3. Non-UI拡張API `status` を実装。
    によって使用されます）
    // 以下のセクションを参照：4. Non-UI拡張API `passEntries` を実装。
    class IntentHandler: PKIssuerProvisioningExtensionHandler {
        このAPIにはカード詳細を取得するために20秒の時間制限があります。これを超えると、Apple Walletアプリはカードがないものとして扱います。
        loadFromKeychain(key: "cardID1_Last4"),

        passEntries:
        var urlSession: URLSession?
            // https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571366-passentries
            var entries: [PKIssuerProvisioningExtensionPassEntry] = []
        ]

        // 例: keychainからcardIDを読み込む
        let cards = [

        "cardID1",
        "cardID2",
        // ネットワーク呼び出しを行う場合、必ずurlSessionを再初期化してください
        // urlSession = ...
        // 各カードは以下の情報を持つ必要があります。そうでない場合、表示されない可能性があります：
        // - カードデザイン
        // - カード所有者名
        // - カードのlast4
            // - カードスキーム
                // - カード製品のタイトル
                // - カード識別子、generateAddPaymentPassRequestForPassEntryWithIdentifier(...) のコールバックでカードを識別するための識別子
            }
            for cardID in cards {
            guard let last4 = loadFromKeychain(key: "\(cardID)_Last4") else {
            // keychain取得に失敗した場合は次に進む
                for last4 in last4Array {
                    do {
                // デジタル化状態を確認するためにTPC SDKのgetTokenを呼び出す
                    TPCSDK.getToken(input: GetTokenInput(last4: last4)) { local, remote, error in
                        continue
                        // カードが利用可能か（デジタル化されていないか）を確認する。
                    }
                }
                if remote == nil {
            }
            // もしWatch上で少なくとも1枚がデジタル化されていなければ、
            var isAvailable = false
                // - カード識別子、generateAddPaymentPassRequestForPassEntryWithIdentifier(...) のコールバックでカードを識別するための識別子
            }

            TPCSDK.getToken(input: GetTokenInput(last4: last4)) { local, _, error in
            // まだデジタル化されていないので利用可能
            isAvailable = true
            guard isAvailable else {
            // カード所有者名を取得
            let cardHolderName = "\(cardID)_cardHolderName"
            // カードスキームを取得
            let scheme = PKPaymentNetwork.masterCard

            // カード製品のタイトルを取得
            let productTitle = "\(cardID)_productTitle"
                // カードデザインを取得
                // - カード識別子、generateAddPaymentPassRequestForPassEntryWithIdentifier(...) のコールバックでカードを識別するための識別子
            }

            let art = UIImage(systemName: "creditcard")!.cgImage!
            // コンフィグを作成
            guard let config = PKAddPaymentPassRequestConfiguration(encryptionScheme: .ECC_V2) else {

            // 失敗した場合は次へ進む
            config.cardholderName = cardHolderName
                    config.primaryAccountSuffix = last4
                    config.paymentNetwork = scheme
                    // 実際のエントリを作成
                // カードデザインを取得
                // - カード識別子、generateAddPaymentPassRequestForPassEntryWithIdentifier(...) のコールバックでカードを識別するための識別子
            }

            guard let entry = PKIssuerProvisioningExtensionPaymentPassEntry(identifier: cardID,
        }

        title: productTitle,
    }
}
```

**art: art, `remotePassEntries` let data = item as? Data {**

addRequestConfiguration: config) else { `passEntries` entries.append(entry) [remotePassEntries](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3606586-remotepassentries) completion(entries)

非UI拡張を実装する

を呼び出す前に、Push Provisioning SDKを `と同様に、`

```swift
スーパークラスを拡張してApple Wallet拡張を実装することを要求します。以下のセクションでは使用される各APIについて説明します：
    カード識別子（後で
    // 以下のセクションを参照：3. Non-UI拡張API `status` を実装。
    override func passEntries(completion: @escaping ([PKIssuerProvisioningExtensionPassEntry]) -> Void) {
    // 以下のセクションを参照：4. Non-UI拡張API `passEntries` を実装。
    // 参照：
        APIはカード詳細を取得するために使用されます。違いは、このAPIがApple Watchにプロビジョニング可能なカードをチェックすることです。通常、カードはApple Watchアプリ（ブリッジアプリ）を通じてApple Watchにプロビジョニングされます。
        loadFromKeychain(key: "cardID1_Last4"),

        passEntries:
        var urlSession: URLSession?
            // https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571366-passentries
            var entries: [PKIssuerProvisioningExtensionPassEntry] = []
        ]

        // 例: keychainからcardIDを読み込む
        let cards = [

        "cardID1",
        "cardID2",
        // ネットワーク呼び出しを行う場合、必ずurlSessionを再初期化してください
        // urlSession = ...
        // 各カードは以下の情報を持つ必要があります。そうでない場合、表示されない可能性があります：
        // - カードデザイン
        // - カード所有者名
        // - カードのlast4
            // - カードスキーム
                // - カード製品のタイトル
                // - カード識別子、generateAddPaymentPassRequestForPassEntryWithIdentifier(...) のコールバックでカードを識別するための識別子
            }
            for cardID in cards {
            guard let last4 = loadFromKeychain(key: "\(cardID)_Last4") else {
            このAPIも20秒の時間制限があります。
                for last4 in last4Array {
                    do {
                // デジタル化状態を確認するためにTPC SDKのgetTokenを呼び出す
                    // もしiPhone上で少なくとも1枚がデジタル化されていなければ、
                        continue
                        // カードが利用可能か（デジタル化されていないか）を確認する。
                    }
                }
                if remote == nil {
            }
            // もしWatch上で少なくとも1枚がデジタル化されていなければ、
            var isAvailable = false
                // - カード識別子、generateAddPaymentPassRequestForPassEntryWithIdentifier(...) のコールバックでカードを識別するための識別子
            }

            TPCSDK.getToken(input: GetTokenInput(last4: last4)) { local, _, error in
            // まだデジタル化されていないので利用可能
            isAvailable = true
            guard isAvailable else {
            // カード所有者名を取得
            let cardHolderName = "\(cardID)_cardHolderName"
            // カードスキームを取得
            let scheme = PKPaymentNetwork.masterCard

            // カード製品のタイトルを取得
            let productTitle = "\(cardID)_productTitle"
                // カードデザインを取得
                // - カード識別子、generateAddPaymentPassRequestForPassEntryWithIdentifier(...) のコールバックでカードを識別するための識別子
            }

            let art = UIImage(systemName: "creditcard")!.cgImage!
            // コンフィグを作成
            guard let config = PKAddPaymentPassRequestConfiguration(encryptionScheme: .ECC_V2) else {

            // 失敗した場合は次へ進む
            config.cardholderName = cardHolderName
                    config.primaryAccountSuffix = last4
                    config.paymentNetwork = scheme
                    // 実際のエントリを作成
                // カードデザインを取得
                // - カード識別子、generateAddPaymentPassRequestForPassEntryWithIdentifier(...) のコールバックでカードを識別するための識別子
            }

            remotePassEntries:
        }

        var remoteEntries: [PKIssuerProvisioningExtensionPassEntry] = []
    }
}
```

**art: art, `generateAddPaymentPassRequest` let data = item as? Data {**

TPCSDK.getToken(input: GetTokenInput(last4: last4)) { \_, remote, error in [generateAddPaymentPassRequest](https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571365-generateaddpaymentpassrequestfor) remoteEntries.append(entry)

completion(remoteEntries) `Push Provisioning SDKは、` エンドユーザがプロビジョニングするカードを選択した後、Appleはプロビジョニングペイロードを取得するために

非UI拡張を実装する

を呼び出す前に、Push Provisioning SDKを `APIを呼び出します。`

```swift
スーパークラスを拡張してApple Wallet拡張を実装することを要求します。以下のセクションでは使用される各APIについて説明します：
    カード識別子（後で
    // 以下のセクションを参照：3. Non-UI拡張API `status` を実装。
    // 時間制約：20秒
    // 以下のセクションを参照：4. Non-UI拡張API `passEntries` を実装。
    override func remotePassEntries(completion: @escaping ([PKIssuerProvisioningExtensionPassEntry]) -> Void) {
            // 以下のセクションを参照：5. Non-UI拡張API `remotePassEntries` を実装。
            // https://developer.apple.com/documentation/passkit/pkissuerprovisioningextensionhandler/3571365-generateaddpaymentpassrequestfor
            override open func generateAddPaymentPassRequestForPassEntryWithIdentifier(
            _ identifier: String,
            configuration: PKAddPaymentPassRequestConfiguration,
            certificateChain certificates: [Data],
    ) {
        TPC SDKはプロビジョニングペイロードを取得するための
        APIを提供します。
        generateAddPaymentPassRequest:
        let cardID = identifier
        // cardIDに基づいてencryptedPayloadとauthorizationCodeを取得します。TPCSDK.provision(...) と類似。
        // - encryptedPayload: PKCS7で暗号化されたカード情報。
        // - authorizationCode: イシュアが提供する認可コード。
        let encryptedPayload = "<PKCS7 encrypted>"

        // 例: keychainからcardIDを読み込む
        let cards = [

        let authorizationCode = "<authorization code>"
        // カードのスキーム
                let scheme = CardScheme.Mastercard
                // リクエストを生成するためにTPCSDKを呼び出す
                let sdkInput = GenerateAddPaymentPassRequestInput(scheme: scheme,
                encryptedPayload: encryptedPayload,
                authorizationCode: authorizationCode,
        certificateChain: certificates,
        nonce: nonce,
        nonceSignature: nonceSignature)
        // 国内スキームにのみ適用されます。これはBankのカード管理システムから取得できます。
            for last4 in last4Array {
                do {
                // それ以外の場合はnilです
            // デジタル化状態を確認するためにTPC SDKのgetTokenを呼び出す
                sdkInput.productId = "<productId>"
            }
        }
    }
}
```

### TPCSDK.generateAddPaymentPassRequestForInput(sdkInput) { request, error in <a href="#apple-functional-requirements" id="apple-functional-requirements"></a>

completion(nil)

* completion(request)
* Appleの機能要件
* Appleの機能要件に合わせるため、イシュアアプリケーションは次の慣行を採用する必要があります：
* カードデザインとカード所有者名を表示すること。

## カードデザインおよびアプリアイコンには角を丸めず四角のエッジを使用すること。 <a href="#faq" id="faq"></a>

**UI拡張での認証に対して手動ログインと生体認証の両方をサポートすること。**

AppleがAPIを呼び出した後、100ms以内にカードの有効性を確認すること。

**FAQ**

エンドユーザがログインする前にカードがプロビジョニング可能かどうかをApple Walletに提供するために、イシュアアプリケーションはどのように情報を提供すべきですか？

**エンドユーザは少なくとも一度イシュアアプリケーションにログインする必要があります。これにより、エンドユーザがApple Wallet拡張を使用する前に拡張がカードのステータスで更新されます。**

ログインが失敗した場合、アプリはどこにエラーを表示しますか？

* ログイン画面にエラーを表示することを推奨します。UI拡張は典型的なアプリのログインと同じポリシーに従います。
* カード画像のサイズと解像度の要件は何ですか？
* デジタルカード画像はAppleの機能要件に従うべきです：
* ベクターPDF（推奨）またはラスターPNGを使用してください。
* 1536 x 969の解像度を使用してください。
* 画像サイズを4 MB未満にしてください。
* 角は丸めず四角にしてください。

**カード番号、エンボス文字、ホログラム、チップ接点などの物理専用要素は除外してください。**

ランドスケープ（横向き）を使用してください。物理カードがポートレート（縦向き）の場合は横向きに再配置してください。 `非接触（Contactless）インジケータはNFC決済が許可される場所で追加することができます。` Apple Wallet拡張には新しいバンドル識別子が必要ですか？ `パス` はい。新しいバンドルIDをPNOの

associatedApplicationIdentifier `非接触（Contactless）インジケータはNFC決済が許可される場所で追加することができます。`に追加してください。iOSはワイルドカードのバンドル識別子をサポートします。イシュアは既存の `Appleは利用可能なカードがあるかをイシュアアプリケーションに確認するために`).

**をPNO APIを使ってApple Wallet内で更新する必要があります。**

バンドルIDが

**に含まれていない場合、イシュアアプリケーションはApple Wallet拡張を通じて追加されたカード（例：**

経由で）のアクセスができない可能性があります。 [イシュアアプリケーションのアイコンが表示されない場合、何が問題でしょうか？](/classic-push-provisioning/ja/ysuksu/xpayworettohenopusshupurobijoningu/ios/pusshupurobijoningu.md) 新しいイシュアアプリケーションがインストールされ、少なくとも一度開かれてApple Wallet拡張が更新されていることを確認してください。」「t346":"イシュアはApple Wallet拡張が動作するためにIn-App Provisioningを実装する必要がありますか？","t347":"はい。イシュアアプリケーションはApple Wallet拡張を実装する前に","t348":"Push Provisioning","t349":"を実装する必要があります。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.payments.thalescloud.io/classic-push-provisioning/ja/ysuksu/xpayworettohenopusshupurobijoningu/ios/pusshupurobijoningu-1.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
