问题
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.
I removed the line "vHTTPREQUEST.Credentials = CredentialCache.DefaultCredentials" because it was not necessary as pointed out by @evry1falls
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