APIにもURLを打ち込むだけで簡単にレスポンスがもらえるパブリックAPIとAPI鍵が必要なプライベートAPIの2種類が存在しています。
パブリックAPIの例は↓のような記事で使っているようなものです。requestで単にドキュメントの仕様に沿ったURLを組んで送るだけで、普通のアクセスでHTMLが返ってくる代わりにjsonが返ってくるだけのものです。
関連記事:【Python】CoinGeckoのAPIからビットコイン・アルトコインの価格データを取得する
そして、PrivateAPIというのはあらかじめユーザー登録などを行って作成してAPI鍵を使用してAPIにアクセスする方式のものです。有名なのがTwitterのAPIなんかになります。
関連記事:【Python】TwitterのAPIを簡単操作できる「Tweepy」の使い方
これは先ほどのパブリックなAPIとは違ってアクセスの際に単にリクエストを飛ばすだけではなく認証・署名という段階が必要になります。
まあそこの部分をラッピングしたライブラリがPythonには多く用意されているので、絶対必要な知識という訳ではありませんが、ドキュメントからAPIの仕様を把握して使用する場合には絶対必要な知識になります。
というわけで、今日はこのPrivateAPIを使用する際に必要な「認証」「署名」の部分をPythonで実際に実装していきたいと思います。
今回使うのはビットフライヤーという仮想通貨取引所のAPIです。ここのAPIを使用できるようになると、自分の口座残高の確認や新規注文・キャンセルがPythonのプログラム上から実行できるようになります。
関連記事:【シストレ】自動取引Botを使ってビットコインFXを行う方法を徹底解説!!
APIドキュメントを確認する
まずはBitflyerのAPIドキュメントを確認します。
APIドキュメント:https://lightning.bitflyer.com/docs?lang=ja
これらの仕様をrequestsを中心にして実装していきます。requestsの便利な点はこういった普段のブラウザアクセスでは使用しないようなhttp通信が簡単に実装できる点にあります。
関連記事:PythonでのWebスクレイピングには「requests」がめっちゃ便利という話
PythonでAPI認証を実装する
まずはドキュメントからPrivate API の呼出に必要なAPI認証を実装していきます。
ログイン後、開発者ページ において発行した API key と API secret を使用します (API key は、bitFlyer Lightning がご利用可能なアカウントクラスのお客様にご利用いただけます)。
まずAPIを使用するためにはBitflyerの開発者ページからAPI鍵を発行する必要があります。API権限は万が一の場合を考えて出金だけは行わせないようにしておきましょう。
API鍵を取得したら、その文字列をPythonに変数として読み込ませます。
API_KEY = '自分のAPI鍵' API_SECRET = '自分のAPI秘密鍵'
そして、まずAPIのエンドポイントURLを確認します。エンドポイントとはAPIにアクセスするためのURIのことを指します。
参考記事:RESTful APIのURI設計(エンドポイント設計)
BitflyerのAPIドキュメントに読むと、エンドポイントURLは「https://api.bitflyer.com/v1/」だと分かります。
なので、Pythonで以下のように書いておきます。最後の/V1の部分は後で諸々するときに被るので省いておきます。
# endpointのURL設定する endpoint = https://api.bitflyer.com
ヘッダー部分の認証情報を作成する
次は送信するAPIリクエストのHeader部分のAPI認証を作成していきます。リクエストヘッダーのAPIの認証については、APIドキュメントに以下のように記載されています。
以下の情報を HTTP リクエストヘッダに含めます。
ACCESS-KEY
: 開発者ページで発行した API keyACCESS-TIMESTAMP
: リクエスト時の Unix TimestampACCESS-SIGN
: 以下の方法でリクエストごとに生成した署名
ACCESS-SIGN
は、ACCESS-TIMESTAMP, HTTP メソッド, リクエストのパス, リクエストボディ を文字列として連結したものを、 API secret で HMAC-SHA256 署名を行った結果です。
基本的にAPIにはAPIKeyとSecretKeyの2つの鍵が用意されることが一般的で、API_KEYはリクエストのヘッダーにそのまま載せる公開鍵、API_Secretは電子署名に使われる秘密鍵という感じです。
今回のリクエストのヘッダーをPythonで実装する場合は、辞書型を使い、以下のようなコードになります。日本語の部分はこれから作っていく部分なので、これをコピペして実行してもエラーになります。
# リクエストのヘッダー部分を作成する headers = { "ACCESS-KEY": API鍵(API_KEY), "ACCESS-TIMESTAMP": タイムスタンプ, "ACCESS-SIGN": 電子署名, "Content-Type": "application/json" }
"Content-Type": "application/json"
は送信するリクエストがjsonであることを示しています。APIでヘッダーに情報を載せる際は基本的にjsonなのでこれになります。
Content-Typeにはいろいろと種類が存在し、「text/html」なら普通のWebページの表示、「text/csv」ならcsvのダウンロードといった具合になります。
参考記事:Content-Typeの一覧
API認証で署名するテキストを作成する
いよいよメイン電子署名(ACCESS-SIGN)を生成します。ここが一番分かりにくいです、逆にここさえわかれば、プライベートAPIを使いこなすことが可能です、署名に関してはAPIドキュメントには以下のように記載されています。
ACCESS-SIGN
は、ACCESS-TIMESTAMP, HTTP メソッド, リクエストのパス, リクエストボディ を文字列として連結したものを、 API secret で HMAC-SHA256 署名を行った結果です。
まず、API認証に必要な署名のテキスト内容は以下の3つ(4つ)を連結させたものだと分かります。()を付けているbody部分に関してはGETの場合は送信するものがないので、特に設定する必要はありません。
「timestamp」 + 「method」 + 「path」 (+ 「body」)
これらを文字列として連結させ、APIの秘密鍵(API_SECRET)で電子署名する流れになります。ちなみに「電子署名」とは、データに電子的に署名することです。電子署名により、本文を公開鍵を用いて署名することができます。
第三者は公開鍵と署名と本文を見比べることで署名をしたのが秘密鍵を持っている人であること(所有権の確認)と本文が改ざんされていないことを検証することができます。これによって第3者の不正アクセスを防止することが可能になります。
参考記事:電子署名の基礎知識
まずはテキストの先頭にくるタイムスタンプを作っていきます。Pythonでのタイムスタンプの生成は「time」を使えば一発で取得できます。
# タイムスタンプ用のUNIXTIMEを取得する timestamp = time.time()
次の「method」というのはhttpメソッドを指し、「GET」「POST」の2つのうちのどちらかになります。GETとPOSTの違いは↓の記事を参考にしてください
関連記事:FlaskによるWebアプリ開発③~formタグでのデータのGET/POST送信
今回はまずは口座残高を取得したいので、APIドキュメントの「資産残高を取得」という部分を見ると、リクエスト「GET /v1/me/getbalance」というのが書いてあります。これはhttp通信における【 [method] [path] 】を意味しています。
つまり、APIから口座残高を取得したい場合はmethodは「GET」を指定して、PATHは「/v1/me/getbalance」にしてね♡ということになります。
これをPythonで書くと以下のようになります。
# 認証設定 method = 'GET' path = 'v1/me/getbalance'
口座残高の取得は「GET」なのでbodyを設定する必要はありません。なので、これら3つを連結させて署名するテキストを作成します。
# 署名するためのテキストを作成する text = timestamp + method + path
これで送信するテキストは作成できました。ですが、これをこのままリクエストに乗せて送信すると、だれのリクエストが分からないため、APIの秘密鍵で電子署名をします。そして、署名したものを暗号化してリクエストのヘッダーに乗せます。
続き<後半>
コメント