# マイナンバーカード券面API

<br>
## **概要**

券面APIは、マイナンバーカードの表面と裏面の画像データを取得するAPIです。
取得する画像に対応した照合番号を入力し、マイナンバーカードのICチップから券面APを読み取ります。
これにより、本人確認時の券面記載情報の改ざん検知、また本人確認の証跡として画像情報の利用が可能となります。
    
## **取得できる項目**
<AccordionGroup>
    <Accordion title="券面（表面と裏面）">
        画像で取得する項目
        - 氏名
        - 住所
        - 顔写真
        - セキュリティコード
        - 個人番号
        
        テキストで取得する項目
        - 生年月日
        - 性別
        - 有効期限
    </Accordion>
    <Accordion title="券面（表面）">
        画像で取得する項目
        - 氏名
        - 住所
        - 顔写真
        - セキュリティコード
        
        テキストで取得する項目
        - 生年月日
        - 性別
        - 有効期限
    </Accordion>
    <Accordion title="券面（裏面）">
        画像で取得する項目
        - 個人番号
    </Accordion>
</AccordionGroup>

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

<AccordionGroup>
    <Accordion title="表面（基本4情報＋顔写真）と裏面（個人番号）の画像を利用する">
        暗証番号（4桁の数字） 
        ※3回連続で券面事項入力補助の暗証番号を間違えた場合には、マイナンバーカードにロックがかかってしまいますのでご注意ください。
    </Accordion>
    <Accordion title="表面（基本4情報＋顔写真）の画像を利用する">
        券面記載の照合番号B（14桁の数字：生年月日6桁＋有効期限の西暦4桁＋セキュリティコード4桁）
        ※10回連続で券面事項確認の照合番号Bを間違えた場合には、マイナンバーカードにロックがかかってしまいますのでご注意ください。
    </Accordion>
    <Accordion title="裏面（個人番号）の画像を利用する">
        券面記載の照合番号A（個人番号12桁の数字）
    </Accordion>
 </AccordionGroup>

## **処理の流れ**

<Tabs>
    <Tab title="対面">
        <Steps>
            <Step title="券面の要求（サービスプロバイダ事業者）">
                取得対象に対応する暗証番号もしくは照合番号を利用者が入力します。
            </Step>
            <Step title="券面データを取得（サービスプロバイダ事業者）">
                SDKを使用して、マイナンバーカードに格納されている券面APを呼び出し、準備した照合番号を照合することで内部認証を行います。内部認証が成功するとマイナンバーカードの券面データとして取得されます。
            </Step>
            <Step title="画像データの変換・返却（プラットフォーム事業者）">
                APIを使用して券面データを利用できる画像形式に変換し、サービスプロバイダ事業者へ返却します。
            </Step>
        </Steps>
    </Tab>
    <Tab title="非対面">
        <Steps>
            <Step title="券面の要求（サービスプロバイダ事業者）">
                取得対象に対応する暗証番号もしくは照合番号を利用者が入力します。
            </Step>
            <Step title="券面データを取得（サービスプロバイダ事業者）">
                SDKを使用して、マイナンバーカードに格納されている券面APを呼び出し、準備した照合番号を照合することで内部認証を行います。内部認証が成功するとマイナンバーカードの券面データとして取得されます。
            </Step>
            <Step title="画像データの変換・返却（プラットフォーム事業者）">
                APIを使用して券面データを利用できる画像形式に変換し、サービスプロバイダ事業者へ返却します。
            </Step>
        </Steps>
    </Tab>
