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

陌路散爱 提交于 2021-01-29 20:31:17

问题


I'm using the QBO API and am at the step where I'm trying to retrieve the access and refresh tokens. When I send my request I get an error when I try to get the response that states "The remote server returned an error: (400) Bad Request". See the code below.

I've tried a number of variations in my header, but cannot get it to work.

Any ideas?

Code (using 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

回答1:


Hooray! I got the answer to my question from an Intuit Developer on their forum, but wanted to share here as well in case others are looking. The issue was I needed to place the parameters that were in my URI in the HTTP request body instead of in the URI itself.

To be more specific, the following part of my original code snippet sets the value for the URI being passed to the request. If you look closely it has the parameters "grant_type", "code", and "redirect_uri". Those need to be removed from here and added to the body of the HTTP POST request instead.

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

Not sure why, or why they set it up that way but it is what it is... something to look into later. For now, here is the full revised code below that works perfectly.

Before you get there, note a couple other changes made that didn't really have any impact, but you should likely be aware of.

  1. I removed the line "vHTTPREQUEST.Credentials = CredentialCache.DefaultCredentials" because it was not necessary as pointed out by @evry1falls

  2. I moved and changed the line "vHTTPREQUEST.ContentLength = 0" to be based on the byte length (see new section added). This matched the suggested change from the developer and likely better practice than what I did originally.

Here is the sample code that I based my solution on that I got from the Intuit developer. It's in "c", so I converted it to "vb".

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

Here's the new code (using 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


来源:https://stackoverflow.com/questions/62248840/quickbooks-online-api-error-the-remote-server-returned-an-error-400-bad-requ

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!