balanced 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,3 +1,6 @@
1
1
  language: ruby
2
+ bundler_args: --without development
3
+ script: "bundle exec rake spec"
2
4
  rvm:
5
+ - 1.9.2
3
6
  - 1.9.3
data/Gemfile CHANGED
@@ -1,7 +1,19 @@
1
- source 'https://rubygems.org'
2
-
1
+ source :rubygems
3
2
 
4
3
  # Specify your gem's dependencies in balanced.gemspec
5
- gemspec
6
4
 
7
- gem 'rspec'
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
data/Rakefile CHANGED
@@ -3,8 +3,10 @@ require "rake"
3
3
  require "rspec/core/rake_task"
4
4
  require "bundler/gem_tasks"
5
5
 
6
- RSpec::Core::RakeTask.new
6
+ desc "Run spec suite"
7
+ RSpec::Core::RakeTask.new(:spec) { |t| }
7
8
 
9
+ desc "Default the task to run the spec"
8
10
  task :default => [:spec]
9
11
 
10
12
 
data/balanced.gemspec CHANGED
@@ -1,9 +1,11 @@
1
+ #!/usr/bin/env gem build
1
2
  # -*- encoding: utf-8 -*-
3
+ require "base64"
2
4
  require File.expand_path('../lib/balanced/version', __FILE__)
3
5
 
4
6
  Gem::Specification.new do |gem|
5
7
  gem.authors = ["Mahmoud Abdelkader"]
6
- gem.email = %w(mahmoud@poundpay.com)
8
+ gem.email = ["bWFobW91ZEBwb3VuZHBheS5jb20="].map { |i| Base64.decode64(i) }
7
9
  gem.description = %q{Balanced is the payments platform for marketplaces.
8
10
  Integrate a payments experience just like Amazon for your marketplace.
9
11
  Forget about dealing with banking systems, compliance, fraud, and security.
@@ -14,17 +16,10 @@ Gem::Specification.new do |gem|
14
16
  gem.add_dependency("faraday", '~> 0.8')
15
17
  gem.add_dependency("faraday_middleware", '~> 0.8.7')
16
18
 
17
- gem.add_development_dependency("rspec", '~> 2.10')
18
- gem.add_development_dependency("vcr", '~> 2.2.0')
19
- gem.add_development_dependency("guard", '~> 1.1.1')
20
- gem.add_development_dependency("guard-rspec", '~> 1.0.0')
21
- gem.add_development_dependency("yard")
22
- gem.add_development_dependency("ruby-debug19")
23
-
24
19
  gem.files = `git ls-files`.split($\)
25
20
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
26
21
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
27
22
  gem.name = "balanced"
28
23
  gem.require_paths = %w(lib)
29
24
  gem.version = Balanced::VERSION
30
- end
25
+ end
data/examples/examples.rb CHANGED
@@ -116,5 +116,3 @@ bank_account['is_valid'] = false
116
116
  bank_account.save
117
117
 
118
118
  raise "This card is INCORRECTLY VALID" if bank_account.is_valid
119
-
120
- puts "and there you have it :)"
@@ -1,7 +1,9 @@
1
- require 'logger'
1
+ require "logger"
2
2
  require "uri"
3
3
  require "faraday"
4
4
  require "faraday_middleware"
5
+ require "balanced_exception_middleware"
6
+
5
7
 
6
8
  module Balanced
7
9
  class Client
@@ -27,12 +29,16 @@ module Balanced
27
29
  logger = Logger.new(STDOUT)
28
30
  logger.level = Logger.const_get(DEFAULTS[:logging_level].to_s)
29
31
 
32
+ Faraday.register_middleware :response,
33
+ :handle_balanced_errors => lambda {Faraday::Response::RaiseBalancedError}
34
+
30
35
  @conn = Faraday.new url do |cxn|
31
36
  cxn.request :json
32
37
 
33
38
  cxn.response :logger, logger
39
+ cxn.response :handle_balanced_errors
34
40
  cxn.response :json
35
- cxn.response :raise_error # raise exceptions on 40x, 50x responses
41
+ # cxn.response :raise_error # raise exceptions on 40x, 50x responses
36
42
  cxn.adapter Faraday.default_adapter
37
43
  end
38
44
  conn.path_prefix = '/'
@@ -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
@@ -7,18 +7,6 @@ module Balanced
7
7
  class Account
8
8
  include Balanced::Resource
9
9
 
10
- class MoreInformationRequiredError < StandardError
11
- attr_reader :response
12
-
13
- def initialize(response)
14
- @response = response
15
- end
16
-
17
- def redirect_uri
18
- response.headers['Location']
19
- end
20
- end
21
-
22
10
  def initialize attributes = {}
23
11
  Balanced::Utils.stringify_keys! attributes
24
12
  unless attributes.has_key? 'uri'
@@ -27,6 +15,17 @@ module Balanced
27
15
  super attributes
28
16
  end
29
17
 
18
+ # Attempts to find an existing buyer account by email
19
+ #
20
+ # @param [String] email An email of a buyer account
21
+ # @return [Account] if buyer is found
22
+ # @return [nil] if buyer is not found
23
+ def self.find_by_email email
24
+ response = Balanced.get Balanced::Marketplace.my_marketplace.accounts_uri, {email_address: email}
25
+ record = response.body["items"].first
26
+ construct_from_response(record) unless record.nil?
27
+ end
28
+
30
29
  def save
31
30
  the_response = super
32
31
  if response.status == 300
@@ -0,0 +1,33 @@
1
+ require 'faraday'
2
+ require 'balanced/error'
3
+
4
+ # @api private
5
+ module Faraday
6
+
7
+ class Response::RaiseBalancedError < Response::Middleware
8
+
9
+ HTTP_STATUS_CODES = {
10
+ 300 => Balanced::MoreInformationRequired,
11
+ 400 => Balanced::BadRequest,
12
+ 401 => Balanced::Unauthorized,
13
+ 402 => Balanced::PaymentRequired,
14
+ 403 => Balanced::Forbidden,
15
+ 404 => Balanced::NotFound,
16
+ 405 => Balanced::MethodNotAllowed,
17
+ 409 => Balanced::Conflict,
18
+ 410 => Balanced::Gone,
19
+ 500 => Balanced::InternalServerError,
20
+ 501 => Balanced::NotImplemented,
21
+ 502 => Balanced::BadGateway,
22
+ 503 => Balanced::ServiceUnavailable,
23
+ 504 => Balanced::GatewayTimeout,
24
+ }
25
+ def on_complete(response)
26
+ status_code = response[:status].to_i
27
+ error_class = HTTP_STATUS_CODES[status_code]
28
+ raise error_class.new(response) if error_class
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -31,8 +31,15 @@ module Balanced
31
31
  end
32
32
 
33
33
  def hash_with_indifferent_read_access base = {}
34
- indifferent = Hash.new { |hash, key| hash[key.to_s] if key.is_a? Symbol }
35
- base.each_pair { |key, value| indifferent[key.to_s] = value }
34
+ indifferent = Hash.new do |hash, key|
35
+ hash[key.to_s] if key.is_a? Symbol
36
+ end
37
+ base.each_pair do |key, value|
38
+ if value.is_a? Hash
39
+ value = hash_with_indifferent_read_access value
40
+ end
41
+ indifferent[key.to_s] = value
42
+ end
36
43
  indifferent
37
44
  end
38
45
 
@@ -1,3 +1,3 @@
1
1
  module Balanced
2
- VERSION = '0.3.3'
2
+ VERSION = '0.3.4'
3
3
  end
data/lib/balanced.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "balanced", "resources")
2
+ $:.unshift File.join(File.dirname(__FILE__), "balanced", "response")
2
3
 