</Tabs>




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

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

    サービスプロバイダ事業者->>SDK: 券面取得の要求
    alt 表面と裏面を利用する
        SDK->>利用者: 券面取得の要求<br>暗証番号4桁の要求
        利用者->>SDK: 券面の読み取り<br>暗証番号4桁の入力
    else 表面のみ利用する
        SDK->>利用者: 券面取得の要求<br>照合番号Bの要求
        利用者->>SDK: 券面の読み取り<br>照合番号Bの入力
    else 裏面のみ利用する
        SDK->>利用者: 券面取得の要求<br>照合番号Aの要求
        利用者->>SDK: 券面の読み取り<br>照合番号Aの入力
    end
    SDK->>SDK: 内部認証
    SDK->>SDK: 券面データ取得
    SDK->>サービスプロバイダ事業者: 券面データの返却
    サービスプロバイダ事業者->>プラットフォーム事業者: 券面データの送信
    プラットフォーム事業者->>プラットフォーム事業者: 券面データの画像変換
    プラットフォーム事業者->>サービスプロバイダ事業者: 画像データの返却
```
    </Tab>
    <Tab title="非対面">
```mermaid
    %%{init:{'theme':'natural'}}%%
    sequenceDiagram
    participant 利用者
    participant SDK
    participant サービスプロバイダ事業者
    participant プラットフォーム事業者
    participant J-LIS

    サービスプロバイダ事業者->>SDK: 券面取得の要求
    alt 表面と裏面を利用する
        SDK->>利用者: 券面取得の要求<br>暗証番号4桁の要求
        利用者->>SDK: 券面の読み取り<br>暗証番号4桁の入力
    else 表面のみ利用する
        SDK->>利用者: 券面取得の要求<br>照合番号Bの要求
        利用者->>SDK: 券面の読み取り<br>照合番号Bの入力
    else 裏面のみ利用する
        SDK->>利用者: 券面取得の要求<br>照合番号Aの要求
        利用者->>SDK: 券面の読み取り<br>照合番号Aの入力
    end
    SDK->>SDK: 内部認証
    SDK->>SDK: 券面データ取得
    SDK->>サービスプロバイダ事業者: 券面データの返却
    サービスプロバイダ事業者->>プラットフォーム事業者: 券面データの送信
    プラットフォーム事業者->>プラットフォーム事業者: 券面データの画像変換
    プラットフォーム事業者->>サービスプロバイダ事業者: 画像データの返却
    サービスプロバイダ事業者->>利用者: 画像データの送信
```
    </Tab>
</Tabs>


## **実装例**

<Tabs>
    <Tab title="iOS">
```swift
// 照合番号Aまたは照合番号B
let pinCode = "暗証番号4桁または照合番号Aまたは照合番号B"

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

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

// 内部認証・券面データ取得
reader.getTicketData(matchingNumber: pinCode) { ticketData in
    
    let parameters = """
    {
        "data": "\(ticketData.base64EncodedString())"
    }
    """
    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
// 照合番号Aまたは照合番号B
val pinCode = "暗証番号4桁または照合番号Aまたは照合番号B"

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

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

// 内部認証・券面データ取得
reader.getTicketData(matchingNumber = pinCode) { ticketData ->
    val client = OkHttpClient()
    
    // リクエスト作成
    val body = JSONObject()
    body.put("data", Base64.encodeToString(ticketData, Base64.NO_WRAP))
    
    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
// エンドポイント
const endpoint = 'APIのエンドポイント';
// 券面PIN
const pinCode = '暗証番号4桁または照合番号Aまたは照合番号B';

// 内部認証・券面データ取得
const cardFaceBase64 = TrustServices.getCardFace(pinCode);

// リクエスト作成
await fetch(endpoint, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-PTS-API-Key': `${token}`,
    },
    body: JSON.stringify({
        data: cardFaceBase64, // Base64の券面データ
    })
});

// リクエストの送信・エラー処理の記述
```
    </Tab>
    <Tab title="Windows">
```cpp
// 照合番号Aまたは照合番号B
std::string pinCode = "照合番号";

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

// SDKの呼び出し
NFCReader reader(delegate);

// 内部認証・券面データ取得
reader.getTicketData(pinCode, [&](const std::vector<unsigned char>& ticketData) {
    // リクエスト作成
    Json::Value body;
    body["data"] = base64_encode(ticketData);
    
    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);
        // リクエストの送信・エラー処理の記述

    }
});
```
    </Tab>
</Tabs>

<br>

