【发布时间】:2019-08-26 16:53:24
【问题描述】:
我正在尝试通过 VBA 代码访问 Appointments-Plus.com API,并且一直被告知我给它的站点 ID/密钥无效。我使用的是 Office365 版本的 Access。
This is the relevant documentation for this API call.
当我使用 Postman 测试 API 时,我能够成功连接并取回数据。邮递员整理的网址是这样的:
https://ws.appointment-plus.com/Locations/GetLocations?Authorization:Basic=<site-ID>:<Key>&response_type=xml
我的 VBA 代码是这样的:
Public Sub RESTtestBigURL()
Dim responseType As String
responseType = "response_type=json"
Dim restRequest As WinHttp.WinHttpRequest
Set restRequest = New WinHttp.WinHttpRequest
Dim restResult As String
With restRequest
.Open "POST", "https://ws.appointment-plus.com/Locations/GetLocations?Authorization:Basic=<site-ID>:<Key>&response_type=xml", False
.Send
.WaitForResponse
Debug.Print ".ResponseText: " & .ResponseText
Debug.Print ".Status: " & .Status
Debug.Print ".StatusText: " & .StatusText
Debug.Print ".ResponseBody: " & .ResponseBody
End With
End Sub
我知道第一个问题是“你确定你的 <site-ID> 和 <key> 正确吗?”是的 - 我已经将 Postman 的整个 URL 复制/粘贴到我的 VBA 代码中,并且我已经让另外几对眼球查看它以确认它们仍然相同。
当我运行该代码时,我得到:
.ResponseText: <?xml version="1.0" encoding="utf-8" ?>
<APResponse>
<resource>customers</resource>
<action>getcustomers</action>
<request></request>
<result>fail</result>
<count>0</count>
<errors>
<error><![CDATA[Web Services authentication failed: invalid Site ID or API Key]]></error>
</errors>
</APResponse>
我尝试了其他几种访问 API 的方法,所有这些方法都给我同样的“无效 ID/密钥”错误:
Public Sub SecondRESTtestMSXML()
Dim restRequest As MSXML2.XMLHTTP60
Set restRequest = New MSXML2.XMLHTTP60
With restRequest
.Open "GET", URL & REQUEST_GET_LOCATIONS, True
.SetRequestHeader "Authorization", "Basic" & SITE_ID & ":" & API_KEY
.SetRequestHeader "response_type", "xml"
.SetRequestHeader "Accept-Encoding", "application/xml"
.Send "{""response_type"":""JSON""&""location"":""582""}"
While .ReadyState <> 4
DoEvents
Wend
Debug.Print ".ResponseText: " & .ResponseText
Debug.Print ".Status: " & .Status
Debug.Print ".StatusText: " & .StatusText
Debug.Print ".ResponseBody: " & .ResponseBody
End With
End Sub
有人建议这是与通过 Base64 编码解决的另一个问题的重复。但是,这种方法虽然不是很明确,但表明我也尝试过。我添加了从这里调用的Base64Encode 函数代码。
Public Sub RESTtest()
Dim restRequest As WinHttp.WinHttpRequest
Set restRequest = New WinHttp.WinHttpRequest
Dim restResult As String
With restRequest
.Open "POST", URL & REQUEST_GET_LOCATIONS, True
.SetRequestHeader "Authorization", "Basic " & SITE_ID & ":" & Base64Encode(API_KEY)
' Note call to Base64Encode() on this line ---------------- ----- ^^^^^^^^^^^^
.Option(WinHttpRequestOption_EnableRedirects) = False
.Send "{""response_type"":""JSON""}"
.WaitForResponse
Debug.Print ".ResponseText: " & .ResponseText
Debug.Print ".Status: " & .Status
Debug.Print ".StatusText: " & .StatusText
Debug.Print ".ResponseBody: " & .ResponseBody
End With
End Sub
Public Function Base64Encode(ByVal inputText As String) As String
Dim xmlDoc As Object
Dim docNode As Variant
Set xmlDoc = CreateObject("Msxml2.DOMDocument.3.0")
Set docNode = xmlDoc.createElement("base64")
docNode.DataType = "bin.base64"
docNode.nodeTypedValue = Stream_StringToBinary(inputText)
Base64Encode = docNode.Text
Set docNode = Nothing
Set xmlDoc = Nothing
End Function
注意事项:
-
URL、REQUEST_GET_LOCATIONS、SITE_ID和API_KEY是在此模块中全局声明的用于测试目的的常量。它们也都被复制/粘贴,并由几个人检查是否存在拼写错误。 - 您可能会注意到 XML 和 JSON 中都有响应请求 - 它们都给了我相同的响应。
- 我确实收到了 Appt Plus 的支持票,但我希望我能在这里得到更快的响应。
是否有人在此代码中看到任何明显的错误?对尝试调用 API 并获得结果的其他方法有什么建议吗?我曾建议用 C# 编写一个 DLL 并调用它,但是,我没有时间学习足够的 C# 来实现这一点,因此在这里切换语言并不是一个真正的选择。
补充说明:
我在 Powershell 会话中使用 curl 进行了尝试,结果相同:
PS H:\> curl -method Post -uri "https://ws.appointment-plus.com/Locations/GetLocations?Authorization:Basic=<ID>:<key>&response_type=json"
结果:
StatusCode : 200
StatusDescription : OK
Content : {"resource":"locations",
"action":"getlocations",
"request":"",
"result":"fail",
"count":"0"
,"errors":[
"Web Services authentication failed: invalid Site ID or API ...
RawContent : HTTP/1.1 200 OK
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Date: Mon, 26 Aug 2019 17:28:41 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Set-Cooki...
Forms : {}
Headers : {[Pragma, no-cache], [Cache-Control, no-store, no-cache, must-revalidate, post-check=0,
pre-check=0], [Date, Mon, 26 Aug 2019 17:28:41 GMT], [Expires, Thu, 19 Nov 1981 08:52:00 GMT]...}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : mshtml.HTMLDocumentClass
RawContentLength : 207
【问题讨论】:
-
我认为这可能是凭据的发送方式。 Basic Auth应该是用户名+“:”+密码的Base64编码。见 --> en.wikipedia.org/wiki/Basic_access_authentication
-
是的,当您选择授权类型/方法时,Postman 会自动执行此操作。此编码值进入
Authorization标头,而不是请求。例如。.SetRequestHeader "Authorization", "Basic " & Base64Encode(SITE_ID & ":" & API_KEY) -
删除换行符。看看这里。 stackoverflow.com/a/41838865/4839827
-
请注意,您可能想看看github.com/VBA-tools/VBA-Web——它极大地简化了从 VBA 使用 REST API 的过程。见stackoverflow.com/a/15801781/3820271