3
4
  require 'uri'
4
5
  require 'balanced/version' unless defined? Balanced::VERSION
5
6
  require 'balanced/client'
6
7
  require 'balanced/utils'
7
8
  require 'balanced/resources'
9
+ require 'balanced/error'
8
10
 
9
11
  module Balanced
10
12
 
@@ -419,4 +419,36 @@ describe Balanced::Account do
419
419
 
420
420
  end
421
421
  end
422
+
423
+ describe ".find_by_email" do
424
+ use_vcr_cassette
425
+ before do
426
+ api_key = Balanced::ApiKey.new.save
427
+ Balanced.configure api_key.secret
428
+ @marketplace = Balanced::Marketplace.new.save
429
+ card = Balanced::Card.new(
430
+ :card_number => "5105105105105100",
431
+ :expiration_month => "12",
432
+ :expiration_year => "2015",
433
+ ).save
434
+ buyer = Balanced::Marketplace.my_marketplace.create_buyer(
435
+ "john.doe@example.com",
436
+ card.uri
437
+ )
438
+ end
439
+
440
+ context "email address is in system" do
441
+ use_vcr_cassette
442
+ it "should return account object" do
443
+ Balanced::Account.find_by_email("john.doe@example.com").should be_instance_of Balanced::Account
444
+ end
445
+ end
446
+
447
+ context "email address does not exist" do
448
+ use_vcr_cassette
449
+ it "should return nil" do
450
+ Balanced::Account.find_by_email("foo@bar.com").should be_nil
451
+ end
452
+ end
453
+ end
422
454
  end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+ require "faraday"
