YahooはYJDN(Yahoo! JAPAN Developer Network)という名前でWeb APIを提供しており、YID連携(ログイン認証)が必要なものとそうでないものがある。
- YID連携必要 - ストア運営のサポート API
- YID連携不要 - ショッピング情報取得 API
今回は、ストア情報の取得・更新ができるYID連携が必要なAPIの利用の方法を紹介する。
事前準備
下記公式サイトを参照して、準備する。
- Yahoo! JAPAN IDを取得する。
-
アプリケーションを登録する。
- ID連携利用有無 = ID連携を利用する
- アプリケーションの種類 = サーバーサイド(Yahoo! ID連携 v2)
- 個人情報提供先としてユーザーへ開示することに同意しますか? = 同意しない
- どちらの用途で発行しますか? = 本番環境用
- ストアURL = https://www.yahoo.co.jp/
- アプリケーションの管理を開き、編集ボタンを押して、以下の欄にURLを記載する
コールバックURL = ツールごとに決められたURL
例) https://www.yahoo.co.jp/ - 従業員登録されているビジネスIDとの紐づける
これらの Yahoo!ID に紐づくビジネス ID を、ストアクリエイタ Pro の権限管理設定に登録する
ストアクリエイタ Pro に「ツール管理権限(Yahoo!ビジネスマネージャー)」を持っているYahoo! JAPANビジネスIDでログインする
設定->権限管理設定を押し、編集を押す
Yahoo! JAPANビジネスIDと氏名、権限管理種別を追加する
API認証
- 下記コードを実行して、認可Code取得に必要なURLを取得する。client_idには上記手順で取得したClient IDを用いる。
# Authorizationエンドポイントへリダイレクト client_id = ******************* url = 'https://auth.login.yahoo.co.jp/yconnect/v2/authorization' params = {} params ['response_type'] = 'code' params ['client_id'] = client_id params ['redirect_uri'] = 'https://www.yahoo.co.jp/' params ['scope'] = 'openid' response = requests.get(url, params) print(response.url)
- 表示されたURLをブラウザで開き、ログイン&二段階認証する
- リダイレクト後のURL末尾の
code=***
の認可codeをコピーする - 下記コードを実行して、アクセストークンとリフレッシュトークンを取得する。auth_codeには取得した認可codeを、secret_keyには上記手順で取得したシークレットを用いる。
#上記のURLへブラウザでアクセスして、二段階認証をすると、リダイレクト先のURLに認可codeが得られる auth_code = ******* secret_key = ******************* url = 'https://auth.login.yahoo.co.jp/yconnect/v2/token' string_to_encode = client_id + ':' + secret_key encoded_string = base64.b64encode(string_to_encode.encode("utf-8")).decode("utf-8") params = {} params ['client_id'] = client_id params ['client_secret'] = secret_key params ['code'] = auth_code params ['grant_type'] = 'authorization_code' params ['redirect_uri'] = 'https://www.yahoo.co.jp/' headers = {} headers ['Authorization'] = 'Basic ' + encoded_string response = requests.post(url,params,headers=headers) results = response.json() if 'access_token' in results.keys(): print('Correctly Get Access Token & Refresh Token!') access_token = results['access_token'] refresh_token = results['refresh_token'] print(results['access_token'], '\n') print(results['refresh_token'], '\n') else: print('Error Access Token & Refresh Token...') print(results)
- リフレッシュトークンでアクセストークンを更新する。
# リフレッシュトークンは、12時間制限 -> 公開鍵を使えば、4週間に伸びる access_token = ******************** refresh_token = ******************** url = 'https://auth.login.yahoo.co.jp/yconnect/v2/token' string_to_encode = client_id + ':' + secret_key encoded_string = base64.b64encode(string_to_encode.encode("utf-8")).decode("utf-8") params = {} params ['refresh_token'] = refresh_token params ['grant_type'] = 'refresh_token' headers = {} headers ['Content-Type'] = 'application/x-www-form-urlencoded' headers ['Authorization'] = 'Basic ' + encoded_string response = requests.post(url,params, headers=headers) results = response.json() access_token = results['access_token'] print(access_token)
ここで取得したアクセストークンを用いて各APIを実行する。
各API実行
下記公式サイトを参照して、実行する。
1.ストアアカウントの在庫情報取得(アイテムコードを指定)
アイテムコード(ショップで一意の商品コード)を指定して在庫情報を取得する
item_code = *********
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getStock"
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item_code'] = item_code
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
response = requests.post(YahooAPIURL, data=params, headers=headers)
print(response.status_code)
print(response.text)
2. ストアアカウントの全在庫情報取得
ストアアカウントが保有する全ての商品・在庫・ストアカテゴリーの情報を取得する。
target_type = 1
# 1 : 商品データ
# 2 : 在庫データ
# 3 : ストアカテゴリ
YahooAPIURL_request = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/downloadRequest"
YahooAPIURL_check = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/downloadList?seller_id={}".format(seller_id)
YahooAPIURL_download = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/downloadSubmit?seller_id={}&type={}".format(seller_id, target_type)
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['type'] = target_type
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
response = requests.post(YahooAPIURL_request, data=params, headers=headers)
print(response.status_code)
print(response.text)
response = requests.get(YahooAPIURL_check, headers=headers)
print(response.status_code)
print(response.text)
response = requests.get(YahooAPIURL_download, headers=headers)
print(response.status_code)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'"(.*?)"'
quoted_strings = re.findall(pattern, escaped_string)
lines = [re.split(r'(?<!\\)\n', quoted_string)[0] for quoted_string in quoted_strings]
sl = 64
lines = [lines[elem*sl : elem*sl + sl] for elem in range(int(len(lines)/sl))]
print(lines)
f = open('ProductList.csv', 'w')
for item in lines:
f.write(','.join(item) + '\n')
3. ストアアカウントの全在庫情報取得
ストアアカウントの全商品の指定した情報を取得する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getRealStock?sellerId={}".format(seller_id)
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['type'] = target_type
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
4. 店舗情報取得
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getRealStore?sellerId={}".format(seller_id)
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
5. 画像一覧取得
ストアアカウントが保有する全てのアップロードした画像を取得する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/itemImageList?seller_id={}&query=&start=1&results=100".format(seller_id)
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
import xml.etree.ElementTree as ET
root = ET.fromstring(response.text)
print(f"root.tag={root.tag} .attrib={root.attrib}")
image_dict = {}
for child in root:
image_dict[child.find("Name").text] = child.find("Url").find("ModeI").text
print(child.find("Name").text, child.find("Url").find("ModeI").text)
print(image_dict)
6. カテゴリID取得
指定した商品カテゴリーIDの子カテゴリーのカテゴリー名とIDを一覧で取得する。
YahooItemSearchURL = "https://shopping.yahooapis.jp/ShoppingWebService/V1/json/categorySearch"
params = {}
params ['appid'] = client_id
params ['category_id'] = 1
response = requests.get(YahooItemSearchURL,params)
print(response.status_code)
res = json.loads(response.text)
print(list(res['ResultSet']['0']['Result']['Categories']['Children'].keys()))
for index in list(res['ResultSet']['0']['Result']['Categories']['Children'].keys()):
if index.isdecimal():
item = res['ResultSet']['0']['Result']['Categories']['Children'][index]
print('%s,%s'%(item['Id'],item['Title']))
YahooItemSearchURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getShopCategory?seller_id={}".format(seller_id)
response = requests.get(YahooItemSearchURL, headers=headers)
print(response.status_code)
print(response.text)
root = ET.fromstring(response.text)
print(f"root.tag={root.tag} .attrib={root.attrib}")
image_dict = {}
for child in root:
print(child.find("CategoryCode").text, child.find("CategoryName").text)
7. 商品登録
1つの商品をストアアカウントへ商品登録する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/editItem"
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item_code'] = 'code01' # 商品コード
params['path'] = 'Category01' # ストアカテゴリのパス
params['name'] = 'sample product' # 商品名
params['product_category'] = 2505 # YahooショッピングカテゴリID
params['original_price'] = 100000 # 定価
params['price'] = 100000 # 通常販売価格
params['lead_time_instock'] = 2000 # 発送日情報管理番号(在庫があり時)
params['lead_time_outstock'] = 4000 # 発送日情報管理番号(在庫が切れ時)
params['postage_set'] = 1 # 商品に紐づく配送グループ管理番号
response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)
8. 商品削除
1つの商品をストアアカウントから削除する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/deleteItem"
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item_code'] = 'code01'
response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)
9. カテゴリーリスト
ストアアカウントの全てのストアカテゴリーを一覧で取得する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/stCategoryList?seller_id={}".format(seller_id)
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<PageKey>(.*?)</PageKey>'
stcat_keys = re.findall(pattern, escaped_string)
print(stcat_keys)
pattern = r'<Name><!\[CDATA\[(.*?)\]\]></Name>'
Name_keys = re.findall(pattern, escaped_string)
print(Name_keys)
10. 商品リスト
指定したストアカテゴリーの全ての商品情報を取得する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/myItemList?seller_id={}&start=1&results=100&stcat_key={}".format(seller_id,stcat_keys[1])
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<Name><!\[CDATA\[(.*?)\]\]></Name>'
ProductName_keys = re.findall(pattern, escaped_string)
print(ProductName_keys)
pattern = r'<ItemCode>(.*?)</ItemCode>'
ItemCode_keys = re.findall(pattern, escaped_string)
print(ItemCode_keys)
11. データチェック履歴一覧API V2
ストアに反映されていないデータを、商品・在庫・画像などの情報を指定して取得する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V2/dataCheckHistorySummary?seller_id={}&offset=0&limit=100&dataType=STOCK".format(seller_id)
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
12. データチェック履歴一覧API V2
反映されていないデータを全て取得する。
# publish_id=0で未反映項目のみ
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/publishHistorySummary?seller_id={}&publish_id=0&start=1&results=100".format(seller_id)
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<PublishId>(.*?)</PublishId>'
PublishId_keys = re.findall(pattern, escaped_string)
print(PublishId_keys)
pattern = r'<ItemPageNum>(.*?)</ItemPageNum>'
ItemPageNum_keys = re.findall(pattern, escaped_string)
print(ItemPageNum_keys)
pattern = r'<CategoryPageNum>(.*?)</CategoryPageNum>'
CategoryPageNum_keys = re.findall(pattern, escaped_string)
print(CategoryPageNum_keys)
13. 全反映予約
反映されていないデータをすぐに全て反映する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/reservePublish"
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['mode'] = 1
response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<Status>(.*?)</Status>'
Status_keys = re.findall(pattern, escaped_string)
print(Status_keys)
14. 在庫更新API
指定したアイテムコードの在庫情報を更新する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/setStock"
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json'
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item_code'] = 'code01'
params['quantity'] = 1
response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)
15. 画像アップロードAPI
画像をアップロードする。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/uploadItemImage?seller_id={}".format(seller_id)
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
}
params = {}
params['appid'] = client_id
files = {'file': ('code01.jpg', open('code01.jpg', 'rb'))}
response = requests.post(YahooAPIURL, headers=headers, files=files, data=params)
print(response.status_code)
print(response.text)
16. SHPカテゴリ検索API
指定した検索キーワードから商品カテゴリーを推測する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/getShopCategoryList?seller_id={}&query=PC&category=2498".format(seller_id)
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
}
response = requests.get(YahooAPIURL, headers=headers)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<CategoryCode>(.*?)</CategoryCode>'
Status_keys = re.findall(pattern, escaped_string)
print(Status_keys)
17. 価格更新API
指定したアイテムコードの価格情報を更新する。
YahooAPIURL = "https://circus.shopping.yahooapis.jp/ShoppingWebService/V1/updateItems"
headers = {
'Host': 'circus.shopping.yahooapis.jp',
'Authorization': 'Bearer ' + access_token,
}
params = {}
params['appid'] = client_id
params['seller_id'] = seller_id
params['item1'] = 'item_code=code01&price=10000&sale_price='.encode('utf-8')
response = requests.post(YahooAPIURL, headers=headers, data=params)
print(response.status_code)
print(response.text)
escaped_string = response.text.replace('\n', r'\n')
pattern = r'<Status>(.*?)</Status>'
Status_keys = re.findall(pattern, escaped_string)
print(Status_keys)
公開鍵の取得・使用方法
公開鍵なしでは下記APIは発行から12時間しかアクセストークンが有効ではない。
- 注文検索API
- 注文詳細API
- 注文内容変更API
- メッセージ投稿API
- 質問詳細API
- 質問一覧API
- 定期購入親注文詳細取得API
- 定期購入情報変更API
- 定期購入情報変更履歴詳細API
公開鍵を使用することで、これを4週間まで延ばすことができる。
公開鍵認証は、Yahoo! ショッピング出店ストアのみ申請が可能。
発行した月より「1年間」有効。
下記リンクから取得することができる。
公開鍵を用いたリクエスト
import time
import base64
import requests
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
# 設定
seller_id = "{ストアアカウント}"
public_key_path = "./public.key" # 公開鍵のパス (例: "C:\\Users\\store\\public.key")
key_version = "1" # 公開鍵のバージョン
access_token = "{アクセストークン}" # アクセストークン
api_url = "{APIのURL}" # APIのURL
# 認証情報作成
authentication_value = f"{seller_id}:{int(time.time())}"
# 公開鍵の読み込み
with open(public_key_path, 'r') as f:
public_key = RSA.import_key(f.read())
# 認証情報の暗号化
cipher = PKCS1_v1_5.new(public_key)
encrypted_authentication_value = cipher.encrypt(authentication_value.encode('utf-8'))
# 認証情報のBase64エンコード
encoded_authentication_value = base64.b64encode(encrypted_authentication_value).decode('utf-8')
# リクエストヘッダーの設定
request_headers = {
"Authorization": f"Bearer {access_token}",
"X-sws-signature": encoded_authentication_value,
"X-sws-signature-version": key_version
}
# HTTP通信実行
response = requests.get(api_url, headers=request_headers)
# 結果表示
print(response.text)
参考文献