arrow_payments 0.1.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 (46) hide show
  1. data/.gitignore +25 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +3 -0
  5. data/README.md +272 -0
  6. data/Rakefile +10 -0
  7. data/arrow_payments.gemspec +25 -0
  8. data/lib/arrow_payments.rb +25 -0
  9. data/lib/arrow_payments/address.rb +11 -0
  10. data/lib/arrow_payments/client.rb +57 -0
  11. data/lib/arrow_payments/client/customers.rb +45 -0
  12. data/lib/arrow_payments/client/payment_methods.rb +90 -0
  13. data/lib/arrow_payments/client/transactions.rb +64 -0
  14. data/lib/arrow_payments/configuration.rb +7 -0
  15. data/lib/arrow_payments/connection.rb +78 -0
  16. data/lib/arrow_payments/customer.rb +38 -0
  17. data/lib/arrow_payments/entity.rb +39 -0
  18. data/lib/arrow_payments/errors.rb +13 -0
  19. data/lib/arrow_payments/line_item.rb +10 -0
  20. data/lib/arrow_payments/payment_method.rb +19 -0
  21. data/lib/arrow_payments/recurring_billing.rb +30 -0
  22. data/lib/arrow_payments/transaction.rb +74 -0
  23. data/lib/arrow_payments/version.rb +3 -0
  24. data/spec/arrow_payments_spec.rb +40 -0
  25. data/spec/client_spec.rb +42 -0
  26. data/spec/configuration_spec.rb +24 -0
  27. data/spec/customer_spec.rb +29 -0
  28. data/spec/customers_spec.rb +160 -0
  29. data/spec/entity_spec.rb +55 -0
  30. data/spec/fixtures/complete_payment_method.json +37 -0
  31. data/spec/fixtures/customer.json +25 -0
  32. data/spec/fixtures/customers.json +133 -0
  33. data/spec/fixtures/headers/payment_method_complete.yml +9 -0
  34. data/spec/fixtures/headers/payment_method_start.yml +9 -0
  35. data/spec/fixtures/line_item.json +8 -0
  36. data/spec/fixtures/start_payment_method.json +6 -0
  37. data/spec/fixtures/transaction.json +29 -0
  38. data/spec/fixtures/transaction_capture.json +5 -0
  39. data/spec/fixtures/transactions.json +68 -0
  40. data/spec/line_item_spec.rb +17 -0
  41. data/spec/payment_method_spec.rb +16 -0
  42. data/spec/payment_methods_spec.rb +181 -0
  43. data/spec/recurring_billing_spec.rb +28 -0
  44. data/spec/spec_helper.rb +19 -0
  45. data/spec/transactions_spec.rb +101 -0
  46. metadata +225 -0
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ *.gem
2
+ *.rbc
3
+ *.swp
4
+ *.tmproj
5
+ *~
6
+ .DS_Store
7
+ .\#*
8
+ .bundle
9
+ .config
10
+ .yardoc
11
+ Gemfile.lock
12
+ InstalledFiles
13
+ \#*
14
+ _yardoc
15
+ coverage
16
+ doc/
17
+ lib/bundler/man
18
+ pkg
19
+ rdoc
20
+ spec/reports
21
+ test/tmp
22
+ test/version_tmp
23
+ tmp
24
+ tmtags
25
+ lib/test.rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=nested
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,272 @@
1
+ # ArrowPayments
2
+
3
+ Ruby wrapper for Arrow Payments gateway
4
+
5
+ **Under Development**
6
+
7
+ ## Installation
8
+
9
+ In your Gemfile add a line:
10
+
11
+ ```
12
+ gem 'arrow_payments', :github => 'sosedoff/arrow_payments'
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ To configure gateway globally, add an initializer with the following:
18
+
19
+ ```ruby
20
+ ArrowPayments::Configuration.api_key = 'foo'
21
+ ArrowPayments::Configuration.mode = 'production'
22
+ ArrowPayments::Configuration.merchant_id = '1231231'
23
+ ```
24
+
25
+ Another way is to configure on the instance level:
26
+
27
+ ```ruby
28
+ client = ArrowPayments::Client.new(
29
+ :api_key => 'foo',
30
+ :mode => 'production',
31
+ :merchant_id => '123451',
32
+ :debug => true
33
+ )
34
+ ```
35
+
36
+ A set of helper methods:
37
+
38
+ ```ruby
39
+ client.production? # => true
40
+ client.sandbox? # => false
41
+ client.debug? # => true
42
+ ```
43
+
44
+ ## Usage
45
+
46
+ Check the **API reference** section for objects details.
47
+
48
+ Initialize a new client:
49
+
50
+ ```ruby
51
+ client = ArrowPayments::Client.new(
52
+ :api_key => 'foo',
53
+ :mode => 'sandbox',
54
+ :merchant_id => '12345'
55
+ )
56
+ ```
57
+
58
+ ### Customers
59
+
60
+ ```ruby
61
+ # Get all customers.
62
+ # Does not include recurring billings and payment methods.
63
+ client.customers # => [Customer, ...]
64
+
65
+ # Get customer details.
66
+ # Returns nil if not found
67
+ client.customer('12345')
68
+
69
+ # Create a new customer.
70
+ # Raises ArrowPayments::Error if unable to create.
71
+ customer = client.create_customer(
72
+ :name => 'John Doe',
73
+ :contact => 'John Doe',
74
+ :code => 'JOHN',
75
+ :email => 'john@doe.com',
76
+ :phone => '(123) 123-12-12'
77
+ )
78
+
79
+ # Update an existing customer
80
+ customer = client.customer('12345')
81
+ customer.name = 'Foo Bar'
82
+ client.update_customer(customer) # => true
83
+
84
+ # Delete an existing customer
85
+ client.delete_customer('12345') # => true
86
+ ```
87
+
88
+ ### Payment Methods
89
+
90
+ Example: Add a new payment method to an existing customer
91
+
92
+ ```ruby
93
+ client_id = '12345'
94
+
95
+ # Initialize a new billing address instance
96
+ address = ArrowPayments::Address.new(
97
+ :address => 'Some Street',
98
+ :address2 => 'Apt 1',
99
+ :city => 'Chicago',
100
+ :state => 'IL',
101
+ :zip => '60657',
102
+ :phone => '123123123'
103
+ )
104
+
105
+ # Initialize a new payment method instance
106
+ cc = ArrowPayments::PaymentMethod.new(
107
+ :first_name => 'John',
108
+ :last_name => 'Doe',
109
+ :number => '4111111111111111',
110
+ :security_code => '123',
111
+ :expiration_month => 12,
112
+ :expiration_year => 14
113
+ )
114
+
115
+ # Step 1: Provide payment method customer and billing address
116
+ url = client.start_payment_method(customer_id, address)
117
+
118
+ # Step 2: Add credit card information
119
+ token = client.setup_payment_method(url, cc)
120
+
121
+ # Step 3: Finalize payment method creation
122
+ cc = client.complete_payment_methodtoken)
123
+
124
+ # Delete an existing payment method
125
+ client.delete_payment_method('123456') # => true
126
+ ```
127
+
128
+ You can also create a payment method using a wrapper method:
129
+
130
+ ```ruby
131
+ address = ArrowPayments::Address.new( ... data ... )
132
+ cc = ArrowPayments::PaymentMethod.new( ... data ... )
133
+
134
+ # Returns a new PaymentMethod instance or raises errors
135
+ client.create_payment_method(customer_id, address, cc)
136
+ ```
137
+
138
+ ### Transactions
139
+
140
+ ```ruby
141
+ # Get list of transactions by customer.
142
+ # Only unsettled transactions will be returns as ArrowPayments does not support
143
+ # any other filters for now
144
+ client.transactions('12345')
145
+
146
+ # Get a single transaction details.
147
+ # Raises ArrowPayments::NotFound if not found
148
+ client.transaction('45678')
149
+
150
+ # Capture a transaction for a specified amount.
151
+ # Returns success result or raises ArrowPayments::Error exception
152
+ client.capture_transaction('45678', 123.00)
153
+
154
+ # Void an existing unsettled transaction
155
+ # Returns a success result or raises ArrowPayments::NotFound if not found
156
+ client.void_transaction('45678')
157
+
158
+ # Create a new transaction for an existing custromer and payment method.
159
+ # Returns a new Transaction instance if request was successfull, otherwise
160
+ # raises ArrowPayments::Error exception with error message.
161
+ transaction = client.create_transaction(
162
+ :customer_id => 'Customer ID',
163
+ :payment_method_id => 'Payment Method ID',
164
+ :transaction_type => 'sale',
165
+ :total_amount => 250,
166
+ :tax_amount => 0,
167
+ :shipping_amount => 0
168
+ )
169
+ ```
170
+
171
+ ## Reference
172
+
173
+ List of all gateway errors:
174
+
175
+ - `ArrowPayments::Error` - Raised on invalid data. Generic error.
176
+ - `ArrowPayments::NotFound` - Raised on invalid API token or non-existing object
177
+ - `ArrowPayments::NotImplemented` - Raised when API endpoint is not implemented
178
+
179
+ List of all gateway objects:
180
+
181
+ - `Customer` - Gateway customer object
182
+ - `PaymentMethod` - Gateway payment method (credit card) object
183
+ - `Transaction` - Contains all information about transaction
184
+ - `Address` - User for shipping and billing addresses
185
+ - `LineItem` - Contains information about transaction item
186
+
187
+ ### Address
188
+
189
+ - `address`
190
+ - `address2`
191
+ - `city`
192
+ - `state`
193
+ - `zip`
194
+ - `phone`
195
+ - `tag`
196
+
197
+ ### Customer
198
+
199
+ - `id`
200
+ - `name`
201
+ - `code`
202
+ - `contact`
203
+ - `phone`
204
+ - `email`
205
+ - `recurring_billings` - Array of `RecurringBilling` instances if any
206
+ - `payment_methods` - Array of PaymentMethod instances if any
207
+
208
+ ### PaymentMethod
209
+
210
+ - `id`
211
+ - `card_type`
212
+ - `last_digits`
213
+ - `first_name`
214
+ - `last_name`
215
+ - `expiration_month`
216
+ - `expiration_year`
217
+ - `address`
218
+ - `address2`
219
+ - `city`
220
+ - `state`
221
+ - `zip`
222
+
223
+ ### LineItem
224
+
225
+ - `id`
226
+ - `commodity_code`
227
+ - `description`
228
+ - `price`
229
+ - `product_code`
230
+ - `unit_of_measure`
231
+
232
+ ### Transaction
233
+
234
+ - `id`
235
+ - `account`
236
+ - `transaction_type`
237
+ - `created_at` - A `DateTime` object of creation
238
+ - `level`
239
+ - `total_amount`
240
+ - `description`
241
+ - `transaction_source`
242
+ - `status` - One of `NotSettled`, `Settled`, `Voided`, `Failed`
243
+ - `capture_amount`
244
+ - `authorization_code`
245
+ - `payment_method_id`
246
+ - `cardholder_first_name`
247
+ - `cardholder_last_name`
248
+ - `card_type`
249
+ - `card_last_digits`
250
+ - `customer_po_number`
251
+ - `tax_amount`
252
+ - `shipping_amount`
253
+ - `shipping_address_id`
254
+ - `shipping_address`
255
+ - `customer_id`
256
+ - `customer_name`
257
+ - `line_items`
258
+ - `billing_address`
259
+
260
+ ## Testing
261
+
262
+ To run a test suite:
263
+
264
+ ```
265
+ rake test
266
+ ```
267
+
268
+ ## TODO
269
+
270
+ There are multiple features that are pending implementation:
271
+
272
+ - Filter transactions by status
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:test) do |t|
6
+ t.pattern = 'spec/*_spec.rb'
7
+ t.verbose = false
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,25 @@
1
+ require File.expand_path('../lib/arrow_payments/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "arrow_payments"
5
+ s.version = ArrowPayments::VERSION.dup
6
+ s.summary = "Ruby wrapper for ArrowPayments gateway"
7
+ s.description = "Ruby wrapper for ArrowPayments gateway"
8
+ s.homepage = "http://github.com/sosedoff/arrow_payments"
9
+ s.authors = ["Dan Sosedoff"]
10
+ s.email = ["dan.sosedoff@gmail.com"]
11
+
12
+ s.add_development_dependency 'webmock', '~> 1.6'
13
+ s.add_development_dependency 'rake', '~> 0.9'
14
+ s.add_development_dependency 'rspec', '~> 2.12'
15
+
16
+ s.add_runtime_dependency 'faraday', '~> 0.8'
17
+ s.add_runtime_dependency 'faraday_middleware', '~> 0.8'
18
+ s.add_runtime_dependency 'hashie', '~> 2.0'
19
+ s.add_runtime_dependency 'json', '~> 1.7'
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'arrow_payments/version'
2
+ require 'arrow_payments/errors'
3
+
4
+ module ArrowPayments
5
+ autoload :Configuration, 'arrow_payments/configuration'
6
+ autoload :Entity, 'arrow_payments/entity'
7
+ autoload :Customer, 'arrow_payments/customer'
8
+ autoload :PaymentMethod, 'arrow_payments/payment_method'
9
+ autoload :RecurringBilling, 'arrow_payments/recurring_billing'
10
+ autoload :Transaction, 'arrow_payments/transaction'
11
+ autoload :Address, 'arrow_payments/address'
12
+ autoload :LineItem, 'arrow_payments/line_item'
13
+ autoload :Connection, 'arrow_payments/connection'
14
+ autoload :Client, 'arrow_payments/client'
15
+
16
+ autoload :Customers, 'arrow_payments/client/customers'
17
+ autoload :PaymentMethods, 'arrow_payments/client/payment_methods'
18
+ autoload :Transactions, 'arrow_payments/client/transactions'
19
+
20
+ class << self
21
+ def client(options={})
22
+ ArrowPayments::Client.new(options)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ module ArrowPayments
2
+ class Address < Entity
3
+ property :address, :from => 'Address1'
4
+ property :address2, :from => 'Address2'
5
+ property :city, :from => 'City'
6
+ property :state, :from => 'State'
7
+ property :zip, :from => 'Postal'
8
+ property :phone, :from => 'Phone'
9
+ property :tag, :from => 'Tag'
10
+ end
11
+ end
@@ -0,0 +1,57 @@
1
+ module ArrowPayments
2
+ class Client
3
+ include ArrowPayments::Connection
4
+ include ArrowPayments::Customers
5
+ include ArrowPayments::PaymentMethods
6
+ include ArrowPayments::Transactions
7
+
8
+ attr_reader :api_key, :mode, :merchant_id, :debug
9
+
10
+ # Initialize a new client instance
11
+ # @param [Hash] client connection options
12
+ #
13
+ # Available options:
14
+ #
15
+ # :api_key - Your API key (required)
16
+ # :mode - API mode (sandox / production)
17
+ # :merchant_id - Your merchant ID
18
+ # :debug - True for request logging
19
+ #
20
+ def initialize(options={})
21
+ @api_key = options[:api_key] || ArrowPayments::Configuration.api_key
22
+ @mode = (options[:mode] || ArrowPayments::Configuration.mode || 'production').to_s
23
+ @merchant_id = options[:merchant_id] || ArrowPayments::Configuration.merchant_id
24
+ @debug = options[:debug] == true
25
+
26
+ if api_key.to_s.empty?
27
+ raise ArgumentError, "API key required"
28
+ end
29
+
30
+ if merchant_id.to_s.empty?
31
+ raise ArgumentError, "Merchant ID required"
32
+ end
33
+
34
+ unless %(sandbox production).include?(mode)
35
+ raise ArgumentError, "Invalid mode: #{mode}"
36
+ end
37
+ end
38
+
39
+ # Check if client is in sandbox mode
40
+ # @return [Boolean]
41
+ def sandbox?
42
+ mode == 'sandbox'
43
+ end
44
+
45
+ # Check if client is in production mode
46
+ # @return [Boolean]
47
+ def production?
48
+ mode == 'production'
49
+ end
50
+
51
+ # Check if debug mode is enabled
52
+ # @return [Boolean]
53
+ def debug?
54
+ debug == true
55
+ end
56
+ end
57
+ end