> 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/implement-nfc-wallet/make-payment/implement-contactless-payments/5.-perform-cdcvm-verification.md).

# 5. CDCVM 検証を実行する

## 概要

非接触取引中、NFC Wallet SDK は次を要求する場合があります。 **エンドユーザー** CDCVM 検証を完了するために認証すること。

あなたの **デジタルウォレットアプリケーション** は、前に設定した CDCVM メソッドを使用してこの認証を行う必要があります。詳しくは次を参照してください。 [CDCVM メソッドを設定する](/nfc-wallet-sdk-android/ja/implement-nfc-wallet/tokenize-a-card/set-cdcvm-method.md).

## SDK 統合

で認証を処理する `ContactlessPaymentServiceListener.onAuthenticationRequired()`。参照： [非接触決済コールバックを実装する](/nfc-wallet-sdk-android/ja/implement-nfc-wallet/make-payment/implement-contactless-payments/2.-implement-contactless-payment-callbacks.md).

エンドユーザーを認証するには、SDK が提供する `CHVerificationMethod` を使用します。これを使って `DeviceCVMVerifier` インスタンスを取得し、認証を開始して結果を `DeviceCVMVerifyListener`.

`cvmResetTimeout` は検証が有効である期間を示します。2 回目のタップの案内に使用してください。

### デバイスのキーカードを用いた CDCVM 検証

デバイスのキーカード（keyguard）が CDCVM メソッドとして使用される場合：

```java
// ContactlessPaymentServiceListener() 実装から
//...

@Override
public void onAuthenticationRequired(
  PaymentService activatedPaymentService,
  CHVerificationMethod cvm,
  long cvmResetTimeout) {

    // CDCVM のタイプを確認する
    if(cvm == CHVerificationMethod.DEVICE_KEYGUARD) {
        // キーガード認証画面を管理する Activity を起動する
        // この例では Activity を 'KeyguardActivity' と呼んでいます
        Intent intent = new Intent(getApplicationContext(), KeyguardActivity.class);
        intent.putExtra(Tags.CVM, cvm);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
}

//...
```

を実装する `KeyguardActivity` をデジタルウォレットアプリケーション内に実装してください。これは次を継承する必要があります： `DeviceCVMKeyguardActivity`。これによりデバイス認証情報を使用した CDCVM 検証が可能になります。

次の例は `KeyguardActivity` クラスの実装を示します：

{% code expandable="true" %}

```java
public class KeyguardActivity extends DeviceCVMKeyguardActivity{

     private static String TAG = KeyguardActivity.class.getName();
     private PaymentBusinessService paymentBusinessService;
     private DeviceCVMVerifier chDeviceCVMVerifier;
     private TextView message;
     private boolean keyguardVerificationStart = false;
     private CharSequence title;
     private CharSequence message1;

     @Override
     protected void onCreate(Bundle savedInstanceState) {

      Log.d(TAG, "KeyguardActivity:onCreate");
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_device_keyguard);
      Log.d(TAG, "KeyguardActivity:unlockAndWake : start");
      unlockAndWake();
      Log.d(TAG, "KeyguardActivity:unlockAndWake : end");

      title=getString(R.string.keyguard_title);
      message1=getString(R.string.keyguard_message);

      Bundle extras = getIntent().getExtras();

      // バンドルから cvm オブジェクトを取得する
      CHVerificationMethod cvm = (CHVerificationMethod) extras.getSerializable(Tags.CVM);

      message = (TextView) findViewById(R.id.message);

      paymentBusinessService = PaymentBusinessManager.getPaymentBusinessService();

      PaymentService paymentService = paymentBusinessService.getActivatedPaymentService();

      // cvm オブジェクトを使って、対応する DeviceCVMVerifier オブジェクトのインスタンスを取得する
      chDeviceCVMVerifier = (DeviceCVMVerifier) paymentService.getCHVerifier(cvm);

      // 取得した DeviceCVMVerifier オブジェクトに対応するリスナーを設定する
      chDeviceCVMVerifier.setDeviceCVMVerifyListener(new DeviceCVMVerifyListener() {

      @Override
      public void onVerifySuccess() {
         // 検証は成功しました！
         message.setText("");
         KeyguardActivity.this.finish();
     }


      @Override
      public void onVerifyError(int errorCode, CharSequence charSequence) {
          // 呼び出されることは想定されていません
      }

      @Override
      public void onVerifyFailed() {
        // 検証は失敗しました！ユーザーに再試行を促す必要があります
        message.setText("認証できませんでした。もう一度お試しください。");
      }


      @Override
      public void onVerifyHelp(int i, CharSequence charSequence) {
          // 呼び出されることは想定されていません
      }

      });

      cbDeviceCVMVerifier.setKeyguardActivity(this);

      // 画面がオンでロック解除されているときに認証を開始する
      if (DeviceUtil.isDeviceScreenOn(getApplicationContext())) {

             Log.d(TAG, "Starting device keyguard authentication");
             keyguardVerificationStart = true;
             DeviceCVMVerifierInput input = new  DeviceCVMVerifierInput(title,message1);
             chDeviceCVMVerifier.startAuthentication(input);
       } else {
             Log.d(TAG, "Screen is disactivate, skiping keyguard authentication");
       }

     }

}
```

