Google Cloud Print を Web API で操作 - Unirest 使用
リフレッシュトークンを使って Google Cloud Print を Web API で操作してみます。
以前、「Google アカウントで Google API を利用 - google-api-services-gmail」 では Apache HTTPClient を使いましたが、今回は Unirest を使っています。
ソースは http://github.com/fits/try_samples/tree/master/blog/20151222/
はじめに
事前準備としてリフレッシュトークンを取得しておきます。
今回は、「Google アカウントで・・・」 にて発行したクライアント ID をそのまま使用します。
(1) コードの取得
下記パラメータを付け https://accounts.google.com/o/oauth2/auth
へ Web ブラウザ等でアクセスし API の利用を許可する事でコードを取得します。
パラメータ | 値 |
---|---|
response_type | code |
client_id | クライアント ID の client_id 値(※1) |
scope | https://www.googleapis.com/auth/cloudprint |
redirect_uri | oob (※2) |
(※1)クライアント ID 発行時にダウンロードした JSON ファイルの client_id 値 (※2)リダイレクトしない場合の設定。 何らかのアプリケーション内から実行する際は それに合わせたリダイレクト先を指定する
例えば、以下のような URL へアクセスします。
URL 例
https://accounts.google.com/o/oauth2/auth?redirect_uri=oob&response_type=code&client_id=xxx.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/cloudprint
Google アカウントでログインすると以下のような画面が表示されますので、「許可」ボタンを押下します。
コードが表示されるのでコピーしておきます。
(2) リフレッシュトークンの取得
次に、下記パラメータを https://www.googleapis.com/oauth2/v3/token
へ POST し、リフレッシュトークンを含んだ JSON を取得します。
パラメータ | 値 |
---|---|
code | (1) で取得したコード |
client_id | クライアント ID の client_id 値 |
client_secret | クライアント ID の client_secret 値 |
grant_type | authorization_code |
redirect_uri | oob (※1) |
(※1)(1) の場合と同様です。 ただし、以下のスクリプトでは urn:ietf:wg:oauth:2.0:oob を設定しています
Groovy スクリプト化すると以下のようになります。
get_refresh-token.groovy
@Grab('com.mashape.unirest:unirest-java:1.4.9') import com.mashape.unirest.http.Unirest import groovy.json.JsonSlurper addShutdownHook { Unirest.shutdown() } def json = new JsonSlurper() def conf = json.parse(new File(args[0])).installed def code = args[1] def res = Unirest.post('https://www.googleapis.com/oauth2/v3/token') .field('code', code) .field('client_id', conf.client_id) .field('client_secret', conf.client_secret) .field('grant_type', 'authorization_code') .field('redirect_uri', conf.redirect_uris[0]) .asJson() println res.body
クライアント ID 発行時にダウンロードした JSON (ここでは client_secret.json) を第1引数、(1) で取得したコードを第2引数へ指定して実行します。
取得したリフレッシュトークン JSON は後で使うので保存しておきます。 (ここでは token.json へ保存)
実行例
> groovy get_refresh-token.groovy client_secret.json 4/9ic・・・ > token.json
プリンタ一覧の取得
リフレッシュトークンを使う場合は、以下のような手順で API を呼び出します。
- リフレッシュトークンからアクセストークンを取得
- アクセストークンを使って API を実行
リフレッシュトークンからアクセストークン取得
アクセストークンを取得するには、下記パラメータを https://www.googleapis.com/oauth2/v3/token
へ POST します。
パラメータ | 値 |
---|---|
client_id | クライアント ID の client_id 値 |
client_secret | クライアント ID の client_secret 値 |
grant_type | refresh_token |
refresh_token | リフレッシュトークンの値 (※1) |
(※1)リフレッシュトークン取得で保存した JSON の refresh_token 値
この処理は共通的に使用するため、Groovy の BaseScript として定義しました。
TokenScript.groovy
import com.mashape.unirest.http.Unirest import groovy.json.JsonSlurper abstract class TokenScript extends Script { // アクセストークンの取得 def accessToken(String clientId, String clientSecret, String refreshToken) { def res = Unirest.post('https://www.googleapis.com/oauth2/v3/token') .field('client_id', clientId) .field('client_secret', clientSecret) .field('grant_type', 'refresh_token') .field('refresh_token', refreshToken) .asJson() res.body.object } }
API 実行 (プリンタの一覧取得)
アクセストークンは HTTP ヘッダーへ Authorization: Bearer <アクセストークン>
のように設定して使います。(例. Authorization: Bearer ya26.pw・・・)
クラウドプリンタ一覧は https://www.google.com/cloudprint/search
へ GET すれば取得できます。 (q や type パラメータを付けて条件検索することも可能)
get_printers.groovy
@Grab('com.mashape.unirest:unirest-java:1.4.9') import com.mashape.unirest.http.Unirest import groovy.json.JsonSlurper import groovy.transform.BaseScript // TokenScript を BaseScript へ設定 @BaseScript TokenScript baseScript addShutdownHook { Unirest.shutdown() } def json = new JsonSlurper() def conf = json.parse(new File(args[0])).installed def token = json.parse(new File(args[1])) // アクセストークン取得 def newToken = accessToken( conf.client_id, conf.client_secret, token.refresh_token ) // API の実行 def printers = Unirest.get('https://www.google.com/cloudprint/search') .header('Authorization', "${newToken.token_type} ${newToken.access_token}") .asJson() println printers.body
実行結果は以下の通りです。
まだプリンタを登録していないためデフォルトの 「ドライブに保存」 しかありません。
実行結果 (出力結果は加工済、実際は改行・字下げは無し)
> groovy get_printers.groovy client_secret.json token.json { "request":{・・・}, "printers":[{ "isTosAccepted":false, "displayName":"ドライブに保存", "capsHash":"", "description":"ドキュメントを Google ドライブで PDF として保存します", "updateTime":"1370287324050", "ownerId":"cloudprinting@gmail.com", "type":"DRIVE", "tags":["save","docs","pdf","google","__google__drive_enabled"], "proxy":"google-wide", "ownerName":"Cloud Print", "createTime":"1311368403894", "defaultDisplayName":"ドライブに保存", "connectionStatus":"ONLINE", "name":"Save to Google Docs", "id":"__google__docs", "accessTime":"1316132041869", "status":"" }], "success":true, ・・・ }
また、https://www.google.com/cloudprint/list?proxy=<プロキシ>
へ GET すると、指定プロキシへ属するプリンタ一覧を取得できます。
印刷処理 (Google Drive へ保存)
最後に、「ドライブに保存」 プリンタへファイルを印刷してみます。 (実際は Google Drive へファイル保存)
印刷は、下記の必須パラメータ(他にもパラメータあり)を multipart/form-data
で https://www.google.com/cloudprint/submit
へ POST します。
パラメータ | 値 |
---|---|
printerid | プリンタ ID (※1) |
title | 印刷タイトル |
ticket | 印刷設定 (※2) |
content | 印刷するファイルの内容 |
(※1)今回は __google__docs を使用 (※2)CJT (Cloud Job Ticket) フォーマットで印刷オプションなどを指定
submit_file.groovy
@Grab('com.mashape.unirest:unirest-java:1.4.9') import com.mashape.unirest.http.Unirest import groovy.json.JsonSlurper import groovy.json.JsonBuilder import groovy.transform.BaseScript @BaseScript TokenScript baseScript addShutdownHook { Unirest.shutdown() } def ticketBuilder = new JsonBuilder() // ticket の内容 ticketBuilder ( version: '1.0', print: {} ) def json = new JsonSlurper() def conf = json.parse(new File(args[0])).installed def token = json.parse(new File(args[1])) def file = new File(args[2]) // アクセストークンの取得 def newToken = accessToken( conf.client_id, conf.client_secret, token.refresh_token ) // ticket の JSON 文字列化 def ticket = ticketBuilder.toString() // 印刷 def res = Unirest.post('https://www.google.com/cloudprint/submit') .header('Authorization', "${newToken.token_type} ${newToken.access_token}") .field('printerid', '__google__docs') .field('title', file.name) .field('ticket', ticket) .field('content', file) .asJson() println res.body
PDF ファイルを POST した結果は以下の通りです。
Google Drive で確認すると sample1.pdf ファイルが保存されていました。
実行結果 (出力結果は加工済、実際は改行・字下げは無し)
> groovy submit_file.groovy client_secret.json token.json data/sample1.pdf { "request":{・・・}, "success":true,"xsrf_token":"AIp・・・", "message":"印刷ジョブが追加されました。", "job":{ "ticketUrl":"https://www.google.com/cloudprint/ticket?format=xps&output=xml&jobid=0db・・・", "printerName":"", "errorCode":"", ・・・ "title":"sample1.pdf", "tags":["^own"], ・・・ "printerid":"__google__docs", ・・・ "contentType":"application/pdf", "status":"DONE" } }
また、試しに以下のような拡張子のファイルを POST してみたところ、自動的に PDF へ変換され Google Drive へ保存されました。 (例えば sample1.html は sample1.html.pdf で保存)
- .html
- .docx
- .odt