Japan Post Digital Address API(郵便番号・デジタルアドレス for Biz)に対する簡易プロキシサーバーです。
利用には日本郵便が提供するビジネス向けポータルへの登録が必要で、次の準備を済ませてから本プロキシを動かしてください 1.
- ゆうIDを取得し、郵便番号・デジタルアドレス for Biz にログインする。
- 開発したいシステムをダッシュボードの「システムリスト」に登録する。このリポジトリをローカルで動かす場合は
127.0.0.1を接続元 IP として登録しておく。 - API用のクライアント資格情報(
client_idとsecret_key)を取得する。
PHP / Node.js / Ruby / Python の 4 つの実装を同梱し、いずれも次のような役割を担います。
/apiへの GET リクエストを受け取り、アクセストークンをキャッシュしながら Japan Post API に代理アクセスする- それ以外のパスにはフロントエンドの
index.htmlを返却する - 住所検索フォームからのリクエストを扱いやすくするため、CORS ヘッダーや簡易ルーティングを提供する
jp-digital-address-proxy/
├── shared/
│ ├── frontend/ # 共通フロントエンド(index.html など)
│ ├── config/ # 資格情報など(ユーザーが配置)
│ └── runtime/ # 実行時生成ファイル(アクセストークン等)
├── php/ # PHP 実装
│ ├── index.php
│ └── server.php.sh # PHP 内蔵サーバー起動用スクリプト
├── node/ # Node.js 実装
│ ├── index.js
│ ├── package.json
│ └── server.nodejs.sh # npm start ラッパースクリプト
├── ruby/ # Ruby (Sinatra) 実装・Docker
│ ├── index.rb
│ ├── Gemfile / Gemfile.lock
│ ├── Dockerfile
│ └── server.ruby.sh
└── python/ # Python (Flask) 実装・Docker
├── index.py
├── requirements.txt
├── Dockerfile
└── server.python.sh
shared/frontend/index.html– 郵便番号から住所を取得するフォーム。/api?search_code=XXXXXXXに fetch し、取得結果をフォームに反映する。php/index.php– PHP 版のプロキシ。cURL でトークン取得 (/api/v1/j/token) と住所検索 (/api/v1/searchcodeor/api/v1/addresszip) を呼び出す。node/index.js– Node.js 版のプロキシ。Express を使用して PHP 版と同等の挙動を提供する。ruby/index.rb– Ruby (Sinatra) 版のプロキシ。Rack/Sinatra 上で PHP/Node と揃えたルーティングを提供する。python/index.py– Python (Flask) 版のプロキシ。requests を用いて API コールとトークンキャッシュを行う。shared/config/credentials.json– API クライアント資格情報(ユーザーが配置する)。shared/runtime/access_token.json– 取得したアクセストークンをキャッシュするためのファイル。初回リクエスト時や期限切れ時に自動で更新される。php/server.php.sh/node/server.nodejs.sh/ruby/server.ruby.sh/python/server.python.sh– 各言語版のローカル開発用起動スクリプト。
- PHP 8.1 以降 (PHP 版を使用する場合)
- Node.js 18 以降 (Node.js 版を使用する場合)
- Ruby 3.1 以降 (Ruby 版を使用する場合)
- Python 3.10 以降 (Python 版を使用する場合)
- Japan Post Digital Address API のクライアント資格情報
💡 Docker を使う場合: すぐに試したい方は「Docker での開発」セクションを参照してください。
shared/config/credentials.jsonを配置後、docker compose upだけで全サービスが起動します。
shared/config/credentials.json を作成します。公開ディレクトリに配置しないことを推奨します。
別場所に置く場合は、PHP/Node.js それぞれのソースで参照先を変更してください。
{
"grant_type": "client_credentials",
"client_id": "your-client_id",
"secret_key": "your-secret_key"
}Japan Post 側で 127.0.0.1 を許可 IP として登録しておくとローカル開発が容易です。
./php/server.php.sh # ブラウザが自動で起動します
./php/server.php.sh 9000 # 引数または PORT=9000 でポート上書き
# 手動で起動する場合(ドキュメントルート: php)
php -S 127.0.0.1:8000 -t php php/index.php
# 動作確認例
curl "http://127.0.0.1:8000/api?search_code=1000001"- PHP 組み込みサーバーが
/api以外のパスをindex.htmlにフォールバックします。 /apiでは GET 以外のメソッドを 204 で返却し、CORS ヘッダーを許可しています。- リクエストログは
[php-proxy] METHOD URL -> STATUS形式で標準エラーに出力されます。 - PHP ファイルは
.php-cs-fixer.phpのルールに従って整形できます。関数の波括弧は同じ行に配置する方針です。
./node/server.nodejs.sh # 初回は自動で npm install を実行
PORT=9000 ./node/server.nodejs.sh # 環境変数または引数でポート上書き
# 直接起動(依存関係は別途 npm install)
cd node && npm start
# 動作確認例
curl "http://127.0.0.1:8000/api?search_code=1000001"- 旧構成で生成されていたリポジトリ直下の
node_modules/やpackage-lock.jsonは不要になったため削除し、node/配下で再生成してください。 node/index.jsはPORT(既定 8000)とHOSTを環境変数で受け取り、shared/frontendを静的配信します。- トークンキャッシュは PHP 版と同じファイル (
shared/runtime/access_token.json) を利用します。 - リクエストログは
[node-proxy] METHOD URL -> STATUS形式でコンソールに出力されます。
./ruby/server.ruby.sh # デフォルトで http://127.0.0.1:8002 へアクセスできます
PORT=9002 ./ruby/server.ruby.sh # ポート番号を変えたい場合
# 直接起動(Bundler を手動で実行する場合)
cd ruby
bundle install --path vendor/bundle
HOST=127.0.0.1 PORT=8002 bundle exec ruby index.rb
# 動作確認例
curl "http://127.0.0.1:8002/api?search_code=1000001"server.ruby.shはbundle install実行後にbundle exec ruby index.rbを起動します。依存ライブラリはruby/vendor/にインストールされ、.gitignoreで除外しています。index.rbは Sinatra を利用し、PHP/Node 版と同じルーティング・トークンキャッシュの挙動を提供します。- リクエストログは
[ruby-proxy] METHOD URL -> STATUS形式でコンソールに出力されます。
./python/server.python.sh # デフォルトで http://127.0.0.1:8003 へアクセスできます
PORT=9003 ./python/server.python.sh # ポート番号を変えたい場合
# 直接起動(手動で仮想環境を作成する場合)
cd python
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
HOST=127.0.0.1 PORT=8003 python index.py
# 動作確認例
curl "http://127.0.0.1:8003/api?search_code=1000001"server.python.shはローカルに.venv/を作成してFlask/requestsをインストールします。.venv/は.gitignore/.dockerignore済みです。index.pyは Flask で/apiを提供し、各言語版と同じトークン管理・ルーティングを実装しています。- リクエストログは
[python-proxy] METHOD URL -> STATUS形式でコンソールに出力されます。
Docker と Docker Compose v2 が利用可能な環境では、コンテナ経由で各言語実装を起動できます。事前に shared/config/credentials.json を用意してから以下を実行してください。
# すべてのサービス (Node / PHP / Ruby / Python) を同時に起動
docker compose up
# 個別に起動
docker compose up node
docker compose up php
docker compose up ruby
docker compose up python
# PHP イメージを再ビルドする場合(docker-entrypoint.sh 等の変更時)
docker compose build --no-cache php
docker compose up --force-recreate php- Node サービスは
http://127.0.0.1:8000/、PHP サービスはhttp://127.0.0.1:8001/、Ruby サービスはhttp://127.0.0.1:8002/、Python サービスはhttp://127.0.0.1:8003/でアクセスできます。 - 共有リソース(
shared/frontendやshared/configなど)はボリュームとしてマウントされるため、ホスト側の変更が即座に反映されます。 - 各サービスのアプリケーションコード(
index.php/index.js/index.rb/index.py)もボリュームマウントなので、ファイル変更後はサービスを再起動するだけで反映されます。 - 初回起動時は Node コンテナ内で
npm installが走るため、準備完了まで少し時間がかかる場合があります。 - 各サービスのホスト側ポートは上記のとおり固定です。変更したい場合は
docker-compose.ymlを編集してください。
すべてのサービスは統一されたログフォーマットでリクエストを記録します:
[node-proxy] GET http://127.0.0.1:8000/api?search_code=1070052 -> 200
[php-proxy] GET http://127.0.0.1:8001/api?search_code=1070052 -> 200
[ruby-proxy] GET http://127.0.0.1:8002/api?search_code=1070052 -> 200
[python-proxy] GET http://127.0.0.1:8003/api?search_code=1070052 -> 200
各サービスのフレームワーク固有のログ(Sinatra や Flask のデフォルトアクセスログなど)は抑制されており、上記の統一フォーマットのみが出力されます。
各サービスは以下の環境変数で動作をカスタマイズできます(docker-compose.yml で設定済み):
BIND_HOST– コンテナ内でバインドするアドレス(通常0.0.0.0)PORT– コンテナ内でリッスンするポートPUBLIC_HOST– ホストからアクセスする際のアドレス(通常127.0.0.1)PUBLIC_PORT– ホストからアクセスする際のポート(各サービスで異なる)
これらはログ出力時の URL 構築に使用されます。
/apiにsearch_codeをクエリで指定して GET を送信します。- サーバーは
access_token.jsonを参照し、有効期限内のトークンがあれば再利用します。無い場合はcredentials.jsonを使ってPOST /api/v1/j/tokenを呼び出し、新しいトークンを保存します。 search_codeが数字 3〜7 桁または英数字 7 文字の場合はGET /api/v1/searchcode/{code}に転送します。それ以外はPOST /api/v1/addresszipに{"freeword": search_code}を送ります。- Japan Post API から返った JSON をそのままレスポンスとして返却します。
- シンプルなフォームで郵便番号を入力し、
fetchで/api?search_code=...を呼び出します。 - レスポンス内の住所データをフォームの都道府県・市区町村・町名欄に反映します。
- ブラウザのオートコンプリートを抑制するため、
autocomplete="off"などの属性を設定しています。
- PHP の場合:
php/docker-entrypoint.shはイメージに含まれるため、変更後はdocker compose build --no-cache phpで再ビルドが必要です。 - Ruby/Python の場合:
$stdout.sync = true(Ruby)やsys.stdout.reconfigure(line_buffering=True)(Python)で即座に flush されます。コンテナを再起動してください。 - ログ確認:
docker compose logs <service>で個別サービスのログを確認できます。
docker-compose.yml で定義されたポート(8000-8003)が既に使用されている場合、該当サービスの ports セクションを編集してください。
# サービスを再起動(設定変更を反映)
docker compose restart <service>
# サービスを再作成(コンテナを作り直す)
docker compose up --force-recreate <service>
# イメージを再ビルド(Dockerfile や COPY 対象が変わった場合)
docker compose build --no-cache <service>
docker compose up --force-recreate <service>credentials.jsonのパスと内容が正しいか確認してください。- Japan Post 側で登録した IP アドレス(
127.0.0.1や実行環境の IP)が許可されているか確認してください。 shared/runtime/access_token.jsonを削除して再取得を試してください。
credentials.jsonとaccess_token.jsonは機微情報を含むため、公開ディレクトリの外に置くか、アクセス制御を施してください。shared/configとshared/runtimeを秘密裏に扱うか、.gitignoreなどで除外することを検討してください。- 認証情報や IP 制限の設定は本番環境に合わせて調整する必要があります。
- プロキシ先 API のステータスコードとレスポンスボディはそのままクライアントへ返されます。必要に応じてエラーハンドリングを追加してください。
MIT License
Footnotes
-
「郵便番号・デジタルアドレス for Biz」公式サイト https://guide-biz.da.pf.japanpost.jp/api/ ↩