> 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/nfc-wallet-sdk-android/ja/additional-features/customize-ppse.md).

# PPSEをカスタマイズする

## 概要

EMV Book B で定義されているとおり、PPSE（Proximity Payment System Environment）は非接触決済のエントリポイントです。各デジタルカードには、トークンプロファイルで定義された独自の PPSE があります。これには、対応するアプリケーションラベルと優先順位を含む、サポートされるアプリケーション識別子（AID）の一覧が含まれます。

NFC Wallet SDK は以下を提供します **PPSE 管理 API。** これにより、デジタルウォレットアプリケーションは次のことができます。

* 取得 **PPSE** (デジタルカードプロファイルで定義されたデフォルトの PPSE)。
* 取得 **補助 PPSE** (共ブランドカード用の補助デジタルカードプロファイルで定義された PPSE)。
* 新しい PPSE をカスタマイズする（**カスタム PPSE**).
* 取得またはリセットする **カスタム PPSE**.

NFC Wallet SDK は **カスタム PPSE** 非接触取引用に定義されている場合にそれを使用します。

{% hint style="info" %}
使用する **PPSE 管理 API** を使用して、共ブランドのデジタルウォレットプログラムにポリシーを適用します。

**NFC Wallet SDK** 以下のみを使用します **PPSE** または **カスタム PPSE**を使用しません **補助 PPSE**.
{% endhint %}

## SDK 連携

この **PPSE 管理 API** 以下を含みます `PpseFciTemplate` クラスと次の `DigitalizedCard` 操作:

* `DigitalizedCard.getPpse()`: トークンプロファイルで定義されたデフォルトの PPSE を取得します。
* `DigitalizedCard.getAuxiliaryPpse()`: 補助デジタルカードプロファイル（共ブランドカード）で定義された PPSE を取得します。
* `DigitalizedCard.getCustomPpse()`: カスタム PPSE を取得します。返します `null` 定義されていない場合は
* `DigitalizedCard.setCustomPpse()`: カスタム PPSE を設定します。 `null` を渡してクリアします。

{% hint style="warning" %}
SDK は `DigitalCard.setCustomPPSE`.

