将参数添加到VBA HTTP Post请求

时间:2017-12-29 18:57:16

标签: excel vba excel-vba

让我在帖子前言,指出我很难利用VBA的这一面。

我有兴趣从Web服务请求令牌,这需要我使用我亲自授权的代码发出HTTP“POST”请求。我需要在我的请求中包含此代码以及其他参数,但我很难成功地这样做。我在网上找到的任何细节都用Java格式化他们的请求如下(所有ID都伪造):

POST /services/oauth2/token HTTP/1.1
Host: "YourURL.com" 
grant_type=authorization_code&code=aPrxsmIEeqM9PiQroGEWx1UiMQd95_5JUZ
VEhsOFhS8EVvbfYBBJli2W5fn3zbo.8hojaNW_1g%3D%3D&client_id=3MVG9lKcPoNI
NVBIPJjdw1J9LLM82HnFVVX19KY1uA5mu0QqEWhqKpoW3svG3XHrXDiCQjK1mdgAvhCs
cA9GE&client_secret=1955279925675241571&
redirect_uri=https%3A%2F%2Fwww.mysite.com%2Fcode_callback.jsp

制作这样的请求一直是个人的真正斗争。以下是我的代码的相关组件:

Dim request As WinHttp.WinHttpRequest
Dim
    client_id, 
    redirect_uri,
    grant_type,
    client_secret,
    authcode,
    result,
    token_url, 
As String

Sub testmod()

Set request = New WinHttp.WinHttpRequest
client_id = "MyClientID"
client_secret = "MyClientSecret"
grant_type = "authorization_code"
redirect_uri = "MyRedirectURI"
authcode = "MyAuthorizationCode"
token_url = "MyTokenURL" <--- No specified query string appended

With request
    .Open method:="POST", Url:=token_url
    ''''Including POST Params with Send method''''
    .Send ("{""code"":" & authcode & 
    ",""grant_type"":authorization_code,""client_id"":" & client_id & 
    ",""client_secret"":" & client_secret & ",""redirect_uri"":" & 
    redirect_uri & "}")
    ''''This returns error code 400 denoting a bad request''''
    Debug.Print .StatusText
end with

结束子

关于为什么这些参数导致此请求失败的任何想法?非常感谢任何见解!

2 个答案:

答案 0 :(得分:0)

请求的正文可能需要具有以下结构:

<?php
if (array_key_exists('delete_file', $_POST)) {
  $filename = $_POST['delete_file'];
  if (file_exists($filename)) {
    unlink($filename);
    echo 'File '.$filename.' has been deleted';
  } else {
    echo 'Could not delete '.$filename.', file does not exist';
  }
}
?>

我发送上面的每个垃圾参数值(您将自己替换)都需要在发送请求之前进行URL编码,以便它们在传输过程中不会被更改/损坏。在对URL进行URL编码之前,某些值可能还需要进行base64编码。要知道服务器期望哪些是base64编码的,请参考API文档(看起来'代码'值首先是base64编码,然后是URL编码)。

URL编码可以在较新的Excel版本中通过以下方式完成:Application.Encode(StringToURLEncode),它将返回一个URL安全字符串。

Base64编码可以通过创建函数来完成。在这个站点搜索base64 encode vba,有很多现成的例子。

根据您要发布到的服务器,您可能需要设置标题,如:

Dim Payload as string

Payload =  "grant_type=" & "authorization_code" & _
"&code=" & "BLAHBLAHBLAH" & _
"&client_id=" & "OFMICEANDMEN" & _
"&client_secret=" & "MELOVEYOULONGTIME" & _
"&redirect_uri=" & "YOUMAYHAVETOUSELOOPBACKADDRESSIFYOUHAVENOREDIRECTURL"

答案 1 :(得分:0)

我不知道您指的是什么API,但是有一个新的API,其中最古老的“指南”的日期可能是“ Mar”,大概是2019年。

https://developer.tdameritrade.com/apis 
https://developer.tdameritrade.com/guides 

其中没有引用“&client_secret =“。 在“最新” API中,您可以直接向浏览器请求以下“代码”。几分钟就好了。

https://auth.tdameritrade.com/oauth?

client_id=XXXX@AMER.OAUTHAP&response_type=code&redirect_uri = https://192.168.0.100

响应将显示在浏览器的条目中,而不是在正文中。您必须对响应进行解码才能使用“代码”。 RefreshToken(有效期为90天)和AccessToken(有效期为30分钟)用作ResponseText中返回的

获取90天的RefreshToken和第一个AccessToken 这是调用Javascript的VBA。

