# 運転免許証API

<br>
## **概要**

運転免許証APIは、運転免許証またはマイナ免許証のICチップを読み取るためのAPIです。
運転免許証の場合は設定されている暗証番号1および暗証番号2、マイナ免許証の場合はマイナ免許証の暗証番号を入力することで、運転免許証またはマイナ免許証の情報を全て取得します（取得項目は選択可能です）。また、運転免許証またはマイナ免許証に格納されている電子署名を検証することで真贋判定を行い、有効期間の末日と当日の日付を比較することで、有効性確認も同時に行います。真贋および有効性が確認できた場合、運転免許証またはマイナ免許証の情報を取得できます。

:::caution[]
注意
マイナ免許証には、氏名・生年月日・住所・性別の基本4情報が格納されていないため、取得するには別途、券面事項入力補助APIを利用する必要があります。券面事項入力補助APIの詳細は[こちら](https://www.primagest.net/document/identity-verification/ic-chip/my-number-card-cardface-information.md)からご覧ください。
また、運転免許証には、性別情報が記載されていないため、取得できません。
:::

## **取得できる項目**
<AccordionGroup>
    <Accordion title="運転免許証の取得項目">
        - 氏名
        - 生年月日
        - 住所
        - 顔写真（モノクロイメージ）
        - 有効期間の末日
        - 外字（旧漢字など、文字コード（JIS X 0208）で表現できない文字が存在する場合のみ取得できるイメージ）
        - 呼び名（カナ）
        - 通称名
        - 統一氏名（カナ）
        - 交付年月日
        - 照会番号
        - 免許証の色区分（優良・新規・その他）
        - 公安委員会
        - 免許証の番号
        - 免許の種別・交付日
        - 免許の条件1～4（「眼鏡等」「準中型（5t）と普通車はAT者に限る」など、免許の条件を取得）
        - 本籍
        - 新本籍（存在する場合のみ取得）
        - 住所地公安委員会名
        - 新氏名（存在する場合のみ取得）
        - 新住所（存在する場合のみ取得）
        - 新呼び名（存在する場合のみ取得）
        - 新条件（存在する場合のみ取得）
        - 条件解除（存在する場合のみ取得）
        - 備考・予備
        - 電子署名
        - シリアル番号
        - 発行者名
        - 主体者名
        - 主体者鍵識別子        
    </Accordion>
    <Accordion title="マイナ免許証の取得項目">
        - 顔写真（モノクロイメージ）
        - 有効期間の末日
        - 運転経歴情報記録番号
        - 運転者区分（優良・一般・違反）
        - 運転経歴情報記録年月
        - 免許情報記録番号（マイナ免許証の免許番号になります）
        - 免許証の色区分（優良・新規・その他）
        - 免許の条件1〜12（「眼鏡等」「準中型（5t）と普通車はAT者に限る」など、免許の条件を取得）
        - 免許の年月日
        - 免許の種類
        - 備考1〜8（「免許の手続き中」や収まりきらなかった「免許の条件」などの事項を格納します）
        - 予備1〜8（備考が全て埋まっている場合に利用されます）
        - 電子署名
        - シリアル番号
        - 発行者名
        - 主体者名
        - 主体者鍵識別子        
    </Accordion>
</AccordionGroup>

## **アクセスコントロール**

<AccordionGroup>
    <Accordion title="運転免許証の読み取り">
        - 運転免許証の暗証番号1（4桁の数字）
        - 運転免許証の暗証番号2（4桁の数字）
        ※3回連続で暗証番号を間違えた場合には、運転免許証の間違えた暗証番号のみロックがかかってしまいますのでご注意ください。
    </Accordion>
    <Accordion title="マイナ免許証の読み取り">
        - マイナ免許証の暗証番号（4桁の数字）
        ※10回連続で暗証番号を間違えた場合には、マイナ免許証にロックがかかってしまいますのでご注意ください。
    </Accordion>
 </AccordionGroup>

## **処理の流れ**

<Tabs>
    <Tab title="対面">        
        <Steps>
            <Step title="運転免許証・マイナ免許証のデータ取得（サービスプロバイダ事業者）">
                SDKを利用して運転免許証またはマイナ免許証のICチップを読み取り、利用者が入力した運転免許証またはマイナ免許証の暗証番号を利用することで、運転免許証またはマイナ免許証のデータを取得します。取得したデータは、署名検証・有効性確認・利用可能な形式への変換を行うため、APIで送信します。
            </Step>
            <Step title="運転免許証・マイナ免許証の署名検証・有効性確認（プラットフォーム事業者）">
                APIで送信されたデータより電子署名を取得し、署名検証による真贋判定を行います。署名検証後は、運転免許証の有効期間の末日と当日の日付を比較し、有効性確認を行います。いずれかの処理が異常終了した場合、運転免許証またはマイナ免許証の情報は取得されず、署名検証および有効性確認の結果のみを返却します。     
            </Step>
            <Step title="運転免許証・マイナ免許証の情報取得（プラットフォーム事業者）">
                署名検証および有効性確認が正常に完了した場合、運転免許証またはマイナ免許証の情報を利用可能な形式に変換し、サービスプロバイダ事業者へ返却します。取得項目を選択している場合は、対象の項目のみ返却されます。
            </Step>
        </Steps>
    </Tab>
    <Tab title="非対面">
        <Steps>
            <Step title="運転免許証・マイナ免許証のデータ取得（サービスプロバイダ事業者）">
                SDKを利用して運転免許証またはマイナ免許証のICチップを読み取り、利用者が入力した運転免許証またはマイナ免許証の暗証番号を利用することで、運転免許証またはマイナ免許証のデータを取得します。取得したデータは、署名検証・有効性確認・利用可能な形式への変換を行うため、APIで送信します。
            </Step>
            <Step title="運転免許証・マイナ免許証の署名検証・有効性確認（プラットフォーム事業者）">
                APIで送信されたデータより電子署名を取得し、署名検証による真贋判定を行います。署名検証後は、運転免許証の有効期間の末日と当日の日付を比較し、有効性確認を行います。いずれかの処理が異常終了した場合、運転免許証またはマイナ免許証の情報は取得されず、署名検証および有効性確認の結果のみを返却します。     
            </Step>
            <Step title="運転免許証・マイナ免許証の情報取得（プラットフォーム事業者）">
                署名検証および有効性確認が正常に完了した場合、運転免許証またはマイナ免許証の情報を利用可能な形式に変換し、サービスプロバイダ事業者へ返却します。取得項目を選択している場合は、対象の項目のみ返却されます。
            </Step>
        </Steps>
    </Tab>
</Tabs>

## **シーケンス図**

<Tabs>
    <Tab title="対面">
```mermaid
    %%{init:{'theme':'natural'}}%%
    sequenceDiagram
    participant 利用者
    participant SDK
    participant サービスプロバイダ事業者
    participant プラットフォーム事業者
    participant J-LIS

    alt 運転免許証の場合
        サービスプロバイダ事業者->>SDK: 運転免許証の読み取り要求
        SDK->>利用者: 運転免許証の読み取り要求
        利用者->>SDK: 運転免許証の読み取り<br>暗証番号1・暗証番号2の入力
        SDK->>SDK: 運転免許証のデータ取得
        SDK->>SDK: ハッシュ値の生成
        SDK->>サービスプロバイダ事業者: 運転免許証のデータ・ハッシュ値の返却
        サービスプロバイダ事業者->>プラットフォーム事業者: 運転免許証のデータ・ハッシュ値の送信
        プラットフォーム事業者->>プラットフォーム事業者: 運転免許証の署名検証
        プラットフォーム事業者->>プラットフォーム事業者: 運転免許証の有効性確認
        alt 署名検証・有効性確認が正常の場合
            プラットフォーム事業者->>プラットフォーム事業者: 運転免許証データの変換
            プラットフォーム事業者->>サービスプロバイダ事業者: 署名検証結果・有効性確認結果<br>運転免許証情報の返却
        else 署名検証・有効性確認が異常の場合
            プラットフォーム事業者->>サービスプロバイダ事業者: 署名検証結果・有効性確認結果の返却
        end
    else マイナ免許証の場合
        サービスプロバイダ事業者->>SDK: マイナ免許証の読み取り要求
        SDK->>利用者: マイナ免許証の読み取り要求
        利用者->>SDK: マイナ免許証の読み取り<br>暗証番号の入力
        SDK->>SDK: マイナ免許証のデータ取得
        SDK->>SDK: ハッシュ値の生成
        SDK->>サービスプロバイダ事業者: マイナ免許証のデータ・ハッシュ値の返却
        サービスプロバイダ事業者->>プラットフォーム事業者: マイナ免許証のデータ・ハッシュ値の送信
        プラットフォーム事業者->>プラットフォーム事業者: マイナ免許証の署名検証
        プラットフォーム事業者->>プラットフォーム事業者: マイナ免許証の有効性確認
        alt 署名検証・有効性確認が正常の場合
            プラットフォーム事業者->>プラットフォーム事業者: マイナ免許証データの変換
            プラットフォーム事業者->>サービスプロバイダ事業者: 署名検証結果・有効性確認結果<br>マイナ免許証情報の返却
        else 署名検証・有効性確認が異常の場合
            プラットフォーム事業者->>サービスプロバイダ事業者: 署名検証結果・有効性確認結果の返却
        end
    end
```
    </Tab>
    <Tab title="非対面">
```mermaid
    %%{init:{'theme':'natural'}}%%
    sequenceDiagram
    participant 利用者
    participant SDK
    participant サービスプロバイダ事業者
    participant プラットフォーム事業者
    participant J-LIS

    alt 運転免許証の場合
        サービスプロバイダ事業者->>SDK: 運転免許証の読み取り要求
        SDK->>利用者: 運転免許証の読み取り要求
        利用者->>SDK: 運転免許証の読み取り<br>暗証番号1・暗証番号2の入力
        SDK->>SDK: 運転免許証のデータ取得
        SDK->>SDK: ハッシュ値の生成
        SDK->>サービスプロバイダ事業者: 運転免許証のデータ・ハッシュ値の返却
        サービスプロバイダ事業者->>プラットフォーム事業者: 運転免許証のデータ・ハッシュ値の送信
        プラットフォーム事業者->>プラットフォーム事業者: 運転免許証の署名検証
        プラットフォーム事業者->>プラットフォーム事業者: 運転免許証の有効性確認
        alt 署名検証・有効性確認が正常の場合
            プラットフォーム事業者->>プラットフォーム事業者: 運転免許証データの変換
            プラットフォーム事業者->>サービスプロバイダ事業者: 署名検証結果・有効性確認結果<br>運転免許証情報の返却
        else 署名検証・有効性確認が異常の場合
            プラットフォーム事業者->>サービスプロバイダ事業者: 署名検証結果・有効性確認結果の返却
        end
    else マイナ免許証の場合
        サービスプロバイダ事業者->>SDK: マイナ免許証の読み取り要求
        SDK->>利用者: マイナ免許証の読み取り要求
        利用者->>SDK: マイナ免許証の読み取り<br>暗証番号の入力
        SDK->>SDK: マイナ免許証のデータ取得
        SDK->>SDK: ハッシュ値の生成
        SDK->>サービスプロバイダ事業者: マイナ免許証のデータ・ハッシュ値の返却
        サービスプロバイダ事業者->>プラットフォーム事業者: マイナ免許証のデータ・ハッシュ値の送信
        プラットフォーム事業者->>プラットフォーム事業者: マイナ免許証の署名検証
        プラットフォーム事業者->>プラットフォーム事業者: マイナ免許証の有効性確認
        alt 署名検証・有効性確認が正常の場合
            プラットフォーム事業者->>プラットフォーム事業者: マイナ免許証データの変換
            プラットフォーム事業者->>サービスプロバイダ事業者: 署名検証結果・有効性確認結果<br>マイナ免許証情報の返却
        else 署名検証・有効性確認が異常の場合
            プラットフォーム事業者->>サービスプロバイダ事業者: 署名検証結果・有効性確認結果の返却
        end
    end
```
    </Tab>
</Tabs>

## **実装例**

<Tabs>
    <Tab title="iOS">
```swift
// 暗証番号1（4桁）＋// 暗証番号2（4桁）
let pin1 = "暗証番号1"
let pin2 = "暗証番号2"

// エンドポイント
let endpoint = "APIのエンドポイント"

// SDKの呼び出し
let reader = NFCReader(delegate: _NFCDelegate())

// 運転免許証情報の取得
reader.getDriversLicenseInfo(pin1: pin1, pin2: pin2) { driverLicenseData in

    let parameters = """
    {
        "data": "\(driverLicenseData)",
        "allFlag":false
    }
    """
    let postData = parameters.data(using: .utf8)
    
    // リクエスト作成
    var request = URLRequest(url: URL(string: endpoint)!, timeoutInterval: Double.infinity)
    request.addValue("<token>", forHTTPHeaderField: "X-PTS-API-Key")
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    request.httpBody = postData
    
    // リクエストの送信・エラー処理の記述
    
}
```
    </Tab>
    <Tab title="Android">
```kotlin
// 暗証番号1（4桁）＋// 暗証番号2（4桁）
val pin1 = "暗証番号1"
val pin2 = "暗証番号2"

// エンドポイント
val endpoint = "APIのエンドポイント"

// SDKの呼び出し
val reader = NFCReader(delegate = NFCDelegate())

// 運転免許証情報の取得
reader.getDriversLicenseInfo(pin1=pin1, pin2=pin2) { driverLicenseData ->
    val client = OkHttpClient()
    
    // リクエスト作成
    val body = JSONObject()
    body.put("data", driverLicenseData)
    body.put("allFlag",false)
    
    val mediaType = "application/json".toMediaType()
    val requestBody = body.toString().toRequestBody(mediaType)
    
    val request = Request.Builder()
        .url(endpoint)
        .post(requestBody)
        .addHeader("Content-Type", "application/json")
        .addHeader("X-PTS-API-Key", "<token>")
        .build()
    
    // リクエストの送信・エラー処理の記述
}
```
    </Tab>
    <Tab title="React Native">
```typescript
// 暗証番号1（4桁）＋// 暗証番号2（4桁）
const pin1 = "暗証番号1"
const pin2 = "暗証番号2"

// エンドポイント
const endpoint = 'APIのエンドポイント';
const token = '<token>';

// 本来はSDKで運転免許証情報を取得する
const driverLicenseData = '<driverLicenseData>'; // 取得結果の想定

// リクエスト作成・送信
await fetch(endpoint, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-PTS-API-KEY': `${token}`,
  },
  body: JSON.stringify({
    data: driverLicenseData,
    allFlag: false
  }),
});
        
// リクエストの送信・エラー処理の記述
```
    </Tab>
    <Tab title="Windows">
```cpp
// 暗証番号1（4桁）＋ 暗証番号2（4桁）
std::string pin1 = "暗証番号1";
std::string pin2 = "暗証番号2";

// エンドポイント
std::string endpoint = "APIのエンドポイント";

std::string responseData;

// 運転免許証情報の取得（C API: get_drivers_license(session, pin1, pin2, data, data_max, data_len)）
const int data_max = 4096;  // 必要に応じてサイズを調整
std::vector<uint8_t> buffer(data_max);
int data_len = 0;

int result = get_drivers_license(session, pin1.c_str(), pin2.c_str(),
                                 buffer.data(), data_max, &data_len);

if (result == 0 && data_len > 0) {
    // APIはBase64のICカードデータを要求するため、バイナリをBase64エンコード
    std::string driverLicenseDataBase64 = base64_encode(buffer.data(), data_len);
    
    // リクエスト作成
    Json::Value body;
    body["data"] = driverLicenseDataBase64;
    body["allFlag"] = false;
    
    std::string jsonString = Json::writeString(Json::StreamWriterBuilder(), body);
    
    CURL* curl = curl_easy_init();
    if (curl) {
        struct curl_slist* headers = curl_slist_append(nullptr, "Content-Type: application/json");
        headers = curl_slist_append(headers, "X-PTS-API-Key: <token>");
        curl_easy_setopt(curl, CURLOPT_URL, endpoint.c_str());
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonString.c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
        
        CURLcode res = curl_easy_perform(curl);
        // リクエストの送信・エラー処理の記述
        
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
}
```
    </Tab>
</Tabs>

<br>