参照 [検証ルール](#validation-rules).
{% endhint %}

### カスタム PPSE の作成

次の方法でカスタム PPSE を構築します `PpseFciTemplate` 。

* 既存の PPSE テンプレートを使用します。
* 生の PPSE バイトを使用します。
* 一から構築します。

#### 方法 1: 既存のテンプレートから PPSE を構築する

デジタルカードの PPSE をベースにして、対象を絞って変更したい場合にこの方法を使用します。

**使用する場面:**

* 優先度やタグなど、既存の PPSE 内の特定のフィールドをカスタマイズしたい。
* 選択的な変更を加えながら、デフォルトの PPSE 構造を保持したい。
* カスタマイズ用のベーステンプレートが必要。

{% code title="カスタム PPSE テンプレートを設定" %}

```kotlin
try {
    // プライマリ PPSE テンプレートを取得します。
    val ppse = card.getPpse()

    // ディレクトリエントリを抽出します。
    val directoryEntryList =
        ppse.proprietaryTemplate.issuerDiscretionaryData.directoryEntryList
    val targetAid = byteArrayOf(
        0xA0.toByte(),
        0x00.toByte(),
        0x00.toByte(),
        0x00.toByte(),
        0x03.toByte(),
        0x10.toByte(),
        0x10.toByte()
    )

    directoryEntryList.forEach { entry ->
        if (entry.applicationIdentifier.contentEquals(targetAid)) {
            entry.priority = byteArrayOf(0x02.toByte())
        }
    }

    // 更新したテンプレートを保存します。
    card.setCustomPpse(ppse)
} catch (e: InternalComponentException) {
    Log.d("PPSE", "Error code: ${e.getmErrorCode()} Error message: ${e.message}")
}
```

{% endcode %}

#### 方法 2: 生のバイトから PPSE を構築する

完全な PPSE 応答データが BER-TLV 形式ですでに利用可能な場合にこの方法を使用します。

**使用する場面:**

* 完全な PPSE 応答データを生のバイトとしてすでに持っています。

{% code title="生のバイトから構築" %}

```kotlin
// BER-TLV 形式の完全な PPSE 応答データ
// 注: Kotlin の符号付き byte 型に対応するため、0x7F を超える値には .toByte() を使用しています
val fciData = byteArrayOf(
    0x6F, 0x50, 0x84.toByte(), 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46,
    0x30, 0x31, 0xA5.toByte(), 0x3E, 0xBF.toByte(), 0x0C, 0x3B, 0x61, 0x2F, 0x4F, 0x07, 0xA0.toByte(), 0x00, 0x00, 0x00, 0x03,
    0x10, 0x10, 0x50, 0x0B, 0x56, 0x69, 0x73, 0x61, 0x20, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x87.toByte(),
    0x01, 0x01, 0x9F.toByte(), 0x2A, 0x01, 0x03, 0x9F.toByte(), 0x0A, 0x04, 0x00, 0x01, 0x01, 0x02, 0xDF.toByte(),
    0x02, 0x03, 0x03, 0x04, 0x05, 0xDF.toByte(), 0x01, 0x02, 0x03, 0x04, 0x9F.toByte(), 0x02, 0x02, 0x01, 0x03,
    0x9F.toByte(), 0x01, 0x02, 0x01, 0x02
)

// 生のバイトから PpseFciTemplate を構築します
val template = PpseFciTemplate(fciData)

// カスタム PPSE を保存します
try {
    digitalCard.setCustomPpse(template)
} catch (e: InternalComponentException) {
    Log.d("PPSE", "Error code: ${e.getmErrorCode()} Error message: ${e.message}")
}
```

{% endcode %}

#### 方法 3: 一から PPSE を構築する

各コンポーネントを個別に定義して、PPSE 構造をプログラムで構築する必要がある場合にこの方法を使用します。

**使用する場面:**

* 既存のバイトデータなしで PPSE データを構築しています。
* ディレクトリエントリ、AID、ラベル、その他の PPSE コンポーネントをプログラムで定義する必要があります。
* コンパイル時検証付きの型安全な構築を希望しています。
* 生のバイトよりも構造化されたオブジェクトを好みます。

`DigitalizedCard` は PPSE 応答を `PpseFciTemplate`として公開します。独自の `PpseFciTemplate`を構築できます。以下の例では、その方法を示します。

{% code title="PpseFciTemplate を使用して一から構築" %}

```kotlin
val dfName = byteArrayOf(
    0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31
)

// ディレクトリエントリを作成
val aid = byteArrayOf(0xA0.toByte(), 0x00, 0x00, 0x00, 0x03, 0x10, 0x10)
val label = byteArrayOf(0x56, 0x69, 0x73, 0x61, 0x20, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74)
val kernelId = byteArrayOf(0x03)
val asrpd = byteArrayOf(0x00, 0x01, 0x01, 0x02)
val priority = byteArrayOf(0x01)
val entry = DirectoryEntry(aid, label, kernelId, asrpd, priority, null, HashMap())

val entries = arrayListOf(entry)

val issuerData = FciIssuerDiscretionaryData(entries, HashMap())
val proprietaryTemplate = FciProprietaryTemplate(issuerData)

// 明示的なパラメータでテンプレートを作成
val template = PpseFciTemplate(dfName, proprietaryTemplate)

// カスタム PPSE を保存します
try {
    digitalCard.setCustomPpse(template)
} catch (e: InternalComponentException) {
    Log.d("PPSE", "Error code: ${e.getmErrorCode()} Error message: ${e.message}")
}
```

{% endcode %}

### カスタム PPSE をクリア

を渡して `null` カスタム PPSE を削除し、デフォルトの PPSE 応答を復元します。

{% code title="カスタム PPSE テンプレートをクリア" %}

```kotlin
try {
    card.setCustomPpse(null)
} catch (e: InternalComponentException) {
    Log.d("PPSE", "Error code: ${e.getmErrorCode()} Error message: ${e.message}")
}
```

{% endcode %}

### 検証ルール

NFC Wallet SDK は、次を呼び出すとカスタム PPSE を検証します `DigitalizedCard.setCustomPpse()`。これにより、カスタム PPSE が EMV 要件と BER-TLV エンコーディングに従っていることが保証されます。

#### サイズ制限

* シリアライズされた BER-TLV ペイロードは 256 バイト以下でなければなりません。
* 内のカスタムタグキー `BF0C` または `61` は 2 バイトを超えてはなりません。

#### 必須タグ

あなたの `PpseFciTemplate` には次を含める必要があります:

1. DF Name — タグ `84`
2. 少なくとも 1 つの Directory Entry — タグ `61` 内 `BF0C`
3. 各ディレクトリエントリ内のアプリケーション識別子 — タグ `4F`

検証に失敗した場合、SDK は `InternalComponentException` をエラーコード `ERROR_CODE_INVALID_PPSE_DATA`.

#### AID ロックの制限

AID を `LockStatus.LOCKED` でロックすることは、単一ブランドの Visa カードでのみサポートされます。

を設定した場合 `LockStatus.LOCKED` サポートされていないカードに対して、SDK は `InternalComponentException`.


---

# 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/nfc-wallet-sdk-android/ja/additional-features/customize-ppse.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.
