square 0.0.0 → 0.0.1

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/Rakefile +17 -0
  4. data/VERSION +1 -1
  5. data/lib/square.rb +6 -1
  6. data/lib/square/connect.rb +15 -0
  7. data/lib/square/connect/connections.rb +10 -0
  8. data/lib/square/connect/connections/bank_accounts.rb +8 -0
  9. data/lib/square/connect/connections/payments.rb +19 -0
  10. data/lib/square/connect/connections/refunds.rb +8 -0
  11. data/lib/square/connect/connections/settlements.rb +8 -0
  12. data/lib/square/connect/device.rb +12 -0
  13. data/lib/square/connect/error.rb +13 -0
  14. data/lib/square/connect/itemization.rb +11 -0
  15. data/lib/square/connect/merchant.rb +29 -0
  16. data/lib/square/connect/money.rb +12 -0
  17. data/lib/square/connect/node.rb +79 -0
  18. data/lib/square/connect/payment.rb +75 -0
  19. data/lib/square/connect/refund.rb +26 -0
  20. data/lib/square/connect/tax.rb +16 -0
  21. data/lib/square/connect/tender.rb +25 -0
  22. data/lib/square/exception.rb +4 -0
  23. data/lib/square/oauth2.rb +8 -0
  24. data/lib/square/oauth2/access_token.rb +11 -0
  25. data/lib/square/oauth2/client.rb +24 -0
  26. data/spec/helpers/webmock_helper.rb +58 -0
  27. data/spec/mock_response/error/unauthorized.json +4 -0
  28. data/spec/mock_response/invalid_grant.json +3 -0
  29. data/spec/mock_response/merchant/me.json +7 -0
  30. data/spec/mock_response/payments/list.json +185 -0
  31. data/spec/mock_response/payments/single.json +61 -0
  32. data/spec/mock_response/token.json +6 -0
  33. data/spec/spec_helper.rb +4 -0
  34. data/spec/square/connect/connections/payments_spec.rb +19 -0
  35. data/spec/square/connect/merchant_spec.rb +50 -0
  36. data/spec/square/connect/node_spec.rb +70 -0
  37. data/spec/square/connect/payment_spec.rb +58 -0
  38. data/spec/square/oauth2/access_token_spec.rb +31 -0
  39. data/spec/square/oauth2/client_spec.rb +90 -0
  40. data/square.gemspec +13 -9
  41. metadata +82 -5
