qbo_api 1.9.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env.test +0 -4
- data/.gitignore +1 -0
- data/.travis.yml +3 -5
- data/README.md +74 -97
- data/example/base.rb +1 -0
- data/example/oauth2.rb +15 -2
- data/example/public/connect-to-qbo.svg +1 -0
- data/example/views/oauth2.erb +4 -14
- data/lib/qbo_api/api_methods.rb +2 -12
- data/lib/qbo_api/attachment.rb +4 -6
- data/lib/qbo_api/configuration.rb +0 -1
- data/lib/qbo_api/connection.rb +9 -34
- data/lib/qbo_api/entity.rb +0 -2
- data/lib/qbo_api/error.rb +5 -1
- data/lib/qbo_api/raise_http_exception.rb +4 -3
- data/lib/qbo_api/supporting.rb +14 -1
- data/lib/qbo_api/util.rb +0 -1
- data/lib/qbo_api/version.rb +1 -1
- data/lib/qbo_api.rb +2 -2
- data/qbo_api.gemspec +3 -4
- metadata +13 -30
- data/.env.example_app.oauth1 +0 -2
- data/example/oauth.rb +0 -62
- data/lib/qbo_api/connection/oauth1.rb +0 -60
- data/lib/qbo_api/connection/oauth2.rb +0 -24
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 162fa8b773e3b73b82ea03e73d06ded342f6ac3bc7daafc9c02cc6a965a34aa7
|
|
4
|
+
data.tar.gz: a074c58fe2826531c2fe7a04cee0fecaf4021aac7e2c9a64fc30062fd3602fd5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 29a5b45354f2dbd9978fee3498dbfa96b660c6c747b93432b00836079f64e35d1448463ba13f055fc866e85804981f0a8110b6a429f23fc118da8a9f732d003b
|
|
7
|
+
data.tar.gz: f733937e458917500539ad443c8bfe61d29584b00caa2d8b7824d525170d2058806a7ad5e6a6a485ac05a6adf45be18feed8afff53372a7b7f643dd1fa1d40c2
|
data/.env.test
CHANGED
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
sudo: false
|
|
2
2
|
language: ruby
|
|
3
3
|
rvm:
|
|
4
|
-
- 2.
|
|
5
|
-
- 2.
|
|
6
|
-
-
|
|
7
|
-
- 2.7.0
|
|
4
|
+
- 2.6.8
|
|
5
|
+
- 2.7.4
|
|
6
|
+
- 3.0.2
|
|
8
7
|
|
|
9
8
|
before_install:
|
|
10
9
|
- gem install bundler
|
|
@@ -15,7 +14,6 @@ before_script:
|
|
|
15
14
|
script:
|
|
16
15
|
- bundle exec rspec spec/
|
|
17
16
|
|
|
18
|
-
|
|
19
17
|
notifications:
|
|
20
18
|
email:
|
|
21
19
|
- christian@minimul.com
|
data/README.md
CHANGED
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
# QboApi
|
|
2
2
|
|
|
3
3
|
Ruby client for the QuickBooks Online API version 3.
|
|
4
|
-
- Built on top of the excellent Faraday gem.
|
|
5
4
|
- JSON only support.
|
|
6
5
|
- Please don't ask about XML support. [Intuit has stated](https://github.com/ruckus/quickbooks-ruby/issues/257#issuecomment-126834454) that JSON is the primary data format for the QuickBooks API (v3 and beyond). This gem will specialize in JSON only. The [`quickbooks-ruby`](https://github.com/ruckus/quickbooks-ruby) gem has fantastic support for those who favor XML.
|
|
7
6
|
- Features specs built directly against a QuickBooks Online Sandbox via the VCR gem.
|
|
8
7
|
- Robust error handling.
|
|
9
8
|
|
|
10
|
-
## Tutorials and Screencasts
|
|
11
|
-
- <a href="https://minimul.com/migrating-a-quickbooks-online-app-from-oauth1-to-oauth2-using-the-qbo_api-gem.html" target="_blank">Migrating a QuickBooks Online App from OAuth1 to OAuth2 using the qbo_api gem - Step 1</a>.
|
|
12
|
-
- <a href="https://minimul.com/migrating-a-quickbooks-online-app-from-oauth1-to-oauth2-using-the-qbo_api-gem-part-2.html" target="_blank">Migrating a QuickBooks Online App from OAuth1 to OAuth2 using the qbo_api gem - Step 2</a>.
|
|
13
|
-
- <a href="https://minimul.com/migrating-a-quickbooks-online-app-from-oauth1-to-oauth2-using-the-qbo_api-gem-part-3.html" target="_blank">Migrating a QuickBooks Online App from OAuth1 to OAuth2 using the qbo_api gem - Step 3</a>.
|
|
14
|
-
- <a href="http://minimul.com/introducing-a-new-ruby-quickbooks-online-client.html" target="_blank">Why qbo_api is a better choice </a> than the <a href="https://github.com/ruckus/quickbooks-ruby" target="_blank">quickbooks-ruby</a> gem.
|
|
15
|
-
- <a href="http://minimul.com/getting-started-with-the-modern-ruby-quickbooks-online-client-qbo_api-part-1.html" target="_blank">Part 1</a>: Learn how to spin up the <a href="https://github.com/minimul/qbo_api#spin-up-an-example">example app</a>.
|
|
16
|
-
- <a href="http://minimul.com/the-modern-ruby-quickbooks-client-part-2.html" target="_blank">Part 2</a>: <a href="https://github.com/minimul/qbo_api#running-the-specs">Running the specs</a> to aid you in understanding a QuickBooks API transaction.
|
|
17
|
-
- <a href="http://minimul.com/the-modern-ruby-quickbooks-client-contributing.html" target="_blank">Part 3</a>: <a href="https://github.com/minimul/qbo_api#creating-new-specs-or-modifying-existing-spec-that-have-been-recorded-using-the-vcr-gem">Contributing to the gem</a>.
|
|
18
|
-
### Important Note: The videos are out of date.
|
|
19
|
-
If you signed up for a Intuit developer account after July 17th, 2017 then you will have to
|
|
20
|
-
follow <a href='#OAuth2-example'>OAuth2: Spin up an example</a>
|
|
21
9
|
## The Book
|
|
22
10
|
|
|
23
11
|
<a href="https://leanpub.com/minimul-qbo-guide-vol-1" target="_blank">
|
|
@@ -25,7 +13,7 @@ follow <a href='#OAuth2-example'>OAuth2: Spin up an example</a>
|
|
|
25
13
|
</a>
|
|
26
14
|
|
|
27
15
|
|
|
28
|
-
## Ruby >= 2.
|
|
16
|
+
## Ruby >= 2.6 required
|
|
29
17
|
|
|
30
18
|
## Installation
|
|
31
19
|
|
|
@@ -46,41 +34,22 @@ Or install it yourself as:
|
|
|
46
34
|
## Usage
|
|
47
35
|
|
|
48
36
|
### Initialize
|
|
49
|
-
#### OAuth
|
|
50
|
-
```ruby
|
|
51
|
-
q = account.qbo_account # or wherever you are storing the OAuth creds
|
|
52
|
-
qbo_api = QboApi.new(token: q.token,
|
|
53
|
-
token_secret: q.secret,
|
|
54
|
-
realm_id: q.companyid,
|
|
55
|
-
consumer_key: '*****',
|
|
56
|
-
consumer_secret: '********')
|
|
57
|
-
```
|
|
58
|
-
#### OAuth2
|
|
59
37
|
```ruby
|
|
60
38
|
qbo_api = QboApi.new(access_token: 'REWR342532asdfae!$4asdfa', realm_id: 32095430444)
|
|
39
|
+
- qbo_api.get :customer, 1
|
|
61
40
|
```
|
|
62
41
|
|
|
63
|
-
### Super fast way to use QboApi
|
|
42
|
+
### Super fast way to use QboApi as long as Ruby >= 2.5 is installed
|
|
64
43
|
```
|
|
65
44
|
- cd ~/<local dir>
|
|
66
45
|
- git clone git@github.com:minimul/qbo_api.git && cd qbo_api
|
|
67
46
|
- bundle
|
|
68
47
|
- bin/console
|
|
69
48
|
- QboApi.production = true
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
token_secret:"g8wcyQEtwxxxxxxm",
|
|
73
|
-
realm_id: "12314xxxxxx7",
|
|
74
|
-
consumer_key: "qyprdwzcxxxxxxbIWsIMIy9PYI",
|
|
75
|
-
consumer_secret: "CyDN4wpxxxxxxxPMv7hDhmh4")
|
|
76
|
-
- # OAuth 2
|
|
77
|
-
- qboapi = QboApi.new(access_token: "qyprd2uvCOdRq8xzoSSiiiiii", realm_id: "12314xxxxxx7")
|
|
78
|
-
- qboapi.get :customer, 1
|
|
49
|
+
- qbo_api = QboApi.new(access_token: "qyprd2uvCOdRq8xzoSSiiiiii", realm_id: "12314xxxxxx7")
|
|
50
|
+
- qbo_api.get :customer, 1
|
|
79
51
|
```
|
|
80
52
|
|
|
81
|
-
### TLS v1.2
|
|
82
|
-
Intuit will be [requiring](https://developer.intuit.com/hub/blog/2017/08/03/upgrading-your-apps-to-support-tls-1-2) API client connections to be negotiated over TLS1.2 by December 31st, 2017. Using the default HTTP client (Net::HTTP) with Faraday this is the case with QboApi, however, if you are using another HTTP client you may need to directly set the TLS version negotiation manually.
|
|
83
|
-
|
|
84
53
|
### DateTime serialization
|
|
85
54
|
Some QBO entities have attributes of type DateTime (e.g., Time Activities with StartTime and EndTime). All DateTimes passed to the QBO API must be serialized in ISO 8601 format.
|
|
86
55
|
If ActiveSupport is loaded, you can achieve proper serialization with the following configuration:
|
|
@@ -122,7 +91,6 @@ QboApi.minor_version = 8
|
|
|
122
91
|
# Works with .get, .create, .update, .query methods
|
|
123
92
|
```
|
|
124
93
|
|
|
125
|
-
|
|
126
94
|
### Create
|
|
127
95
|
```ruby
|
|
128
96
|
invoice = {
|
|
@@ -194,6 +162,40 @@ QboApi.minor_version = 8
|
|
|
194
162
|
p response.size # => 28
|
|
195
163
|
```
|
|
196
164
|
|
|
165
|
+
### Import/retrieve all
|
|
166
|
+
*Note: There is some overlap with the `all` and the `get` methods. The `get` method is limited to 1000 results where the `all` method will return all the results no matter the number.*
|
|
167
|
+
```ruby
|
|
168
|
+
# retrieves all active customers
|
|
169
|
+
qbo_api.all(:customers).each do |c|
|
|
170
|
+
p "#{c['Id']} #{c['DisplayName']}"
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# retrieves all active or inactive employees
|
|
174
|
+
qbo_api.all(:employees, inactive: true).each do |e|
|
|
175
|
+
p "#{e['Id']} #{e['DisplayName']}"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# retrieves all vendors by groups of 5
|
|
179
|
+
qbo_api.all(:vendor, max: 5).each do |v|
|
|
180
|
+
p v['DisplayName']
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# retrieves all customers by groups of 2 using a custom select query
|
|
184
|
+
where = "WHERE Id IN ('5', '6', '7', '8', '9', '10')"
|
|
185
|
+
qbo_api.all(:customer, max: 2, select: "SELECT * FROM Customer #{where}").each do |c|
|
|
186
|
+
p c['DisplayName']
|
|
187
|
+
end
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### Note: .all() returns a Ruby Enumerator
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
api.all(:clients).take(50).each { |c| p c["Id"] }
|
|
194
|
+
api.all(:clients).count
|
|
195
|
+
api.all(:clients).first
|
|
196
|
+
api.all(:clients).to_a
|
|
197
|
+
```
|
|
198
|
+
|
|
197
199
|
### Search with irregular characters
|
|
198
200
|
```ruby
|
|
199
201
|
# Use the .esc() method
|
|
@@ -204,6 +206,12 @@ QboApi.minor_version = 8
|
|
|
204
206
|
p response['Id'] # => 1
|
|
205
207
|
```
|
|
206
208
|
|
|
209
|
+
|
|
210
|
+
### Email a transaction entity
|
|
211
|
+
```ruby
|
|
212
|
+
api.send_invoice(invoice_id: 1, email_address: 'billy@joe.com')
|
|
213
|
+
```
|
|
214
|
+
|
|
207
215
|
### Uploading an attachment
|
|
208
216
|
```ruby
|
|
209
217
|
payload = {"AttachableRef":
|
|
@@ -267,7 +275,7 @@ Be aware that any errors will not raise a `QboApi::Error`, but will be returned
|
|
|
267
275
|
}
|
|
268
276
|
]
|
|
269
277
|
}
|
|
270
|
-
response =
|
|
278
|
+
response = qbo_api.batch(payload)
|
|
271
279
|
expect(response['BatchItemResponse'].size).to eq 2
|
|
272
280
|
expect(batch_response.detect{ |b| b["bId"] == "bid1" }["Vendor"]["DisplayName"]).to eq "Smith Family Store"
|
|
273
281
|
```
|
|
@@ -276,7 +284,7 @@ Be aware that any errors will not raise a `QboApi::Error`, but will be returned
|
|
|
276
284
|
|
|
277
285
|
```ruby
|
|
278
286
|
params = { start_date: '2015-01-01', end_date: '2015-07-31', customer: 1, summarize_column_by: 'Customers' }
|
|
279
|
-
response =
|
|
287
|
+
response = qbo_api.reports(name: 'ProfitAndLoss', params: params)
|
|
280
288
|
p response["Header"]["ReportName"]) #=> 'ProfitAndLoss'
|
|
281
289
|
```
|
|
282
290
|
|
|
@@ -313,31 +321,6 @@ See [docs](https://developer.intuit.com/docs/0100_quickbooks_online/0100_essenti
|
|
|
313
321
|
end
|
|
314
322
|
```
|
|
315
323
|
|
|
316
|
-
### Import/retrieve all
|
|
317
|
-
*Note: There is some overlap with the `all` and the `get` methods. The `get` method is limited to 1000 results where the `all` method will return all the results no matter the number.*
|
|
318
|
-
```ruby
|
|
319
|
-
# retrieves all active customers
|
|
320
|
-
qbo_api.all(:customers).each do |c|
|
|
321
|
-
p "#{c['Id']} #{c['DisplayName']}"
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
# retrieves all active or inactive employees
|
|
325
|
-
qbo_api.all(:employees, inactive: true).each do |e|
|
|
326
|
-
p "#{e['Id']} #{e['DisplayName']}"
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
# retrieves all vendors by groups of 5
|
|
330
|
-
qbo_api.all(:vendor, max: 5).each do |v|
|
|
331
|
-
p v['DisplayName']
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
# retrieves all customers by groups of 2 using a custom select query
|
|
335
|
-
where = "WHERE Id IN ('5', '6', '7', '8', '9', '10')"
|
|
336
|
-
qbo_api.all(:customer, max: 2, select: "SELECT * FROM Customer #{where}").each do |c|
|
|
337
|
-
p c['DisplayName']
|
|
338
|
-
end
|
|
339
|
-
```
|
|
340
|
-
|
|
341
324
|
### What kind of QuickBooks entity?
|
|
342
325
|
```ruby
|
|
343
326
|
p qbo_api.is_transaction_entity?(:invoice) # => true
|
|
@@ -346,9 +329,8 @@ See [docs](https://developer.intuit.com/docs/0100_quickbooks_online/0100_essenti
|
|
|
346
329
|
p qbo_api.is_transaction_entity?(:customer) # => false
|
|
347
330
|
p qbo_api.is_name_list_entity?(:vendors) # => true
|
|
348
331
|
```
|
|
349
|
-
## <a name='OAuth2-example'>
|
|
350
|
-
|
|
351
|
-
- <a href="http://minimul.com/access-the-quickbooks-online-api-with-oauth2.html" target="_blank">Check out this article on spinning up the OAuth2 example</a>.
|
|
332
|
+
## <a name='OAuth2-example'>Spin up an example</a>
|
|
333
|
+
- <a href="http://minimul.com/access-the-quickbooks-online-api-with-oauth2.html" target="_blank">Check out this article on spinning up the example</a>.
|
|
352
334
|
- `git clone git://github.com/minimul/qbo_api && cd qbo_api`
|
|
353
335
|
- `bundle`
|
|
354
336
|
- Create a `.env` file
|
|
@@ -363,7 +345,7 @@ See [docs](https://developer.intuit.com/docs/0100_quickbooks_online/0100_essenti
|
|
|
363
345
|
- Create a new Company ([from the manage sandboxes page](https://developer.intuit.com/v2/ui#/sandbox))
|
|
364
346
|
Don't use it for anything else besides testing this app.
|
|
365
347
|
-. Copy the 'Company ID' to your .env as QBO_API_COMPANY_ID
|
|
366
|
-
- Start up the example
|
|
348
|
+
- Start up the example app
|
|
367
349
|
- `ruby example/oauth2.rb`
|
|
368
350
|
- Go to `http://localhost:9393/oauth2`
|
|
369
351
|
- Use the `Connect to QuickBooks` button to connect to your QuickBooks sandbox, which you receive when signing up at [https://developer.intuit.com](https://developer.intuit.com).
|
|
@@ -373,35 +355,13 @@ See [docs](https://developer.intuit.com/docs/0100_quickbooks_online/0100_essenti
|
|
|
373
355
|
- Checkout [`example/oauth2.rb`](https://github.com/minimul/qbo_api/blob/master/example/oauth2.rb)
|
|
374
356
|
to see what is going on under the hood.
|
|
375
357
|
|
|
376
|
-
## OAuth1: Spin up an example
|
|
377
|
-
### OLD LEGACY - SEE OAUTH2 EXAMPLE ABOVE
|
|
378
|
-
- <a href="http://minimul.com/getting-started-with-the-modern-ruby-quickbooks-online-client-qbo_api-part-1.html" target="_blank">Check out this tutorial and screencast on spinning up an example</a>.
|
|
379
|
-
- `git clone git://github.com/minimul/qbo_api && cd qbo_api`
|
|
380
|
-
- `bundle`
|
|
381
|
-
- Create a `.env` file
|
|
382
|
-
- `cp .env.example_app.oauth1 .env`
|
|
383
|
-
- If needed create an account at [https://developer.intuit.com](https://developer.intuit.com)
|
|
384
|
-
- Click `Get started coding`
|
|
385
|
-
- Create an app with both the `Accounting` & `Payments` selected.
|
|
386
|
-
- Go to the `Development` tab and copy and paste the consumer key and secret into the `.env` file
|
|
387
|
-
as QBO_API_CONSUMER_KEY and QBO_API_CONSUMER_SECRET respectively.
|
|
388
|
-
- Start up the example app
|
|
389
|
-
- `ruby example/oauth.rb`
|
|
390
|
-
- Go to `http://localhost:9393`
|
|
391
|
-
- Use the `Connect to QuickBooks` button to connect to your QuickBooks sandbox, which you receive when signing up at [https://developer.intuit.com](https://developer.intuit.com).
|
|
392
|
-
- After successfully connecting to your sandbox run:
|
|
393
|
-
- `http://localhost:9393/customer/5`
|
|
394
|
-
- You should see "Dukes Basketball Camp" displayed
|
|
395
|
-
- Checkout [`example/oauth.rb`](https://github.com/minimul/qbo_api/blob/master/example/oauth.rb)
|
|
396
|
-
to see what is going on under the hood.
|
|
397
|
-
|
|
398
358
|
## Webhooks
|
|
399
359
|
- <a href="http://minimul.com/getting-started-with-quickbooks-online-webhooks.html" target="_blank">Check out this tutorial and screencast on handling a webhook request</a>. Also checkout [`example/app.rb`](https://github.com/minimul/qbo_api/blob/master/example/app.rb) for the request handling code.
|
|
400
360
|
|
|
401
361
|
See https://www.twilio.com/blog/2015/09/6-awesome-reasons-to-use-ngrok-when-testing-webhooks.html
|
|
402
362
|
for how to install ngrok and what it is.
|
|
403
363
|
|
|
404
|
-
- With
|
|
364
|
+
- With the example app running, run:
|
|
405
365
|
`ngrok http 9393 -subdomain=somereasonablyuniquenamehere`
|
|
406
366
|
|
|
407
367
|
- Go to the [`Development` tab](https://developer.intuit.com/v2/ui#/app/dashboard)
|
|
@@ -411,7 +371,7 @@ for how to install ngrok and what it is.
|
|
|
411
371
|
- After saving the webhook, click 'show token'.
|
|
412
372
|
Add the token to your .env as QBO_API_VERIFIER_TOKEN
|
|
413
373
|
|
|
414
|
-
- In another tab, create a customer via the
|
|
374
|
+
- In another tab, create a customer via the API:
|
|
415
375
|
`bundle exec ruby -rqbo_api -rdotenv -e 'Dotenv.load; p QboApi.new(access_token: ENV.fetch("QBO_API_OAUTH2_ACCESS_TOKEN"), realm_id: ENV.fetch("QBO_API_COMPANY_ID")).create(:customer, payload: { DisplayName: "TestCustomer" })'`
|
|
416
376
|
(You'll also need to have added the QBO_API_COMPANY_ID and QBO_API_OAUTH2_ACCESS_TOKEN to your .env)
|
|
417
377
|
|
|
@@ -424,6 +384,28 @@ for how to install ngrok and what it is.
|
|
|
424
384
|
"POST /webhooks HTTP/1.1" 200 - 0.0013
|
|
425
385
|
```
|
|
426
386
|
|
|
387
|
+
### Just For Hackers
|
|
388
|
+
|
|
389
|
+
- Using the build_connection method
|
|
390
|
+
```
|
|
391
|
+
connection = build_connection('https://oauth.platform.intuit.com', headers: { 'Accept' => 'application/json' }) do |conn|
|
|
392
|
+
conn.basic_auth(client_id, client_secret)
|
|
393
|
+
conn.request :url_encoded # application/x-www-form-urlencoded
|
|
394
|
+
conn.use FaradayMiddleware::ParseJson, parser_options: { symbolize_names: true }
|
|
395
|
+
conn.use Faraday::Response::RaiseError
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
raw_response = connection.post do |req|
|
|
399
|
+
req.body = { grant_type: :refresh_token, refresh_token: current_refresh_token }
|
|
400
|
+
req.url '/oauth2/v1/tokens/bearer'
|
|
401
|
+
end
|
|
402
|
+
```
|
|
403
|
+
- Once your .env file is completely filled out you can use the console to play around in your sandbox
|
|
404
|
+
```
|
|
405
|
+
bin/console test
|
|
406
|
+
>> @qbo_api.get :customer, 1
|
|
407
|
+
```
|
|
408
|
+
|
|
427
409
|
## Contributing
|
|
428
410
|
|
|
429
411
|
Bug reports and pull requests are welcome on GitHub at https://github.com/minimul/qbo_api.
|
|
@@ -441,11 +423,6 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/minimu
|
|
|
441
423
|
- All specs that require interaction with the API must be recorded against your personal QuickBooks sandbox. More coming on how to create or modifying existing specs against your sandbox.
|
|
442
424
|
- <a href="http://minimul.com/the-modern-ruby-quickbooks-client-contributing.html" target="_blank">Check out this tutorial and screencast on contributing to qbo_api</a>.
|
|
443
425
|
|
|
444
|
-
#### Protip: Once your .env file is completely filled out you can use the console to play around in your sandbox
|
|
445
|
-
```
|
|
446
|
-
bin/console test
|
|
447
|
-
>> @qbo_api.get :customer, 1
|
|
448
|
-
```
|
|
449
426
|
|
|
450
427
|
## License
|
|
451
428
|
|
data/example/base.rb
CHANGED
data/example/oauth2.rb
CHANGED
|
@@ -24,16 +24,29 @@ class OAuth2App < Sinatra::Base
|
|
|
24
24
|
Rack::OAuth2::Client.new(
|
|
25
25
|
identifier: CLIENT_ID,
|
|
26
26
|
secret: CLIENT_SECRET,
|
|
27
|
-
redirect_uri:
|
|
27
|
+
redirect_uri: redirect_url,
|
|
28
28
|
authorization_endpoint: "https://appcenter.intuit.com/connect/oauth2",
|
|
29
29
|
token_endpoint: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer"
|
|
30
30
|
)
|
|
31
31
|
end
|
|
32
|
+
|
|
33
|
+
def authorize_url(state:)
|
|
34
|
+
oauth2_client.authorization_uri(
|
|
35
|
+
client_id: CLIENT_ID,
|
|
36
|
+
scope: "com.intuit.quickbooks.accounting",
|
|
37
|
+
redirect_uri: redirect_url,
|
|
38
|
+
response_type: "code",
|
|
39
|
+
state: state
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def redirect_url
|
|
44
|
+
"http://localhost:#{PORT}/oauth2-redirect"
|
|
45
|
+
end
|
|
32
46
|
end
|
|
33
47
|
|
|
34
48
|
get '/oauth2' do
|
|
35
49
|
session[:state] = SecureRandom.uuid
|
|
36
|
-
@client = oauth2_client
|
|
37
50
|
erb :oauth2
|
|
38
51
|
end
|
|
39
52
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" style="isolation:isolate" viewBox="0 0 775.39 132"><defs><clipPath id="a"><path d="M0 0h775.39v132H0z"/></clipPath></defs><g clip-path="url(#a)"><path d="M775.395 124c0 4.4-3.6 8-8 8H8c-4.4 0-8-3.6-8-8V8c0-4.4 3.6-8 8-8h759.395c4.4 0 8 3.6 8 8v116z" fill="#328538"/><path d="M775.395 124c0 4.4-3.6 8-8 8H8c-4.4 0-8-3.6-8-8V8c0-4.4 3.6-8 8-8h759.395c4.4 0 8 3.6 8 8v116z" fill="none" vector-effect="non-scaling-stroke" stroke-width="4" stroke="#328538" stroke-miterlimit="10"/><path d="M178.168 56.127c-1.033-1.4-2.38-2.424-4.039-3.07-1.66-.645-3.284-.968-4.869-.968-2.028 0-3.872.368-5.532 1.106a13.005 13.005 0 0 0-4.287 3.042c-1.198 1.292-2.121 2.804-2.766 4.538-.646 1.733-.968 3.614-.968 5.642 0 2.14.313 4.093.941 5.864.627 1.771 1.521 3.291 2.683 4.563a12.012 12.012 0 0 0 4.176 2.96c1.622.703 3.448 1.052 5.477 1.052 2.103 0 3.964-.415 5.588-1.244 1.623-.831 2.932-1.928 3.928-3.292l5.587 3.926a17.878 17.878 0 0 1-6.362 5.063c-2.509 1.198-5.441 1.799-8.796 1.799-3.062 0-5.873-.508-8.437-1.523-2.564-1.014-4.767-2.433-6.611-4.258-1.844-1.826-3.282-4.002-4.314-6.53-1.034-2.524-1.55-5.318-1.55-8.38 0-3.134.544-5.965 1.632-8.492 1.088-2.527 2.582-4.674 4.482-6.445 1.898-1.77 4.14-3.135 6.721-4.094 2.581-.958 5.384-1.437 8.408-1.437 1.255 0 2.564.119 3.928.359 1.365.24 2.675.608 3.928 1.105a19.141 19.141 0 0 1 3.541 1.855 11.42 11.42 0 0 1 2.82 2.654l-5.309 4.205m13.056 16.597c0 1.032.156 2.065.471 3.097a8.468 8.468 0 0 0 1.41 2.767 7.381 7.381 0 0 0 2.378 1.991c.96.517 2.102.774 3.43.774 1.328 0 2.471-.257 3.43-.774a7.42 7.42 0 0 0 2.38-1.991 8.566 8.566 0 0 0 1.41-2.767 10.66 10.66 0 0 0 .47-3.097c0-1.033-.158-2.056-.47-3.071a8.637 8.637 0 0 0-1.41-2.738 7.1 7.1 0 0 0-2.38-1.963c-.959-.5-2.102-.748-3.43-.748-1.328 0-2.47.248-3.43.748a7.063 7.063 0 0 0-2.378 1.963 8.536 8.536 0 0 0-1.41 2.738 10.303 10.303 0 0 0-.471 3.071zm-6.749 0c0-2.103.377-4.011 1.134-5.726.755-1.714 1.779-3.181 3.07-4.398 1.29-1.217 2.821-2.157 4.592-2.821 1.77-.664 3.65-.996 5.642-.996 1.992 0 3.872.332 5.643.996 1.771.664 3.3 1.604 4.592 2.821 1.291 1.217 2.313 2.684 3.071 4.398.754 1.715 1.133 3.623 1.133 5.726 0 2.103-.379 4.02-1.133 5.753-.758 1.733-1.78 3.218-3.071 4.454-1.292 1.236-2.821 2.203-4.592 2.903-1.771.7-3.651 1.052-5.643 1.052s-3.872-.352-5.642-1.052c-1.771-.7-3.302-1.667-4.592-2.903-1.291-1.236-2.315-2.721-3.07-4.454-.757-1.733-1.134-3.65-1.134-5.753m33.91-13.167h6.307v4.26h.111c.589-1.328 1.612-2.498 3.069-3.513 1.457-1.015 3.181-1.521 5.173-1.521 1.734 0 3.218.303 4.454.912 1.234.609 2.249 1.412 3.042 2.408a9.715 9.715 0 0 1 1.742 3.429 14.43 14.43 0 0 1 .554 3.983v16.597h-6.638V71.396c0-.775-.056-1.586-.167-2.435a6.59 6.59 0 0 0-.719-2.294 4.775 4.775 0 0 0-1.521-1.688c-.647-.443-1.504-.664-2.572-.664-1.071 0-1.992.212-2.767.637a5.872 5.872 0 0 0-1.908 1.631 7.188 7.188 0 0 0-1.134 2.296 9.124 9.124 0 0 0-.387 2.628v14.605h-6.639V59.557m30.814 0h6.306v4.26h.111c.588-1.328 1.612-2.498 3.069-3.513 1.458-1.015 3.182-1.521 5.174-1.521 1.732 0 3.217.303 4.452.912 1.236.609 2.25 1.412 3.044 2.408a9.713 9.713 0 0 1 1.741 3.429c.369 1.292.553 2.619.553 3.983v16.597h-6.638V71.396c0-.775-.055-1.586-.166-2.435a6.569 6.569 0 0 0-.718-2.294 4.788 4.788 0 0 0-1.522-1.688c-.646-.443-1.504-.664-2.572-.664-1.07 0-1.992.212-2.766.637a5.851 5.851 0 0 0-1.908 1.631 7.169 7.169 0 0 0-1.135 2.296 9.124 9.124 0 0 0-.387 2.628v14.605h-6.638V59.557m49.51 10.622c0-.848-.12-1.66-.358-2.435a5.614 5.614 0 0 0-1.135-2.047c-.516-.588-1.171-1.06-1.964-1.411-.793-.349-1.724-.525-2.793-.525-1.992 0-3.679.6-5.063 1.799-1.383 1.198-2.148 2.737-2.295 4.619h13.608zm6.639 2.988v.885c0 .294-.019.589-.055.884h-20.192c.072.96.322 1.836.747 2.628a6.69 6.69 0 0 0 1.687 2.048 8.437 8.437 0 0 0 2.378 1.355 7.86 7.86 0 0 0 2.767.497c1.659 0 3.06-.304 4.204-.912a7.856 7.856 0 0 0 2.821-2.518l4.426 3.541c-2.619 3.541-6.418 5.311-11.396 5.311-2.066 0-3.964-.323-5.698-.969-1.734-.644-3.236-1.557-4.509-2.738-1.272-1.179-2.268-2.627-2.987-4.342-.72-1.716-1.078-3.661-1.078-5.837 0-2.139.358-4.084 1.078-5.836.719-1.752 1.706-3.245 2.96-4.481 1.254-1.235 2.738-2.194 4.452-2.878 1.716-.681 3.57-1.022 5.56-1.022 1.844 0 3.55.303 5.118.912a11.122 11.122 0 0 1 4.066 2.71c1.143 1.2 2.038 2.693 2.683 4.483.645 1.788.968 3.881.968 6.279m23.179-6.252c-.518-.738-1.291-1.355-2.324-1.852-1.032-.5-2.084-.748-3.152-.748-1.218 0-2.288.248-3.21.748a6.992 6.992 0 0 0-2.296 1.962 8.446 8.446 0 0 0-1.354 2.739 10.907 10.907 0 0 0-.443 3.07c0 1.033.156 2.057.471 3.07a8.538 8.538 0 0 0 1.409 2.739 7.183 7.183 0 0 0 2.352 1.964c.94.498 2.037.746 3.292.746a8.386 8.386 0 0 0 3.097-.608c1.032-.405 1.862-.996 2.49-1.77l4.149 4.204c-1.107 1.181-2.517 2.094-4.232 2.738-1.715.646-3.568.969-5.56.969-1.956 0-3.808-.314-5.56-.941-1.752-.626-3.283-1.549-4.592-2.766-1.309-1.218-2.341-2.691-3.097-4.426-.756-1.733-1.134-3.707-1.134-5.919 0-2.138.378-4.074 1.134-5.809.756-1.733 1.778-3.208 3.07-4.425a13.728 13.728 0 0 1 4.508-2.821c1.715-.664 3.55-.996 5.506-.996 1.954 0 3.844.369 5.67 1.106 1.826.738 3.272 1.752 4.342 3.043l-4.536 3.983m6.417-2.047v-5.311h4.647v-7.689h6.528v7.689h6.638v5.311h-6.638v12.336c0 1.181.212 2.157.636 2.932.424.774 1.373 1.161 2.849 1.161.443 0 .921-.045 1.439-.137a5.718 5.718 0 0 0 1.382-.415l.222 5.2c-.591.222-1.291.395-2.103.526-.811.129-1.585.194-2.323.194-1.77 0-3.209-.25-4.314-.748-1.107-.497-1.984-1.18-2.628-2.047-.646-.865-1.088-1.862-1.328-2.986a17.355 17.355 0 0 1-.36-3.624V64.868h-4.647m29.872 0v-5.311h4.648v-7.689h6.527v7.689h6.638v5.311h-6.638v12.336c0 1.181.212 2.157.637 2.932.423.774 1.373 1.161 2.849 1.161.443 0 .92-.045 1.438-.137a5.704 5.704 0 0 0 1.382-.415l.222 5.2c-.591.222-1.291.395-2.102.526-.812.129-1.586.194-2.324.194-1.77 0-3.208-.25-4.314-.748-1.107-.497-1.983-1.18-2.628-2.047-.646-.865-1.088-1.862-1.328-2.986a17.356 17.356 0 0 1-.359-3.624V64.868h-4.648m26.444 7.856c0 1.032.156 2.065.469 3.097a8.512 8.512 0 0 0 1.412 2.767 7.381 7.381 0 0 0 2.378 1.991c.958.517 2.102.774 3.43.774 1.328 0 2.471-.257 3.43-.774a7.392 7.392 0 0 0 2.378-1.991 8.531 8.531 0 0 0 1.412-2.767 10.66 10.66 0 0 0 .47-3.097c0-1.033-.158-2.056-.47-3.071a8.601 8.601 0 0 0-1.412-2.738 7.072 7.072 0 0 0-2.378-1.963c-.959-.5-2.102-.748-3.43-.748-1.328 0-2.472.248-3.43.748a7.063 7.063 0 0 0-2.378 1.963 8.58 8.58 0 0 0-1.412 2.738 10.365 10.365 0 0 0-.469 3.071zm-6.749 0c0-2.103.377-4.011 1.133-5.726.756-1.714 1.779-3.181 3.071-4.398 1.29-1.217 2.821-2.157 4.592-2.821 1.77-.664 3.65-.996 5.642-.996 1.992 0 3.872.332 5.643.996 1.771.664 3.3 1.604 4.592 2.821 1.291 1.217 2.313 2.684 3.071 4.398.754 1.715 1.133 3.623 1.133 5.726 0 2.103-.379 4.02-1.133 5.753-.758 1.733-1.78 3.218-3.071 4.454-1.292 1.236-2.821 2.203-4.592 2.903-1.771.7-3.651 1.052-5.643 1.052s-3.872-.352-5.642-1.052c-1.771-.7-3.302-1.667-4.592-2.903-1.292-1.236-2.315-2.721-3.071-4.454-.756-1.733-1.133-3.65-1.133-5.753" fill="#FFF"/><path d="M449.899 52.2c-1.882 0-3.643.351-5.283 1.051-1.641.701-3.053 1.658-4.233 2.876-1.18 1.217-2.111 2.674-2.794 4.371-.682 1.697-1.024 3.541-1.024 5.531 0 2.103.323 4.011.968 5.727.646 1.715 1.551 3.18 2.712 4.397 1.162 1.217 2.554 2.167 4.176 2.85 1.623.682 3.412 1.022 5.367 1.022 1.917 0 3.696-.34 5.339-1.022 1.64-.683 3.05-1.633 4.232-2.85 1.178-1.217 2.101-2.682 2.765-4.397.664-1.716.996-3.624.996-5.727 0-1.99-.313-3.834-.94-5.531-.628-1.697-1.521-3.154-2.683-4.371-1.162-1.218-2.554-2.175-4.177-2.876-1.623-.7-3.429-1.051-5.421-1.051zm23.51 33.912h-23.621c-3.136 0-5.984-.452-8.548-1.356-2.563-.904-4.757-2.213-6.583-3.928-1.825-1.715-3.236-3.818-4.232-6.307-.996-2.489-1.493-5.318-1.493-8.492 0-2.986.525-5.707 1.576-8.16 1.052-2.452 2.517-4.564 4.399-6.333 1.88-1.771 4.101-3.144 6.665-4.123 2.564-.976 5.339-1.464 8.327-1.464 2.986 0 5.753.488 8.298 1.464 2.544.979 4.748 2.352 6.611 4.123 1.861 1.769 3.309 3.881 4.341 6.333 1.034 2.453 1.551 5.174 1.551 8.16 0 1.771-.204 3.393-.609 4.868-.407 1.476-.932 2.813-1.578 4.011a15.475 15.475 0 0 1-2.212 3.155 16.224 16.224 0 0 1-2.573 2.294v.111h9.681v5.644m27.439 0h-6.307v-4.261h-.11c-.591 1.328-1.614 2.498-3.07 3.513-1.457 1.015-3.181 1.522-5.173 1.522-1.733 0-3.217-.305-4.453-.913-1.236-.609-2.25-1.41-3.042-2.408a9.677 9.677 0 0 1-1.744-3.429 14.461 14.461 0 0 1-.553-3.983V59.557h6.639v14.716c0 .773.056 1.586.166 2.434.111.849.351 1.613.719 2.296a4.767 4.767 0 0 0 1.521 1.686c.646.443 1.503.664 2.572.664 1.034 0 1.946-.212 2.74-.636.792-.424 1.438-.968 1.936-1.632a7.23 7.23 0 0 0 1.134-2.296 9.19 9.19 0 0 0 .386-2.626V59.557h6.639v26.555m6.693-26.555h6.639v26.555h-6.639V59.557zm-.941-9.017c0-1.069.397-2 1.189-2.795.794-.792 1.799-1.188 3.016-1.188 1.218 0 2.24.379 3.07 1.134.83.757 1.245 1.705 1.245 2.849 0 1.143-.415 2.093-1.245 2.849-.83.756-1.852 1.133-3.07 1.133-1.217 0-2.222-.395-3.016-1.188-.792-.793-1.189-1.724-1.189-2.794zm32.419 16.375c-.518-.738-1.291-1.355-2.324-1.852-1.032-.5-2.084-.748-3.154-.748-1.217 0-2.286.248-3.208.748a6.962 6.962 0 0 0-2.296 1.962 8.47 8.47 0 0 0-1.356 2.739 10.978 10.978 0 0 0-.442 3.07c0 1.033.157 2.057.47 3.07a8.583 8.583 0 0 0 1.411 2.739 7.183 7.183 0 0 0 2.352 1.964c.94.498 2.036.746 3.291.746a8.395 8.395 0 0 0 3.098-.608c1.032-.405 1.862-.996 2.49-1.77l4.149 4.204c-1.107 1.181-2.517 2.094-4.232 2.738-1.716.646-3.568.969-5.56.969-1.956 0-3.809-.314-5.56-.941-1.752-.626-3.283-1.549-4.592-2.766-1.309-1.218-2.343-2.691-3.097-4.426-.758-1.733-1.135-3.707-1.135-5.919 0-2.138.377-4.074 1.135-5.809.754-1.733 1.778-3.208 3.07-4.425a13.718 13.718 0 0 1 4.508-2.821c1.715-.664 3.55-.996 5.504-.996 1.955 0 3.846.369 5.671 1.106 1.825.738 3.272 1.752 4.343 3.043l-4.536 3.983m7.578-22.627h6.639v26.444h.165l10.07-11.175h8.518l-11.506 12.006 12.225 14.549h-8.795l-10.512-13.609h-.165v13.609h-6.639V44.288zm35.847 35.958h6.252c.885 0 1.843-.063 2.876-.193a9.396 9.396 0 0 0 2.849-.802 5.593 5.593 0 0 0 2.158-1.77c.572-.774.857-1.808.857-3.097 0-2.065-.701-3.504-2.101-4.316-1.403-.811-3.523-1.217-6.363-1.217h-6.528v11.395zm0-17.37h6.196c2.324 0 4.093-.46 5.311-1.383 1.217-.921 1.826-2.23 1.826-3.928 0-1.77-.628-3.022-1.881-3.761-1.255-.739-3.209-1.107-5.864-1.107h-5.588v10.179zm-6.969-15.932h15.268c1.474 0 2.932.175 4.37.525 1.439.351 2.719.923 3.844 1.715 1.126.793 2.038 1.817 2.739 3.071.7 1.253 1.052 2.765 1.052 4.536 0 2.213-.628 4.038-1.881 5.477-1.255 1.439-2.896 2.471-4.924 3.097v.111c2.47.332 4.5 1.292 6.085 2.877 1.585 1.587 2.379 3.707 2.379 6.363 0 2.139-.424 3.936-1.272 5.393-.85 1.456-1.964 2.627-3.348 3.512-1.383.886-2.968 1.522-4.756 1.91a25.792 25.792 0 0 1-5.45.581h-14.106V46.944m39.277 25.78c0 1.032.156 2.065.469 3.097a8.49 8.49 0 0 0 1.411 2.767 7.395 7.395 0 0 0 2.379 1.991c.958.517 2.102.774 3.43.774 1.327 0 2.47-.257 3.43-.774a7.413 7.413 0 0 0 2.378-1.991 8.51 8.51 0 0 0 1.411-2.767c.313-1.032.471-2.065.471-3.097 0-1.033-.158-2.056-.471-3.071a8.578 8.578 0 0 0-1.411-2.738 7.092 7.092 0 0 0-2.378-1.963c-.96-.5-2.103-.748-3.43-.748-1.328 0-2.472.248-3.43.748a7.076 7.076 0 0 0-2.379 1.963 8.558 8.558 0 0 0-1.411 2.738 10.365 10.365 0 0 0-.469 3.071zm-6.749 0c0-2.103.377-4.011 1.133-5.726.756-1.714 1.779-3.181 3.071-4.398 1.29-1.217 2.821-2.157 4.59-2.821 1.771-.664 3.652-.996 5.644-.996 1.991 0 3.872.332 5.643.996 1.769.664 3.3 1.604 4.591 2.821 1.29 1.217 2.314 2.684 3.07 4.398.756 1.715 1.135 3.623 1.135 5.726 0 2.103-.379 4.02-1.135 5.753-.756 1.733-1.78 3.218-3.07 4.454-1.291 1.236-2.822 2.203-4.591 2.903-1.771.7-3.652 1.052-5.643 1.052-1.992 0-3.873-.352-5.644-1.052-1.769-.7-3.3-1.667-4.59-2.903-1.292-1.236-2.315-2.721-3.071-4.454-.756-1.733-1.133-3.65-1.133-5.753m39.11 0c0 1.032.156 2.065.471 3.097a8.47 8.47 0 0 0 1.411 2.767 7.367 7.367 0 0 0 2.377 1.991c.96.517 2.103.774 3.431.774 1.328 0 2.47-.257 3.429-.774a7.41 7.41 0 0 0 2.38-1.991 8.588 8.588 0 0 0 1.411-2.767c.312-1.032.469-2.065.469-3.097 0-1.033-.157-2.056-.469-3.071a8.66 8.66 0 0 0-1.411-2.738 7.09 7.09 0 0 0-2.38-1.963c-.959-.5-2.101-.748-3.429-.748-1.328 0-2.471.248-3.431.748a7.05 7.05 0 0 0-2.377 1.963 8.538 8.538 0 0 0-1.411 2.738 10.303 10.303 0 0 0-.471 3.071zm-6.749 0c0-2.103.377-4.011 1.135-5.726.754-1.714 1.778-3.181 3.069-4.398 1.291-1.217 2.821-2.157 4.592-2.821 1.771-.664 3.651-.996 5.643-.996s3.872.332 5.642.996c1.771.664 3.3 1.604 4.592 2.821 1.291 1.217 2.314 2.684 3.071 4.398.755 1.715 1.133 3.623 1.133 5.726 0 2.103-.378 4.02-1.133 5.753-.757 1.733-1.78 3.218-3.071 4.454-1.292 1.236-2.821 2.203-4.592 2.903-1.77.7-3.65 1.052-5.642 1.052-1.992 0-3.872-.352-5.643-1.052-1.771-.7-3.301-1.667-4.592-2.903-1.291-1.236-2.315-2.721-3.069-4.454-.758-1.733-1.135-3.65-1.135-5.753m34.021-28.436h6.638v26.444h.166l10.068-11.175h8.52l-11.506 12.006 12.226 14.549H691.7l-10.511-13.609h-.166v13.609h-6.638V44.288z" fill="#F4F5F5"/><path d="M717.149 66.639c-.589-.775-1.402-1.448-2.433-2.02a6.867 6.867 0 0 0-3.376-.858c-1.069 0-2.047.222-2.932.664-.885.443-1.328 1.182-1.328 2.214 0 1.033.489 1.759 1.467 2.185.976.424 2.405.856 4.288 1.298.996.222 2 .518 3.014.886 1.014.369 1.936.857 2.767 1.467a7.23 7.23 0 0 1 2.019 2.268c.516.903.773 2.001.773 3.291 0 1.623-.303 2.997-.912 4.122a7.773 7.773 0 0 1-2.433 2.739c-1.015.7-2.196 1.208-3.542 1.52a18.318 18.318 0 0 1-4.177.471c-2.064 0-4.075-.379-6.029-1.134-1.956-.756-3.579-1.835-4.868-3.237l4.37-4.094c.738.96 1.695 1.752 2.876 2.379 1.18.628 2.49.94 3.928.94.479 0 .968-.055 1.466-.165.498-.111.96-.286 1.384-.526.424-.24.764-.561 1.024-.968.256-.406.386-.904.386-1.493 0-1.107-.508-1.9-1.521-2.379-1.016-.48-2.536-.96-4.564-1.438a21.777 21.777 0 0 1-2.904-.859 9.374 9.374 0 0 1-2.517-1.383 6.382 6.382 0 0 1-1.771-2.129c-.443-.848-.664-1.899-.664-3.154 0-1.474.304-2.746.912-3.817a7.867 7.867 0 0 1 2.408-2.628c.995-.682 2.12-1.188 3.373-1.52a15.082 15.082 0 0 1 3.874-.498c1.917 0 3.789.332 5.614.996 1.827.664 3.274 1.677 4.343 3.042l-4.315 3.818" fill="#F4F5F5"/><path d="M95.897 66.634c0-9.662-7.862-17.524-17.525-17.524h-1.604v6.157h1.604c6.269 0 11.368 5.1 11.368 11.367 0 6.27-5.099 11.37-11.368 11.37h-5.507v-37.37h-6.157V84.16h11.664c9.663 0 17.525-7.862 17.525-17.526zM62.793 49.11H51.13c-9.663 0-17.525 7.862-17.525 17.524 0 9.664 7.862 17.526 17.525 17.526h1.604v-6.156H51.13c-6.269 0-11.369-5.1-11.369-11.37 0-6.267 5.1-11.367 11.369-11.367h5.506v37.367h6.157V49.11zm45.991 17.557c0 24.301-19.7 44-44 44-24.301 0-44-19.699-44-44 0-24.3 19.699-44 44-44 24.3 0 44 19.7 44 44z" fill="#FFF"/></g></svg>
|
data/example/views/oauth2.erb
CHANGED
|
@@ -3,20 +3,10 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<title>QBO Connect via OAuth2</title>
|
|
6
|
-
|
|
7
|
-
<script type="text/javascript" src="<%= QboApi::APP_CENTER_BASE %>/Content/IA/intuit.ipp.anywhere-1.3.1.js"></script>
|
|
8
|
-
<script>
|
|
9
|
-
intuit.ipp.anywhere.setup({
|
|
10
|
-
grantUrl: "<%= @client.authorization_uri(scope: 'com.intuit.quickbooks.accounting', state: session[:state]) %>",
|
|
11
|
-
datasources: {
|
|
12
|
-
quickbooks : true,
|
|
13
|
-
payments : true
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
</script>
|
|
17
6
|
</head>
|
|
18
|
-
<body>
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
<body style="padding:15px;">
|
|
8
|
+
<a href="<%= authorize_url(state: session[:state]) %>">
|
|
9
|
+
<img src="connect-to-qbo.svg" alt="Connect to QuickBooks Online Button" width="400">
|
|
10
|
+
</a>
|
|
21
11
|
</body>
|
|
22
12
|
</html>
|
data/lib/qbo_api/api_methods.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
class QboApi
|
|
2
2
|
module ApiMethods
|
|
3
|
-
|
|
4
3
|
def all(entity, max: 1000, select: nil, inactive: false, params: nil, &block)
|
|
5
|
-
enumerator = create_all_enumerator(entity, max: max, select: select,
|
|
6
|
-
|
|
4
|
+
enumerator = create_all_enumerator(entity, max: max, select: select,
|
|
5
|
+
inactive: inactive, params: params)
|
|
7
6
|
if block_given?
|
|
8
7
|
enumerator.each(&block)
|
|
9
8
|
else
|
|
@@ -17,9 +16,6 @@ class QboApi
|
|
|
17
16
|
request(:get, entity: entity, path: path, params: params)
|
|
18
17
|
end
|
|
19
18
|
|
|
20
|
-
# @example
|
|
21
|
-
# get(:customer, 5)
|
|
22
|
-
# @see #get_by_query_filter
|
|
23
19
|
def get(entity, id_or_query_filter_args, params: nil)
|
|
24
20
|
if id_or_query_filter_args.is_a?(Array)
|
|
25
21
|
get_by_query_filter(entity, id_or_query_filter_args, params: params)
|
|
@@ -29,11 +25,6 @@ class QboApi
|
|
|
29
25
|
end
|
|
30
26
|
end
|
|
31
27
|
|
|
32
|
-
# @example
|
|
33
|
-
# get_by_query_filter(:customer, ["DisplayName", "Dukes Basketball Camp"])
|
|
34
|
-
# get_by_query_filter(:customer, ["DisplayName", "LIKE", "Dukes%"])
|
|
35
|
-
# get_by_query_filter(:vendor, ["DisplayName", "IN", "(true, false)"])
|
|
36
|
-
# get_by_query_filter(:customer, ["DisplayName", "Amy's Bird Sanctuary"])
|
|
37
28
|
def get_by_query_filter(entity, query_filter_args, params: nil)
|
|
38
29
|
query_str = get_query_str(entity, query_filter_args)
|
|
39
30
|
if resp = query(query_str, params: params)
|
|
@@ -143,6 +134,5 @@ class QboApi
|
|
|
143
134
|
resp = get(entity, id)
|
|
144
135
|
build_deactivate(entity, resp)
|
|
145
136
|
end
|
|
146
|
-
|
|
147
137
|
end
|
|
148
138
|
end
|
data/lib/qbo_api/attachment.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
class QboApi
|
|
2
2
|
module Attachment
|
|
3
|
-
|
|
4
3
|
def read_attachment(id:)
|
|
5
4
|
raw_response = connection.get do |request|
|
|
6
5
|
request.url "#{realm_id}/attachable/#{id}"
|
|
@@ -14,10 +13,10 @@ class QboApi
|
|
|
14
13
|
raw_response = attachment_connection.post do |request|
|
|
15
14
|
request.url "#{realm_id}/upload"
|
|
16
15
|
request.body = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
'file_metadata_01':
|
|
17
|
+
Faraday::UploadIO.new(StringIO.new(payload.to_json), 'application/json', 'attachment.json'),
|
|
18
|
+
'file_content_01':
|
|
19
|
+
Faraday::UploadIO.new(attachment, content_type, file_name)
|
|
21
20
|
}
|
|
22
21
|
end
|
|
23
22
|
response(raw_response, entity: :attachable)
|
|
@@ -36,7 +35,6 @@ class QboApi
|
|
|
36
35
|
def attachment_connection
|
|
37
36
|
@attachment_connection ||= authorized_multipart_connection(endpoint_url)
|
|
38
37
|
end
|
|
39
|
-
|
|
40
38
|
end
|
|
41
39
|
end
|
|
42
40
|
|
data/lib/qbo_api/connection.rb
CHANGED
|
@@ -4,16 +4,10 @@ require 'faraday/detailed_logger'
|
|
|
4
4
|
|
|
5
5
|
class QboApi
|
|
6
6
|
module Connection
|
|
7
|
-
AUTHORIZATION_MIDDLEWARES = []
|
|
8
|
-
|
|
9
|
-
def Connection.add_authorization_middleware(strategy_name)
|
|
10
|
-
Connection::AUTHORIZATION_MIDDLEWARES << strategy_name
|
|
11
|
-
end
|
|
12
|
-
|
|
13
7
|
def authorized_json_connection(url, headers: nil)
|
|
14
8
|
headers ||= {}
|
|
15
|
-
headers['Accept'] ||= 'application/json'
|
|
16
|
-
headers['Content-Type'] ||= 'application/json;charset=UTF-8'
|
|
9
|
+
headers['Accept'] ||= 'application/json'
|
|
10
|
+
headers['Content-Type'] ||= 'application/json;charset=UTF-8'
|
|
17
11
|
build_connection(url, headers: headers) do |conn|
|
|
18
12
|
add_authorization_middleware(conn)
|
|
19
13
|
add_exception_middleware(conn)
|
|
@@ -35,17 +29,6 @@ class QboApi
|
|
|
35
29
|
end
|
|
36
30
|
end
|
|
37
31
|
|
|
38
|
-
# @example
|
|
39
|
-
# connection = build_connection('https://oauth.platform.intuit.com', headers: { 'Accept' => 'application/json' }) do |conn|
|
|
40
|
-
# conn.basic_auth(client_id, client_secret)
|
|
41
|
-
# conn.request :url_encoded # application/x-www-form-urlencoded
|
|
42
|
-
# conn.use FaradayMiddleware::ParseJson, parser_options: { symbolize_names: true }
|
|
43
|
-
# conn.use Faraday::Response::RaiseError
|
|
44
|
-
# end
|
|
45
|
-
# raw_response = connection.post {|req|
|
|
46
|
-
# req.body = { grant_type: :refresh_token, refresh_token: current_refresh_token }
|
|
47
|
-
# req.url '/oauth2/v1/tokens/bearer'
|
|
48
|
-
# }
|
|
49
32
|
def build_connection(url, headers: nil)
|
|
50
33
|
Faraday.new(url: url) { |conn|
|
|
51
34
|
conn.response :detailed_logger, QboApi.logger, LOG_TAG if QboApi.log
|
|
@@ -54,14 +37,17 @@ class QboApi
|
|
|
54
37
|
}
|
|
55
38
|
end
|
|
56
39
|
|
|
57
|
-
def request(method, path:, entity: nil, payload: nil, params: nil)
|
|
58
|
-
raw_response = raw_request(method, conn: connection, path: path, params: params, payload: payload)
|
|
40
|
+
def request(method, path:, entity: nil, payload: nil, params: nil, headers: nil)
|
|
41
|
+
raw_response = raw_request(method, conn: connection, path: path, params: params, payload: payload, headers: headers)
|
|
59
42
|
response(raw_response, entity: entity)
|
|
60
43
|
end
|
|
61
44
|
|
|
62
|
-
def raw_request(method, conn:, path:, payload: nil, params: nil)
|
|
45
|
+
def raw_request(method, conn:, path:, payload: nil, params: nil, headers: nil)
|
|
63
46
|
path = finalize_path(path, method: method, params: params)
|
|
47
|
+
|
|
64
48
|
conn.public_send(method) do |req|
|
|
49
|
+
req.headers = headers if headers
|
|
50
|
+
|
|
65
51
|
case method
|
|
66
52
|
when :get, :delete
|
|
67
53
|
req.url path
|
|
@@ -119,22 +105,11 @@ class QboApi
|
|
|
119
105
|
end
|
|
120
106
|
|
|
121
107
|
def add_authorization_middleware(conn)
|
|
122
|
-
|
|
123
|
-
raise QboApi::Error.new error_body: 'Add a configured authorization_middleware'
|
|
124
|
-
end) do |strategy_name|
|
|
125
|
-
next unless public_send("use_#{strategy_name}_middleware?")
|
|
126
|
-
public_send("add_#{strategy_name}_authorization_middleware", conn)
|
|
127
|
-
true
|
|
128
|
-
end
|
|
108
|
+
conn.request :oauth2, access_token, token_type: 'bearer'
|
|
129
109
|
end
|
|
130
110
|
|
|
131
111
|
def entity_name(entity)
|
|
132
112
|
singular(entity)
|
|
133
113
|
end
|
|
134
|
-
|
|
135
|
-
require_relative 'connection/oauth1'
|
|
136
|
-
include OAuth1
|
|
137
|
-
require_relative 'connection/oauth2'
|
|
138
|
-
include OAuth2
|
|
139
114
|
end
|
|
140
115
|
end
|
data/lib/qbo_api/entity.rb
CHANGED
data/lib/qbo_api/error.rb
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
#200 OK The request succeeded. However, the response body may contain a <Fault> element, indicating an error.
|
|
3
2
|
#400 Bad request Generally, the request cannot be fulfilled due to bad syntax. In some cases, this response code is returned for a request with bad authorization data.
|
|
4
3
|
#401 Unauthorized Authentication or authorization has failed.
|
|
@@ -8,10 +7,12 @@
|
|
|
8
7
|
#500 Internal Server Error An error occurred on the server while processing the request. Resubmit request once; if it persists, contact developer support.
|
|
9
8
|
#502 Bad Gateway The server, while acting as a gateway or proxy, received an invalid response from an inbound server it accessed while attempting to fulfill the request.
|
|
10
9
|
#503 Service Unavailable The service is temporarily unavailable.
|
|
10
|
+
#504 Gateway Timeout
|
|
11
11
|
# Custom error class for rescuing from all QuickBooks Online errors
|
|
12
12
|
class QboApi
|
|
13
13
|
class Error < StandardError
|
|
14
14
|
attr_reader :fault
|
|
15
|
+
|
|
15
16
|
def initialize(errors = nil)
|
|
16
17
|
if errors
|
|
17
18
|
@fault = errors
|
|
@@ -46,4 +47,7 @@ class QboApi
|
|
|
46
47
|
|
|
47
48
|
# Raised when QuickBooks Online returns the HTTP status code 503
|
|
48
49
|
class ServiceUnavailable < Error; end
|
|
50
|
+
|
|
51
|
+
# Raised when QuickBooks Online returns the HTTP status code 504
|
|
52
|
+
class GatewayTimeout < Error; end
|
|
49
53
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require 'faraday'
|
|
2
2
|
require 'nokogiri'
|
|
3
|
-
|
|
4
3
|
# @private
|
|
5
4
|
module FaradayMiddleware
|
|
6
5
|
# @private
|
|
@@ -25,6 +24,8 @@ module FaradayMiddleware
|
|
|
25
24
|
raise QboApi::BadGateway.new({ error_body: response.reason_phrase })
|
|
26
25
|
when 503
|
|
27
26
|
raise QboApi::ServiceUnavailable.new(error_message(response))
|
|
27
|
+
when 504
|
|
28
|
+
raise QboApi::GatewayTimeout.new(error_message(response))
|
|
28
29
|
end
|
|
29
30
|
end
|
|
30
31
|
end
|
|
@@ -40,7 +41,8 @@ module FaradayMiddleware
|
|
|
40
41
|
method: response.method,
|
|
41
42
|
url: response.url,
|
|
42
43
|
status: response.status,
|
|
43
|
-
error_body: error_body(response.body)
|
|
44
|
+
error_body: error_body(response.body),
|
|
45
|
+
intuit_tid: response[:response_headers]['intuit_tid']
|
|
44
46
|
}
|
|
45
47
|
end
|
|
46
48
|
|
|
@@ -78,6 +80,5 @@ module FaradayMiddleware
|
|
|
78
80
|
}
|
|
79
81
|
end
|
|
80
82
|
end
|
|
81
|
-
|
|
82
83
|
end
|
|
83
84
|
end
|
data/lib/qbo_api/supporting.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
class QboApi
|
|
2
2
|
module Supporting
|
|
3
|
-
|
|
4
3
|
def cdc(entities:, changed_since:)
|
|
5
4
|
path = "#{realm_id}/cdc"
|
|
6
5
|
path = add_params_to_path(path: path, params: { entities: entities, changedSince: cdc_time(changed_since) })
|
|
@@ -18,5 +17,19 @@ class QboApi
|
|
|
18
17
|
request(:get, path: path)
|
|
19
18
|
end
|
|
20
19
|
|
|
20
|
+
def deliver(entity, entity_id:, email_address: nil)
|
|
21
|
+
valid_entities = %i(invoice estimate purchaseorder creditmemo salesreceipt refundreceipt)
|
|
22
|
+
unless valid_entities.include?(entity.to_sym)
|
|
23
|
+
raise ArgumentError, "Invalid entity type '#{entity}'. Must be one of: #{valid_entities.join(', ')}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
path = "#{realm_id}/#{entity}/#{entity_id}/send"
|
|
27
|
+
unless email_address.nil?
|
|
28
|
+
params = { minorversion: 63, sendTo: email_address }
|
|
29
|
+
path = add_params_to_path(path: path, params: params)
|
|
30
|
+
end
|
|
31
|
+
headers = { 'Content-Type' => 'application/octet-stream' }
|
|
32
|
+
request(:post, path: path, headers: headers)
|
|
33
|
+
end
|
|
21
34
|
end
|
|
22
35
|
end
|
data/lib/qbo_api/util.rb
CHANGED
data/lib/qbo_api/version.rb
CHANGED
data/lib/qbo_api.rb
CHANGED
|
@@ -22,15 +22,15 @@ class QboApi
|
|
|
22
22
|
include Attachment
|
|
23
23
|
include ApiMethods
|
|
24
24
|
|
|
25
|
-
attr_accessor :realm_id
|
|
25
|
+
attr_accessor :access_token, :realm_id
|
|
26
26
|
attr_accessor :endpoint
|
|
27
27
|
|
|
28
28
|
V3_ENDPOINT_BASE_URL = 'https://sandbox-quickbooks.api.intuit.com/v3/company/'
|
|
29
29
|
PAYMENTS_API_BASE_URL = 'https://sandbox.api.intuit.com/quickbooks/v4/payments'
|
|
30
30
|
LOG_TAG = "[QuickBooks]"
|
|
31
31
|
|
|
32
|
-
# @param attributes [Hash<Symbol,String>]
|
|
33
32
|
def initialize(attributes = {})
|
|
33
|
+
raise ArgumentError, "missing keyword: access_token" unless attributes.key?(:access_token)
|
|
34
34
|
raise ArgumentError, "missing keyword: realm_id" unless attributes.key?(:realm_id)
|
|
35
35
|
attributes = default_attributes.merge!(attributes)
|
|
36
36
|
attributes.each do |attribute, value|
|
data/qbo_api.gemspec
CHANGED
|
@@ -18,14 +18,13 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
-
spec.add_development_dependency "bundler"
|
|
22
|
-
spec.add_development_dependency "rake"
|
|
21
|
+
spec.add_development_dependency "bundler"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
23
|
spec.add_development_dependency "rspec"
|
|
24
24
|
spec.add_development_dependency 'webmock'
|
|
25
|
-
spec.add_development_dependency 'simple_oauth'
|
|
26
25
|
spec.add_development_dependency 'dotenv'
|
|
27
26
|
spec.add_development_dependency 'vcr'
|
|
28
|
-
spec.add_development_dependency '
|
|
27
|
+
spec.add_development_dependency 'amazing_print'
|
|
29
28
|
spec.add_runtime_dependency 'faraday'
|
|
30
29
|
spec.add_runtime_dependency 'faraday_middleware'
|
|
31
30
|
spec.add_runtime_dependency 'faraday-detailed_logger'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: qbo_api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Christian Pelczarski
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-04-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -16,30 +16,16 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '10.0'
|
|
34
|
-
type: :development
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - "~>"
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '10.0'
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: rspec
|
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
|
44
30
|
requirements:
|
|
45
31
|
- - ">="
|
|
@@ -53,7 +39,7 @@ dependencies:
|
|
|
53
39
|
- !ruby/object:Gem::Version
|
|
54
40
|
version: '0'
|
|
55
41
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
42
|
+
name: rspec
|
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
|
58
44
|
requirements:
|
|
59
45
|
- - ">="
|
|
@@ -67,7 +53,7 @@ dependencies:
|
|
|
67
53
|
- !ruby/object:Gem::Version
|
|
68
54
|
version: '0'
|
|
69
55
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
56
|
+
name: webmock
|
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
|
72
58
|
requirements:
|
|
73
59
|
- - ">="
|
|
@@ -109,7 +95,7 @@ dependencies:
|
|
|
109
95
|
- !ruby/object:Gem::Version
|
|
110
96
|
version: '0'
|
|
111
97
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
98
|
+
name: amazing_print
|
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
|
114
100
|
requirements:
|
|
115
101
|
- - ">="
|
|
@@ -178,14 +164,13 @@ dependencies:
|
|
|
178
164
|
- - ">="
|
|
179
165
|
- !ruby/object:Gem::Version
|
|
180
166
|
version: '0'
|
|
181
|
-
description:
|
|
167
|
+
description:
|
|
182
168
|
email:
|
|
183
169
|
- christian@minimul.com
|
|
184
170
|
executables: []
|
|
185
171
|
extensions: []
|
|
186
172
|
extra_rdoc_files: []
|
|
187
173
|
files:
|
|
188
|
-
- ".env.example_app.oauth1"
|
|
189
174
|
- ".env.example_app.oauth2"
|
|
190
175
|
- ".env.test"
|
|
191
176
|
- ".gitignore"
|
|
@@ -197,8 +182,8 @@ files:
|
|
|
197
182
|
- bin/console
|
|
198
183
|
- bin/setup
|
|
199
184
|
- example/base.rb
|
|
200
|
-
- example/oauth.rb
|
|
201
185
|
- example/oauth2.rb
|
|
186
|
+
- example/public/connect-to-qbo.svg
|
|
202
187
|
- example/views/customer.erb
|
|
203
188
|
- example/views/index.erb
|
|
204
189
|
- example/views/oauth2.erb
|
|
@@ -208,8 +193,6 @@ files:
|
|
|
208
193
|
- lib/qbo_api/attachment.rb
|
|
209
194
|
- lib/qbo_api/configuration.rb
|
|
210
195
|
- lib/qbo_api/connection.rb
|
|
211
|
-
- lib/qbo_api/connection/oauth1.rb
|
|
212
|
-
- lib/qbo_api/connection/oauth2.rb
|
|
213
196
|
- lib/qbo_api/entity.rb
|
|
214
197
|
- lib/qbo_api/error.rb
|
|
215
198
|
- lib/qbo_api/raise_http_exception.rb
|
|
@@ -221,7 +204,7 @@ homepage: https://github.com/minimul/qbo_api
|
|
|
221
204
|
licenses:
|
|
222
205
|
- MIT
|
|
223
206
|
metadata: {}
|
|
224
|
-
post_install_message:
|
|
207
|
+
post_install_message:
|
|
225
208
|
rdoc_options: []
|
|
226
209
|
require_paths:
|
|
227
210
|
- lib
|
|
@@ -236,8 +219,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
236
219
|
- !ruby/object:Gem::Version
|
|
237
220
|
version: '0'
|
|
238
221
|
requirements: []
|
|
239
|
-
rubygems_version: 3.
|
|
240
|
-
signing_key:
|
|
222
|
+
rubygems_version: 3.2.22
|
|
223
|
+
signing_key:
|
|
241
224
|
specification_version: 4
|
|
242
225
|
summary: Ruby JSON-only client for QuickBooks Online API v3. Built on top of the Faraday
|
|
243
226
|
gem.
|
data/.env.example_app.oauth1
DELETED
data/example/oauth.rb
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
require 'bundler/inline'
|
|
2
|
-
|
|
3
|
-
require File.expand_path(File.join('..', 'base'), __FILE__)
|
|
4
|
-
|
|
5
|
-
install_gems = true
|
|
6
|
-
gemfile(install_gems) do
|
|
7
|
-
source 'https://rubygems.org'
|
|
8
|
-
|
|
9
|
-
instance_eval(&BASE_GEMS)
|
|
10
|
-
|
|
11
|
-
gem 'omniauth'
|
|
12
|
-
gem 'omniauth-quickbooks'
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
instance_eval(&BASE_SETUP)
|
|
16
|
-
|
|
17
|
-
class OAuthApp < Sinatra::Base
|
|
18
|
-
instance_eval(&BASE_APP_CONFIG)
|
|
19
|
-
|
|
20
|
-
CONSUMER_KEY = ENV['QBO_API_CONSUMER_KEY']
|
|
21
|
-
CONSUMER_SECRET = ENV['QBO_API_CONSUMER_SECRET']
|
|
22
|
-
|
|
23
|
-
use Rack::Session::Cookie, secret: '34233adasf/qewrq453agqr9(lasfa)'
|
|
24
|
-
use OmniAuth::Builder do
|
|
25
|
-
provider :quickbooks, CONSUMER_KEY, CONSUMER_SECRET
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
get '/' do
|
|
29
|
-
@app_center = QboApi::APP_CENTER_BASE
|
|
30
|
-
@auth_data = oauth_data
|
|
31
|
-
@port = PORT
|
|
32
|
-
erb :index
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
get '/customer/:id' do
|
|
36
|
-
if session[:token]
|
|
37
|
-
api = QboApi.new(oauth_data)
|
|
38
|
-
@resp = api.get :customer, params[:id]
|
|
39
|
-
end
|
|
40
|
-
erb :customer
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
get '/auth/quickbooks/callback' do
|
|
44
|
-
auth = env["omniauth.auth"][:credentials]
|
|
45
|
-
session[:token] = auth[:token]
|
|
46
|
-
session[:secret] = auth[:secret]
|
|
47
|
-
session[:realm_id] = params['realmId']
|
|
48
|
-
'<!DOCTYPE html><html lang="en"><head></head><body><script>window.opener.location.reload(); window.close();</script></body></html>'
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def oauth_data
|
|
52
|
-
{
|
|
53
|
-
consumer_key: CONSUMER_KEY,
|
|
54
|
-
consumer_secret: CONSUMER_SECRET,
|
|
55
|
-
token: session[:token],
|
|
56
|
-
token_secret: session[:secret],
|
|
57
|
-
realm_id: session[:realm_id]
|
|
58
|
-
}
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
OAuthApp.run!
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
class QboApi
|
|
2
|
-
APP_CENTER_BASE = 'https://appcenter.intuit.com'
|
|
3
|
-
APP_CENTER_URL = APP_CENTER_BASE + '/Connect/Begin?oauth_token='
|
|
4
|
-
APP_CONNECTION_URL = APP_CENTER_BASE + '/api/v1/connection'
|
|
5
|
-
|
|
6
|
-
attr_accessor :token, :token_secret
|
|
7
|
-
attr_accessor :consumer_key, :consumer_secret
|
|
8
|
-
|
|
9
|
-
module Connection::OAuth1
|
|
10
|
-
|
|
11
|
-
def self.included(*)
|
|
12
|
-
QboApi::Connection.add_authorization_middleware :oauth1
|
|
13
|
-
super
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def default_attributes
|
|
17
|
-
super.merge!(
|
|
18
|
-
token: nil, token_secret: nil,
|
|
19
|
-
consumer_key: defined?(CONSUMER_KEY) ? CONSUMER_KEY : nil,
|
|
20
|
-
consumer_secret: defined?(CONSUMER_SECRET) ? CONSUMER_SECRET : nil,
|
|
21
|
-
)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def add_oauth1_authorization_middleware(conn)
|
|
25
|
-
gem 'simple_oauth'
|
|
26
|
-
require 'simple_oauth'
|
|
27
|
-
conn.request :oauth, oauth_data
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def use_oauth1_middleware?
|
|
31
|
-
token != nil
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# https://developer.intuit.com/docs/0100_quickbooks_online/0100_essentials/0085_develop_quickbooks_apps/0004_authentication_and_authorization/oauth_management_api#/Reconnect
|
|
35
|
-
def disconnect
|
|
36
|
-
path = "#{APP_CONNECTION_URL}/disconnect"
|
|
37
|
-
request(:get, path: path)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# https://developer.intuit.com/docs/0100_quickbooks_online/0100_essentials/0085_develop_quickbooks_apps/0004_authentication_and_authorization/oauth_management_api#/Reconnect
|
|
41
|
-
def reconnect
|
|
42
|
-
path = "#{APP_CONNECTION_URL}/reconnect"
|
|
43
|
-
request(:get, path: path)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
# Use with simple_oauth OAuth1 middleware
|
|
49
|
-
# @see #add_authorization_middleware
|
|
50
|
-
def oauth_data
|
|
51
|
-
{
|
|
52
|
-
consumer_key: @consumer_key,
|
|
53
|
-
consumer_secret: @consumer_secret,
|
|
54
|
-
token: @token,
|
|
55
|
-
token_secret: @token_secret
|
|
56
|
-
}
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
class QboApi
|
|
2
|
-
attr_accessor :access_token
|
|
3
|
-
|
|
4
|
-
module Connection::OAuth2
|
|
5
|
-
|
|
6
|
-
def self.included(*)
|
|
7
|
-
QboApi::Connection.add_authorization_middleware :oauth2
|
|
8
|
-
super
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def default_attributes
|
|
12
|
-
super.merge!(
|
|
13
|
-
access_token: nil
|
|
14
|
-
)
|
|
15
|
-
end
|
|
16
|
-
def add_oauth2_authorization_middleware(conn)
|
|
17
|
-
conn.request :oauth2, access_token, token_type: 'bearer'
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def use_oauth2_middleware?
|
|
21
|
-
access_token != nil
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|