ach_client 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/README.md +10 -0
- data/lib/ach_client/objects/return_code.rb +4 -1
- data/lib/ach_client/providers/soap/i_check_gateway/ach_transaction.rb +26 -1
- data/lib/ach_client/providers/soap/i_check_gateway/instant_rejection_error.rb +33 -0
- data/lib/ach_client/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdcfddb63a2f873af45df29f8fcf6765ec99aff800eb04e8ec2b7500f0827e3c
|
4
|
+
data.tar.gz: 3bfa32675ec76f4e31b830b3616cc913b13f865c2c789394d49cc07758e93b89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25670e16c050eb8248d80f22ffeea4a649cef6f624828118e32c866b7b7e0b0e19f0735150b7b636e5cb88dafc7d57fe7a2ac3225b8c507100b42a3a9fba668e
|
7
|
+
data.tar.gz: ed197b466da4182a732f463b7c51f4a0bd24fdfbfa58755bd058d2f830790719e5f6d6c600abf480e045430e186c962f331ee0a7e17534546d93f7ed44cc8819
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
### 2.0.0
|
2
|
+
|
3
|
+
* Add new AchClient::ICheckGateway::InstantRejectionError to handle API errors raised by ICheckGateway in situations
|
4
|
+
where other providers would accept the transaction and issue a return when polling in the future. This is a breaking
|
5
|
+
change as previous versions would raise a RuntimeError with the message 'ICheckGateway ACH Transaction Failure' and
|
6
|
+
including the API response.
|
7
|
+
|
8
|
+
* Include "internal corrections" (return codes starting with 'XZ') in the AchClient::ReturnCode#correction? predicate
|
9
|
+
|
10
|
+
### 1.1.0
|
11
|
+
|
12
|
+
* Add AchClient::Fake provider to facilitate testing
|
13
|
+
|
14
|
+
### 1.0.3
|
15
|
+
|
16
|
+
* Add presumed description for X09 return code
|
17
|
+
|
18
|
+
### 1.0.2
|
19
|
+
|
20
|
+
* Add previously undocumented X01 internal return code
|
21
|
+
|
22
|
+
### 1.0.1
|
23
|
+
|
24
|
+
* Remove newline characters from fields before generating NACHA files
|
25
|
+
|
26
|
+
### 1.0.0
|
27
|
+
|
28
|
+
* Prior to 1.0.0, ach_client did not have a stable API.
|
data/README.md
CHANGED
@@ -115,6 +115,16 @@ returned by the `#send` method. So you should:
|
|
115
115
|
|
116
116
|
4) When you eventually poll the provider for the status of your transactions, you can use the `external_ach_id` you stored to reconcile the returned data against your records
|
117
117
|
|
118
|
+
### ICheckGateway instant rejection caveat
|
119
|
+
|
120
|
+
ICheckGateway sometimes returns an API error when a valid ACH transaction is sent in a handful of
|
121
|
+
rejection scenarios. This is unusual because most providers will accept the transaction, return an
|
122
|
+
`external_ach_id`, and then supply the rejection info when you poll for responses (see section on response polling
|
123
|
+
below) at a later date. This idiosyncrasy is handled by raising an exception `InstantRejectionError` which contains
|
124
|
+
information about the premature ACH return. In this case, no `external_ach_id` is returned by the `#send` method
|
125
|
+
because ICheck does not return one, nor do they maintain a record of the transaction in their system. See the
|
126
|
+
`InstantRejectionError` class for more details.
|
127
|
+
|
118
128
|
## Batched ACH transactions
|
119
129
|
|
120
130
|
A group of ACH transactions can also be sent in a single batched transaction to
|
@@ -9,6 +9,9 @@ module AchClient
|
|
9
9
|
# The first character in an internal return code
|
10
10
|
INTERNAL_START_CHARACTER = 'X'
|
11
11
|
|
12
|
+
# Returns that are both internal and corrections start with this string
|
13
|
+
INTERNAL_CORRECTION_STRING = 'XZ'
|
14
|
+
|
12
15
|
attr_accessor :code,
|
13
16
|
:description,
|
14
17
|
:reason
|
@@ -25,7 +28,7 @@ module AchClient
|
|
25
28
|
|
26
29
|
# @return Whether or not this return is a correction/notice of change
|
27
30
|
def correction?
|
28
|
-
@code.start_with?(CORRECTION_START_CHARACTER)
|
31
|
+
@code.start_with?(CORRECTION_START_CHARACTER) || @code.start_with?(INTERNAL_CORRECTION_STRING)
|
29
32
|
end
|
30
33
|
|
31
34
|
# @return Whether or not the return is internal
|
@@ -3,11 +3,23 @@ module AchClient
|
|
3
3
|
# ICheckGateway implementation for AchTransaction
|
4
4
|
class AchTransaction < Abstract::AchTransaction
|
5
5
|
|
6
|
+
# When ICheck API gives us an error response containing a correction, the response field looks like this:
|
7
|
+
# DECLINED - Notice of Change (XXX - Change Data: YYYYYY)
|
8
|
+
# Where X is a three character string representing the return code (example: C01)
|
9
|
+
# Where Y is any number of digits representing the updated information for the correction - the
|
10
|
+
# ACH attribute that should be updated (example: 123456789)
|
11
|
+
# The (\w{3}) capture group matches the return code, while the (\d+) capture group matches the correction data
|
12
|
+
# for later use.
|
13
|
+
NOC_RESPONSE_MATCHER = /DECLINED - Notice of Change \((\w{3}) - Change Data: (\d+)\)/
|
14
|
+
|
6
15
|
# Sends this transaction to ICheckGateway
|
7
16
|
# If successful, returns a string from the response that seems to be
|
8
17
|
# a unique identifier for the transaction from ICheckGateway
|
9
18
|
# Raises an exception with as much info as possible if something goes
|
10
|
-
# wrong
|
19
|
+
# wrong.
|
20
|
+
# ICheck sometimes returns an API error for certain rejection scenarios. In this case we raise a
|
21
|
+
# InstantRejectionError which can be caught to handle any business logic appropriate for this edge case.
|
22
|
+
# The exception contains a method ach_response that returns the information about the return.
|
11
23
|
# @return [String] a string returned by ICheckGateway - external_ach_id
|
12
24
|
def do_send
|
13
25
|
# The response comes back as a | separated list of field values with
|
@@ -21,6 +33,19 @@ module AchClient
|
|
21
33
|
if response[0] == 'APPROVED'
|
22
34
|
# Return the confirmation number
|
23
35
|
response[7]
|
36
|
+
elsif response[0].include?('DECLINED - Notice of Change')
|
37
|
+
return_code, addendum = NOC_RESPONSE_MATCHER.match(response[0]).captures
|
38
|
+
# The API error message incorrectly uses the normal correction return codes when the internal correction
|
39
|
+
# return codes should be used instead (since the transaction is never forwarded through to the NACHA system)
|
40
|
+
# Correcting this involves replacing `C0` with `XZ` (ie C01 becomes XZ1)
|
41
|
+
corrected_return_code = "XZ#{return_code.last}"
|
42
|
+
raise ICheckGateway::InstantRejectionError.new(
|
43
|
+
nacha_return_code: corrected_return_code,
|
44
|
+
addendum: addendum,
|
45
|
+
transaction: self
|
46
|
+
), response[0]
|
47
|
+
elsif response[0].include?('DECLINED - Invalid Routing Number')
|
48
|
+
raise ICheckGateway::InstantRejectionError.new(nacha_return_code: 'X13', transaction: self), response[0]
|
24
49
|
else
|
25
50
|
# Don't have a reliable way of getting the error message, so we will
|
26
51
|
# just raise the whole response.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module AchClient
|
2
|
+
class ICheckGateway
|
3
|
+
# ICheckGateway sometimes returns an API error when a valid ACH transaction is sent in a handful of
|
4
|
+
# rejection scenarios. This is unusual because most providers will accept the transaction, return an
|
5
|
+
# external_ach_id, and then supply the rejection info when you poll for responses at a later date.
|
6
|
+
# So far we have observed this happening in the following scenarios:
|
7
|
+
# - When an invalid routing number is supplied (X13 - Invalid ACH Routing Number - Entry contains a Receiving DFI
|
8
|
+
# Identification or Gateway Identification that is not a valid ACH routing number.)
|
9
|
+
# - When there is a Notice of Change for the account number (C01 - ACH Change Code. Incorrect Account Number)
|
10
|
+
# - When there is a Notice of Change for the routing number (C02 - ACH Change Code. Incorrect Transit Route)
|
11
|
+
# This exception can be caught to handle the API error in the appropriate manner.
|
12
|
+
# The NACHA return code inferred from the error message is retrievable from the exception instance as well as any
|
13
|
+
# addendum information provided by the API error (ie the correct new account/routing number)
|
14
|
+
class InstantRejectionError < RuntimeError
|
15
|
+
attr_reader :ach_response
|
16
|
+
|
17
|
+
def initialize(message = nil, nacha_return_code:, addendum: nil, transaction:)
|
18
|
+
super(message)
|
19
|
+
return_code = ReturnCodes.find_by(code: nacha_return_code)
|
20
|
+
response_args = {
|
21
|
+
amount: transaction.amount,
|
22
|
+
date: transaction.effective_entry_date,
|
23
|
+
return_code: return_code,
|
24
|
+
}
|
25
|
+
@ach_response = if return_code.correction?
|
26
|
+
CorrectedAchResponse.new(**response_args, corrections: addendum)
|
27
|
+
else
|
28
|
+
ReturnedAchResponse.new(**response_args)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/ach_client/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ach_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zach Cotter
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ach
|
@@ -262,6 +262,7 @@ files:
|
|
262
262
|
- ".tool-versions"
|
263
263
|
- ".tool-versions-e"
|
264
264
|
- ".travis.yml"
|
265
|
+
- CHANGELOG.md
|
265
266
|
- Gemfile
|
266
267
|
- README.md
|
267
268
|
- Rakefile
|
@@ -321,6 +322,7 @@ files:
|
|
321
322
|
- lib/ach_client/providers/soap/i_check_gateway/ach_transaction.rb
|
322
323
|
- lib/ach_client/providers/soap/i_check_gateway/company_info.rb
|
323
324
|
- lib/ach_client/providers/soap/i_check_gateway/i_check_gateway.rb
|
325
|
+
- lib/ach_client/providers/soap/i_check_gateway/instant_rejection_error.rb
|
324
326
|
- lib/ach_client/providers/soap/i_check_gateway/response_record_processor.rb
|
325
327
|
- lib/ach_client/providers/soap/i_check_gateway/transaction_type_transformer.rb
|
326
328
|
- lib/ach_client/providers/soap/soap_provider.rb
|