balanced-ach 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 (77) hide show
  1. data/.idea/.name +1 -0
  2. data/.idea/.rakeTasks +7 -0
  3. data/.idea/balanced-ach.iml +9 -0
  4. data/.idea/encodings.xml +5 -0
  5. data/.idea/misc.xml +5 -0
  6. data/.idea/modules.xml +9 -0
  7. data/.idea/scopes/scope_settings.xml +5 -0
  8. data/.idea/vcs.xml +7 -0
  9. data/.idea/workspace.xml +561 -0
  10. data/CONTRIBUTORS +1 -0
  11. data/Gemfile +19 -0
  12. data/Gemfile.lock +64 -0
  13. data/Guardfile +7 -0
  14. data/LICENSE +22 -0
  15. data/README.md +64 -0
  16. data/Rakefile +12 -0
  17. data/balanced.gemspec +22 -0
  18. data/lib/balanced.rb +84 -0
  19. data/lib/balanced/client.rb +82 -0
  20. data/lib/balanced/error.rb +85 -0
  21. data/lib/balanced/pager.rb +201 -0
  22. data/lib/balanced/resources.rb +5 -0
  23. data/lib/balanced/resources/bank_account.rb +36 -0
  24. data/lib/balanced/resources/credit.rb +20 -0
  25. data/lib/balanced/resources/debit.rb +27 -0
  26. data/lib/balanced/resources/resource.rb +158 -0
  27. data/lib/balanced/response/balanced_exception_middleware.rb +33 -0
  28. data/lib/balanced/utils.rb +62 -0
  29. data/lib/balanced/version.rb +3 -0
  30. data/spec/balanced/pager_spec.rb +42 -0
  31. data/spec/balanced/resources/account_spec.rb +571 -0
  32. data/spec/balanced/resources/api_key_spec.rb +55 -0
  33. data/spec/balanced/resources/hold_spec.rb +55 -0
  34. data/spec/balanced/resources/marketplace_spec.rb +97 -0
  35. data/spec/balanced/resources/transactions_spec.rb +72 -0
  36. data/spec/balanced/response/balanced_exception_middleware_spec.rb +47 -0
  37. data/spec/balanced_spec.rb +77 -0
  38. data/spec/cassettes/Balanced/configure.yml +48 -0
  39. data/spec/cassettes/Balanced/configure/reconfigure_with_new_api_key.yml +48 -0
  40. data/spec/cassettes/Balanced_Account.yml +110 -0
  41. data/spec/cassettes/Balanced_Account/Account_uri/when_ApiKey_is_configured.yml +240 -0
  42. data/spec/cassettes/Balanced_Account/Account_uri/when_ApiKey_is_not_configured.yml +44 -0
  43. data/spec/cassettes/Balanced_Account/_find.yml +400 -0
  44. data/spec/cassettes/Balanced_Account/_find/_all_some_field_op_.yml +186 -0
  45. data/spec/cassettes/Balanced_Account/_find/_first_some_field_op_.yml +186 -0
  46. data/spec/cassettes/Balanced_Account/_find_by_email.yml +400 -0
  47. data/spec/cassettes/Balanced_Account/_find_by_email/email_address_does_not_exist.yml +175 -0
  48. data/spec/cassettes/Balanced_Account/_find_by_email/email_address_is_in_system.yml +186 -0
  49. data/spec/cassettes/Balanced_Account/buyer/_add_card/after_executing.yml +530 -0
  50. data/spec/cassettes/Balanced_Account/buyer/_add_card/when_executing.yml +455 -0
  51. data/spec/cassettes/Balanced_Account/buyer/_debit.yml +363 -0
  52. data/spec/cassettes/Balanced_Account/buyer/_promote_to_merchant/after_executing.yml +281 -0
  53. data/spec/cassettes/Balanced_Account/buyer/_promote_to_merchant/when_executing.yml +281 -0
  54. data/spec/cassettes/Balanced_Account/buyer/_save/after_save/attributes.yml +1013 -0
  55. data/spec/cassettes/Balanced_Account/buyer/_save/when_creating.yml +229 -0
  56. data/spec/cassettes/Balanced_Account/merchant/_add_bank_account/after_executing.yml +536 -0
  57. data/spec/cassettes/Balanced_Account/merchant/_add_bank_account/when_executing.yml +460 -0
  58. data/spec/cassettes/Balanced_Account/merchant/_save/after_save/attributes.yml +232 -0
  59. data/spec/cassettes/Balanced_Account/merchant/_save/when_creating.yml +232 -0
  60. data/spec/cassettes/Balanced_Account/merchant/new.yml +179 -0
  61. data/spec/cassettes/Balanced_ApiKey/attributes.yml +48 -0
  62. data/spec/cassettes/Balanced_ApiKey/new_key/after_configure.yml +93 -0
  63. data/spec/cassettes/Balanced_ApiKey/new_key/before_configure.yml +48 -0
  64. data/spec/cassettes/Balanced_Hold.yml +335 -0
  65. data/spec/cassettes/Balanced_Hold/_void.yml +62 -0
  66. data/spec/cassettes/Balanced_Hold/_void/after.yml +62 -0
  67. data/spec/cassettes/Balanced_Hold/_void/when_exception_is_thrown.yml +306 -0
  68. data/spec/cassettes/Balanced_Marketplace.yml +339 -0
  69. data/spec/cassettes/Balanced_Transaction.yml +1261 -0
  70. data/spec/cassettes/Balanced_Transaction/Transaction.yml +634 -0
  71. data/spec/cassettes/Balanced_Transaction/Transaction_paginate.yml +634 -0
  72. data/spec/client_spec.rb +12 -0
  73. data/spec/spec_helper.rb +31 -0
  74. data/spec/utils_spec.rb +8 -0
  75. data/upload_docs.rb +39 -0
  76. data/x.rb +22 -0
  77. metadata +199 -0
