QuickBooks Online Api Error "The remote server returned an error: (400) Bad Request"

QuickBooks Online Api Error "The remote server returned an error: (400) Bad Request"

我正在使用 QBO API 并且正处于尝试检索访问和刷新令牌的步骤。当我发送我的请求时,当我试图获得状态为 "The remote server returned an error: (400) Bad Request" 的响应时,我收到了一个错误。请参阅下面的代码。

我在 header 中尝试了多种变体,但无法正常工作。

有什么想法吗?

代码(使用vb.net):

Sub Step2_GetTokens()
    'Delcare variables. 
    Dim vHTTPREQUEST As HttpWebRequest
    Dim vHTTPRESPONSE As HttpWebResponse
    Dim vSTREAMOBJECT As Stream
    Dim vSTREAMREADER As StreamReader
    Dim vSTREAMDATA As String

    Dim vAUTHORIZATIONCODE As String
    Dim vREDIRECTURI As String
    Dim vCLIENTID As String
    Dim vCLIENTSECRET As String
    Dim vURI As String
    Dim vTOKEN As String

    'Set variables. 
    vAUTHORIZATIONCODE = "myauthorizationcodefrompreviousstep"
    vREDIRECTURI = "http://localhost:8000/myredirectpage.aspx"
    vCLIENTID = "myclientid"
    vCLIENTSECRET = "myclientsecret"

    'Set URI and Token. 
    vURI = String.Format("https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer?grant_type=authorization_code&code={0}&redirect_uri={1}", vAUTHORIZATIONCODE, vREDIRECTURI)
    vTOKEN = "Basic " + System.Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(vCLIENTID + ":" + vCLIENTSECRET))

    'Create and send Http request.
    vHTTPREQUEST = CType(WebRequest.Create(vURI), HttpWebRequest)
    vHTTPREQUEST.Method = "POST"
    vHTTPREQUEST.ContentLength = 0
    vHTTPREQUEST.Credentials = CredentialCache.DefaultCredentials
    vHTTPREQUEST.ContentType = "application/x-www-form-urlencoded"
    vHTTPREQUEST.Accept = "application/json"
    vHTTPREQUEST.Headers.Add("Authorization", vTOKEN)

    'Return Http response.   THE ERROR OCCURS AT NEXT LINE
    vHTTPRESPONSE = CType(vHTTPREQUEST.GetResponse(), HttpWebResponse)
    vSTREAMOBJECT = vHTTPRESPONSE.GetResponseStream()
    vSTREAMREADER = New StreamReader(vSTREAMOBJECT, Text.Encoding.UTF8)
    vSTREAMDATA = vSTREAMREADER.ReadToEnd()

    'Display results from respense.
    TextBox1.Text = vSTREAMDATA

    'All done. 
    vHTTPRESPONSE.Close()
    vSTREAMREADER.Close()
End Sub

万岁!我从他们论坛上的一位 Intuit 开发人员那里得到了我的问题的答案,但我也想在这里分享以防其他人正在寻找。问题是我需要将我的 URI 中的参数放在 HTTP 请求正文中,而不是放在 URI 本身中。

更具体地说,我的原始代码片段的以下部分设置了传递给请求的 URI 的值。如果仔细观察,它具有参数 "grant_type"、"code" 和 "redirect_uri"。这些需要从此处删除并添加到 HTTP POST 请求的正文中。

vURI = String.Format("https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer?grant_type=authorization_code&code={0}&redirect_uri={1}", vAUTHORIZATIONCODE, vREDIRECTURI)

不知道为什么,或者为什么他们这样设置它,但它就是这样……稍后再研究。现在,下面是完整修改后的代码,可以完美运行。

在你到达那里之前,请注意其他一些没有真正影响的变化,但你应该知道。

  1. 我删除了行 "vHTTPREQUEST.Credentials = CredentialCache.DefaultCredentials" 因为正如@evry1falls

  2. 指出的那样没有必要
  3. 我移动并更改了行 "vHTTPREQUEST.ContentLength = 0" 以基于字节长度(请参阅添加的新部分)。这符合开发人员建议的更改,并且可能比我最初所做的更好。

这是我的解决方案基于从 Intuit 开发人员那里获得的示例代码。它在 "c" 中,所以我将其转换为 "vb"。

https://github.com/IntuitDeveloper/OAuth2-Dotnet-WithoutSDK/blob/08d47724c5879d30da9cd8d6b365751514462953/OAuth2_SampleApp_Dotnet/OAuth2Manager.aspx.cs#L423

这是新代码(使用 vb.net)

Sub step2_get_token()
    'Delcare variables. 
    Dim vHTTPREQUEST As HttpWebRequest
    Dim vHTTPRESPONSE As HttpWebResponse
    Dim vSTREAMOBJECT As Stream
    Dim vSTREAMREADER As StreamReader
    Dim vSTREAMDATA As String

    Dim vAUTHORIZATIONCODE As String
    Dim vREDIRECTURI As String
    Dim vCLIENTID As String
    Dim vCLIENTSECRET As String
    Dim vURI As String
    Dim vTOKEN As String

    'Set variables. 
    vAUTHORIZATIONCODE = "myauthorizationcodefrompreviousstep"
    vREDIRECTURI = "http://localhost:8000/myredirectpage.aspx"
    vCLIENTID = "myclientid"
    vCLIENTSECRET = "myclientsecret"

    'Set URI and Token. NOTE: I removed the parameters from the URI. 
    vURI = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"
    vTOKEN = "Basic " + System.Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(vCLIENTID + ":" + vCLIENTSECRET))

    'Create a Http request with the appropriate headers. NOTE: I removed the credentials line and moved the content length line.
    vHTTPREQUEST = CType(WebRequest.Create(vURI), HttpWebRequest)
    vHTTPREQUEST.Method = "POST"
    vHTTPREQUEST.ContentType = "application/x-www-form-urlencoded"
    vHTTPREQUEST.Accept = "application/json"
    vHTTPREQUEST.Headers.Add("Authorization", vTOKEN)

    '*** HERE IS THE SECTION I ADDED ***
    'Build request body. Not sure how this is working, but it works. (You can use UTF8 or ASCII)
    Dim vHTTPREQUESTBODY As String = String.Format("grant_type=authorization_code&code={0}&redirect_uri={1}", vAUTHORIZATIONCODE, System.Uri.EscapeDataString(vREDIRECTURI))
    Dim vBYTEVERSIONOFBODY As Byte() = Encoding.ASCII.GetBytes(vHTTPREQUESTBODY)
    vHTTPREQUEST.ContentLength = vBYTEVERSIONOFBODY.Length
    Dim vDATASTREAM As Stream = vHTTPREQUEST.GetRequestStream()
    vDATASTREAM.Write(vBYTEVERSIONOFBODY, 0, vBYTEVERSIONOFBODY.Length)
    vDATASTREAM.Close()
    '*** END OF THE SECTION I ADDED ***

    'Send Http request and get a repsonse. The "GetResponse" method both sends a request to an Internet resource and returns a WebResponse instance.
    vHTTPRESPONSE = CType(vHTTPREQUEST.GetResponse(), HttpWebResponse)
    vSTREAMOBJECT = vHTTPRESPONSE.GetResponseStream()
    vSTREAMREADER = New StreamReader(vSTREAMOBJECT, Text.Encoding.UTF8)
    vSTREAMDATA = vSTREAMREADER.ReadToEnd()

    'Set output parameter.
    TextBox1.Text = vSTREAMDATA

    'All done. 
    vHTTPRESPONSE.Close()
    vSTREAMREADER.Close()
End Sub