@@ -0,0 +1,8 @@
1
+ module Square
2
+ module OAuth2
3
+ ROOT_URL = 'https://squareup.com'
4
+ end
5
+ end
6
+
7
+ require 'square/oauth2/access_token'
8
+ require 'square/oauth2/client'
@@ -0,0 +1,11 @@
1
+ module Square
2
+ module OAuth2
3
+ class AccessToken < Rack::OAuth2::AccessToken::Bearer
4
+ def initialize(*options)
5
+ attributes = options.extract_options!
6
+ attributes[:access_token] ||= options.first
7
+ super attributes
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ module Square
2
+ module OAuth2
3
+ class Client < Rack::OAuth2::Client
4
+ def initialize(*options)
5
+ attributes = options.extract_options!
6
+ attributes[:identifier] ||= options.first
7
+ attributes[:secret] ||= options.second
8
+ attributes[:host] ||= 'squareup.com'
9
+ super attributes
10
+ end
11
+
12
+ def renew!
13
+ # TODO
14
+ end
15
+
16
+ private
17
+
18
+ def handle_success_response(response)
19
+ token_hash = JSON.parse(response.body).with_indifferent_access
20
+ AccessToken.new token_hash
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ require 'webmock/rspec'
2
+
3
+ module WebMockHelper
4
+ def mock_request(path_or_uri, response_file, options = {})
5
+ method = options[:method] || :get
6
+ endpoint = endpoint_for(path_or_uri)
7
+ stub_request(method, endpoint).with(
8
+ request_for(method, options)
9
+ ).to_return(
10
+ response_for(response_file, options)
11
+ )
12
+ if block_given?
13
+ response = yield
14
+ a_request(method, endpoint).with(
15
+ request_for(method, options)
16
+ ).should have_been_made.once
17
+ response
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def endpoint_for(path_or_uri)
24
+ if path_or_uri =~ /^https?:\/\//
25
+ path_or_uri
26
+ else
27
+ File.join Square::Connect::ROOT_URL, path_or_uri
28
+ end
29
+ end
30
+
31
+ def request_for(method, options = {})
32
+ request = {}
33
+ if options[:params]
34
+ case method
35
+ when :post, :put
36
+ request[:body] = options[:params]
37
+ else
38
+ request[:query] = options[:params]
39
+ end
40
+ end
41
+ if options[:request_header]
42
+ request[:headers] = options[:request_header]
43
+ end
44
+ request
45
+ end
46
+
47
+ def response_for(response_file, options = {})
48
+ response = {}
49
+ response[:body] = File.new File.join(File.dirname(__FILE__), '../mock_response', "#{response_file}.json")
50
+ if options[:status]
51
+ response[:status] = options[:status]
52
+ end
53
+ response
54
+ end
55
+ end
56
+
57
+ include WebMockHelper
58
+ WebMock.disable_net_connect!
@@ -0,0 +1,4 @@
1
+ {
2
+ "message": "Unauthorized",
3
+ "type": "service.unauthorized"
4
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "error": "invalid_grant"
3
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "id": "merchant_id",
3
+ "name": "Nov Matake",
4
+ "email": "nov@matake.jp",
5
+ "country_code": "JP",
6
+ "language_code": "ja-JP"
7
+ }
@@ -0,0 +1,185 @@
1
+ [{
2
+ "id": "payment_1",
3
+ "merchant_id": "merchant_id",
4
+ "creator_id": "creator_id",
5
+ "created_at": "2013-05-23T09:43:59Z",
6
+ "device": {
7
+ "name": "iPhone"
8
+ },
9
+ "inclusive_tax_money": {
10
+ "amount": 0,
11
+ "currency_code": "JPY"
12
+ },
13
+ "additive_tax_money": {
14
+ "amount": 0,
15
+ "currency_code": "JPY"
16
+ },
17
+ "tax_money": {
18
+ "amount": 0,
19
+ "currency_code": "JPY"
20
+ },
21
+ "tip_money": {
22
+ "amount": 0,
23
+ "currency_code": "JPY"
24
+ },
25
+ "discount_money": {
26
+ "amount": 0,
27
+ "currency_code": "JPY"
28
+ },
29
+ "total_collected_money": {
30
+ "amount": 0,
31
+ "currency_code": "JPY"
32
+ },
33
+ "processing_fee_money": {
34
+ "amount": 0,
35
+ "currency_code": "JPY"
36
+ },
37
+ "net_total_money": {
38
+ "amount": 0,
39
+ "currency_code": "JPY"
40
+ },
41
+ "refunded_money": {
42
+ "amount": 0,
43
+ "currency_code": "JPY"
44
+ },
45
+ "inclusive_tax": [],
46
+ "additive_tax": [],
47
+ "tender": [{
48
+ "type": "CASH",
49
+ "name": "Cash",
50
+ "total_money": {
51
+ "amount": 0,
52
+ "currency_code": "JPY"
53
+ },
54
+ "tendered_money": {
55
+ "amount": 0,
56
+ "currency_code": "JPY"
57
+ }
58
+ }],
59
+ "refunds": [],
60
+ "itemizations": []
61
+ }, {
62
+ "id": "payment_2",
63
+ "merchant_id": "merchant_id",
64
+ "creator_id": "creator_id",
65
+ "created_at": "2013-05-23T09:44:59Z",
66
+ "device": {
67
+ "name": "iPhone"
68
+ },
69
+ "inclusive_tax_money": {
70
+ "amount": 0,
71
+ "currency_code": "JPY"
72
+ },
73
+ "additive_tax_money": {
74
+ "amount": 0,
75
+ "currency_code": "JPY"
76
+ },
77
+ "tax_money": {
78
+ "amount": 0,
79
+ "currency_code": "JPY"
80
+ },
81
+ "tip_money": {
82
+ "amount": 0,
83
+ "currency_code": "JPY"
84
+ },
85
+ "discount_money": {
86
+ "amount": 0,
87
+ "currency_code": "JPY"
88
+ },
89
+ "total_collected_money": {
90
+ "amount": 20000,
91
+ "currency_code": "JPY"
92
+ },
93
+ "processing_fee_money": {
94
+ "amount": 0,
95
+ "currency_code": "JPY"
96
+ },
97
+ "net_total_money": {
98
+ "amount": 20000,
99
+ "currency_code": "JPY"
100
+ },
101
+ "refunded_money": {
102
+ "amount": 0,
103
+ "currency_code": "JPY"
104
+ },
105
+ "inclusive_tax": [],
106
+ "additive_tax": [],
107
+ "tender": [{
108
+ "type": "CASH",
109
+ "name": "Cash",
110
+ "total_money": {
111
+ "amount": 20000,
112
+ "currency_code": "JPY"
113
+ },
114
+ "tendered_money": {
115
+ "amount": 20000,
116
+ "currency_code": "JPY"
117
+ },
118
+ "change_back_money": {
119
+ "amount": 0,
120
+ "currency_code": "JPY"
121
+ }
122
+ }],
123
+ "refunds": [],
124
+ "itemizations": []
125
+ }, {
126
+ "id": "payment_3",
127
+ "merchant_id": "merchant_id",
128
+ "creator_id": "creator_id",
129
+ "created_at": "2013-05-23T09:46:42Z",
130
+ "device": {
131
+ "name": "iPhone"
132
+ },
133
+ "inclusive_tax_money": {
134
+ "amount": 0,
135
+ "currency_code": "JPY"
136
+ },
137
+ "additive_tax_money": {
138
+ "amount": 0,
139
+ "currency_code": "JPY"
140
+ },
141
+ "tax_money": {
142
+ "amount": 0,
143
+ "currency_code": "JPY"
144
+ },
145
+ "tip_money": {
146
+ "amount": 0,
147
+ "currency_code": "JPY"
148
+ },
149
+ "discount_money": {
150
+ "amount": 0,
151
+ "currency_code": "JPY"
152
+ },
153
+ "total_collected_money": {
154
+ "amount": 0,
155
+ "currency_code": "JPY"
156
+ },
157
+ "processing_fee_money": {
158
+ "amount": 0,
159
+ "currency_code": "JPY"
160
+ },
161
+ "net_total_money": {
162
+ "amount": 0,
163
+ "currency_code": "JPY"
164
+ },
165
+ "refunded_money": {
166
+ "amount": 0,
167
+ "currency_code": "JPY"
168
+ },
169
+ "inclusive_tax": [],
170
+ "additive_tax": [],
171
+ "tender": [{
172
+ "type": "CASH",
173
+ "name": "Cash",
174
+ "total_money": {
175
+ "amount": 0,
176
+ "currency_code": "JPY"
177
+ },
178
+ "tendered_money": {
179
+ "amount": 0,
180
+ "currency_code": "JPY"
181
+ }
182
+ }],
183
+ "refunds": [],
184
+ "itemizations": []
185
+ }]
@@ -0,0 +1,61 @@
1
+ {
2
+ "id": "payment_1",
3
+ "merchant_id": "merchant_id",
4
+ "creator_id": "creator_id",
5
+ "created_at": "2013-05-23T09:43:59Z",
6
+ "device": {
7
+ "name": "iPhone"
8
+ },
9
+ "inclusive_tax_money": {
10
+ "amount": 0,
11
+ "currency_code": "JPY"
12
+ },
13
+ "additive_tax_money": {
14
+ "amount": 0,
15
+ "currency_code": "JPY"
16
+ },
17
+ "tax_money": {
18
+ "amount": 0,
19
+ "currency_code": "JPY"
20
+ },
21
+ "tip_money": {
22
+ "amount": 0,
23
+ "currency_code": "JPY"
24
+ },
25
+ "discount_money": {
26
+ "amount": 0,
27
+ "currency_code": "JPY"
28
+ },
29
+ "total_collected_money": {
30
+ "amount": 0,
31
+ "currency_code": "JPY"
32
+ },
33
+ "processing_fee_money": {
34
+ "amount": 0,
35
+ "currency_code": "JPY"
36
+ },
37
+ "net_total_money": {
38
+ "amount": 0,
39
+ "currency_code": "JPY"
40
+ },
41
+ "refunded_money": {
42
+ "amount": 0,
43
+ "currency_code": "JPY"
44
+ },
45
+ "inclusive_tax": [],
46
+ "additive_tax": [],
47
+ "tender": [{
48
+ "type": "CASH",
49
+ "name": "Cash",
50
+ "total_money": {
51
+ "amount": 0,
52
+ "currency_code": "JPY"
53
+ },
54
+ "tendered_money": {
55
+ "amount": 0,
56
+ "currency_code": "JPY"
57
+ }
58
+ }],
59
+ "refunds": [],
60
+ "itemizations": []
61
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "access_token": "access_token_xyz",
3
+ "token_type": "bearer",
4
+ "expires_at": "2014-01-10T19:42:08Z",
5
+ "merchant_id": "merchant_id_xyz"
6
+ }
@@ -0,0 +1,4 @@
1
+ require 'cover_me'
2
+ require 'rspec'
3
+ require 'square'
4
+ require 'helpers/webmock_helper'
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Square::Connect::Connections::Payments do
4
+ let(:access_token) { 'access_token' }
5
+ let(:me) { Square::Connect::Merchant.me access_token }
6
+
7
+ describe '#payments' do
8
+ it 'should return an array of Square::Connect::Payment' do
9
+ payments = mock_request 'me/payments', 'payments/list' do
10
+ me.payments
11
+ end
12
+ payments.should be_a Array
13
+ payments.should_not be_blank
14
+ payments.each do |payment|
15
+ payment.should be_a Square::Connect::Payment
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Square::Connect::Merchant do
4
+ let(:klass) { Square::Connect::Merchant }
5
+ let(:identifier) { 'merchant_id' }
6
+ let(:name) { 'Nov Matake' }
7
+ let(:email) { 'nov@matake.jp' }
8
+ let(:country_code) { 'JP' }
9
+ let(:language_code) { 'ja-JP' }
10
+ let(:access_token) { 'access_token' }
11
+
12
+ describe '#initialize' do
13
+ subject { klass.new attributes }
14
+ let(:attributes) do
15
+ {
16
+ identifier: identifier,
17
+ email: email,
18
+ name: name,
19
+ country_code: country_code,
20
+ language_code: language_code
21
+ }
22
+ end
23
+ its(:identifier) { should == identifier }
24
+ its(:name) { should == name }
25
+ its(:email) { should == email }
26
+ its(:country_code) { should == country_code }
27
+ its(:language_code) { should == language_code }
28
+ its(:endpoint) { should == File.join(Square::Connect::ROOT_URL, identifier) }
29
+
30
+ context 'when access_token given' do
31
+ subject { klass.new attributes.merge(access_token: access_token) }
32
+
33
+ context 'as String' do
34
+ let(:access_token) { 'access_token' }
35
+ its(:access_token) { should be_a Square::OAuth2::AccessToken }
36
+ end
37
+
38
+ context 'as Square::OAuth2::AccessToken' do
39
+ let(:access_token) { Square::OAuth2::AccessToken.new 'access_token' }
40
+ its(:access_token) { should be_a Square::OAuth2::AccessToken }
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '.me' do
46
+ subject { klass.me access_token }
47
+ its(:identifier) { should == :me }
48
+ its(:access_token) { should be_a Square::OAuth2::AccessToken }
49
+ end
50
+ end