callcredit 0.3.8 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1213865aa7687c9adfd222ffeed8c2e1e6a76ccd
4
- data.tar.gz: 2e1265299afc2b3198eb4c1c0c07da6e809dd6fe
3
+ metadata.gz: a36f71d745577cbb7014548b3bfb274aaf08daec
4
+ data.tar.gz: 54086f749c30f37c3055298450d4ec4988f5f1e2
5
5
  SHA512:
6
- metadata.gz: 88f56e2dce84202fdaed7891de549f8e6c4d89400c6c6b1718efe717fc50368f7ef990ccd9a066ff5568f69388db2a6e9020e38b0e06f732bc1d4cb0581f4259
7
- data.tar.gz: 321382da4b9e994eeb5c702c166ff78a8372e5bfb3d640b17a6d8dc596339427c1d507354f87e437bf0945b6021ea5f9cd53887762a2faf4e0bbd8f90e2ba80f
6
+ metadata.gz: adf512665d1906b25a37cb658b39875d680360a6465f9e7f256e4a7e6f6ec568ed2d7841734c0874db2ba355f3330f866aa7facdcb856382e08f6d291c9e535b
7
+ data.tar.gz: 8a597828c0501da6782c48813f59abaddf82f66da96d2897059fef7a640ebf01cb7354389f43feb1a1b5784d512e92466a50861ac2cd07ddde199a00f938f9f3
@@ -0,0 +1,41 @@
1
+ # For all options see https://github.com/bbatsov/rubocop/tree/master/config
2
+
3
+ inherit_from: .rubocop_todo.yml
4
+
5
+ AllCops:
6
+ Exclude:
7
+ - bin/*
8
+
9
+ LineLength:
10
+ Max: 80
11
+
12
+ ClassLength:
13
+ Enabled: false
14
+
15
+ # Avoid methods longer than 30 lines of code
16
+ MethodLength:
17
+ CountComments: false # count full line comments?
18
+ Max: 87
19
+
20
+ # Avoid single-line methods.
21
+ SingleLineMethods:
22
+ AllowIfMethodIsEmpty: true
23
+
24
+ StringLiterals:
25
+ Enabled: false
26
+
27
+ GlobalVars:
28
+ Enabled: false
29
+
30
+ # Wants underscores in all large numbers. Pain in the ass for things like
31
+ # unix timestamps.
32
+ NumericLiterals:
33
+ Enabled: false
34
+
35
+ # Wants you to use the same argument names for every reduce. This seems kinda
36
+ # naff compared to naming them semantically
37
+ SingleLineBlockParams:
38
+ Enabled: false
39
+
40
+ Style/SignalException:
41
+ EnforcedStyle: 'only_raise'
@@ -0,0 +1,154 @@
1
+ # This configuration was generated by `rubocop --auto-gen-config`
2
+ # on 2014-10-30 22:45:17 +0000 using RuboCop version 0.27.0.
3
+ # The point is for the user to remove these configuration records
4
+ # one by one as the offenses are removed from the code base.
5
+ # Note that changes in the inspected code, or installation of new
6
+ # versions of RuboCop, may require this file to be generated again.
7
+
8
+ # Offense count: 27
9
+ # Cop supports --auto-correct.
10
+ Lint/UnusedBlockArgument:
11
+ Enabled: false
12
+
13
+ # Offense count: 128
14
+ Metrics/AbcSize:
15
+ Max: 64
16
+
17
+ # Offense count: 9
18
+ Metrics/CyclomaticComplexity:
19
+ Max: 10
20
+
21
+ # Offense count: 5
22
+ Metrics/PerceivedComplexity:
23
+ Max: 10
24
+
25
+ # Offense count: 17
26
+ Style/AccessorMethodName:
27
+ Enabled: false
28
+
29
+ # Offense count: 64
30
+ # Cop supports --auto-correct.
31
+ # Configuration parameters: EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle, SupportedLastArgumentHashStyles.
32
+ Style/AlignHash:
33
+ Enabled: false
34
+
35
+ # Offense count: 72
36
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
37
+ Style/ClassAndModuleChildren:
38
+ Enabled: false
39
+
40
+ # Offense count: 16
41
+ # Configuration parameters: Keywords.
42
+ Style/CommentAnnotation:
43
+ Enabled: false
44
+
45
+ # Offense count: 336
46
+ Style/Documentation:
47
+ Enabled: false
48
+
49
+ # Offense count: 1285
50
+ # Cop supports --auto-correct.
51
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
52
+ Style/DotPosition:
53
+ Enabled: false
54
+
55
+ # Offense count: 6
56
+ Style/DoubleNegation:
57
+ Enabled: false
58
+
59
+ # Offense count: 11
60
+ Style/EachWithObject:
61
+ Enabled: false
62
+
63
+ # Offense count: 92
64
+ # Configuration parameters: MinBodyLength.
65
+ Style/GuardClause:
66
+ Enabled: false
67
+
68
+ # Offense count: 24
69
+ # Cop supports --auto-correct.
70
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
71
+ Style/IndentHash:
72
+ Enabled: false
73
+
74
+ # Offense count: 60
75
+ Style/Lambda:
76
+ Enabled: false
77
+
78
+ # Offense count: 141
79
+ # Cop supports --auto-correct.
80
+ Style/LineEndConcatenation:
81
+ Enabled: false
82
+
83
+ # Offense count: 3
84
+ # Cop supports --auto-correct.
85
+ Style/MethodCallParentheses:
86
+ Enabled: false
87
+
88
+ Style/ModuleFunction:
89
+ Enabled: false
90
+
91
+ # Offense count: 449
92
+ # Cop supports --auto-correct.
93
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
94
+ Style/MultilineOperationIndentation:
95
+ Enabled: false
96
+
97
+ # Offense count: 4
98
+ # Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
99
+ Style/Next:
100
+ Enabled: false
101
+
102
+ # Offense count: 11
103
+ # Configuration parameters: NamePrefix, NamePrefixBlacklist.
104
+ Style/PredicateName:
105
+ Enabled: false
106
+
107
+ # Offense count: 5
108
+ # Cop supports --auto-correct.
109
+ Style/Proc:
110
+ Enabled: false
111
+
112
+ # Offense count: 9
113
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
114
+ Style/RaiseArgs:
115
+ Enabled: false
116
+
117
+ # Offense count: 5
118
+ # Cop supports --auto-correct.
119
+ # Configuration parameters: AllowMultipleReturnValues.
120
+ Style/RedundantReturn:
121
+ Enabled: false
122
+
123
+ # Offense count: 177
124
+ # Cop supports --auto-correct.
125
+ Style/RedundantSelf:
126
+ Enabled: false
127
+
128
+ # Offense count: 17
129
+ # Cop supports --auto-correct.
130
+ Style/SingleSpaceBeforeFirstArg:
131
+ Enabled: false
132
+
133
+ # Offense count: 87
134
+ # Cop supports --auto-correct.
135
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
136
+ Style/StringLiteralsInInterpolation:
137
+ Enabled: false
138
+
139
+ # Offense count: 53
140
+ # Cop supports --auto-correct.
141
+ # Configuration parameters: EnforcedStyleForMultiline, SupportedStyles.
142
+ Style/TrailingComma:
143
+ Enabled: false
144
+
145
+ # Offense count: 8
146
+ # Cop supports --auto-correct.
147
+ # Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, Whitelist.
148
+ Style/TrivialAccessors:
149
+ Enabled: false
150
+
151
+ # Offense count: 1
152
+ # Cop supports --auto-correct.
153
+ Style/WhileUntilDo:
154
+ Enabled: false
@@ -1,6 +1,13 @@
1
+ ## 0.4.0 - December 31, 2014
2
+
3
+ - Add support for BankStandard and BankEnhanced checks
4
+ - Tweak `Callcredit::Response#result` to support multiple kinds of check (i.e. not just
5
+ identity checks)
6
+ - Enforce code style with Rubocop
7
+
1
8
  ## 0.3.8 - July 16, 2014
2
9
 
3
- - Include requiest ID (RID) on all requests
10
+ - Include request ID (RID) on all requests
4
11
 
5
12
  ## 0.3.7 - June 3, 2014
6
13
 
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Grey Baker
1
+ Copyright (c) 2014 GoCardless
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person
4
4
  obtaining a copy of this software and associated documentation
data/README.md CHANGED
@@ -45,7 +45,30 @@ The library will raise an error if you're missing any of the required
45
45
  parameters (first_name, last_name, date_of_birth, building_number and
46
46
  postcode).
47
47
 
48
+ #### BankStandard check
49
+
50
+ To perform a BankStandard check use:
51
+
52
+ ```ruby
53
+ Callcredit.bank_standard_check(account_number: "44779911", sort_code: "200000")
54
+ ```
55
+
56
+ The library will raise an error unless you provide both account_number and sort_code.
57
+
58
+ #### BankEnhanced check
59
+
60
+ To perform a BankEnhanced check use:
61
+
62
+ ```ruby
63
+ Callcredit.bank_enhanced_check(first_name: "Tim", last_name: "Rogers", postcode: "EC1V 7LQ", account_number: "44779911", sort_code: "200000", building_number: "338-346")
64
+ ```
65
+
66
+ The library will raise an error if you're missing any of the required
67
+ parameters (first_name, last_name, building_number, postcode, account_number
68
+ and sort_code).
69
+
48
70
  #### Other checks
71
+
49
72
  For any other check, simply pass the name of the check you'd like to perform
50
73
  into the `perform_check` method, along with details of the individual you're
51
74
  checking.
@@ -63,11 +86,6 @@ data_hash = { personal_data: { first_name: "Grey", last_name: "Baker" } }
63
86
  Callcredit.perform_check([:id_enhanced, :credit_score], data_hash)
64
87
  ```
65
88
 
66
- NOTE: Currently, this gem only supports checks on the payer's personal
67
- information (other information won't be passed through to Callcredit).
68
- Extending the gem should be trivial if Callcredit have given you access to
69
- other checks.
70
-
71
89
  ### Parsing responses
72
90
 
73
91
  Unless you've set the "raw" argument to true in your config, checks called by
@@ -80,7 +98,8 @@ Callcredit.id_enhanced_check(...) # => Callcredit::Response
80
98
  Callcredit.id_enhanced_check(...).input # => Hash of input params, as
81
99
  # returned by Callcredit
82
100
 
83
- Callcredit.id_enhanced_check(...).result # => Hash of results
101
+ Callcredit.id_enhanced_check(...).result # => Hash of results, mapping
102
+ # a check type to its results
84
103
 
85
104
  Callcredit.id_enhanced_check(...).full_result # => Hash of the full XML body
86
105
  # returned by Callcredit
@@ -10,13 +10,13 @@ Gem::Specification.new do |gem|
10
10
  gem.add_development_dependency 'webmock', '~> 1.18.0'
11
11
 
12
12
  gem.authors = ['Grey Baker']
13
- gem.description = %q{Ruby wrapper for Callcredit's CallValidate API}
13
+ gem.description = "Ruby wrapper for Callcredit's CallValidate API"
14
14
  gem.email = ['grey@gocardless.com']
15
15
  gem.files = `git ls-files`.split("\n")
16
16
  gem.homepage = 'https://github.com/gocardless/callcredit-ruby'
17
17
  gem.name = 'callcredit'
18
18
  gem.require_paths = ['lib']
19
- gem.summary = %q{Ruby wrapper for Callcredit's CallValidate API}
19
+ gem.summary = "Ruby wrapper for Callcredit's CallValidate API"
20
20
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
21
  gem.version = Callcredit::VERSION.dup
22
22
  end
@@ -11,6 +11,8 @@ require 'callcredit/validations'
11
11
  require 'callcredit/client'
12
12
  require 'callcredit/response'
13
13
  require 'callcredit/checks/id_enhanced'
14
+ require 'callcredit/checks/bank_standard'
15
+ require 'callcredit/checks/bank_enhanced'
14
16
  require 'callcredit/middleware/check_response'
15
17
 
16
18
  # Errors
@@ -28,6 +30,14 @@ module Callcredit
28
30
  client.id_enhanced_check(*args)
29
31
  end
30
32
 
33
+ def self.bank_standard_check(*args)
34
+ client.bank_standard_check(*args)
35
+ end
36
+
37
+ def self.bank_enhanced_check(*args)
38
+ client.bank_enhanced_check(*args)
39
+ end
40
+
31
41
  def self.perform_check(*args)
32
42
  client.perform_check(*args)
33
43
  end
@@ -49,4 +59,3 @@ module Callcredit
49
59
  end
50
60
  private_class_method :client
51
61
  end
52
-
@@ -0,0 +1,49 @@
1
+ module Callcredit
2
+ module Checks
3
+ class BankEnhanced
4
+ REQUIRED_INPUTS = [:first_name, :last_name, :postcode, :account_number,
5
+ :sort_code, :account_number, :sort_code]
6
+
7
+ PERSONAL_DATA_KEYS = [:first_name, :last_name, :postcode,
8
+ :building_name, :building_number]
9
+
10
+ BANK_DATA_KEYS = [:account_number, :sort_code]
11
+
12
+ def initialize(client)
13
+ @client = client
14
+ end
15
+
16
+ def perform(data = {})
17
+ check_params(data)
18
+ response = @client.perform_check([:bank_standard, :bank_enhanced],
19
+ build_params(data))
20
+
21
+ @client.config[:raw] ? response : Response.new(response)
22
+ end
23
+
24
+ private
25
+
26
+ def build_params(data)
27
+ {
28
+ personal_data: data.select { |k, v| PERSONAL_DATA_KEYS.include?(k) },
29
+ bank_data: data.select { |k, v| BANK_DATA_KEYS.include?(k) }
30
+ }
31
+ end
32
+
33
+ def check_params(data)
34
+ REQUIRED_INPUTS.each do |param|
35
+ if data[param].nil?
36
+ msg = "An BankEnhanced check requires a #{param}"
37
+ raise InvalidRequestError.new(msg, param)
38
+ end
39
+ end
40
+
41
+ # For a BankEnhanced check, we also need a building name or number
42
+ unless data[:building_number] || data[:building_name]
43
+ msg = "A BankEnhanced check requires a building number or name"
44
+ raise InvalidRequestError.new(msg, :building_number)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,28 @@
1
+ module Callcredit
2
+ module Checks
3
+ class BankStandard
4
+ REQUIRED_INPUTS = [:account_number, :sort_code]
5
+
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def perform(data = {})
11
+ check_params(data)
12
+ response = @client.perform_check(:bank_standard, bank_data: data)
13
+ @client.config[:raw] ? response : Response.new(response)
14
+ end
15
+
16
+ private
17
+
18
+ def check_params(data)
19
+ REQUIRED_INPUTS.each do |param|
20
+ if data[param].nil?
21
+ msg = "An BankStandard check requires a #{param}"
22
+ raise InvalidRequestError.new(msg, param)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -23,7 +23,7 @@ module Callcredit
23
23
  end
24
24
  end
25
25
 
26
- # For and ID Enhanced check, we also need a building name or number
26
+ # For an ID Enhanced check, we also need a building name or number
27
27
  unless data[:building_number] || data[:building_name]
28
28
  msg = "An IDEnhanced check requires a building number or name"
29
29
  raise InvalidRequestError.new(msg, :building_number)
@@ -1,9 +1,19 @@
1
1
  module Callcredit
2
2
  class Client
3
- def initialize(config=nil)
3
+ def initialize(config = nil)
4
4
  @config = (config || Callcredit.config).clone
5
5
  end
6
6
 
7
+ def bank_standard_check(check_data)
8
+ check = Checks::BankStandard.new(self)
9
+ check.perform(check_data)
10
+ end
11
+
12
+ def bank_enhanced_check(check_data)
13
+ check = Checks::BankEnhanced.new(self)
14
+ check.perform(check_data)
15
+ end
16
+
7
17
  def id_enhanced_check(check_data)
8
18
  check = Checks::IDEnhanced.new(self)
9
19
  check.perform(check_data)
@@ -7,7 +7,8 @@ module Callcredit
7
7
  password: nil,
8
8
  application_name: nil,
9
9
  raw: false,
10
- api_endpoint: "https://ct.callcreditsecure.co.uk/callvalidateapi/incomingserver.php",
10
+ api_endpoint: "https://ct.callcreditsecure.co.uk/callvalidateapi/" \
11
+ "incomingserver.php",
11
12
  user_agent: "Callcredit Ruby Gem #{Callcredit::VERSION}".freeze
12
13
  }.freeze
13
14
 
@@ -25,8 +26,7 @@ module Callcredit
25
26
  end
26
27
 
27
28
  def clone
28
- Config.new { |config| @config.each { |k,v| config[k] = v } }
29
+ Config.new { |config| @config.each { |k, v| config[k] = v } }
29
30
  end
30
31
  end
31
32
  end
32
-
@@ -47,5 +47,10 @@ module Callcredit
47
47
  delivery_town: "Deliverytown",
48
48
  delivery_postcode: "Deliverypostcode"
49
49
  }
50
+
51
+ BANK_DETAILS = {
52
+ account_number: "Bankaccountnumber",
53
+ sort_code: "Banksortcode"
54
+ }
50
55
  end
51
- end
56
+ end
@@ -2,12 +2,16 @@ module Callcredit
2
2
  class CallcreditError < StandardError
3
3
  attr_reader :message
4
4
  attr_reader :status
5
- attr_reader :response_body
5
+ attr_reader :response
6
6
 
7
- def initialize(message=nil, status=nil, response=nil)
7
+ def initialize(message = nil, status = nil, response = nil)
8
8
  @message = message
9
9
  @status = status
10
- @response_body = response_body
10
+ @response = response
11
+ end
12
+
13
+ def response_body
14
+ response.fetch(:body, nil) if response.responds_to?(:fetch)
11
15
  end
12
16
 
13
17
  def to_s
@@ -1,9 +1,9 @@
1
1
  module Callcredit
2
2
  class InvalidRequestError < CallcreditError
3
- attr_accessor :param
3
+ attr_reader :param
4
4
 
5
- def initialize(message, param, status=nil, response_body=nil)
6
- super(message, status, response_body)
5
+ def initialize(message, param, status = nil, response = nil)
6
+ super(message, status, response)
7
7
  @param = param
8
8
  end
9
9
  end
@@ -2,18 +2,22 @@ module Callcredit
2
2
  module Middleware
3
3
  class CheckResponse < Faraday::Middleware
4
4
  def call(env)
5
- @app.call(env).on_complete do |env|
6
- unless results = env[:body]["Results"]
5
+ @app.call(env).on_complete do |completed_env|
6
+ results = completed_env[:body]["Results"]
7
+
8
+ unless results
7
9
  raise InvalidResponseError.new(
8
- "Invalid response", env[:status], env)
10
+ "Invalid response", completed_env[:status], completed_env)
9
11
  end
10
12
 
11
13
  if results["Errors"]
12
14
  errors = results["Errors"].values.flatten
13
15
  messages = errors.map { |e| e.is_a?(Hash) ? e["__content__"] : e }
14
- raise APIError.new(messages.join(" | "), env[:status], env)
16
+
17
+ raise APIError.new(messages.join(" | "), completed_env[:status],
18
+ completed_env)
15
19
  end
16
- response_values(env)
20
+ response_values(completed_env)
17
21
  end
18
22
  end
19
23
 
@@ -22,7 +22,7 @@ module Callcredit
22
22
  end
23
23
 
24
24
  # Compile the complete XML request to send to Callcredit
25
- def build_request_xml(checks, check_data={})
25
+ def build_request_xml(checks, check_data = {})
26
26
  builder = Nokogiri::XML::Builder.new do |xml|
27
27
  xml.callvalidate do
28
28
  authentication(xml)
@@ -66,9 +66,11 @@ module Callcredit
66
66
  end
67
67
 
68
68
  def personal_data(xml, data)
69
+ return unless data
70
+
69
71
  unless data.is_a? Hash
70
72
  raise InvalidRequestError.new(
71
- "All checks require personal_data", :personal_data)
73
+ "Personal data must be a hash (if provided)", :personal_data)
72
74
  end
73
75
 
74
76
  xml.Personalinformation do
@@ -87,15 +89,27 @@ module Callcredit
87
89
  end
88
90
  end
89
91
 
90
- def card_data(xml, data)
92
+ def card_data(_xml, _data)
91
93
  # Not implemented
92
94
  end
93
95
 
94
96
  def bank_data(xml, data)
95
- # Not implemented
97
+ return unless data
98
+
99
+ unless data.is_a? Hash
100
+ raise InvalidRequestError.new(
101
+ "Bank data must be a hash (if provided)", :bank_data)
102
+ end
103
+
104
+ xml.Bankinformation do
105
+ Constants::BANK_DETAILS.each do |param, element_name|
106
+ value = Validations.clean_param(param, data[param])
107
+ xml.send(element_name, value) if value
108
+ end
109
+ end
96
110
  end
97
111
 
98
- def income_data(xml, data)
112
+ def income_data(_xml, _data)
99
113
  # Not implemented
100
114
  end
101
115
  end
@@ -17,7 +17,8 @@ module Callcredit
17
17
  end
18
18
 
19
19
  def result
20
- @response_data["Results"]["Result"]["Displays"]["IdentityCheck"]
20
+ @response_data["Results"]["Result"]["Displays"].
21
+ reject { |k, v| displays_excluded_from_results.include?(k) }
21
22
  end
22
23
 
23
24
  def warnings
@@ -27,5 +28,11 @@ module Callcredit
27
28
  def full_result
28
29
  @response_data
29
30
  end
31
+
32
+ private
33
+
34
+ def displays_excluded_from_results
35
+ %w(ChecksCompleted InputData Warnings InternalUse)
36
+ end
30
37
  end
31
38
  end
@@ -7,10 +7,10 @@ module Callcredit
7
7
  end
8
8
 
9
9
  def underscore(str)
10
- str.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
11
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
10
+ str.to_s.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
11
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
12
12
  tr("-", "_").
13
13
  downcase
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -1,19 +1,19 @@
1
1
  module Callcredit
2
2
  module Validations
3
-
4
3
  VALIDATIONS = {
5
- date_of_birth: ->(value) { clean_date_of_birth(value) },
6
- title: ->(value) { value || "Unknown" },
7
- first_name: ->(value) { clean_name(value, :first_name) },
8
- last_name: ->(value) { clean_name(value, :last_name) },
9
- middle_names: ->(value) { clean_name(value, :middle_names) },
10
- postcode: ->(value) { clean_postcode(value, :postcode) },
11
- previous_postcode: ->(value) { clean_postcode(value, :previous_postcode) },
12
- delivery_postcode: ->(value) { clean_postcode(value, :delivery_postcode) }
4
+ date_of_birth: ->(val) { clean_date_of_birth(val) },
5
+ title: ->(val) { val || "Unknown" },
6
+ first_name: ->(val) { clean_name(val, :first_name) },
7
+ last_name: ->(val) { clean_name(val, :last_name) },
8
+ middle_names: ->(val) { clean_name(val, :middle_names) },
9
+ postcode: ->(val) { clean_postcode(val, :postcode) },
10
+ previous_postcode: ->(val) { clean_postcode(val, :previous_postcode) },
11
+ account_number: ->(val) { clean_account_number(val) },
12
+ sort_code: ->(val) { clean_sort_code(val) },
13
13
  }
14
14
 
15
15
  def self.clean_param(key, value)
16
- validator = VALIDATIONS.fetch(key, ->(value){ value })
16
+ validator = VALIDATIONS.fetch(key, ->(val) { val })
17
17
  validator.call(value)
18
18
  end
19
19
 
@@ -28,7 +28,7 @@ module Callcredit
28
28
  def self.clean_name(name, param)
29
29
  return unless name
30
30
  # Convert name to ASCII characters only
31
- name = UnicodeUtils.nfkd(name).gsub(/(\p{Letter})\p{Mark}+/,'\\1')
31
+ name = UnicodeUtils.nfkd(name).gsub(/(\p{Letter})\p{Mark}+/, '\\1')
32
32
  input_error(param, name) unless name =~ /\A[a-z A-Z'-]{1,30}\z/
33
33
  name
34
34
  end
@@ -40,13 +40,30 @@ module Callcredit
40
40
  postcode
41
41
  end
42
42
 
43
- def self.input_error(param, value=nil)
44
- msg = if value.nil?
45
- "#{param} is a required param"
46
- else
47
- %{Invalid value "#{value}" for #{param}}
43
+ def self.clean_account_number(account_number)
44
+ return unless account_number
45
+ cleaned_value = account_number.to_s.gsub(/[-\s]/, '')
46
+ unless cleaned_value =~ /\A\d{6,8}\z/
47
+ input_error(:account_number, account_number)
48
48
  end
49
+ cleaned_value
50
+ end
51
+
52
+ def self.clean_sort_code(sort_code)
53
+ return unless sort_code
54
+ cleaned_value = sort_code.to_s.gsub(/[-\s]/, '')
55
+ input_error(:sort_code, sort_code) unless cleaned_value =~ /\A\d{6}\z/
56
+ cleaned_value
57
+ end
58
+
59
+ def self.input_error(param, value = nil)
60
+ msg = if value.nil?
61
+ "#{param} is a required param"
62
+ else
63
+ "Invalid value \"#{value}\" for #{param}"
64
+ end
65
+
49
66
  raise InvalidRequestError.new(msg, param)
50
67
  end
51
68
  end
52
- end
69
+ end
@@ -1,3 +1,3 @@
1
1
  module Callcredit
2
- VERSION = '0.3.8'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
@@ -10,7 +10,7 @@ describe Callcredit do
10
10
  before { Callcredit.configure { |config| config[key] = key } }
11
11
 
12
12
  describe [key] do
13
- subject { super()[key] }
13
+ subject { Callcredit.config[key] }
14
14
  it { should == key }
15
15
  end
16
16
  end
@@ -36,6 +36,28 @@ describe Callcredit do
36
36
  end
37
37
  end
38
38
 
39
+ describe '#bank_standard_check' do
40
+ before { configure_callcredit }
41
+ let(:data) { { account_number: "44779911", sort_code: "200000" } }
42
+
43
+ it "delegates to the client" do
44
+ expect_any_instance_of(Callcredit::Client).
45
+ to receive(:bank_standard_check).with(data)
46
+ Callcredit.bank_standard_check(data)
47
+ end
48
+ end
49
+
50
+ describe '#bank_enhanced_check' do
51
+ before { configure_callcredit }
52
+ let(:data) { { first_name: "Grey", last_name: "Baker" } }
53
+
54
+ it "delegates to the client" do
55
+ expect_any_instance_of(Callcredit::Client).
56
+ to receive(:bank_enhanced_check).with(data)
57
+ Callcredit.bank_enhanced_check(data)
58
+ end
59
+ end
60
+
39
61
  describe '#perform_check' do
40
62
  before { configure_callcredit }
41
63
  let(:data) do
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Callcredit::Checks::BankEnhanced do
4
+ let(:bank_enhanced_check) { Callcredit::Checks::BankEnhanced.new(client) }
5
+ let(:client) { Callcredit::Client.new(config) }
6
+ let(:config) { Callcredit::Config.new }
7
+
8
+ let(:response_hash) { { status: status, body: body } }
9
+ let(:status) { 200 }
10
+ let(:body) { response_xml }
11
+ let(:response_xml) { load_fixture('response.xml') }
12
+ before { stub_request(:get, config[:api_endpoint]).to_return(response_hash) }
13
+
14
+ describe "#perform" do
15
+ subject(:perform_check) { bank_enhanced_check.perform(check_data) }
16
+
17
+ let(:check_data) do
18
+ { first_name: "Grey",
19
+ last_name: "Baker",
20
+ postcode: "EC2A 1DX",
21
+ building_number: "22-25",
22
+ sort_code: "200000",
23
+ account_number: "44779911" }
24
+ end
25
+
26
+ it "separates the supplied data into personal and bank details" do
27
+ expect(client).to receive(:perform_check) do |check_types, data|
28
+ expect(data[:personal_data][:postcode]).to eq(check_data[:postcode])
29
+ expect(data[:bank_data][:sort_code]).to eq(check_data[:sort_code])
30
+ end
31
+
32
+ perform_check
33
+ end
34
+
35
+ it "makes a get request" do
36
+ perform_check
37
+ expect(a_request(:get, config[:api_endpoint])).to have_been_made
38
+ end
39
+
40
+ it { is_expected.to be_a Callcredit::Response }
41
+
42
+ context "when the config[:raw] is true" do
43
+ before { config[:raw] = true }
44
+ it { is_expected.to be_a Faraday::Response }
45
+
46
+ describe '#body' do
47
+ subject { perform_check.body }
48
+ it { should be_a String }
49
+ end
50
+ end
51
+
52
+ describe "validates inputs" do
53
+ it_behaves_like "it validates presence", :first_name
54
+ it_behaves_like "it validates presence", :last_name
55
+ it_behaves_like "it validates presence", :postcode
56
+ it_behaves_like "it validates presence", :building_number
57
+ it_behaves_like "it validates presence", :account_number
58
+ it_behaves_like "it validates presence", :sort_code
59
+
60
+ context "with a building_name instead of building number" do
61
+ before { check_data.delete(:building_number) }
62
+ before { check_data[:building_name] = "The Mill" }
63
+
64
+ it "makes a get request" do
65
+ perform_check
66
+ expect(a_request(:get, config[:api_endpoint])).to have_been_made
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Callcredit::Checks::BankStandard do
4
+ let(:bank_standard_check) { Callcredit::Checks::BankStandard.new(client) }
5
+ let(:client) { Callcredit::Client.new(config) }
6
+ let(:config) { Callcredit::Config.new }
7
+
8
+ let(:response_hash) { { status: status, body: body } }
9
+ let(:status) { 200 }
10
+ let(:body) { response_xml }
11
+ let(:response_xml) { load_fixture('response.xml') }
12
+ before { stub_request(:get, config[:api_endpoint]).to_return(response_hash) }
13
+
14
+ describe "#perform" do
15
+ subject(:perform_check) { bank_standard_check.perform(check_data) }
16
+
17
+ let(:check_data) do
18
+ { account_number: "44779911",
19
+ sort_code: "200000" }
20
+ end
21
+
22
+ it "makes a get request" do
23
+ perform_check
24
+ expect(a_request(:get, config[:api_endpoint])).to have_been_made
25
+ end
26
+
27
+ it { is_expected.to be_a Callcredit::Response }
28
+
29
+ context "when the config[:raw] is true" do
30
+ before { config[:raw] = true }
31
+ it { is_expected.to be_a Faraday::Response }
32
+
33
+ describe '#body' do
34
+ subject { perform_check.body }
35
+ it { should be_a String }
36
+ end
37
+ end
38
+
39
+ describe "validates inputs" do
40
+ it_behaves_like "it validates presence", :account_number
41
+ it_behaves_like "it validates presence", :sort_code
42
+ end
43
+ end
44
+ end
@@ -34,7 +34,7 @@ describe Callcredit::Checks::IDEnhanced do
34
34
  it { is_expected.to be_a Faraday::Response }
35
35
 
36
36
  describe '#body' do
37
- subject { super().body }
37
+ subject { perform_check.body }
38
38
  it { should be_a String }
39
39
  end
40
40
  end
@@ -11,7 +11,7 @@ describe Callcredit::Client do
11
11
  subject(:new_client) { Callcredit::Client.new }
12
12
 
13
13
  describe '#config' do
14
- subject { super().config }
14
+ subject { new_client.config }
15
15
  it { should_not == Callcredit.config }
16
16
  end
17
17
  it "has the attributes of the global config" do
@@ -24,7 +24,7 @@ describe Callcredit::Client do
24
24
  subject(:new_client) { Callcredit::Client.new(config) }
25
25
 
26
26
  describe '#config' do
27
- subject { super().config }
27
+ subject { new_client.config }
28
28
  it { should_not == config }
29
29
  end
30
30
  it "has the attributes of the passed in config" do
@@ -41,6 +41,22 @@ describe Callcredit::Client do
41
41
  end
42
42
  end
43
43
 
44
+ describe "#bank_standard_check" do
45
+ it "delegates to an instance of BankStandard" do
46
+ expect_any_instance_of(Callcredit::Checks::BankStandard).
47
+ to receive(:perform).once
48
+ client.bank_standard_check(check_data)
49
+ end
50
+ end
51
+
52
+ describe "#bank_enhanced_check" do
53
+ it "delegates to an instance of BankEnhanced" do
54
+ expect_any_instance_of(Callcredit::Checks::BankEnhanced).
55
+ to receive(:perform).once
56
+ client.bank_enhanced_check(check_data)
57
+ end
58
+ end
59
+
44
60
  describe "#perform_check" do
45
61
  subject(:perform_check) { client.perform_check(:check_type, check_data) }
46
62
 
@@ -41,6 +41,40 @@ describe Callcredit::Request do
41
41
  expect(xsd.validate(request_xml)).to eq([])
42
42
  end
43
43
  end
44
+
45
+ context "for a BankStandard check" do
46
+ before do
47
+ check_data.merge!(
48
+ bank_data: { account_number: 55779911, sort_code: 200000 }
49
+ )
50
+ end
51
+
52
+ subject(:request_xml) do
53
+ request.build_request_xml(:bank_standard, check_data)
54
+ end
55
+
56
+ it "generates a valid XML request" do
57
+ expect(xsd.validate(request_xml)).to eq([])
58
+ end
59
+ end
60
+
61
+ context "for a BankEnhanced check" do
62
+ before do
63
+ check_data.merge!(
64
+ bank_data: { account_number: 55779911, sort_code: 200000 },
65
+ personal_data: { first_name: "Tim", last_name: "Rogers",
66
+ postcode: "EC1V 7LQ", building_number: "338-346" }
67
+ )
68
+ end
69
+
70
+ subject(:request_xml) do
71
+ request.build_request_xml(:bank_enhanced, check_data)
72
+ end
73
+
74
+ it "generates a valid XML request" do
75
+ expect(xsd.validate(request_xml)).to eq([])
76
+ end
77
+ end
44
78
  end
45
79
 
46
80
  describe "#perform" do
@@ -56,7 +90,7 @@ describe Callcredit::Request do
56
90
  it { is_expected.to be_a Faraday::Response }
57
91
 
58
92
  describe '#body' do
59
- subject { super().body }
93
+ subject { perform_check.body }
60
94
  it { should be_a String }
61
95
  end
62
96
  end
@@ -85,4 +85,70 @@ describe Callcredit::Validations do
85
85
  end
86
86
  end
87
87
  end
88
+
89
+ describe '#clean_account_number' do
90
+ subject { Callcredit::Validations.clean_account_number(account_number) }
91
+
92
+ context "without an account_number" do
93
+ let(:account_number) { nil }
94
+ it { is_expected.to eq(nil) }
95
+ end
96
+
97
+ context "with a correct account_number" do
98
+ let(:account_number) { "12345678" }
99
+ it { is_expected.to eq(account_number) }
100
+ end
101
+
102
+ context "with a padded account_number" do
103
+ let(:account_number) { " 1234 5678 " }
104
+ it { is_expected.to eq("12345678") }
105
+ end
106
+
107
+ context "with an account_number with letters" do
108
+ let(:account_number) { "N1234567" }
109
+ it "raises an error" do
110
+ expect { subject }.to raise_error Callcredit::InvalidRequestError
111
+ end
112
+ end
113
+
114
+ context "with an account_number with too many numbers" do
115
+ let(:account_number) { "123456789" }
116
+ it "raises an error" do
117
+ expect { subject }.to raise_error Callcredit::InvalidRequestError
118
+ end
119
+ end
120
+ end
121
+
122
+ describe '#clean_sort_code' do
123
+ subject { Callcredit::Validations.clean_sort_code(sort_code) }
124
+
125
+ context "without a sort_code" do
126
+ let(:sort_code) { nil }
127
+ it { is_expected.to eq(nil) }
128
+ end
129
+
130
+ context "with a correct sort_code" do
131
+ let(:sort_code) { "123456" }
132
+ it { is_expected.to eq(sort_code) }
133
+ end
134
+
135
+ context "with a padded sort_code" do
136
+ let(:sort_code) { " 1234 56 " }
137
+ it { is_expected.to eq("123456") }
138
+ end
139
+
140
+ context "with a sort_code with letters" do
141
+ let(:sort_code) { "N12345" }
142
+ it "raises an error" do
143
+ expect { subject }.to raise_error Callcredit::InvalidRequestError
144
+ end
145
+ end
146
+
147
+ context "with a sort_code with too many numbers" do
148
+ let(:sort_code) { "1234567" }
149
+ it "raises an error" do
150
+ expect { subject }.to raise_error Callcredit::InvalidRequestError
151
+ end
152
+ end
153
+ end
88
154
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: callcredit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grey Baker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-16 00:00:00.000000000 Z
11
+ date: 2014-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday_middleware
@@ -108,6 +108,8 @@ extensions: []
108
108
  extra_rdoc_files: []
109
109
  files:
110
110
  - .gitignore
111
+ - .rubocop.yml
112
+ - .rubocop_todo.yml
111
113
  - .travis.yml
112
114
  - CHANGELOG.md
113
115
  - Gemfile
@@ -115,6 +117,8 @@ files:
115
117
  - README.md
116
118
  - callcredit.gemspec
117
119
  - lib/callcredit.rb
120
+ - lib/callcredit/checks/bank_enhanced.rb
121
+ - lib/callcredit/checks/bank_standard.rb
118
122
  - lib/callcredit/checks/id_enhanced.rb
119
123
  - lib/callcredit/client.rb
120
124
  - lib/callcredit/config.rb
@@ -130,6 +134,8 @@ files:
130
134
  - lib/callcredit/validations.rb
131
135
  - lib/callcredit/version.rb
132
136
  - spec/callcredit_spec.rb
137
+ - spec/checks/bank_enhanced_spec.rb
138
+ - spec/checks/bank_standard_spec.rb
133
139
  - spec/checks/id_enhanced_spec.rb
134
140
  - spec/client_spec.rb
135
141
  - spec/fixtures/access_denied.xml
@@ -166,6 +172,8 @@ specification_version: 4
166
172
  summary: Ruby wrapper for Callcredit's CallValidate API
167
173
  test_files:
168
174
  - spec/callcredit_spec.rb
175
+ - spec/checks/bank_enhanced_spec.rb
176
+ - spec/checks/bank_standard_spec.rb
169
177
  - spec/checks/id_enhanced_spec.rb
170
178
  - spec/client_spec.rb
171
179
  - spec/fixtures/access_denied.xml