法人番号をLightningWebComponentで取得する

### 目的
取引先ごとに法人番号を管理するため

### 背景
インボイス制度により企業は「区分記載請求書」に「登録番号」、「適用税率」及び「消費税額等」の記載が追加された書類やデータを交付・保存する必要がある
https://www.nta.go.jp/taxes/shiraberu/zeimokubetsu/shohi/keigenzeiritsu/invoice_about.htm

登録番号の構成は、次のとおりです

法人番号を有する課税事業者
「T」（ローマ字）　＋　法人番号（数字13桁）
上記以外の課税事業者（個人事業者、人格のない社団等）
「T」（ローマ字）　＋　数字13桁（注）
　（注）13桁の数字には、マイナンバー（個人番号）は用いず、法人番号とも重複しない事業者ごとの番号になります。

### 本記事でやること
経済産業省から提供されている法人データ付与ツールを用いてSalesforceのLightningWebComponent経由で取得し、法人名と法人番号をSalesforceの取引先へ保存する

法人番号付与ツール
https://info.gbiz.go.jp/tools/nayose/index.html

利用申請ページから申請を行い、APIキーを取得する
https://info.gbiz.go.jp/hojin/user_registration/application

### 実装結果
1.取引先データを表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542419/70e18c60-aa08-9b33-df12-a467e809fe4e.png)

2.法人番号検索セクションの検索ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542419/ad30c8d6-1d44-f339-2de7-a8bef4d82253.png)

3.該当する法人を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542419/17892e58-acd3-5111-9d5b-326bc78e52d2.png)

4.保存ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542419/d31ac796-eeed-392c-c134-97d5350779f2.png)

5.法人名（取引先名）と法人番号が書き換わっていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542419/b9569e29-934f-9c5c-b268-6527454217c6.png)

### 実装内容
* LightningWebComponent

searchCorporateNumber

searchCorporateNumber.html
```
<template>
    <lightning-card title="法人番号検索">
        <div class="slds-var-m-around_medium">
            <lightning-button variant="brand" label="検索" title="SearchCorporateNumber"  
              onclick={handleClick}  record-id={recordId} class="slds-m-left_x_medium"></lightning-button>
        </div>
    </lightning-card>
</template>
```
searchCorporateNumber.js
```
import { LightningElement, api, track, wire } from 'lwc';
import searchCorporateNumber from '@salesforce/apex/CorporateInformationController.searchCorporateNumber';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';

export default class SearchCorporateNumber extends LightningElement {
    @api recordId;
    @track companyInfo;
   
    handleClick() {
        searchCorporateNumber({ accountId: this.recordId })
        .then(result => {
            this.companyInfo = JSON.stringify(result);
            this.companyInfoMessage = JSON.parse(JSON.stringify(result))["message"];
 
            if (this.companyInfoMessage == "200 - OK.") {
                const e = new CustomEvent('clickbutton', { detail: this.companyInfo});
                this.dispatchEvent(e);
            } else {
                const evt = new ShowToastEvent({
                    message: '企業情報の候補がありません',
                    variant: 'info',
                });
                this.dispatchEvent(evt);
            }
        });
    }

}
```
searchCorporateNumber.js-meta.xml
```
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
```

corporateNumber
corporateNumber.html
```
<template>
    <c-search-corporate-number onclickbutton={setCompanyInfo} record-id={recordId}></c-search-corporate-number>
    <template if:true={companyInfo}>
        <lightning-card>
            <lightning-radio-group 
                class="slds-var-m-around_medium"
                name="radioGroup"
                label="検索結果"
                options={options}
                value={value}
                onchange={handleChange}
                type="radio">
            </lightning-radio-group>
            <lightning-button variant="brand" label="保存" title="SaveCorporateNumber" 
                onclick={updateAccountData} class="slds-var-m-around_medium slds-m-left_x_medium"></lightning-button>
        </lightning-card>
    </template>
    <template if:false={companyInfo}>
    </template>
</template>
```
corporateNumber.js
```
import { track,LightningElement,api,wire } from 'lwc';
import updateAccount from '@salesforce/apex/CorporateInformationController.updateAccount';
import wireSimpleOrComplexData from '@salesforce/apex/CorporateInformationController.wireSimpleOrComplexData';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class CorporateNumber extends LightningElement {
@track companyInfo;
@track options = [];
@track selectedIndex;

@api
    get recordId() {
        return this.accountId;
    }
    set recordId(value) {
        this.accountId = value;
    }
    
    wiredData;
    accountId;
    account;
    error;
  
    @wire(wireSimpleOrComplexData, { accountId: '$_accountId' })
    wiredData(result) {
        this.wiredData = result; 
        if (result.data) {
            this.account = { ...result.data.accountFromServer };
        } else {
            console.log(result.error);
        }
    }
    
    setCompanyInfo(event) {
        this.options = "";
        this.companyInfo = JSON.parse(event.detail)["hojin-infos"];
        
        for(var index in this.companyInfo){
            const option = {
                label: this.companyInfo[index].name + '(' + this.companyInfo[index].corporate_number + ') ' + this.companyInfo[index].location,
                value: index
            };
            this.options = [ ...this.options, option ];
        }
    }

    handleChange(event) {
        this.selectedIndex = event.target.value;
    }

    updateAccountData() {
        let newAccount = {};
        newAccount.Id = this.recordId;
        newAccount.Name = this.companyInfo[this.selectedIndex].name;
        newAccount.AccountNumber = this.companyInfo[this.selectedIndex].corporate_number;

        updateAccount({account: newAccount})
            .then(() => {
                const evt = new ShowToastEvent({
                    message: '保存しました',
                    variant: 'success',
                });
                this.dispatchEvent(evt);
                
                this.companyInfo = null;
                setTimeout(() => {
                eval("$A.get('e.force:refreshView').fire();");
            }, 1000); 
        })
        .catch(error => {
            const evt = new ShowToastEvent({
                message: '保存できませんでした',
                variant: 'error',
            });
            this.dispatchEvent(evt);
            console.log(error);
        });
    }
}
```
corporateNumber.js-meta.xml
```
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
```

* Apex

CorporateInformationController.cls
```
public with sharing class CorporateInformationController {
    @AuraEnabled (cacheable=true)
    public static Map<String, Object> wireSimpleOrComplexData(String accountId) {
      Map<String, Object> result = new Map<String, Object>();
      Account acc = [SELECT Id, Name, AccountNumber FROM Account WHERE Id =: accountId LIMIT 1];
      result.put('accountFromServer', acc);
  
      return result;
    }

    @AuraEnabled
    public static Map<String, Object> searchCorporateNumber(String accountId){
        try {
            String accountname = [SELECT Name FROM Account WHERE Id =: accountId].Name;
            
            HttpRequest req = new HttpRequest();
            String searchKey = EncodingUtil.urlEncode(accountName, 'UTF-8');
            req.setEndpoint('https://info.gbiz.go.jp/hojin/v1/hojin?name=' + searchKey + '&page=1&limit=50');
            req.setMethod('GET');
            req.setHeader('Accept','application/json');
            req.setHeader('X-hojinInfo-api-token','利用申請して取得したAPIキー');
            
            Http http = new Http();
            HTTPResponse res = http.send(req);
            Map<String, Object> mapJson = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());

            return mapJson;
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }

    @AuraEnabled
    public static Account updateAccount(Account account) {
        update account;

        return account;
    }
}
```