PythonでネクストエンジンAPIのトークンを取得したい

皆さん初めまして!

システム担当、吉原です。


本日はこれまでとガラっと毛色を変えまして、システム方面のブログを書きたいと思います。



Fun Standard では各種モールや自社サイトからの注文に対し、いろんなサービスやツールを使用して受注処理を行っていますが、そのサービスの一つとして「ネクストエンジン」を使っています。

https://next-engine.net/


ネクストエンジンはEC・通販業界ではとても有名なサービスですので、業界の方には説明するまでもないと思いますが、「ECの現場から生まれたサービス」とうたっているだけのことはあって、とても優れたサービスを実現しており、弊社もやりたいことが色々と実現できていて、ものすごく助かっています。


今回はそのとてもメジャーで素晴らしいネクストエンジンの機能のうち、APIを使ったバックグラウンド処理の前段「バックエンドで認証」について、弊社での実装を(簡単に)紹介します。


ネクストエンジン API についてはこちら

https://developer.next-engine.com/



さて、みなさん。

スケジューリングされたバッチ処理、したくないですか? したいですよね?


特定のタイミングで受注処理をゴニョゴニョしたり、特殊な注文に対する特殊な処理をするために、定期的に各種データへアクセスしたいのが人情というもの。

じゃあ、やりましょう! ということで、ネクストエンジンがAPIとして提供している各種エンドポイントに接続をする処理を組んでみることにしました。


言語は Python です。

Fun Standard の既存システムが Python で構築されているので、その資産上で動かすために Python で実装します。


APIですから当然ノーガードで接続できるわけでもなく、認証が必要になるわけですが、世の中で様々なAPI認証が出回っている昨今、ネクストエンジンも特に問題なく接続できるはず・・・

実はネクストエンジンAPIでは言語ごとにSDKが用意されているので、それを使えば

 認証 → 情報取得 と難なく実現できますよね。


以下がそのSDKですが・・・

https://developer.next-engine.com/api/sdk


言語:PHP、Java、Node、Ruby

と、どうやら Pythonがありません。


Javaで組んで既存システムからキックしてもいいのですが、既存システムをPythonで動かしている関係上、出来ればそのまま Python でいきたいところ。

あと、できれば社内システムの使用言語も統一しておきたい。

何かいい方法は無いものかと検索していると、以下の記事に出会いました。


https://qol-kk.com/wp2/blog/2021/01/15/post-2451/


紹介されているのは PHP (Laravel) ですが、やりたいことは基本的に同じです。

また、ここで紹介されている通り、SDKを使用せずにネクストエンジンAPIを使用するには、まずブラウザログインが必要だということが分かったのですが、そのフローやイメージをつかむのに大変参考になりました。ありがとうございます~!


というわけで、前置きが長くなりましたが、今回は「PythonでネクストエンジンAPIのトークンを取得」についてご紹介します。


それでは、以下が弊社実装のコード(の一部抜粋)です。


# Seleniumのimport のみ紹介。それ以外は省略します
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
    
①Selenium
    options = webdriver.ChromeOptions()
    options.add_argument("--headless")
    options.add_argument("--disable-gpu")
    options.add_argument("--hide-scrollbars")
    options.add_argument("--single-process")
    options.add_argument("--ignore-certificate-errors")
    options.add_argument("--window-size=880x996")
    options.add_argument("--no-sandbox")
    options.add_argument("--homedir=/tmp")
    
    UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
    options.add_argument('--user-agent=' + UA)
    
②Selenium重要ポイント
    options.add_experimental_option("w3c", True)
    options.add_experimental_option('prefs', {
        'download.prompt_for_download': False,
    })
    options.binary_location = "/opt/headless/python/bin/headless-chromium"

    #ブラウザの定義
    browser = webdriver.Chrome(
        "/opt/headless/python/bin/chromedriver",
        options=options
    )

    base = "https://base.next-engine.org/"
    browser.get(base)
    
    time.sleep(1)
        
    # ID
    element_login_code = browser.find_element_by_name('user[login_code]')
    element_login_code.send_keys(ログインID)
    
    # password
    element_password = browser.find_element_by_name('user[password]')
    element_password.send_keys(パスワード)
    
    # ログインクリック
    browser.find_element_by_name('commit').click()

    time.sleep(1)
       
