在Microsoft Access VBA中调用Dropbox /oauth2/token接口失败求助
我无法在Microsoft Access VBA中调用Dropbox的/oauth2/token接口获取有效令牌。
之前我用手动生成的临时access token,能通过以下VBA代码成功下载Dropbox文件:
Dim xmlhttp As Object Dim myurl As String Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1") myurl = "https://content.dropboxapi.com/2/files/download" Dim argumentString As String argumentString = "{" & Chr(34) & "path" & Chr(34) & ":" & Chr(34) & "/testfile.txt" & Chr(34) & "}" 'argumentString 最终格式为 {"path":"/testfile.txt"} xmlhttp.Open "POST", myurl, False xmlhttp.SetRequestHeader "Authorization", "Bearer TemporaryGeneratedAccessToken" xmlhttp.SetRequestHeader "Dropbox-API-Arg", argumentString xmlhttp.send MsgBox (xmlhttp.ResponseText) If xmlhttp.Status = 200 Then Set oStream = CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 oStream.Write xmlhttp.responseBody oStream.SaveToFile MyPCPathToWriteTo, 2 oStream.Close End If
但临时token有效期太短,没法用于正式场景,所以我想实现Dropbox的OAuth 2.0离线访问流程,已经完成两步:
- 创建了权限足够的Dropbox应用
- 通过授权链接拿到了authorization code
现在卡在用authorization code换access token和refresh token的步骤,试了两段代码都失败,返回错误:Invalid_request. The Request parameters do not match any of the supported authorization flows. Please refer to the API documentation for the correct parameters.
尝试过的代码1:
Dim xmlhttp As Object Dim myurl As String Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1") myurl = "https://api.dropboxapi.com/oauth2/token" 'myurl = "https://api.dropbox.com/oauth2/token" xmlhttp.Open "POST", myurl, False xmlhttp.SetRequestHeader "code", "MY AUTHORIZATION CODE" xmlhttp.SetRequestHeader "grant_type", "authorization_code" xmlhttp.SetRequestHeader "client_id", "MyAppKey" xmlhttp.SetRequestHeader "client_secret", "MySECRETAppKey" xmlhttp.send argumentString MsgBox (xmlhttp.ResponseText)
尝试过的代码2(对Client ID和Secret做Base64编码):
Dim xmlhttp As Object Dim myurl As String Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1") myurl = "https://api.dropboxapi.com/oauth2/token" Dim argumentString As String xmlhttp.Open "POST", myurl, False xmlhttp.SetRequestHeader "code", "MyAuthorizationCode" xmlhttp.SetRequestHeader "grant_type", "authorization_code" Dim ClientID As String Dim ClientSec As String ClientID = EncodeBase64(StrConv("AppID", vbFromUnicode)) ClientSec = EncodeBase64(StrConv("AppSecretID", vbFromUnicode)) xmlhttp.SetRequestHeader "client_id", ClientID xmlhttp.SetRequestHeader "client_secret", ClientSec xmlhttp.send argumentString MsgBox (xmlhttp.ResponseText)
我也试过把参数放到argumentString里传递,但还是同样的错误,请问哪里错了?
问题背景
我正在开发一款Access应用,需要自动更新多台PC上的前端程序。之前用OneDrive上传新版本并生成直链实现,但OneDrive API变更后这个方法失效了,所以转用Dropbox API,现在卡在OAuth授权这一步。
你的核心错误是没有遵循Dropbox OAuth2令牌接口的参数传递规则:
- 参数不能放在Request Header里,必须以
application/x-www-form-urlencoded格式放在请求体中 - 客户端身份验证有两种合规方式:要么把
client_id和client_secret作为表单参数传递,要么把client_id:client_secret做Base64编码后放在AuthorizationHeader里(格式为Basic 编码串)
下面是修正后的VBA代码(两种验证方式二选一即可):
方式一:表单参数传递客户端信息
Dim xmlhttp As Object Dim myurl As String Dim postData As String Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1") myurl = "https://api.dropboxapi.com/oauth2/token" ' 构造表单格式的请求体 postData = "grant_type=authorization_code" & _ "&code=你的授权CODE" & _ "&client_id=你的AppKey" & _ "&client_secret=你的AppSecret" xmlhttp.Open "POST", myurl, False ' 设置正确的Content-Type xmlhttp.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" xmlhttp.Send postData ' 查看响应结果 MsgBox xmlhttp.ResponseText ' 解析响应(如果需要) ' 成功响应会包含access_token、refresh_token、expires_in等字段 If xmlhttp.Status = 200 Then ' 这里可以把refresh_token保存到本地,后续用来刷新access token End If
方式二:Basic Auth头传递客户端信息
Dim xmlhttp As Object Dim myurl As String Dim postData As String Dim authString As String Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1") myurl = "https://api.dropboxapi.com/oauth2/token" ' 构造表单请求体 postData = "grant_type=authorization_code" & _ "&code=你的授权CODE" ' 构造Basic Auth字符串:client_id:client_secret 做Base64编码 authString = "Basic " & EncodeBase64(StrConv("你的AppKey:你的AppSecret", vbFromUnicode)) xmlhttp.Open "POST", myurl, False xmlhttp.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" xmlhttp.SetRequestHeader "Authorization", authString xmlhttp.Send postData MsgBox xmlhttp.ResponseText If xmlhttp.Status = 200 Then ' 保存refresh_token End If
注意事项
- 授权code只能使用一次,用过就失效,需要重新获取
- 拿到refresh_token后,后续可以用它调用同一个接口(grant_type改为
refresh_token)刷新access token,不用再走授权流程 - 确保你的
EncodeBase64函数能正确处理字符串编码,避免乱码导致验证失败
内容的提问来源于stack exchange,提问作者Mawimu

