Closed Pro777 closed 5 years ago
Interesting. It appears as if the current oauth
gem we're using only supports 1.0.
Presumably we'd need to swap that library out for one that is full OAuth 2.0, perhaps:
https://github.com/intridea/oauth2
Methinks this is going to be a non-trivial swap
Yeah, I just tried to use your gem for an app I am looking to write to connect Quickbooks Online to Shippo, but couldn't get it to auth and then realized that Intuit is requiring Oauth2 now. Doesn't that mean that anyone using this gem is broken until Oauth2 is integrated? Any plans to tackle this?
Correction: I see on the Intuit dev site where it says that as of 7/17/17... "new or existing developers with no previous apps must implement OAuth 2.0". So I guess that's me!
I have started to look into this and what its going to take to support OAuth 2.0. I dont have any idea of when I will be able to deliver something, but I am hoping its within 2-3 weeks.
My testing/exploration uses a small Sinatra web app to implement the UI / callbacks
https://github.com/ruckus/quickbooks-ruby/compare/389-oauth2
@bradleybennett We chatted with Quickbooks support and they said that existing apps can continue using OAuth 1.0 for a while. We just got ours out into the wild last week, so they grandfathered us in.
Thanks for the update @Pro777 - good to know that existing apps / OAuth 1.0 will be supported for awhile. New apps are basically SOL right now w/o a OAuth 2.0 solution
caught it purgatory myself - any workaround suggestions?
@PatrickatPaperlessPCS I've started working on this and actually have a working proof of concept of completing the OAuth 2 authorization process with making a sample dummy request against the API
See here:
https://github.com/ruckus/quickbooks-ruby/blob/389-oauth2/webapp/app.rb
You might need to adjust Line 29 with a different Customer ID to fetch - this PoC assumes you have a Customer with ID=1
Depending on your own needs (e.g. you just need something simple on your end to get your own project going, e.g. fetch a list of customers or something) you could basically start rolling your own mini-library, just taking the new OAuth2 connection logic and making your own HTTP calls with an Access Token
The next challenge on my end is making this library compatible with both versions of OAuth. We cannot just rip out support for OAuth1 wholesale and move to OAuth2 -- so all of this has to be done in such a way where the library allows you to set a oauth version to use and the internals adjust accordingly.
Unfortunately I dont have a timeframe for this.
Pretty annoying that Intuit kicked this off with no advance notice.
@ruckus Much obliged for your Sinatra example for the oauth2 gem. I just arrived to the world of Quickbooks in the last couple of weeks and was also struggling to get going since most examples online are using the old API. Your code got got me off to a good start on interacting with Quickbooks Online from Ruby on Rails.
edit: I especially appreciated your help since it's my first true foray into OAuth of any version and the oauth2 gem is hardly documented. :)
@stephenhuey thats good to hear! I'm still working on OAuth2 support and bending the library to support both versions behind the scenes.
If you're already off to the races with OAuth2 then you'll need to be refreshing your access-token constantly (they expire every 1 hour).
In a nutshell wherever you make an API call in your own code you'll need to capture the 401
failure and then issue a refresh-token request, then retry your original operation.
See this helper script for an example:
https://github.com/ruckus/quickbooks-ruby/blob/389-oauth2/webapp/client.rb#L33
Its still not 100% clear to me if the access_token
and/or the refresh_token
themselves change after/during a refresh. If they dont change then its conceivable the library could handle a refresh internally. But if they do change then I think its best (albeit a pain in the ass) to leave it up to the caller to handle this - since they'll need to persist the changes wherever they need to.
@ruckus Thanks, your script will come in handy! I am indeed off to the races but so far I've procrastinated on handling the refresh and was just doing it manually when testing. ;)
Any update on this? Thanks for your hard work so far.
@thejourneydude yes I have been working on this. Admittedly the move to be backwards compatible and support both oauth versions is bringing lots of complexity to the table. Yes, if we just wholesale cut out oauth v1 then I probably would've been done earlier.
But I'm not sure thats really possible (?). I mean, wouldnt it require that all current oauth v1 users just stop-the-world and update their apps / integrations? I know it would for me at $JOB.
That being said, I feel like I am 90% done. I'm working on the test suite. It does raise the question: would we just have the same tests but for v2? LIke straight-up copy and paste those tests but run them under Quickbooks.oauth_version=2
?
That doesnt make much sense either. My current half-baked idea is to literally implement an RSpec-before-all hook which before each spec run just randomly sets the framework in either version and then runs that test. So across many test iterations ostensibly every spec would be run under both versions. Just a thought.
@ruckus thanks for digging into this problem and for sharing some insight into your approach to support the new QBO changes. I'd like to submit a thought based on your last message.
I don't think it's required to support both OAuth1 and OAuth2 in the same version of the library, especially if it's creating more work/complexity and we know the OAuth1 support is EOL soon. I think you can rely on the awesome power of semantic versioning to draw a symbolic line in the sand between supporting OAuth1 and OAuth2 with a major version bump, that package managers and consuming dev teams will honor. With a new major version out, you can still maintain bug fixes and general patching of the previous major version by incrementing the minor release or patch release versions and maintaining a separate tag, from which you can cut branches.
Again, just a thought to share, take it or leave it. We use this awesome package in one of our projects and are currently blocked from moving forward because QBO is only creating OAuth2 apps so we would love to see the support launch as fast as possible :)
I think the major version bump makes quite a bit of sense if you just have one set of credentials to upgrade. Having both auth flows available would be helpful for apps that have multiple sets of stored credentials. In our case getting all our users to upgrade their credentials after upgrading the gem would be pretty inconvenient. It would be much nicer if we could mark all the current credentials as OAuth v1 and start replacing them with V2 tokens as people reauthenticate. That assumes QBO will give you client credentials for both versions at the same time… I suppose you could do separate apps if not.
@stevenmaguire great idea on the versioning approach. I didnt even think of that but it does sound like it could be a great solution.
However, as @drewish points out it would be problematic for existing users (like all of us) and needing to store two different credentials (marking existing as oauth v1 and new credentials as v2) but now that I'm thinking more about it would require jumping thru more hoops, e.g. when a new user of ours/yours product needs to connect with QBO we'd need to set the Quickbooks.oauth_version=2
and then proceed with the connection, etc.
To even add more complexity a question that just came to mind: is taking a global approach like Quickbooks.oauth_version=X
thread-safe? I dont think it is. And this could cause problems with users doing operations in threaded environments like Puma / Sidekiq..
Given all of this, the next thought is to then possibly consider forking the whole library into quickbooks-oauth2
or something, changing all of the namespaces and then requiring us existing users to add both gems to our apps and then having client-logic switching between one or the other as needed. This would mean we'd have:
QuickbooksOauth2::Model::Customer
Quickbooks::Model::Customer
etc. Which might not be that bad since all callers of that code would ostensibly be safe in that both versions of a name
property - or whatever - so the objects are the same shape. And since Ruby is un-typed ....
The issue of supporting both in parallel does seem to be a practical use case; not a problem we are currently facing. I think the namespacing idea is a nice way to effectively fork the code while keeping in the same project. I would offer a suggestion to name the new namespace based on some upstream version or project name from QBO instead of the technical implementation. What if they change their API again but still use OAuth2? Or will the new namespace be isolated to Auth related activities and the existing auth agnostic code will still function as expected?
I would still bump a major release to keep things clean :)
Hi @ruckus - thanks for all your work on this.
I'm thinking more about it would require jumping thru more hoops, e.g. when a new user of ours/yours product needs to connect with QBO we'd need to set the Quickbooks.oauth_version=2 and then proceed with the connection, etc.
What if instead the version is set at the service level? e.g., service = Quickbooks::Service::Customer.new(oauth: 2)
. That way you could initialize the appropriate service for the current user.
The value of a global Quickbooks.oauth_version
could be used to determine the default setting when no oauth:
argument is passed, but changing the global flag on the fly would be discouraged.
Thanks everyone for your thoughts and suggestions. Honestly I dont know what to do and feel like I'm stuck in analysis-paralsysis.
How would you feel about determining which response type to wrap based on the result of response.is_a?
? I am using the following code in my version, and it's working ok for simple GET requests:
def self.wrap(response)
if response.is_a?(OAuth2::Response)
Quickbooks::Service::Responses::OAuth2HttpResponse.new(response)
else
Quickbooks::Service::Responses::OAuth1HttpResponse.new(response)
end
end
This would allow you to remove the troublesome global attribute.
Regarding testing: What I would do, personally, is test one version of OAuth at a time using an environment variable. I would then set up CI to run rspec twice, once for each version of OAuth. I noticed that the specs here run very fast, so running twice shouldn't be too much of a burden. Here is what my OAuthHelpers
currently looks like:
module OauthHelpers
def construct_oauth
FakeWeb.allow_net_connect = false
if ENV['OAUTH'] == '1'
oauth1_token
else
oauth2_token
end
end
def oauth1_token
oauth_consumer = OAuth::Consumer.new("app_key", "app_secret", {
:site => "https://oauth.intuit.com",
:request_token_path => "/oauth/v1/get_request_token",
:authorize_url => "https://appcenter.intuit.com/Connect/Begin",
:access_token_path => "/oauth/v1/get_access_token"
})
OAuth::AccessToken.new(oauth_consumer, "token", "secret")
end
def oauth2_token
client = OAuth2::Client.new('client_id', 'app_secret',
site: 'https://appcenter.intuit.com/connect/oauth2',
authorize_url: 'https://appcenter.intuit.com/connect/oauth2',
token_url: 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer'
)
OAuth2::AccessToken.new(client, 'token')
end
# [...]
end
https://github.com/moser-inc/quickbooks-ruby/tree/oauth2-wip
@gregawoods good point and question. I've just pushed the latest of my work-in-progress to the 389-oauth2
branch -- one thing that changed is that making requests has slightly changed:
See here:
So its not just reading the response type and going from there. The library needs to knows its OAuth version so it can make a different request signature.
Makes sense. I feel like similar logic could be applied though?
def oauth_post(url, body, headers)
if @oauth.is_a? OAuth::AccessToken
@oauth.post(url, body, headers)
elsif @oauth.is_a? OAuth2::AccessToken
@oauth.post(url, headers: headers, body: body)
end
end
I spent some time this morning getting file uploads to work. Here is what I've found.
The OAuth2 client, which uses faraday, needs to be configured with a :multipart
handler. I have a helper in my app that looks like this, and works for both file uploads and regular api requests:
module QuickbooksHelper
def self.client
OAuth2::Client.new(client_id, secret,
site: 'https://appcenter.intuit.com/connect/oauth2',
authorize_url: 'https://appcenter.intuit.com/connect/oauth2',
token_url: 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer'
) do |builder|
builder.request :multipart
builder.request :url_encoded
builder.adapter :net_http
end
end
end
In my testing the builder.request :url_encoded
may not be 100% necessary. I'm still learning how faraday works with regards to which request handler it prioritizes.
Would it be worthwhile for the quickbooks-ruby gem to check for this? For example when an upload is ran, we could inspect the contents of client.connection.builder.handlers
to see if the multipart handler is present, and if not, append it? Or is it better for the readme to instruct developers to use the appropriate handler on their own?
In services/upload.rb
I had to determine what class to use for the upload - UploadIO
or Faraday::UploadIO
.
def upload(path_to_file, mime_type, attachable = nil)
url = url_for_resource("upload")
uploadIO = class_for_io.new(path_to_file, mime_type)
response = do_http_file_upload(uploadIO, url, attachable)
prefix = "AttachableResponse/xmlns:Attachable"
if response.code.to_i == 200
model.from_xml(parse_singular_entity_response(model, response.plain_body, prefix))
else
nil
end
end
def class_for_io
oauth.is_a?(OAuth2::AccessToken) ? Faraday::UploadIO : UploadIO
end
If any of this sounds useful I'm happy to create a PR - not trying to be pushy if you have other plans. Thanks!
@gregawoods thanks so much! No, please by pushy; your initiative is much appreciated. I dont have any concrete plans .. as you can see :)
Would it be worthwhile for the quickbooks-ruby gem to check for this? For example when an upload is ran, we could inspect the contents of client.connection.builder.handlers to see if the multipart handler is present, and if not, append it? Or is it better for the readme to instruct developers to use the appropriate handler on their own?
Is there any harm to just doing this configuration once like you've done and keep it that way? You say it works for both regular & upload requests? So if thats the case lets just lock it in!
Your Faraday::UploadIO : UploadIO
stuff looks great too.
I also like your previous responses of just doing is_a?
checks to determine the oauth version. That seems like a good approach.
If you want to run with that and whip up a PR that would be amazing.
It seems like the final question is then how to approach the testing aspect. It would suck to duplicate all tests for 1 and 2 modes.
Cool! I'll look at PR'ing my stuff. Two quick questions:
389-oauth
branch, or master?My current test strategy is to run the entire rspec suite twice. Not ideal, but on the bright side the specs do run very fast.
#!/bin/bash
set -e
OAUTH=1 bundle exec rspec spec
OAUTH=2 bundle exec rspec spec
Hi @gregawoods yes if/when I merge 389-oauth2
into master
I would squash all those intermediate commits. I'm not concerned about history.
My current test strategy is to run the entire rspec suite twice.
I think this is probably the best plan. Good idea.
Thanks @gregawoods for the PR!
All tests are passing. Now the real question: who wants to be the first to try the 389-oauth2
branch in their production? :| :)
We can give it whirl starting tomorrow or Friday. Are the docs updated?
Hi @stevenmaguire no, the README has not been updated right now.
Great question though. I/we do need to think about what exactly that needs to be updated.
In terms of the library itself theoretically its plug-and-play compatible in terms of creating a new consumer:
client_id = ENV['OAUTH_CLIENT_ID']
client_secret = ENV['OAUTH_CLIENT_SECRET']
oauth_params = {
:site => "https://appcenter.intuit.com/connect/oauth2",
:authorize_url => "https://appcenter.intuit.com/connect/oauth2",
:token_url => "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
:connection_opts => {
:proxy => "http://127.0.0.1:8888"
}
}
oauth_client = OAuth2::Client.new(client_id, client_secret, oauth_params)
Of course the token requesting / granting flow has changed a little as well. Please have a look at this sinatra app for the new flow:
https://github.com/ruckus/quickbooks-ruby/blob/389-oauth2/webapp/app.rb
Once a token has been retrieved you can feed it to any Service
implementation "like normal".
The biggest change that you will need to be aware of (and implement in your own application) is the token refreshment.
@minimul has done a great job of documenting this and providing a proof of concept solution at:
http://minimul.com/refreshing-the-quickbooks-oauth2-access-token.html
Thank you @ruckus and @gregawoods! I'm working on making use of your changes and am wondering: is disconnect/revoke fxnality something planned or in-progress, perchance?
Hello guys, I'm going to use QB in production so happy to help with this branch.
Something to clarify, even this branch is called oauth2, it's still making the requests using oauth1 right? I ask because this is the error I'm getting when trying to pull customers:
#<Quickbooks::Service::Responses::OAuth1HttpResponse:0x007fee3e6e6fe8 @real_response=nil>
NoMethodError: undefined method `code' for nil:NilClass
This is the line causing the error: https://github.com/ruckus/quickbooks-ruby/blob/389-oauth2/lib/quickbooks/service/responses/oauth1_http_response.rb#L19
I do not want to add or update any code pieces until I'm sure the above is not just a problem on my end.
Are you using the latest from the branch? I have a local version in my Rails app:
gem "quickbooks-ruby", :path => "/Users/cody/Projects/quickbooks-ruby"
and no outstanding commits to push and I can write a new Customer
and read all Customers
@fabrouy
Something to clarify, even this branch is called oauth2, it's still making the requests using oauth1 right?
Yes. The library automatically detects the OAuth version ala
So assuming you've made no changes on your end you should be OAuth1 mode.
<Quickbooks::Service::Responses::OAuth1HttpResponse:0x007fee3e6e6fe8 @real_response=nil>
NoMethodError: undefined method `code' for nil:NilClass
This suggests that the request itself did not complete (@real_response
is nil
) or at least the request didn't get properly executed and deserialized at the first stage.
Can you enable logging and post more output?
on @gregawoods question above:
we could inspect the contents of client.connection.builder.handlers to see if the multipart handler is present, and if not, append it? Or is it better for the readme to instruct developers to use the appropriate handler on their own?
I just hit a snag in trying to use the same OAuth2::Client
instance to refresh an access token and then perform a quickbooks api call (non-upload-related), and ended up with StackLocked
exception ("can't modify middleware stack after making a request"). I hadn't set up the client with the 'multipart' Faraday middleware, and the (successful) refresh call locked the stack; the subsequent api call hit https://github.com/ruckus/quickbooks-ruby/blob/389-oauth2/lib/quickbooks/service/base_service.rb#L28, trying to mod the stack (here), which errored out, as Faraday doesn't allow the change after initial use.
Seems like useful info to have in the readme - even if you don't plan to use upload, you should set up your client with multipart. (or, maybe it makes sense to include something like @gregawoods 's QuickbooksHelper::client
functionality to try to abstract away the underlying oauth/faraday guts and quickbooks urls?)
Ah, fascinating. It looks like we can check builder.locked?
to detect that and avoid rebuilding the connection. I would probably log a warning, and raise an error within post_with_multipart
only if the developer attempts to perform a file upload without multipart support. That way developers not using the file upload feature are not affected.
Though, I do like the idea of building client helpers directly into the library. @ruckus, do you see any problems with that?
v1_client = Quickbooks.oauth_v1_client(key, secret)
v2_client = Quickbooks.oauth_v2_client(key, secret)
I haven't touched the README so far, mostly because I'm not sure how @ruckus wants to organize information re OAuth v1 and v2.
Hey @ruckus,
This is what I'm doing:
gem 'quickbooks-ruby', git: 'https://github.com/ruckus/quickbooks-ruby.git', branch: '389-oauth2'
service = Quickbooks::Service::Customer.new(company_id: QuickbooksToken.realm_id, access_token: QuickbooksToken.access_token)
customers = service.query()
And this is the logger output:
I, [2017-10-20T14:14:38.673769 #11901] INFO -- : ------ QUICKBOOKS-RUBY REQUEST ------
I, [2017-10-20T14:14:38.673849 #11901] INFO -- : METHOD = get
I, [2017-10-20T14:14:38.673869 #11901] INFO -- : RESOURCE = https://sandbox-quickbooks.api.intuit.com/v3/company/193514638242359/query?query=SELECT+%2A+FROM+Customer+STARTPOSITION+1+MAXRESULTS+20
I, [2017-10-20T14:14:38.673887 #11901] INFO -- : REQUEST BODY:
I, [2017-10-20T14:14:38.673905 #11901] INFO -- : {}
I, [2017-10-20T14:14:38.673943 #11901] INFO -- : REQUEST HEADERS = {"Content-Type"=>"application/xml", "Accept"=>"application/xml", "Accept-Encoding"=>"gzip, deflate"}
I, [2017-10-20T14:14:38.673980 #11901] INFO -- : ------ QUICKBOOKS-RUBY RESPONSE ------
NoMethodError: undefined method `code' for nil:NilClass
from /.../ruby-2.2.5/bundler/gems/quickbooks-ruby-3c2b7b9a6508/lib/quickbooks/service/responses/oauth1_http_response.rb:19:in `code'
I can perform the request and pull the customers manually (without the gem) just fine. Any ideas where I'm stuck into?
Great find!
Though, I do like the idea of building client helpers directly into the library. @ruckus, do you see any problems with that?
That could be useful. If you want to attach a PR onto 389
that would be great.
I haven't touched the README so far, mostly because I'm not sure how @ruckus wants to organize information re OAuth v1 and v2.
Great question. I haven't tackled this yet because I am waiting for the dust to settle.
Here is a quick diff on a proposed solution. When assigning the access_token=
we'll just build the Faraday client if in oauth_v2?
diff --git a/lib/quickbooks/service/base_service.rb b/lib/quickbooks/service/base_service.rb
index 581226f..d5a7154 100644
--- a/lib/quickbooks/service/base_service.rb
+++ b/lib/quickbooks/service/base_service.rb
@@ -25,7 +25,11 @@ module Quickbooks
def access_token=(token)
@oauth = token
- verify_multipart!
+
+ # OAuth2 requires the Faraday stack to be built with multipart support
+ if oauth_v2?
+ verify_multipart!
+ end
end
def company_id=(company_id)
@@ -47,7 +51,9 @@ module Quickbooks
# Multipart is required for file upload
def verify_multipart!
- if oauth_v2? && !@oauth.client.connection.builder.handlers.include?(Faraday::Request::Multipart)
+ return if @oauth.client.connection.builder.locked?
+
+ unless @oauth.client.connection.builder.handlers.include?(Faraday::Request::Multipart)
@oauth.client.connection.build do |builder|
builder.request :multipart
builder.request :url_encoded
@fabrouy You might be hitting this snag I found yesterday where the asterisk was necessary in the pseudo-SQL. It was resolved here:
https://github.com/ruckus/quickbooks-ruby/commit/3c2b7b9a6508ceb8837d2f3928bb10644a5f0b67
Can you try the latest from the branch and try again? Thanks!
@ruckus Same result. I will to some digging and get back.
@fabrouy I'd be curious to know if the API response from Intuit is truly blank or whether its an issue in the deserialization of that response.
You can hook a HTTP proxy into the library to see the raw HTTP operations and this should answer that question, see
https://github.com/ruckus/quickbooks-ruby#debugging
Personally I'm a big fan of Charles Proxy and I have it running all the time when doing quickbooks-ruby development.
@ruckus I know you're not responsible for Faraday or oauth2 but after you showed us how to get started, I've made some great headway with it. I wanted to be able to see in the logs the requests that oauth2 was making with Faraday, but after setting the environment variable OAUTH_DEBUG to 'true' I'm running into this problem:
Faraday::RackBuilder::StackLocked (can't modify middleware stack after making a request):
app/models/quickbooks_client.rb:184:in request_access_token' app/controllers/quickbooks_controller.rb:62:in
webhook'
I'm specifically seeing this when I try to call this method which always worked before:
oauth2_client.auth_code.get_token(authorization_code, :redirect_uri => QB_REDIRECT_URI)
I imagine you would've needed this at some point, so do you know some other way to log the outgoing requests and their parameters?
@ruckus based on the documentation:
service = Quickbooks::Service::AccessToken.new
service.access_token = access_token
service.company_id = record.company_id
new_token = service.renew
Can I use the same call to refresh the token for OAuth 2.0? I've tried using it but no luck :( Getting the same result as comments above, apparently it's still calling OAuth 1 based on the stacktrace:
NoMethodError: undefined method `code' for nil:NilClass
from /Users/yoonwaiyan/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/bundler/gems/quickbooks-ruby-fbe96496fa40/lib/quickbooks/service/responses/oauth1_http_response.rb:19:in `code`
@yoonwaiyan Can you try the code on this PR please? Your exception seems like the one I was getting.
@stephenhuey I haven't wrestled this problem, but it looks like others have. Perhaps a fix listed/linked from there can help with that flag.
Otherwise, @ruckus 's comment on a proxy could help - you could opt to not use the debug flag and instead watch the requests/responses in the proxy (for local use, anyway). I don't use Charles, but Owasp ZAP can log your HTTP(S) requests as well (and is free).
@fabrouy tried the merged branch of your PR, unfortunately it's not working but the error is different now:
/Users/yoonwaiyan/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/nokogiri-1.6.8.1/lib/nokogiri/xml/document.rb:44: warning: constant ::Fixnum is deprecated
Quickbooks::IntuitRequestException: :
<?xml version="1.0"?>
from /Users/yoonwaiyan/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/bundler/gems/quickbooks-ruby-053460340765/lib/quickbooks/service/base_service.rb:381:in `parse_and_raise_exception'
any idea?
@yoonwaiyan Would you be so kind to enable logging? Quickbooks.log = true
@fabrouy This is the output after enabling logging:
[7] pry(main)> new_token = service.renew
I, [2017-10-25T11:23:42.201653 #54041] INFO -- : ------ QUICKBOOKS-RUBY REQUEST ------
I, [2017-10-25T11:23:42.201769 #54041] INFO -- : METHOD = get
I, [2017-10-25T11:23:42.201812 #54041] INFO -- : RESOURCE = https://appcenter.intuit.com/api/v1/connection/reconnect
I, [2017-10-25T11:23:42.201851 #54041] INFO -- : REQUEST BODY:
I, [2017-10-25T11:23:42.201924 #54041] INFO -- : {}
I, [2017-10-25T11:23:42.201972 #54041] INFO -- : REQUEST HEADERS = {"Content-Type"=>"application/xml", "Accept"=>"application/xml", "Accept-Encoding"=>"gzip, deflate"}
I, [2017-10-25T11:23:46.030669 #54041] INFO -- : ------ QUICKBOOKS-RUBY RESPONSE ------
I, [2017-10-25T11:23:46.030757 #54041] INFO -- : RESPONSE CODE = 200
I, [2017-10-25T11:23:46.030803 #54041] INFO -- : RESPONSE BODY:
/Users/yoonwaiyan/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/nokogiri-1.6.8.1/lib/nokogiri/xml/document.rb:44: warning: constant ::Fixnum is deprecated
I, [2017-10-25T11:23:46.040571 #54041] INFO -- : <?xml version="1.0"?>
Quickbooks::IntuitRequestException: :
<?xml version="1.0"?>
from /Users/yoonwaiyan/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/bundler/gems/quickbooks-ruby-053460340765/lib/quickbooks/service/base_service.rb:381:in `parse_and_raise_exception'
@yoonwaiyan It looks like you're running Ruby 2.4.x - I saw that :Fixnum
issue come up when another user reported issues with Ruby 2.4.x:
@ruckus deprecation warning shows on other call as well. By the way one workaround for token refresh is just refresh the token directly from OAuth2 client. Seems like it was undocumented in OAuth2 client as well and I have to search through the OAuth2 repo to know that it can be refreshed in this way:
new_access_token = access_token.refresh!
since the snippets in README.md is not working.
@yoonwaiyan Great find! Would you be so kind to submit a PR with this changes to 389-oauth2
branch? As you can see this branch is a WIP and docs are mentioning the old OAuth library.
By the way, could you test with ruby < 2.4 to check if the error you are getting persists?
Per this page: https://developer.intuit.com/docs/0100_quickbooks_online/0100_essentials/000500_authentication_and_authorization/connect_from_within_your_app