ヤマト運輸「送り状発行システムB2クラウド」のAPIを開発してパッケージを公開した

## 結論

ヤマト運輸さんの「[送り状発行サービスB2クラウド](https://business.kuronekoyamato.co.jp/service/lineup/b2/index.html
)」のAPIパッケージをPythonで開発して公開しました。

## 動機：APIがなくて不便だった

- データのやり取りは基本CSV
- シールに印刷してDMに貼る
シールを貼りに時間がかかる。直接印刷する方式は提供されていない。
- 宛先データに不備があるとリジェクトされる
自動補正の機能はない。


## なのでAPIを開発しました

1. データの送受信はAPI経由で
1. 伝票毎にイメージが分割されるので、直接DMに印刷可能になった
1. 宛先を郵便番号、都道府県、市区、町村・番地に分割する

### ちょっと宣伝

住所を都道県、市区、町、番地、ビル名に仕分ける機能は、自社開発した住所を正規化するサービスAddressianを使っています。

https://addressian.netlify.app/

## APIの機能一覧
### b2cloud
|  function  |  機能  |
| ---- | ---- |
|login|  ヤマトビジネスメンバーズにログインして、sessionを返します。以降のほぼ全てのfunctionの引数として必要です。|
|get_history|発行済み伝票の履歴を取得します。paramsに検索クエリを指定できます。|
|get_history_all|発行済み伝票の履歴を取得します。伝票はB2クラウド上に最大90日間保持されるようです。|
|get_history_deleted|削除済みに移された履歴を取得します。|
|put_tracking|配送状況を更新・取得します。get_historyでは、配送状況は更新されません。|
|post_new_checkonly|伝票情報に不備がないかチェックして、エラーまたはOKのfeedを返します。|
|post_new|新規に伝票を登録します。伝票チェックを行うpost_new_checkonlyでOKとなった戻り値です。|
|check_shipment|post_new_checkonlyの結果から必要情報だけを取得します。単体用|
|check_shipment|post_new_checkonlyの結果から必要情報だけを取得します。リスト用|
|get_new|発行されていない保存済みの伝票情報を取得します。paramsに検索クエリを指定できます。|
|delete_new|発行されていない保存済みの伝票情報を削除します。削除された伝票情報は元に戻せません。|
|print_issue|伝票を印刷してPDFで取得します。新規と再発行とも共通です。新規は印刷されると履歴に所属が移ります。|
|put_history_delete|伝票を履歴から削除します。display_flg=0にする|
|put_history_display|削除された伝票を履歴に戻します。display_flg=1にする|
|get_dm_number_print|DMの送り状番号一覧を印刷します。|
|search_history|発行済み伝票の履歴の検索クエリのうち、よく使うパラメータを引数にした関数です。|


### b2cloud.utilities

|  function  |  機能  |
| ---- | ---- |
|get_postal | B2クラウドの郵便番号情報を取得します。 |
|create_dm_shipment|DM用の送り状情報を生成します。|
|create_empty_shipment|空の送り状情報を生成します。|
|split_pdf_dm|DMの送り状PDF（１ページあたり8伝票）を１伝票毎に分割します。|
|split_pdf_nekopos|ネコポスの送り状PDF（１ページあたり6伝票）を１伝票毎に分割します。|
|choice_postal|郵便情報のうち、住所に一番ちかい郵便情報を選択します。|
|get_address_info|住所を郵便番号、都道府県、市区、町村+番地、ビル・マンション等に分割します。住所正規化サービス[Addressian](https://addressian.netlify.app/)のAPIキーが必要です。|


## インストール

```shell
pip install b2cloud
```

## コード例

### 履歴の取得

```python
import b2cloud
import b2cloud.utilities

session = b2cloud.login('your customer_code', 'your customer_password')
dm = b2cloud.search_history(session, service_type='3')

for entry in dm['feed']['entry']:
    print(entry['shipment']['tracking_number'], entry['shipment']['consignee_name'])
```

### 新規に伝票を作成し、データに不備がないかチェックする

```python
# 伝票情報を生成する
shipment = b2cloud.utilities.create_dm_shipment(
    shipment_date='2022/12/24',
    consignee_telephone_display='00-0000-0000',
    consignee_name='テスト',
    consignee_zip_code='8900053',
    consignee_address1='鹿児島県',
    consignee_address2='鹿児島市',
    consignee_address3='中央町10',
    consignee_address4='キャンセビル６階',
    consignee_department1='インターマン株式会社'
)

# データに不備がないかチェックする
res = b2cloud.check_shipment(session, shipment)
print(res)

e.g.
{'success': True, 'errors': []}
```

### 伝票の新規保存

```python
# shipmentsをpost_new_checkonlyを通す
checked_feed = b2cloud.post_new_checkonly(session, [shipment])
# 伝票情報をB2クラウドに保存する
res = b2cloud.post_new(session, checked_feed)
```

### 保存した伝票をDM形式で印刷し各伝票毎にPDFファイルに保存する

```python
# 保存済みのDM伝票を取得
dm_feed = b2cloud.get_new(session, params={'service_type':'3'})
# DM伝票形式（１シート8枚）で印刷
dm_pdf = b2cloud.print_issue(session,'3', dm_feed)
# １伝票毎に分割する
pdfs = b2cloud.utilities.split_pdf_dm(dm_pdf)
for i in range(len(pdfs)):
    with open(f'dm_{i}.pdf', 'wb') as f:
        f.write(pdfs[i])
```

### 住所を伝票情報に変換する

実行する前に[住所正規化サービスAddressian(https://addressian.netlify.app/）](https://addressian.netlify.app/)のAPI Keyを取得してください。
Googleアカウントがあれば数秒で取得できます。

```python
consignee_address = b2cloud.utilities.get_address_info(
                                                session=session,
                                                addressian_api_key='______apikey_______',
                                                address='鹿児島市中央町10キャンセビル6F'
                                            )
print(consignee_address)

e.g.
{
    "consignee_zip_code": "8900053",
    "consignee_address1": "鹿児島県",
    "consignee_address2": "鹿児島市",
    "consignee_address3": "中央町10",
    "consignee_address4": "キャンセビル6F"
}
```

## 今回開発したパッケージは公開しています

[github レポジトリ（https://github.com/interman-corp/b2cloud)](https://github.com/interman-corp/b2cloud)
[pypi b2cloud　(https://pypi.org/project/b2cloud/)](https://pypi.org/project/b2cloud/)