@@ -0,0 +1 @@
1
+ Mahmoud Abdelkader
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source :rubygems
2
+
3
+ # Specify your gem's dependencies in balanced.gemspec
4
+
5
+ gem "faraday"
6
+ gem "faraday_middleware"
7
+
8
+ group :development do
9
+ gem "yard"
10
+ gem "ruby-debug19"
11
+ gem "guard", '~> 1.1.1'
12
+ gem "guard-rspec", '~> 1.0.0'
13
+ end
14
+
15
+ group :test do
16
+ gem "rspec", '~> 2.10'
17
+ gem "rake", '~> 0.9.2'
18
+ gem "vcr", '~> 2.2.0'
19
+ end
@@ -0,0 +1,64 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ archive-tar-minitar (0.5.2)
5
+ columnize (0.3.6)
6
+ diff-lcs (1.1.3)
7
+ faraday (0.8.0)
8
+ multipart-post (~> 1.1)
9
+ faraday_middleware (0.8.7)
10
+ faraday (>= 0.7.4, < 0.9)
11
+ ffi (1.0.11)
12
+ guard (1.1.1)
13
+ listen (>= 0.4.2)
14
+ thor (>= 0.14.6)
15
+ guard-rspec (1.0.1)
16
+ guard (>= 1.1)
17
+ linecache19 (0.5.12)
18
+ ruby_core_source (>= 0.1.4)
19
+ listen (0.4.6)
20
+ rb-fchange (~> 0.0.5)
21
+ rb-fsevent (~> 0.9.1)
22
+ rb-inotify (~> 0.8.8)
23
+ multipart-post (1.1.5)
24
+ rake (0.9.2.2)
25
+ rb-fchange (0.0.5)
26
+ ffi
27
+ rb-fsevent (0.9.1)
28
+ rb-inotify (0.8.8)
29
+ ffi (>= 0.5.0)
30
+ rspec (2.10.0)
31
+ rspec-core (~> 2.10.0)
32
+ rspec-expectations (~> 2.10.0)
33
+ rspec-mocks (~> 2.10.0)
34
+ rspec-core (2.10.0)
35
+ rspec-expectations (2.10.0)
36
+ diff-lcs (~> 1.1.3)
37
+ rspec-mocks (2.10.1)
38
+ ruby-debug-base19 (0.11.25)
39
+ columnize (>= 0.3.1)
40
+ linecache19 (>= 0.5.11)
41
+ ruby_core_source (>= 0.1.4)
42
+ ruby-debug19 (0.11.6)
43
+ columnize (>= 0.3.1)
44
+ linecache19 (>= 0.5.11)
45
+ ruby-debug-base19 (>= 0.11.19)
46
+ ruby_core_source (0.1.5)
47
+ archive-tar-minitar (>= 0.5.2)
48
+ thor (0.15.3)
49
+ vcr (2.2.2)
50
+ yard (0.8.2.1)
51
+
52
+ PLATFORMS
53
+ ruby
54
+
55
+ DEPENDENCIES
56
+ faraday
57
+ faraday_middleware
58
+ guard (~> 1.1.1)
59
+ guard-rspec (~> 1.0.0)
60
+ rake (~> 0.9.2)
61
+ rspec (~> 2.10)
62
+ ruby-debug19
63
+ vcr (~> 2.2.0)
64
+ yard
@@ -0,0 +1,7 @@
1
+ ignore %r{^doc}
2
+ guard 'rspec', :version => 2 do
3
+ watch(%r{^spec/.+_spec\.rb$})
4
+ watch(%r{^lib/balanced/(.+)\.rb$}) { |m| "spec/balanced/#{m[1]}_spec.rb" }
5
+ watch(%r{^lib/balanced/resources/(.+)\.rb$}) { |m| "spec/balanced/resources/#{m[1]}_spec.rb" }
6
+ watch('spec/spec_helper.rb') { "spec" }
7
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Mahmoud Abdelkader
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ # Balanced
2
+
3
+ Online Marketplace Payments
4
+
5
+ [![Build Status](https://secure.travis-ci.org/balanced/balanced-ruby.png)](http://travis-ci.org/balanced/balanced-ruby)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'balanced'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install balanced
20
+
21
+ ## Usage
22
+
23
+ See https://www.balancedpayments.com/docs/ruby for tutorials and documentation.
24
+
25
+
26
+ ## Contributing
27
+
28
+ 1. Fork it
29
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
30
+ 3. Write your code **and unit tests**
31
+ 4. Ensure all tests still pass (`bundle exec rspec`)
32
+ 5. Commit your changes (`git commit -am 'Add some feature'`)
33
+ 6. Push to the branch (`git push origin my-new-feature`)
34
+ 7. Create new pull request
35
+
36
+
37
+ ### Specs
38
+
39
+ The spec suite is a work in progress. Existing specs can either be run
40
+ using [guard](https://github.com/guard/guard) or rake.
41
+
42
+ Guard
43
+
44
+ $ bundle exec guard
45
+
46
+ Rake
47
+
48
+ $ rake spec
49
+
50
+ We use [VCR](https://www.relishapp.com/myronmarston/vcr/docs) to stub
51
+ out and save http interactions. Cassettes are not stored in the repo.
52
+ They are generated the first time the spec suite is run and stored in
53
+ spec/cassettes. To clear them and regenerate:
54
+
55
+ $ rm -rf spec/cassettes
56
+
57
+
58
+ ### Building Documentation
59
+
60
+ Documentation is build using YARD - http://rubydoc.info/docs/yard
61
+
62
+ export AMAZON_ACCESS_KEY_ID='xxx'
63
+ export AMAZON_SECRET_ACCESS_KEY='yyy'
64
+ ./upload_docs.rb
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "rake"
3
+ require "rspec/core/rake_task"
4
+ require "bundler/gem_tasks"
5
+
6
+ desc "Run spec suite"
7
+ RSpec::Core::RakeTask.new(:spec) { |t| }
8
+
9
+ desc "Default the task to run the spec"
10
+ task :default => [:spec]
11
+
12
+
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env gem build
2
+ # -*- encoding: utf-8 -*-
3
+ require "base64"
4
+ require File.expand_path('../lib/balanced/version', __FILE__)
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.authors = ["Mahmoud Abdelkader"]
8
+ gem.email = ["bWFobW91ZEBwb3VuZHBheS5jb20="].map { |i| Base64.decode64(i) }
9
+ gem.description = %q{Balanced ACH experimental API}
10
+ gem.summary = %q{Sign up on https://balancedpayments.com/}
11
+ gem.homepage = "https://balancedpayments.com"
12
+
13
+ gem.add_dependency("faraday", '~> 0.8')
14
+ gem.add_dependency("faraday_middleware", '~> 0.8.7')
15
+
16
+ gem.files = `git ls-files`.split($\)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.name = "balanced-ach"
20
+ gem.require_paths = %w(lib)
21
+ gem.version = Balanced::VERSION
22
+ end
@@ -0,0 +1,84 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "balanced", "resources")
2
+ $:.unshift File.join(File.dirname(__FILE__), "balanced", "response")
3
+
4
+ require 'uri'
5
+ require 'balanced/version' unless defined? Balanced::VERSION
6
+ require 'balanced/client'
7
+ require 'balanced/utils'
8
+ require 'balanced/resources'
9
+ require 'balanced/error'
10
+
11
+ module Balanced
12
+
13
+ @client = nil
14
+ @config = {
15
+ :scheme => 'https',
16
+ :host => 'x.balancedpayments.com',
17
+ :port => 443,
18
+ :version => 'a0',
19
+ }
20
+
21
+ class << self
22
+
23
+ attr_accessor :client
24
+ attr_accessor :config
25
+
26
+ def configure(api_key=nil, options={})
27
+ @client = Balanced::Client.new(api_key, @config.merge(options))
28
+ end
29
+
30
+ def is_configured_with_api_key?
31
+ !@client.api_key.nil?
32
+ end
33
+
34
+ def split_the_uri uri
35
+ URI.parse(uri).path.sub(/\/$/, '').split('/')
36
+ end
37
+
38
+ def from_uri uri
39
+ split_uri = split_the_uri(uri)
40
+ # this is such an ugly hack, basically, we're trying to
41
+ # see if we have the symbol that matches the capitalized
42
+ #
43
+ class_name = Balanced::Utils.classify(split_uri[-1])
44
+ begin
45
+ klass = Balanced.const_get class_name
46
+ rescue NameError
47
+ class_name = Utils.classify(split_uri[-2])
48
+ klass = Balanced.const_get(class_name)
49
+ end
50
+ klass
51
+ end
52
+
53
+ def is_collection uri
54
+ split_uri = split_the_uri(uri)
55
+ class_name = Balanced::Utils.classify(split_uri[-1])
56
+ begin
57
+ Balanced.const_get class_name
58
+ rescue NameError
59
+ return false
60
+ end
61
+ true
62
+ end
63
+
64
+ def get(*args, &block)
65
+ self.client.get *args
66
+ end
67
+
68
+ def post(*args, &block)
69
+ self.client.post *args
70
+ end
71
+
72
+ def put(*args, &block)
73
+ self.client.put *args
74
+ end
75
+
76
+ def delete(*args, &block)
77
+ self.client.delete *args
78
+ end
79
+ end
80
+
81
+ # configure on import so we don't have to configure for creating
82
+ # an api key
83
+ configure
84
+ end
@@ -0,0 +1,82 @@
1
+ require "logger"
2
+ require "uri"
3
+ require "faraday"
4
+ require "faraday_middleware"
5
+ require "balanced_exception_middleware"
6
+
7
+
8
+ module Balanced
9
+ class Client
10
+
11
+ DEFAULTS = {
12
+ :scheme => 'http',
13
+ :host => 'localhost',
14
+ :port => 5000,
15
+ :version => 'v1',
16
+ :logging_level => 'WARN',
17
+ :connection_timeout => 2,
18
+ :read_timeout => 5,
19
+ :logger => nil
20
+ }
21
+
22
+ attr_reader :conn
23
+ attr_accessor :api_key, :config
24
+
25
+ def initialize(api_key, options={})
26
+ @api_key = api_key.nil? ? api_key : api_key.strip
27
+ @config = DEFAULTS.merge options
28
+ build_conn
29
+ end
30
+
31
+ def build_conn
32
+ if config[:logger]
33
+ logger = config[:logger]
34
+ else
35
+ logger = Logger.new(STDOUT)
36
+ logger.level = Logger.const_get(config[:logging_level].to_s)
37
+ end
38
+
39
+ Faraday.register_middleware :response,
40
+ :handle_balanced_errors => lambda {Faraday::Response::RaiseBalancedError}
41
+
42
+ options = {
43
+ :request => {
44
+ :open_timeout => config[:connection_timeout],
45
+ :timeout => config[:read_timeout]
46
+ }
47
+ }
48
+ @conn = Faraday.new(url, options) do |cxn|
49
+ cxn.request :json
50
+
51
+ cxn.response :logger, logger
52
+ cxn.response :handle_balanced_errors
53
+ cxn.response :json
54
+ # cxn.response :raise_error # raise exceptions on 40x, 50x responses
55
+ cxn.adapter Faraday.default_adapter
56
+ end
57
+ conn.path_prefix = '/'
58
+ conn.headers['User-Agent'] = "balanced-ach-ruby/#{Balanced::VERSION}"
59
+ end
60
+
61
+ #def inspect # :nodoc:
62
+ #"<Balanced::Client @api_key=#{api_key}, @url=#{url}>"
63
+ #end
64
+
65
+ def url
66
+ URI::HTTP.build :host => config[:host], :port => config[:port]
67
+ end
68
+
69
+ private
70
+
71
+ def method_missing(method, *args, &block)
72
+ case method
73
+ when :get, :post, :put, :delete
74
+ conn.basic_auth(api_key, '') unless api_key.nil?
75
+ conn.send method, *args
76
+ else
77
+ super
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,85 @@
1
+ module Balanced
2
+
3
+ # Custom error class for rescuing from all Balanced errors
4
+ class Error < StandardError
5
+ attr_reader :response
6
+
7
+ def initialize(response)
8
+ @response = response
9
+ super error_message
10
+ end
11
+
12
+ def body
13
+ Utils.hash_with_indifferent_read_access response[:body]
14
+ end
15
+
16
+ def error_message
17
+ set_attrs
18
+ extra = body[:additional] ? " -- #{body[:additional]}" : ""
19
+ "#{self.class.name}(#{response[:status]})::#{body[:status]}:: "\
20
+ "#{response[:method].to_s.upcase} #{response[:url].to_s}: "\
21
+ "#{body[:category_code]}: #{body[:description]} #{extra}"
22
+ end
23
+
24
+ private
25
+ def set_attrs
26
+ body.keys.each do |name|
27
+ self.class.instance_eval {
28
+ define_method(name) { body[name] } # Get.
29
+ define_method("#{name}?") { !!body[name].nil? } # Present.
30
+ }
31
+ end
32
+ end
33
+ end
34
+
35
+ class MoreInformationRequired < Error
36
+ def redirect_uri
37
+ response.headers['Location']
38
+ end
39
+
40
+ def error_message
41
+ set_attrs
42
+ "#{self.class.name} :: #{response[:method].to_s.upcase} #{response[:url].to_s}: "\
43
+ "#{response[:status]}: \n#{body[:friendly_html]}"
44
+ end
45
+ end
46
+
47
+ # Raised when Balanced returns a 400 HTTP status code
48
+ class BadRequest < Error; end
49
+
50
+ # Raised when Balanced returns a 401 HTTP status code
51
+ class Unauthorized < Error; end
52
+
53
+ # Raised when Balanced returns a 402 HTTP status code
54
+ class PaymentRequired < Error; end
55
+
56
+ # Raised when Balanced returns a 403 HTTP status code
57
+ class Forbidden < Error; end
58
+
59
+ # Raised when Balanced returns a 404 HTTP status code
60
+ class NotFound < Error; end
61
+
62
+ # Raised when Balanced returns a 405 HTTP status code
63
+ class MethodNotAllowed < Error; end
64
+
65
+ # Raised when Balanced returns a 409 HTTP status code
66
+ class Conflict < Error; end
67
+
68
+ # Raised when Balanced returns a 410 HTTP status code
69
+ class Gone < Error; end
70
+
71
+ # Raised when Balanced returns a 500 HTTP status code
72
+ class InternalServerError < Error; end
73
+
74
+ # Raised when Balanced returns a 501 HTTP status code
75
+ class NotImplemented < Error; end
76
+
77
+ # Raised when Balanced returns a 502 HTTP status code
78
+ class BadGateway < Error; end
79
+
80
+ # Raised when Balanced returns a 503 HTTP status code
81
+ class ServiceUnavailable < Error; end
82
+
83
+ # Raised when Balanced returns a 504 HTTP status code
84
+ class GatewayTimeout < Error; end
85
+ end