適格請求書発行事業者番号を会社名で検索する方法
【問題の所在】
2022年9月19日現在、適格請求書発行事業者かそうでないかを調べる方法は、国税庁のインボイス制度適格請求書発行事業者公表サイトにおいて、適格請求書発行事業者番号(T+13桁の数字。以下「番号」と省略する)を入力し検索するしかない。
インボイスとして見なせるかどうかは、ヒアリングした番号と、その後発行される各種帳票に記載された番号の一致をチェックする必要があるとされている。
したがって、新規取引先は取引前に、既存取引先は2023年10月1日までに番号のヒアリングを行い、対象帳票が提出される度に記載された番号をチェックするフローさえ構築すればよい(仕訳やその先のことはさておくとして)。
しかし、図の段階で課税事業者か免税事業者かを判断するのでは遅い場合もありうる。課税、免税はどちらでもよいが、経理実務上判定は早くできるに越したことはない。
どちらかというと上記図の方が望ましい。
上記フローで問題となるのが、事前に検索を行う際の手間である。請求書受領代行サービスなどで検索を外注するなど手段は徐々に整いつつあるが、前提としてそのようなサービスが力を発揮するのは請求書を受領してからである。
取引先を選定し「内定」のような手続きを行う場合において、インボイス制度適格請求書発行事業者公表サイトにて番号検索するしかないことが実務上の障害となる。
取引する前から番号を聞き出すことは(少なくともインボイス制度黎明期においては)購買先選定のフローにおいて手続き漏れになる可能性が高いからである。せめて文言検索がさくっとできるようにはなってほしい。
上記理由から、インボイス制度に対応するにあたり、取引業者が適格請求書を発行できる事業者かどうかを文言検索する方法はないか検討した。
実際にこのように行うことはできるが、手間がかかる。
ちなみにだが、インボイス制度が施行されたからといってこの検索方法で取引先が適格請求書発行事業者であると断定し仕入税額控除を行ってはならない。適格請求書発行事業者であることは仕入税額控除の条件のひとつであるだけだし、取引先の提出されてくる書類が適格請求書かどうかのチェックフローを省くことができるわけではない。今回の記事で実現できたことは、あくまで事前検索の手段の簡略化である。
【この記事でしなかったこと、できなかったこと】
法人番号を持たない事業者の文言検索
スプレッドシート以外でのアウトプット、及び検索
【解決へのアプローチ】
文言検索完了の結果を得るまでのプロセスは、下記の3つのステップに分けられると考えた。
- 社会保障・税番号制度国税庁法人番号公表サイトにおいて対象事業者の文言で検索し、法人番号を取得する。
- 「T+13桁の数字」は、「T+法人番号」で構成されるので、検索対象も事業者の法人番号を取得する必要がある。
3. インボイス制度適格請求書発行事業者公表サイトにおいて「T+13桁の数字」で検索し、適格請求書発行事業者か否かの結果を得る。
1、3のサイトにおいては、国税庁がサイト内にて検索できるようにしてある。もしくは登録された情報をCSV等をダウンロードできる仕組みもある。今回は、わざわざ国税庁のサイトにて2回検索する手間、登録情報が更新されるたびにCSV等をダウンロードしてローカルのマスタを更新する手間を省くため、webAPIによる取得が望ましいと考えた。
【実装手順】
下記の手順で情報を取得し、アウトプットの構築を行なった。
- 国税庁のAPIを利用するにあたり、「アプリケーションID」を取得する必要がある。これは、当該サイトの窓口からメールアドレスと氏名、電話番号を入力し申請することで発行される。筆者は3日から4日ほどで発行された。また、インボイス制度適格請求書発行事業者公表サイトと社会保障・税番号制度国税庁法人番号公表サイトのアプリケーションIDは共通なので、少なくとも上記サイトの利用だけであれば申請は一度でよい。
2.次にスプレッドシートを作成し、GASでスクリプトを書いた。概要と実際のスプレッドシート、スクリプトの詳細は下記セルに法人名を入力して「実行」ボタンを押すと、該当した法人の上位20件の法人名、法人番号、都道府県、適格請求書発行事業者番号が返ってくる。
全体像
スクリプト全文
function getxml() {
// シートをシート名で取得
let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('適格請求書発行事業者検索用シート');
// 以前の検索結果を削除
// そのシートにある B7:E26 のセル範囲を取得
let range2 = sheet.getRange("B7:E26");
// そのセル範囲にある値のみクリア
range2.clearContent();
// 国税庁から発行される13桁のappIDを入力
let appID = '●●●●●●●●●●●●●';
// 検索したい文言を入力するセル(B2)の値を取得
let range1 = sheet.getRange(2,2).getValue();
// 形式(xml)を指定
let type = 12;
// 検索の方法を指定
let mode = 2;
// 法人番号検索用のURLを生成
let url = 'https://api.houjin-bangou.nta.go.jp/4/name?id=' + appID + '&name=' + range1 + '&type=' + type + '&mode=' + mode;
try{
// 生成したURLからUrlFetchAppでxmlデータを取得
let corporatenumber_response = UrlFetchApp.fetch(url).getContentText();
}
// エラーの場合、エラーメッセージを表示
catch (e) {
sheet.getRange(7,2,1,1).setValue('法人番号検索に失敗しました。エラーメッセージを確認してください。半角英数字で検索していないかを確認してください');
}
finally{
let corporatenumber_response = UrlFetchApp.fetch(url).getContentText();
// xmlデータから検索結果件数を抽出
let count = corporatenumber_response.match(/(?<=<count>)(.{1,30})(?=<\/count>)/g)[0];
// 検索結果件数に合わせて処理を分岐させる
// 0件の場合は「検索結果がありません」と表示
if(count == 0){
sheet.getRange(7,2,1,1).setValue('検索結果はありません');
}
// 20件以上の場合は検索結果を20件にするため19に変更
if(count > 19){
let result = 19;
output(sheet,corporatenumber_response,result);
}
//それ以外の場合は件数に-1した値をresultに渡す
else{
let result = count - 1;
output(sheet,corporatenumber_response,result);
}
}
};
// sheet,corporatenumber_response,resultをもらって検索結果を整理してシートに情報を記載
function output(sheet,corporatenumber_response,result){
// 国税庁から発行される13桁のappIDを入力
let appID = '●●●●●●●●●●●●●';
// 形式(json)を指定
let type = 21;
// 変更履歴を含める
let history = 1;
//0からresult(countよりも1低い値)まで以下を繰り返す
for (var i=0; i <= result; i++){
// 会社名、法人番号、都道府県を取得
let name = corporatenumber_response.match(/(?<=<name>)(.{1,30})(?=<\/name>)/g)[i];
let corporatenumber = corporatenumber_response.match(/(?<=<corporateNumber>)(.{1,30})(?=<\/corporateNumber>)/g)[i];
let prefecture = corporatenumber_response.match(/(?<=<prefectureName>)(.{1,30})(?=<\/prefectureName>)/g)[i];
// 法人番号の頭文字に「T」を付け加える
let registratedNumber = "T" + corporatenumber;
console.log(registratedNumber);
// 適格請求書発行事業者検索用のURLを生成
let url = 'https://web-api.invoice-kohyo.nta.go.jp/1/num?id=' + appID + '&number=' + registratedNumber + '&type=' + type + '&history' + history;
// 生成したURLからUrlFetchAppでxmlデータを取得
let registrated_response = UrlFetchApp.fetch(url);
let json = JSON.parse(registrated_response);
// 会社名、法人番号、都道府県を記載
sheet.getRange(7+i,2,1,1).setValue(name);
sheet.getRange(7+i,3,1,1).setValue(corporatenumber);
sheet.getRange(7+i,4,1,1).setValue(prefecture);
// 該当する適格請求書発行事業者の番号があれば番号を記載
try{
let is_registrated = json["announcement"][0]["registratedNumber"];
sheet.getRange(7+i,5,1,1).setValue(is_registrated);
}
// 該当する適格請求書発行事業者の番号がなければ「現時点該当なし」と記載
catch (e) {
sheet.getRange(7+i,5,1,1).setValue("現時点該当なし");
}
}
};
- リクエストのフォーマットについての留意点
- まずは法人番号検索用のリクエストURLを生成する。
- リクエストURLはフォーマットが決まっているので、合わせて生成する。
https://api.houjin-bangou.nta.go.jp/4/name?id={appID}&name={検索したい文言}&type={}&mode={};
- typeはxmlとcsvから選択できるので、今回はxmlである12を入力する。modeは部分一致にしたいので2を入力する。
- targetは検索方式ですが、指定しない場合はあいまい検索になるので何も入力しない。なお、ここで英語表記を選択しないと、英数字は全角での検索が必須になる。
- 詳細は下記のリンク先を確認。
第六編 Web-API(Ver.4.0)の リクエストの設定方法及び 提供データの内容について -公表サイト
第二編 Web-API のリクエストの設定方法 及び提供データの内容について (概要編) -公表サイト
- gitはこちら。
Discussion