③Seleniumからrequestsに移行
    # requestsセッションモード
    session = requests.session()
    
    # セッションの受け渡し
    for cookie in browser.get_cookies():
        session.cookies.set(cookie["name"], cookie["value"])
    
    # selenium は終了
    browser.close()
    
    # sign_in
    params = {  
        "client_id":    <client_id>, 
        "redirect_uri": <リダイレクトURI>
    }
    p = urllib.parse.urlencode(params)
    endpoint = '%s%s?%s' % (base, 'users/sign_in/', p)
        
    st = session.get(endpoint)
    current_url = st.url

    qs = urllib.parse.urlparse(current_url).query
    qs_d = urllib.parse.parse_qs(qs)
    
    # パラメータをパース
    redirect_uri = qs_d['redirect_uri'][0]
    uid          = qs_d['uid'][0]
    state        = qs_d['state'][0]

    # access_token取得
    params = {  'uid':          uid,
                'state':        state,
                'client_id':    <client_id>,
                'client_secret':<client_secret>,
            }
    
    endpoint = 'https://api.next-engine.org/api_neauth/'
    result = session.post(endpoint, data=params)
    
    json_data = result.json()
    
④トークン取り出し
    xxx = json_data['uid'],
    xxx = json_data['access_token']
    xxx = json_data['refresh_token']

コードを説明します。


①Selenium

 参考にさせていただいた記事はPHPでしたので、そのままWeb接続でブラウザと同じ挙動が可能ですが、Pythonでは代わりにSeleniumを使ってブラウザログインを実装します。

PythonでのSelenium実装については、検索すれば情報がたくさん出てくるので割愛します。

 ※念のためにuser-agentを設定していますが、不要かもしれません。


②Selenium重要ポイント

 検索すれば情報がたくさん出てくると書きましたが、Webで紹介されているSelenium解説をそのままPython3.7で実装するとうまく動きませんでした。

色々と調査しましたが、結論としてSeleniumの設定に

    options.add_experimental_option("w3c", True)

が必要でした。

この設定がない場合は正常に動作しませんでしたので、重要なポイントです。

※Python、Seleniumのバージョンによっては不要かもしれません。


③Seleniumからrequestsに移行

 ブラウザログインができた後、RequestsでAPIを呼びだすために、セッション情報を引き継ぎます。


④トークン取り出し

 最後に、アクセストークン・リフレッシュトークンを取り出し、DBに保存するなり煮るなり焼くなりします。


この処理を定期的に(例えば1時間単位で)実行してトークンを取得、常に最新情報を確保できますね。


あとは、好きなタイミングで各種APIのエンドポイントを呼びだして、やりたかった処理を存分に実行しましょう。


そんなわけで、今回は

PythonでネクストエンジンAPIのトークンを取得したい

をお届けしました。

ネクストエンジンAPIをバックグラウンドで処理したい方の一助になれば幸いです。


それでは、また次回、技術系の紹介記事でお会いしましょう。








福岡で通販、web系求人をお探しの方はFun Standard株式会社へ!



福岡県大野城市パセオ南ヶ丘に本社を置くFun Standard株式会社(ファンスタンダード)は通販事業を中心に様々な事業を展開しています。



アウトドア用品、フィットネス用品、スマートフォンやタブレットの保護フィルム、レディースアパレル、自動車アクセサリーなど、様々な商品を取り扱っており、まだまだ一緒に働いてくれる仲間を募集中です!



「商品企画・開発・EC店舗管理」

「SNSマーケター(広報・PR担当)」「WEBデザイナー」

「カスタマーサポート(アルバイト・パート)」


興味のある職種がありましたら、ぜひ求人フォームよりお問い合わせください!


Fun Standard株式会社求人フォームはこちら






閲覧数:196回0件のコメント

最新記事

すべて表示