3
+
4
+ describe Faraday::Response::RaiseBalancedError, :type => :response do
5
+ context "when used" do
6
+ let(:raise_server_error) { described_class.new }
7
+ end
8
+
9
+ context "integration test" do
10
+
11
+ before(:each) do
12
+ Faraday.register_middleware :response,
13
+ :handle_balanced_errors => lambda { described_class }
14
+ VCR.turn_off!
15
+ end
16
+
17
+ after(:each) do
18
+ VCR.turn_on!
19
+ end
20
+
21
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
22
+ let(:connection) do
23
+ Faraday::Connection.new do |builder|
24
+ builder.response :handle_balanced_errors
25
+ builder.response :json
26
+ builder.adapter :test, stubs
27
+ end
28
+ end
29
+
30
+ it "should raise exceptions on bad request errors" do
31
+ stubs.get("/error") {
32
+ [400, {}, JSON.dump({
33
+ :status =>"Bad Request",
34
+ :status_code =>400,
35
+ :description => "Missing expected field expiration_year Your request "\
36
+ "id is OHM62bf258abfea11e1aaba026ba7e5e72e.",
37
+ :request_id => "OHM62bf258abfea11e1aaba026ba7e5e72e"
38
+ })]
39
+ }
40
+
41
+ lambda {
42
+ connection.get('/error')
43
+ }.should raise_error(Balanced::BadRequest)
44
+ end
45
+
46
+ end
47
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,15 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
- require 'ruby-debug'
4
3
  require 'balanced'
5
4
  require 'vcr'
6
5
 
6
+ begin
7
+ require 'ruby-debug'
8
+ rescue LoadError
9
+ # ignored
10
+ end
11
+
12
+
7
13
  VCR.configure do |c|
8
14
  c.cassette_library_dir = 'spec/cassettes'
9
15
  c.hook_into :faraday
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: balanced
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-21 00:00:00.000000000 Z
12
+ date: 2012-06-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -43,102 +43,6 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: 0.8.7
46
- - !ruby/object:Gem::Dependency
47
- name: rspec
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ~>
52
- - !ruby/object:Gem::Version
53
- version: '2.10'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '2.10'
62
- - !ruby/object:Gem::Dependency
63
- name: vcr
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ~>
68
- - !ruby/object:Gem::Version
69
- version: 2.2.0
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- version: 2.2.0
78
- - !ruby/object:Gem::Dependency
79
- name: guard
80
- requirement: !ruby/object:Gem::Requirement
81
- none: false
82
- requirements:
83
- - - ~>
84
- - !ruby/object:Gem::Version
85
- version: 1.1.1
86
- type: :development
87
- prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ~>
92
- - !ruby/object:Gem::Version
93
- version: 1.1.1
94
- - !ruby/object:Gem::Dependency
95
- name: guard-rspec
96
- requirement: !ruby/object:Gem::Requirement
97
- none: false
98
- requirements:
99
- - - ~>
100
- - !ruby/object:Gem::Version
101
- version: 1.0.0
102
- type: :development
103
- prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
107
- - - ~>
108
- - !ruby/object:Gem::Version
109
- version: 1.0.0
110
- - !ruby/object:Gem::Dependency
111
- name: yard
112
- requirement: !ruby/object:Gem::Requirement
113
- none: false
114
- requirements:
115
- - - ! '>='
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
- requirements:
123
- - - ! '>='
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: ruby-debug19
128
- requirement: !ruby/object:Gem::Requirement
129
- none: false
130
- requirements:
131
- - - ! '>='
132
- - !ruby/object:Gem::Version
133
- version: '0'
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
139
- - - ! '>='
140
- - !ruby/object:Gem::Version
141
- version: '0'
142
46
  description: ! "Balanced is the payments platform for marketplaces.\n Integrate
143
47
  a payments experience just like Amazon for your marketplace.\n Forget about dealing
144
48
  with banking systems, compliance, fraud, and security.\n "
@@ -172,6 +76,7 @@ files:
172
76
  - examples/examples.rb
173
77
  - lib/balanced.rb
174
78
  - lib/balanced/client.rb
79
+ - lib/balanced/error.rb
175
80
  - lib/balanced/resources.rb
176
81
  - lib/balanced/resources/account.rb
177
82
  - lib/balanced/resources/api_key.rb
@@ -185,12 +90,14 @@ files:
185
90
  - lib/balanced/resources/refund.rb
186
91
  - lib/balanced/resources/resource.rb
187
92
  - lib/balanced/resources/transaction.rb
93
+ - lib/balanced/response/balanced_exception_middleware.rb
188
94
  - lib/balanced/utils.rb
189
95
  - lib/balanced/version.rb
190
96
  - spec/balanced/resources/account_spec.rb
191
97
  - spec/balanced/resources/api_key_spec.rb
192
98
  - spec/balanced/resources/hold_spec.rb
193
99
  - spec/balanced/resources/marketplace_spec.rb
100
+ - spec/balanced/response/balanced_exception_middleware_spec.rb
194
101
  - spec/balanced_spec.rb
195
102
  - spec/client_spec.rb
196
103
  - spec/spec_helper.rb
@@ -225,7 +132,9 @@ test_files:
225
132
  - spec/balanced/resources/api_key_spec.rb
226
133
  - spec/balanced/resources/hold_spec.rb
227
134
  - spec/balanced/resources/marketplace_spec.rb
135
+ - spec/balanced/response/balanced_exception_middleware_spec.rb
228
136
  - spec/balanced_spec.rb
229
137
  - spec/client_spec.rb
230
138
  - spec/spec_helper.rb
231
139
  - spec/utils_spec.rb
140
+ has_rdoc: