今回はVBAを用いたGoogle APIの認証方法を紹介します。
使用するAPIはGoogle Analytics APIです。
■OAuth 2.0認証
最近のGoogle APIは全てOAuth 2.0認証が必要でこの認証を用いてAPIの通信を行うようになっています。ですのでVBAからGoogle APIを使用する時もOAuth 2.0認証が必要になります。
詳しくは参考サイトのOAuth 2.0認証を参照してください。
■Google Developer Consoleでの設定
Google Developer Consoleでは認証に必要な「クライアントID」「クライアント シークレット」「リダイレクトURI」を取得し、使用するAPIを有効にします。
まずGoogle Developer Consoleにアクセスし、適当なプロジェクトを選択します。
左メニューの「認証情報」からOAuthの「新しいクライアントIDを作成」を選択します。
アプリケーションの種類に「インストールされているアプリケーション」、インストールされているアプリケーションの種類に「その他」を選択しクライアントIDを作成します。
作成すると下図のような「クライアントID」「クライアント シークレット」「リダイレクトURI」が表示されるのでメモしておきます。
そして左メニューの「API」から今回使用するGoogle Analytics APIを有効にします。
■VBAでのAPI通信の認証方法
方法はまず認証用コードを取得します。次に認証用コードを使ってアクセストークンを取得します。アクセストークンをヘッダーに付加してリクエストを行うことでAPI通信ができるようになります。
認証情報の定義、認証用コードの取得、アクセストークンの取得に分けて説明を行います。
○認証情報の定義
認証に必要な情報を定義します。
Google Developer ConsoleにアクセスしたGmailのアカウントとパスワード、Google Developer Consoleで取得した「クライアントID」「クライアント シークレット」「リダイレクトURI」を定義します。
それから今回使用するGoogle Analytics APIのスコープ(認証の範囲)を定義します。
※各APIにそれぞれスコープがあります。
Private Const email As String = "Gmailアカウント" Private Const password As String = "Gmailパスワード" Private Const client_id As String = "クライアントID" Private Const client_secret As String = "クライアント シークレット" Private Const redirect_uri As String = "リダイレクトURI" Private Const scope As String = "https://www.googleapis.com/auth/analytics.readonly"
○認証用コードの取得
ここではInternet Explorerを自動で開き認証用コードを取得する方法を取ります。
下記の手順で説明します。
1.認証用URLを作成
2.Internet Explorerで認証用URLにアクセス
3.ログイン処理
4.承認処理
5・認証用コード取得処理
1.認証用URLの作成
認証用URLはベースとなるURL(https://accounts.google.com/o/oauth2/auth?)に
client_id、response_type、redirect_uri、scopeのパラメータを足したものです。
Dim sUrl As String sUrl = "https://accounts.google.com/o/oauth2/auth?" & _ "client_id=" & client_id & "&" & _ "response_type=code" & "&" & _ "redirect_uri=" & redirect_uri & "&" & _ "scope=" & scope
2.Internet Explorerで認証用URLにアクセス
readyStateが4になるまで待ち、全データ読込完了状態します。
この処理をしないとエラーが発生します。
Dim oIE As Object
Set oIE = CreateObject("InternetExplorer.Application")
With oIE
.Visible = False 'IEのブラウザを表示するか否か
.Navigate sUrl
While oIE.readyState <> 4
DoEvents
Wend
3.ログイン処理
ログイン処理では複数のアカウントがある時とログインしていない時の処理をします。
アカウントが1つの時の処理
Dim ancAcl As Object
If InStr(LCase(.document.Location.href), "https://accounts.google.com/servicelogin") Then
With .document
On Error Resume Next
Set ancAcl = .getElementById("account-chooser-link")
On Error GoTo 0
If Not ancAcl Is Nothing Then ancAcl.Click
End With
While oIE.readyState <> 4
DoEvents
Wend
End If
複数のアカウントがある時の処理
ここでは該当するアカウントがあっても処理が複雑になるので画面をスルーしています。
Dim oAcaa As Object
Set oAcaa = Nothing
If InStr(LCase(.document.Location.href), "https://accounts.google.com/accountchooser") Then
With .document
On Error Resume Next
Set oAcaa = .getElementById("account-chooser-add-account")
On Error GoTo 0
If Not oAcaa Is Nothing Then oAcaa .Click
End With
While oIE.readyState <> 4
DoEvents
Wend
ElseIf InStr(LCase(.document.Location.href), "https://accounts.google.com/servicelogin") Then
With .document
On Error Resume Next
Set oAcaa = .getElementById("account-chooser-add-account")
On Error GoTo 0
If Not oAcaa Is Nothing Then oAcaa .Click
End With
While oIE.readyState <> 4
DoEvents
Wend
End If
ログインしていない時の処理
Gmailアカウントとパスワードの値を入力しサインインします。
Dim oEmail As Object
Set oEmail = Nothing
Dim oPassword As Object
Set oPassword = Nothing
Dim oSignIn As Object
Set oSignIn = Nothing
If InStr(LCase(.document.Location.href), "https://accounts.google.com/servicelogin") Then
With .document
On Error Resume Next
Set iptEmail = .getElementById("Email")
If Not iptEmail Is Nothing Then iptEmail.Value = email
Set iptPasswd = .getElementById("Passwd-hidden")
If Not iptPasswd Is Nothing Then iptPasswd.Value = passwd
Application.Wait Now + TimeValue("00:00:01")
.getElementById("next").Click
Set iptSignIn = .getElementById("signIn")
Application.Wait Now + TimeValue("00:00:01")
If Not iptSignIn Is Nothing Then iptSignIn.Click
End With
While oIE.readyState <> 4
DoEvents
Wend
End If
4.承認処理
承認を求められるので承認を行います。
Dim oApprove As Object
Set oApprove = Nothing
If InStr(LCase(.document.Location.href), "https://accounts.google.com/o/oauth2/auth") Then
With .document
On Error Resume Next
Set btnApprove = .getElementById("submit_approve_access")
On Error GoTo 0
If Not oApprove Is Nothing Then
While oApprove.disabled <> False
DoEvents
Wend
oApprove.Click
End If
End With
While oIE.readyState <> 4
DoEvents
Wend
End If
5.認証用コード取得処理
認証用コードが表示されるので認証用コードを取得します。
Dim oCode As Object
Dim auth_code As String
If InStr(LCase(.document.Location.href), "https://accounts.google.com/o/oauth2/approval") Then
With .document
On Error Resume Next
Set oCode = .getElementById("code")
On Error GoTo 0
If Not oCode Is Nothing Then auth_code = oCode.Value
End With
While oIE.readyState <> 4
DoEvents
Wend
End If
.Quit
○アクセストークンの取得
アクセストークンは認証用コードを用いて取得します。
このアクセストークンを用いてAPIの通信が可能になります。
Dim auth_code As String
Dim access_token As String
Dim sJson As String
Dim vParam As Variant
Dim oData As Object
Dim oElm As Object
auth_code = "認証用コード"
If Len(Trim(auth_code)) > 0 Then
vParam = "code=" & auth_code & "&" & _
"client_id=" & client_id & "&" & _
"client_secret=" & client_secret & "&" & _
"redirect_uri=" & redirect_uri & "&" & _
"grant_type=authorization_code"
With CreateObject("WinHttp.WinHttpRequest.5.1")
.Open "POST", "https://accounts.google.com/o/oauth2/token"
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"
.send vParam
'成功時の処理
If .Status = 200 Then
sJson = .ResponseText
If Len(Trim(sJson)) > 0 Then
sJson = "(" & .ResponseText & ")"
Set oData = CreateObject("htmlfile")
Set oElm = oData.createElement("span")
oElm.setAttribute "id", "result"
oData.appendChild oElm
oData.parentWindow.execScript
"document.getElementById('result').innerText=eval(" & sJson & ").access_token;"
access_token = oElm.innerText
End If
End If
End With
End If
アクセストークンをリクエストURLと一緒に送信することにより
APIの通信ができるようになります。
Dim sUrl As String Dim access_token As String Dim oHTTP As Object access_token = "アクセストークン" sUrl="リクエストURL" oHTTP.Open "GET", sUrl, False oHTTP.setRequestHeader "Authorization", "Bearer " & access_token oHTTP.setRequestHeader "Content-Type", "application/atom+xml" oHTTP.send
以上がVBAを用いたGoogle APIの認証方法です。
VBAを用いたAPIの開発は資料が少ないので参考になればと思います。
付録に完全なVBAのコードがありますので参考にしてください。
OAuth 2.0認証はどの言語(JavaScript以外)でも同じようなアクセス方法になるようなので、
Google APIでアプリを開発する際は参考になると思います。
アクセストークンの有効期限なのですが、調べたところ公式にありました。
アクセストークンの有効期限はアクセストークン取得時に「expires_in」というパラメータで取得できます。
次回はGoogle Analyticsについて紹介します。
<参考サイト>
OAuth 2.0認証
<付録>
VBAでAPI通信するためのコードです。
'アカウント等の定義
Private Const email As String = "Gmailアカウント"
Private Const password As String = "Gmailパスワード"
Private Const client_id As String = "クライアントID"
Private Const client_secret As String = "クライアント シークレット"
Private Const redirect_uri As String = "リダイレクトURI"
Private Const scope As String = "https://www.googleapis.com/auth/analytics.readonly"
'認証用コードの取得
Private Function getAuthCode() As String
Dim oIE As Object
Dim sUrl As String
Dim oAcaa As Object
Set oAcaa = Nothing
Dim oAcl As Object
Set oAcl = Nothing
Dim oEmail As Object
Set oEmail = Nothing
Dim oPassword As Object
Set oPassword = Nothing
Dim oSignIn As Object
Set oSignIn = Nothing
Dim oCode As Object
Set oCode = Nothing
Dim oApprove As Object
Set oApprove = Nothing
Dim auth_code As String
'1.認証用URLの作成
sUrl = "https://accounts.google.com/o/oauth2/auth?" & _
"client_id=" & client_id & "&" & _
"response_type=code" & "&" & _
"redirect_uri=" & redirect_uri & "&" & _
"scope=" & scope
'2.Internet Explorerで認証用URLにアクセス
Set oIE = CreateObject("InternetExplorer.Application")
With oIE
.Visible = False 'IEのブラウザを表示するか否か
.Navigate sUrl
Call waitIE(oIE)
'3.アカウントが1つの時の処理
If InStr(LCase(.document.Location.href), "https://accounts.google.com/servicelogin") Then
With .document
On Error Resume Next
Set oAcl= .getElementById("account-chooser-link")
On Error GoTo 0
If Not oAclIs Nothing Then oAcl.Click
End With
Call waitIE(oIE)
End If
'3.複数のアカウントがある時の処理
If InStr(LCase(.document.Location.href), "https://accounts.google.com/accountchooser") Then
With .document
On Error Resume Next
Set oAcaa = .getElementById("account-chooser-add-account")
On Error GoTo 0
If Not oAcaa Is Nothing Then oAcaa .Click
End With
Call waitIE(oIE)
ElseIf InStr(LCase(.document.Location.href), "https://accounts.google.com/servicelogin") Then
With .document
On Error Resume Next
Set oAcaa = .getElementById("account-chooser-add-account")
On Error GoTo 0
If Not oAcaa Is Nothing Then oAcaa .Click
End With
Call waitIE(oIE)
End If
'3.ログインしていない時の処理
If InStr(LCase(.document.Location.href), "https://accounts.google.com/servicelogin") Then
With .document
On Error Resume Next
Set oEmail = .getElementById("Email")
If Not oEmail Is Nothing Then oEmail.Value = email
Set oPasswd = .getElementById("Passwd-hidden")
If Not oPasswd Is Nothing Then oPasswd.Value = passwd
Application.Wait Now + TimeValue("00:00:01")
.getElementById("next").Click
Set oSignIn = .getElementById("signIn")
Application.Wait Now + TimeValue("00:00:01")
If Not oSignIn Is Nothing Then oSignIn.Click
End With
Call waitIE(oIE)
End If
'4.承認処理
If InStr(LCase(.document.Location.href), "https://accounts.google.com/o/oauth2/auth") Then
With .document
On Error Resume Next
Set oApprove = .getElementById("submit_approve_access")
On Error GoTo 0
If Not oApprove Is Nothing Then
While oApprove.disabled <> False
DoEvents
Wend
oApprove.Click
End If
End With
Call waitIE(oIE)
End If
'5.認証用コード取得処理
If InStr(LCase(.document.Location.href), "https://accounts.google.com/o/oauth2/approval") Then
With .document
On Error Resume Next
Set iptCode = .getElementById("code")
On Error GoTo 0
If Not iptCode Is Nothing Then auth_code = iptCode.Value
End With
.Navigate "https://accounts.google.com/o/logout"
Call waitIE(oIE)
End If
.Quit
End With
getAuthCode = auth_code
End Function
'アクセストークンの取得
Private Function getAccessToken() As String
Dim auth_code As String
Dim access_token As String
Dim sJson As String
Dim vParam As Variant
Dim oData As Object
Dim oElm As Object
auth_code = getAuthCode()
If Len(Trim(auth_code)) > 0 Then
vParam = "code=" & auth_code & "&" & _
"client_id=" & client_id & "&" & _
"client_secret=" & client_secret & "&" & _
"redirect_uri=" & redirect_uri & "&" & _
"grant_type=authorization_code"
With CreateObject("WinHttp.WinHttpRequest.5.1")
.Open "POST", "https://accounts.google.com/o/oauth2/token"
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"
.send vParam
'成功時の処理
If .Status = 200 Then
sJson = .ResponseText
If Len(Trim(sJson)) > 0 Then
sJson = "(" & .ResponseText & ")"
Set oData = CreateObject("htmlfile")
Set oElm = oData.createElement("span")
oElm.setAttribute "id", "result"
oData.appendChild oElm
oData.parentWindow.execScript
"document.getElementById('result').innerText=eval(" & sJson & ").access_token;"
access_token = oElm.innerText
End If
End If
End With
End If
getAccessToken = access_token
End Function
'IEの表示待ち処理
Private Sub waitIE(ByRef oIE As Object)
While oIE.readyState <> 4
DoEvents
Wend
End Sub