Private Sub Get_RefreshToken()'有效期为90天,然后需要一个新的'代码',请参见上文,并获得第一个有效时间为30分钟的AccessToken     暗码为字符串编码,而不是URL编码,等待响应,无回调     昏暗的shtSheetToWork作为工作表     设置shtSheetToWork = ActiveWorkbook.Sheets(“ AUTH”)'<< ==可能需要更改     使用shtSheetToWork         authorizationcode = .Range(3,“ C”)//转储到Excel中并按行JSON'split'解码

Dim xmlhttp As Object
Dim scriptControl As Object
Dim Response, JsonObj As Object

Set xmlhttp = CreateObject("MSXML2.serverXMLHTTP")
Set scriptControl = CreateObject("MSScriptControl.ScriptControl")
scriptControl.Language = "JScript"
authUrl = "https://api.tdameritrade.com/v1/oauth2/token"

xmlhttp.Open "Post", authUrl, False
xmlhttp.Send "{grant_type: authorization_code, authorizationcode: ,access_type: offline, client_id: .UserId, redirect_uri: .URLredirect}"
Response = scriptControl.Eval(xmlhttp.responseText)

    .Range(4, "C") = Response.refresh_token 'RefreshToken

xmlhttp.setRequestHeader "Authorization", Response.refresh_token
xmlhttp.Send

MsgBox (xmlhttp.responseText)
Select Case xmlhttp.Status
     Case 200
        Dim i As Integer
        Dim strKey As String
        Dim strVal As Variant
        Dim JsonData As Variant

        JsonObj = JsonDate.Parse(xmlhttp.responseText)
        Cells(colstr, toprow - 1) = JsonObj
            i = 1
            Do While Trim(Cells(i, 1)) <> ""
                 Name = Split(Cells(i, 1).Text, ":")
                If Name = "RefreshToken" Then .RefreshToken = Name: .nextRefreshToken = DateAdd("d", 90, Now)
                If Name = "AccessToken" Then .AccessToken = Name: .nextAccessToken = DateAdd("m", 30, Now)

     Case 400
            MsgBox (" validation problem suthorization 'CODE' ")

停止          案例401                 MsgBox(“无效凭据”) 停止          案例403                 MsgBox(“呼叫者无权访问该帐户”) 停止          案例405                 MsgBox(“没有允许标题的响应”) 停止          案例500                 MsgBox(“服务器意外错误”) 停止          案例503                 MsgBox(“临时问题正在响应,正在重试!”)                 '等待一分钟并重试

 End Select

Set xmlhttp = Nothing
Set JsonObj = Nothing
End With

结束子

Private Sub AccessToken()'等待响应,没有回调     暗码为String编码,而非URL编码     昏暗的shtSheetToWork作为工作表     设置shtSheetToWork = ActiveWorkbook.Sheets(“ AUTH”)'<< ==可能需要更改  使用shtSheetToWork

Dim xmlhttp As Object
Dim scriptControl As Object
Dim Response, JsonObj As Object

Set xmlhttp = CreateObject("MSXML2.serverXMLHTTP")
Set scriptControl = CreateObject("MSScriptControl.ScriptControl")
scriptControl.Language = "JScript"
authUrl = "https://api.tdameritrade.com/v1/oauth2/token"

xmlhttp.Open "Post", authUrl, False
xmlhttp.Send "{grant_type: refresh_token, authorizationcode: .RefreshToken, access_type: , client_id: .MYUserId, redirect_uri: }"
Response = scriptControl.Eval(xmlhttp.responseText)
.AccessToken = Response.refresh_token

xmlhttp.setRequestHeader "Authorization", RefreshToken
xmlhttp.Send

'MsgBox (xmlhttp.responseText)
Select Case xmlhttp.Status
     Case 200
        Dim i As Integer
        Private strKey As String
        Private strVal As Variant
        Private Data As Variant

        JsonObj = Json.Parse(xmlhttp.responseText)
        Cells(colstr, toprow - 1) = JsonObj
        NextText = Cells(colstr, toprow - 1)
        JsonObj = Nothing

            i = 1
            Do While Trim(Cells(i, 1)) <> ""
                 Name = Split(Cells(i, 1).Text, ":")
                If Name = "RefreshToken" Then .RefreshToken = Name: .nextRefreshToken = DateAdd("d", 90, Now)
                If Name = "AccessToken" Then .AccessToken = Name: .nextAccessToken = DateAdd("m", 30, Now)

     Case 400
            MsgBox (" validation problem suthorization 'CODE' ")

停止          案例401                 MsgBox(“无效凭据”) 停止          案例403                 MsgBox(“呼叫者无权访问该帐户”) 停止          案例405                 MsgBox(“没有允许标题的响应”) 停止          案例500                 MsgBox(“服务器意外错误”) 停止          案例503                 MsgBox(“临时问题正在响应,正在重试!”)                 '等待一分钟并重试

 End Select
            Next i

Set xmlhttp = Nothing

结尾为 结束