{% endcode %}

### バイオメトリクスを用いた CDCVM 検証（指紋の例）

デバイスが生体認証をサポートしている場合にこの方法を使用してください（例では指紋を示します）。

次の例は、この仕組みをどのように実装できるかを示します：

```java
// ContactlessPaymentServiceListener() 実装から
//...

@Override
public void onAuthenticationRequired(
  PaymentService activatedPaymentService,
  CHVerificationMethod cvm,
  long cvmResetTimeout) {

    // CDCVM のタイプを確認する
    if(cvm == CHVerificationMethod.FINGERPRINT) {
        // 指紋認証画面を管理する Activity を起動する
        // この場合、該当の Activity は 'BioFingerprintActivity' と呼ばれます
        Intent intent = new Intent(getApplicationContext(),
        BioFingerprintActivity.class);
        intent.putExtra(Tags.CVM, cvm);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
}

//...
```

専用の `Activity` を実装し、それが次を継承するようにしてください： `DeviceCVMKeyguardActivity`。これにより、生体認証が失敗したときにデバイスのキーカードへフォールバックできます。

{% code expandable="true" %}

```java
public class BioFingerprintActivity extends DeviceCVMKeyguardActivity {

    private static String TAG = BioFingerprintActivity.class.getName();
    private PaymentBusinessService paymentBusinessService;
    private DeviceCVMVerifier deviceCVMVerifier;
    private CancellationSignal cancellationSignal;
    private TextView message;
    private boolean isBioFPVerificationStarted = false;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_bio_fingerprint_2);
      unlockAndWake();
      Bundle extras = getIntent().getExtras();

      // バンドルで渡された cvm オブジェクトを取得する
      CHVerificationMethod cvm = (CHVerificationMethod) extras.getSerializable(Tags.CVM);

      message = (TextView) findViewById(R.id.message);
      paymentBusinessService = PaymentBusinessManager.getPaymentBusinessService();
      PaymentService paymentService = paymentBusinessService.getActivatedPaymentService();

      // cvm オブジェクトのおかげで 'DeviceCVMVerifier' のインスタンスを取得する
      deviceCVMVerifier = (DeviceCVMVerifier) paymentService.getCHVerifier(cvm);

			// 対応するリスナーを設定する
      deviceCVMVerifier.setDeviceCVMVerifyListener(new DeviceCVMVerifyListener() {

            @Override
            public void onVerifySuccess() {
              // 検証は成功しました！
              message.setText("");
              BioFingerprintActivity.this.finish();
            }

            @Override
            public void onVerifyError(int errorCode, CharSequence charSequence) {

              Log.d(TAG, "BioFingerprintActivity:error :" + errorCode);

              // ロックスクリーンモードでトリガーされた特殊なケース
              // FINGERPRINT_ERROR_CANCELED エラーが発生する
              if (errorCode == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
                  Log.d(TAG, "restart Fp");
                  if (cancellationSignal != null)
                      cancellationSignal.cancel();

              isBioFPVerificationStarted=true;
              cancellationSignal = new CancellationSignal();
              DeviceCVMVerifierInput input = new DeviceCVMVerifierInput(cancellationSignal);
              deviceCVMVerifier.startAuthentication(input);
              }
              // エラーコードの通常の処理
              else {
                        message.setText(charSequence + ". もう一度お試しください...");
                        if(errorCode == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT) {
                            confirmCredential("キーガードで検証", "試行回数が多すぎます。PIN / パターン / パスワードで検証してください");
                  }
              }
            }

            @Override
            public void onVerifyFailed() {
                message.setText("指紋を認識できませんでした。もう一度お試しください。");
            }


            @Override
            public void onVerifyHelp(int i, CharSequence charSequence) {
                message.setText(charSequence + ". もう一度お試しください。");
            }

        });

        deviceCVMVerifier.setKeyguardActivity(this);
        cancellationSignal = new CancellationSignal();

        // 画面がオンでロック解除されているときに認証を開始する
        if (DeviceUtil.isDeviceScreenOn(getApplicationContext())) {
            Log.d(TAG, "Starting Fingerprint authentication");
            DeviceCVMVerifierInput input = new DeviceCVMVerifierInput(cancellationSignal);
            deviceCVMVerifier.startAuthentication(input);
        } else {
            Log.d(TAG, "Screen is de-activated, skipping Fingerprint authentication");
        }
    }

  	/* 指紋検証が失敗した場合、次のコールバックを実装して
    キーガード検証へフォールバックすることが可能です。
    **/
    public void onKeyguardFallback(View v) {

      Log.d(TAG, "onKeyguardFallback");
      // deviceCVMVerifier.startAuthentication(input) を呼び出す


    }

  	@Override
  	public void onCancel(View v) {
      Log.d(TAG, "Cancel authentication");
      cancelTransaction("取引はキャンセルされました。");
    }

    @Override
    public void onBackPressed() {
        Log.d(TAG, "onBackPressed()");
        cancelTransaction("取引はキャンセルされました。");
    }


    /*
    指紋生体認証をキャンセルした後、Payment サービスは無効化されるべきです
    **/
  	private void cancelTransaction(String message) {
          if (cancellationSignal != null) {
              cancellationSignal.cancel();
          }
          PaymentBusinessManager.getPaymentBusinessService().deactivate();
    }

}
```

