Skip to content

郵便番号・デジタルアドレス API 連携(未登録時は CSV/DB 検索へフォールバック) #1424

Description

@nanasess

背景・目的

日本郵便「郵便番号・デジタルアドレス for Biz」API に対応し、住所自動補完を API 経由でも行えるようにする。ただし OSS 配布の性質上、本体に共通の認証キーを同梱することは規約違反(第8条(8)(9)、第5条4項)となるため、各店舗が管理画面から自店のクライアントID/シークレットを登録する方式とする。未登録の店舗は従来どおり mtb_zip(KEN_ALL.CSV 由来)での DB 検索にフォールバックし、既存挙動を完全に維持する。

規約上の前提・制約(設計の制約条件)

「郵便番号・デジタルアドレス API 個別利用規約」+「第三者提供のための特約」より、以下を設計不変条件とする:

  1. 認証キーを本体に同梱・ハードコードしない(第8条(8)(9)、第5条4項)。→ 各店舗が管理画面で登録。
  2. API はサーバサイドから呼ぶ。シークレットをブラウザに露出させない。
  3. 取得データを網羅蓄積して独自DB化しない(第8条(5)、第7条)。→ API 結果を mtb_zip へキャッシュ保存しない。トークン等のキャッシュは可。
  4. 個人情報として扱う(第9・10条、特約第2条)。デジタルアドレス復号住所やシークレットをログ出力しない。
  5. レートリミット対応(第6条2項、特約第3条)。タイムアウト・失敗時フォールバックを実装。
  6. 規約同意の明示。各店舗が自店で連携システムを登録し規約に同意する必要があるため、設定画面に規約リンクと注意書きを掲示。

現状の実装(調査済み)

項目 場所
エンドポイント html/input_zip.phpLC_Page_InputZip::process()data/class/pages/LC_Page_InputZip.php:50
DB 検索本体 SC_Utils_Ex::sfGetAddress($zipcode)data/class/util/SC_Utils.php:1616)→ SELECT state,city,town FROM mtb_zip WHERE zipcode=?
別ルート(JSON) API_AddrFromZip::doAction()data/class/api/operations/AddrFromZip.php:40)も同じ sfGetAddress を使用
レスポンス input_zip.phpstate|city|town のパイプ区切りテキスト(state は mtb_pref で都道府県ID化)
JS eccube.getAddress()data/eccube.js:111)が $.getdata.split("|")eccube.putAddress()
CSV→DB LC_Page_Admin_Basis_ZipInstallmtb_zip へ登録)
設定保存の慣例 店舗固有設定は dtb_baseinfo(1行)+ SC_Helper_DB::registerBasisData/getBasisDataFromDB(SHOPマスター LC_Page_Admin_Basis が代表例)

設計方針

全体アーキテクチャ

flowchart TD
    Browser["ブラウザ<br/>eccube.getAddress(JS/テンプレート変更なし)"]
    Endpoint["html/input_zip.php<br/>→ LC_Page_InputZip::process()"]
    Helper["SC_Helper_Zip(新規)<br/>分岐を一元化"]
    ApiClient["日本郵便 API クライアント<br/>SC_Helper_JpAddressApi"]
    Db["SC_Utils_Ex::sfGetAddress()<br/>mtb_zip DB 検索(従来)"]
    Result["戻り値は従来と同一形式<br/>[['state'=&gt;都道府県ID,'city'=&gt;...,'town'=&gt;...], ...]<br/>→ パイプ区切り応答も JSON API 応答も無改修で成立"]

    Browser -->|"$.get input_zip.php?zip1=&zip2="| Endpoint
    Endpoint -->|"SC_Helper_Zip_Ex::getAddress($zipcode)"| Helper
    Helper -->|"認証情報あり"| ApiClient
    Helper -->|"認証情報なし"| Db
    ApiClient -.->|"失敗/タイムアウト時はフォールバック(ログ記録)"| Db
    ApiClient --> Result
    Db --> Result
Loading

分岐を新ヘルパー SC_Helper_Zip に一元化し、LC_Page_InputZipAPI_AddrFromZip の両呼び出し元をこのヘルパー経由に差し替える。API 応答の都道府県名は mtb_pref 反転で ID 化し、既存の戻り値契約(都道府県ID)に正規化する。これにより下流(JS・テンプレート・JSON API)は無改修。