{% endcode %}

デジタルウォレットアプリがバックグラウンドに移行した場合、指紋認証のリスニングを停止してください。

これは次のコードスニペットで実現できます：

```java
@Override
public void onResume() {
       super.onResume();
       cancellationSignal=new CancellationSignal();
       deviceCVMVerifier.startAuthentication(cancellationSignal);
   }

@Override
public void onPause() {
     if(cancellationSignal != null)
             cancellationSignal.cancel();
}
```

### ロックスクリーンシナリオをサポートする（オプション）

デバイスがロックされているときに認証プロンプトをサポートする必要がある場合、次を確認してください：

* 支払い中に表示される Activity は次で宣言されていること： `showOnLockScreen=true`.
* wake lock を取得し、ロックスクリーンで UI を表示するためのウィンドウフラグを設定します。
* 支払いが完了したら、 `wakeLock` を解放してバッテリー使用量を減らしてください。

マニフェストで次の設定を行い、必要に応じてサンプルコードを実装してください：

```xml
<activity
        android:name=".BioFingerprintActivity"
        android:showOnLockScreen="true"
        android:screenOrientation="portrait" />
```

```java
@Override
public void onCreate() {
        //…
        unlockAndWake();
        //…
}

private void unlockAndWake() {

    PowerManager.WakeLock mWl;
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    if (!pm.isScreenOn()) {
        mWl = pm.newWakeLock(
                PowerManager.SCREEN_BRIGHT_WAKE_LOCK | 
                PowerManager.FULL_WAKE_LOCK | 
                PowerManager.ACQUIRE_CAUSES_WAKEUP, "");
        mWl.acquire();
    }

    getWindow().addFlags(
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | 
            WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON   | 
            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON   | 
            WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}

@Override
public void onDestroy() {

  try{
      if(null!=mW1){
          mWl.release();
      }
  }
 	catch(Exception e){ }
}
```

### 委任認証

委任認証により、デジタルウォレットアプリはエンドユーザーに認証を促し、その後支払いを進めてよいことを SDK に通知できます。

認証は、ユーザー認証によって保護される基盤となるキーストアのロックを解除するためにデバイスのキーカードまたは生体認証を使用できます。

このフローは、SDK が支払い中に認証を要求する場合に適用されます。デジタルウォレットアプリは次のいずれかを行えます：

* エンドユーザーに認証を促し、その後次を呼び出す： `DeviceCVMVerifier.onDelegatedAuthPerformed(timeOfAuth)`.
* 最近の成功した認証（構成された鍵有効期間内）を再利用し、次を呼び出す： `DeviceCVMVerifier.onDelegatedAuthPerformed(timeOfAuth)` 直ちに。

エンドユーザーがトランザクションを中止した場合は、次を呼び出してください `DeviceCVMVerifier.onDelegatedAuthCancelled()`.

```java
@Override
public void onAuthenticationRequired(final PaymentService service, CHVerificationMethod cvm, long cvmResetTimeout) {
                            
  // 生体認証またはKeyGuard方式にのみ適用されます
   if(cvm == CHVerificationMethod.BIOMETRICS || cvm == CHVerificationMethod.DEVICE_KEYGUARD){
      // 検証器を取得する
      final DeviceCVMVerifier verifier = (DeviceCVMVerifier)service.getCHVerifier(cvm);
                                
      // MPAは認証を実行し、認証のタイムスタンプを提供する
      ...

      // タイムスタンプはSDKが現在時刻と比較して、まだキー有効期間内であることを確認するために使用されます

      // 検証方法が生体認証の場合、MPAはCVMタイプをFINGERPRINTに設定することができます
      verifier.setCVMType(CVMType.FINGERPRINT);

      // また、MPAはエンドユーザーがトランザクションの2回目のタップを行うのに十分な時間が残っていることを確認するチェックを行うことが推奨されます。
      verifier.onDelegatedAuthPerformed(timeOfAuth);
                                
      // ユーザーが認証を行いたくない場合、MPAはトランザクションをキャンセルする必要があります
      verifier.onDelegatedAuthCancelled();
  }
}
```


---

# 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/implement-nfc-wallet/make-payment/implement-contactless-payments/5.-perform-cdcvm-verification.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.