設定保存

  • 格納先: dtb_baseinfo に新カラム追加(既存慣例に準拠、extractOnlyColsOf で自動反映)。
    • 例: jp_addr_api_client_id TEXT, jp_addr_api_client_secret TEXT, jp_addr_api_enabled SMALLINT(同意フラグ兼用も可)
  • 管理画面: data/class/pages/admin/basis/専用ページ LC_Page_Admin_Basis_AddressApi を新設(SHOPマスターに混ぜず、規約リンク・同意チェック・接続テストを載せられるようにする)。
    • 保存は SC_Helper_DB_Ex::registerBasisData() を再利用。
    • 読取は SC_Helper_DB_Ex::sfGetBasisData()
    • シークレット表示欄はマスク(●●●●+再入力方式、値未変更時は保持)。
    • CSRF は LC_Page_Admin::init()doValidToken を継承(既存パターン)。
    • 管理メニューへのリンク追加(basis 配下)。

API クライアント(新規 SC_Helper_JpAddressApi 等)

  • OAuth2 client credentials フロー: client_id/secret → トークンエンドポイント → Bearer トークン取得 → 住所検索エンドポイント。
  • トークンはキャッシュ(取得データではなく認証情報のため蓄積可。有効期限まで再利用)。
  • HTTP クライアント: 既存依存(guzzlehttp/* が composer にあり)を優先。タイムアウト短め・リトライ最小。→ 要確認: 標準化する HTTP クライアント
  • エラー時はフォールバック(zip→住所は DB があるため安全に切替可能)。シークレット・復号住所はログに残さない。

デジタルアドレス対応(Phase 2)

デジタルアドレス(英数字コード)→ 復号住所は mtb_zip に相当データが無くフォールバック不可、かつ住所詳細(番地・建物)まで返るため、state|city|town の3項目では表現できない。

  • 新モード/新エンドポイント(例 input_zip.php?mode=digital か新 input_digital_address.php)で JSON レスポンス(addr01/addr02/建物等を含む)を返す。
  • 対応する入力欄・JS を各フォーム(会員登録・受注編集等)に追加。
  • 認証情報未登録時は当機能を非表示(フォールバック先が無いため)。

変更・新規ファイル一覧(想定)

新規

  • data/class/helper/SC_Helper_Zip.php(+ _Ex 拡張スタブ)— 分岐の一元化
  • data/class/helper/SC_Helper_JpAddressApi.php(+ _Ex)— APIクライアント
  • data/class/pages/admin/basis/LC_Page_Admin_Basis_AddressApi.php(+ _Ex
  • html/admin/basis/address_api.php
  • data/Smarty/templates/admin/basis/address_api.tpl
  • DBマイグレーション SQL(dtb_baseinfo カラム追加、html/install/sql/ および更新用スクリプト)

変更

  • data/class/pages/LC_Page_InputZip.phpsfGetAddressSC_Helper_Zip_Ex::getAddress
  • data/class/api/operations/AddrFromZip.php — 同上
  • 管理メニュー定義(basis リンク追加)
  • Phase 2: data/eccube.js 等にデジタルアドレス用関数追加

フォールバック/エラー時挙動

状況 郵便番号→住所 デジタルアドレス
認証情報 未登録 mtb_zip DB 検索(従来通り) 機能非表示
認証情報 登録済・API 正常 API 結果 API 結果
API タイムアウト/エラー mtb_zip DB 検索にフォールバック(ログ) エラーメッセージ表示
レートリミット超過 同上フォールバック エラー表示+再試行案内

段階実装

  • Phase 1: 設定画面+郵便番号→住所の API/DB 分岐+フォールバック(既存挙動を壊さない最小実装)
  • Phase 2: デジタルアドレス復号(新入力欄・新レスポンス)

テスト計画

  • Unit: SC_Helper_Zip::getAddress の分岐(認証あり/なし/API失敗時フォールバック)を HTTP モックで検証。都道府県名→ID 正規化。
  • Unit: 設定保存(registerBasisData 経由)、シークレットのマスク保持。
  • E2E: 未登録店舗で従来どおり住所補完される(回帰)。登録店舗で API 経路(要モックまたはサンドボックス)。
  • MySQL / PostgreSQL 両系で実施。

未確定・要確認事項

  • 日本郵便 API の正式エンドポイント URL・認証仕様・レスポンススキーマ(公式リファレンス入手後に確定)
  • 標準化する HTTP クライアント(guzzle か既存 HTTP_Request か)
  • シークレットの暗号化要否(既存はメールパスワード等も平文。規約第5条4項との兼ね合い)
  • 設定画面での規約同意 UI の要否・文言

受け入れ条件

  • 認証情報未登録の既存店舗で住所補完の挙動が変わらない(回帰なし)
  • 認証情報を登録すると郵便番号検索が API 経由になる
  • API 障害時に DB 検索へ自動フォールバックする
  • 認証キーがブラウザ・ログ・リポジトリに露出しない

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions