vaulted_billing 1.1.6 → 1.2.0
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.
@@ -0,0 +1,43 @@
|
|
1
|
+
module VaultedBilling
|
2
|
+
module Gateways
|
3
|
+
class Bogus
|
4
|
+
module Failure
|
5
|
+
FailureCards = %w(4222222222222)
|
6
|
+
FailureMessages = [
|
7
|
+
'This transaction has been declined.',
|
8
|
+
'This transaction has been approved.',
|
9
|
+
'This transaction has been declined.',
|
10
|
+
'This transaction has been declined.',
|
11
|
+
'This transaction has been declined.',
|
12
|
+
'A valid amount is required.',
|
13
|
+
'The credit card number is invalid.',
|
14
|
+
'The credit card expiration date is invalid',
|
15
|
+
'The credit card has expired.',
|
16
|
+
'The ABA code is invalid',
|
17
|
+
'The account number is invalid.',
|
18
|
+
'A duplicate transaction has been submitted.',
|
19
|
+
]
|
20
|
+
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
|
25
|
+
def error_code_for(credit_card, amount)
|
26
|
+
amount.to_i
|
27
|
+
end
|
28
|
+
|
29
|
+
def failure_message_for(credit_card, amount)
|
30
|
+
FailureMessages[error_code_for(credit_card, amount)] || FailureMessages.first
|
31
|
+
end
|
32
|
+
|
33
|
+
def success?(credit_card, amount)
|
34
|
+
credit_card.nil? || !failure?(credit_card, amount)
|
35
|
+
end
|
36
|
+
|
37
|
+
def failure?(credit_card, amount)
|
38
|
+
!credit_card.nil? && FailureCards.include?(credit_card.card_number)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -5,15 +5,49 @@ module VaultedBilling
|
|
5
5
|
##
|
6
6
|
# The Bogus gateway should only be used for simple interface testing
|
7
7
|
# to the VaultedBilling library. All customer and credit card requests
|
8
|
-
# will always return successfully.
|
9
|
-
# authorize, capture, etc.) will always return successfully
|
8
|
+
# will always return successfully. All transaction requests (purchase,
|
9
|
+
# authorize, capture, etc.) will always return successfully, unless a
|
10
|
+
# failure credit card number is given.
|
11
|
+
#
|
12
|
+
# If a failure credit card number is given, then the transaction amount is
|
13
|
+
# used to determine the error message and code to return.
|
10
14
|
#
|
11
15
|
# The primary purpose of this gateway is to provide you with an end
|
12
16
|
# point for testing your interface, as well as a fairly reasonable
|
13
17
|
# gateway for performing simple, non-network based tests against.
|
14
18
|
#
|
19
|
+
# To test failure messages, use the credit card number '4222222222222'.
|
20
|
+
# This card number will trigger failed transaction responses from the
|
21
|
+
# Bogus gateway for purchase and authorize requests. In order to receive a
|
22
|
+
# specific error message / code, set the transaction amount to one of the
|
23
|
+
# following:
|
24
|
+
#
|
25
|
+
# 0: 'This transaction has been declined.'
|
26
|
+
# 1: 'This transaction has been approved.'
|
27
|
+
# 2: 'This transaction has been declined.'
|
28
|
+
# 3: 'This transaction has been declined.'
|
29
|
+
# 4: 'This transaction has been declined.'
|
30
|
+
# 5: 'A valid amount is required.'
|
31
|
+
# 6: 'The credit card number is invalid.'
|
32
|
+
# 7: 'The credit card expiration date is invalid'
|
33
|
+
# 8: 'The credit card has expired.'
|
34
|
+
# 9: 'The ABA code is invalid'
|
35
|
+
# 10: 'The account number is invalid.'
|
36
|
+
# 11: 'A duplicate transaction has been submitted.'
|
37
|
+
#
|
38
|
+
# Example:
|
39
|
+
#
|
40
|
+
# customer = Customer.new(...)
|
41
|
+
# credit_card = CreditCard.new(:card_number => '4222222222222')
|
42
|
+
# bogus.purchase(customer, credit_card, 6.00)
|
43
|
+
# # => Failed transaction, 'The credit card number is invalid.'
|
44
|
+
#
|
15
45
|
class Bogus
|
46
|
+
autoload :Failure, 'vaulted_billing/gateways/bogus/failure'
|
47
|
+
|
16
48
|
include VaultedBilling::Gateway
|
49
|
+
include VaultedBilling::Gateways::Bogus::Failure
|
50
|
+
|
17
51
|
|
18
52
|
def initialize(options = {})
|
19
53
|
end
|
@@ -43,23 +77,23 @@ module VaultedBilling
|
|
43
77
|
end
|
44
78
|
|
45
79
|
def authorize(customer, credit_card, amount, options = {})
|
46
|
-
transaction_response
|
80
|
+
transaction_response credit_card, amount
|
47
81
|
end
|
48
82
|
|
49
83
|
def purchase(customer, credit_card, amount, options = {})
|
50
|
-
transaction_response
|
84
|
+
transaction_response credit_card, amount
|
51
85
|
end
|
52
86
|
|
53
87
|
def void(transaction_id, options = {})
|
54
|
-
transaction_response
|
88
|
+
transaction_response nil, nil
|
55
89
|
end
|
56
90
|
|
57
91
|
def capture(transaction_id, amount, options = {})
|
58
|
-
transaction_response
|
92
|
+
transaction_response nil, amount
|
59
93
|
end
|
60
94
|
|
61
95
|
def refund(transaction_id, amount, options = {})
|
62
|
-
transaction_response
|
96
|
+
transaction_response nil, amount
|
63
97
|
end
|
64
98
|
|
65
99
|
|
@@ -70,13 +104,22 @@ module VaultedBilling
|
|
70
104
|
Digest::MD5.hexdigest("--#{Time.now.to_f}--#{rand(1_000_000)}--#{rand(1_000_000)}--")
|
71
105
|
end
|
72
106
|
|
73
|
-
def transaction_response
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
107
|
+
def transaction_response(credit_card, amount)
|
108
|
+
attributes = { :id => new_identifier }
|
109
|
+
attributes[:masked_card_number] = "XXXX%04d" % [credit_card ? credit_card.card_number.to_s[-4..-1].to_i : rand(9999)]
|
110
|
+
success = true
|
111
|
+
error_code = nil
|
112
|
+
|
113
|
+
if success?(credit_card, amount)
|
114
|
+
attributes[:authcode] = new_identifier[0..5]
|
115
|
+
else
|
116
|
+
success = false
|
117
|
+
attributes[:message] = failure_message_for(credit_card, amount)
|
118
|
+
error_code = error_code_for(credit_card, amount)
|
119
|
+
end
|
120
|
+
|
121
|
+
respond_with VaultedBilling::Transaction.new(attributes), :success => success, :error_code => error_code
|
79
122
|
end
|
80
123
|
end
|
81
124
|
end
|
82
|
-
end
|
125
|
+
end
|
@@ -17,6 +17,11 @@ module VaultedBilling
|
|
17
17
|
#
|
18
18
|
class Ipcommerce
|
19
19
|
include VaultedBilling::Gateway
|
20
|
+
|
21
|
+
AvsResults = [
|
22
|
+
"Not Set", "Not Included", "Match", "No Match", "Issuer Not Certified",
|
23
|
+
"No Response From Card Association", "Unknown Response From Card Association", "Not Verified", "Bad Format"
|
24
|
+
]
|
20
25
|
|
21
26
|
Countries = %w(
|
22
27
|
!! AF AX AL DZ AS AD AO AI AQ
|
@@ -44,7 +49,7 @@ module VaultedBilling
|
|
44
49
|
TG TK TP TO TT TN TR TM TC TV
|
45
50
|
UG UA AE GB US UM UY UZ VU VE
|
46
51
|
VN VG VI WF EH YE YU ZM ZW
|
47
|
-
)
|
52
|
+
).freeze
|
48
53
|
|
49
54
|
Companies = {
|
50
55
|
2 => /^4\d{12}(\d{3})?$/, # Visa
|
@@ -54,6 +59,12 @@ module VaultedBilling
|
|
54
59
|
6 => /^(6011|65\d{2}|64[4-9]\d)\d{12}|(62\d{14})$/, # Discover
|
55
60
|
7 => /^35(28|29|[3-8]\d)\d{12}$/ # JCB
|
56
61
|
}.freeze
|
62
|
+
|
63
|
+
CVResults = [
|
64
|
+
"Not Set", "Match", "No Match", "Not Processed", "Not Included",
|
65
|
+
"No Code Present", "Should Have Been Present", "Issuer Not Certified", "Invalid", "No Response",
|
66
|
+
"Not Applicable"
|
67
|
+
].freeze
|
57
68
|
|
58
69
|
Endpoints = [
|
59
70
|
"https://cws-01.ipcommerce.com/REST/2.0.15/",
|
@@ -325,32 +336,28 @@ module VaultedBilling
|
|
325
336
|
|
326
337
|
def card_data(credit_card)
|
327
338
|
return nil if credit_card.nil?
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
:CVData => credit_card.cvv_number
|
351
|
-
}.select { |k, v| !v.nil? }
|
352
|
-
}
|
353
|
-
end
|
339
|
+
{
|
340
|
+
'PaymentAccountDataToken' => credit_card.vault_id,
|
341
|
+
'CardData' => {
|
342
|
+
'CardholderName' => credit_card.name_on_card.blank? ? nil : credit_card.name_on_card,
|
343
|
+
'CardType' => self.class.credit_card_type_id(credit_card.card_number),
|
344
|
+
'Expire' => credit_card.expires_on.try(:strftime, "%m%y"),
|
345
|
+
'PAN' => credit_card.vault_id ? ("XXXXXXXXXXX%04d" % [credit_card.card_number[-4..-1]]) : credit_card.card_number
|
346
|
+
},
|
347
|
+
'CardSecurityData' => {
|
348
|
+
'AVSData' => {
|
349
|
+
'CardholderName' => credit_card.name_on_card.blank? ? nil : credit_card.name_on_card,
|
350
|
+
'Street' => credit_card.street_address.try(:[], (0...20)),
|
351
|
+
'City' => credit_card.locality,
|
352
|
+
'StateProvince' => credit_card.region,
|
353
|
+
'PostalCode' => credit_card.postal_code.try(:gsub, /[^[:alnum:]]/, '').try(:[], (0...8)),
|
354
|
+
'Country' => credit_card.country.try(:to_ipcommerce_id),
|
355
|
+
'Phone' => credit_card.phone
|
356
|
+
}.select { |k, v| !v.nil? },
|
357
|
+
'CVDataProvided' => credit_card.cvv_number.nil? ? nil : 2,
|
358
|
+
'CVData' => credit_card.cvv_number
|
359
|
+
}.select { |k, v| v.is_a?(Hash) ? !v.empty? : !v.nil? }
|
360
|
+
}.select { |k, v| !v.nil? }
|
354
361
|
end
|
355
362
|
|
356
363
|
private
|
@@ -411,8 +418,8 @@ module VaultedBilling
|
|
411
418
|
if response.success?
|
412
419
|
Transaction.new({
|
413
420
|
:id => response.body['TransactionId'],
|
414
|
-
:avs_response => response.body['AVSResult']
|
415
|
-
:cvv_response => response.body['CVResult']
|
421
|
+
:avs_response => parse_avs_result(response.body['AVSResult']),
|
422
|
+
:cvv_response => parse_cvv_result(response.body['CVResult']),
|
416
423
|
:authcode => response.body['ApprovalCode'],
|
417
424
|
:message => response.body['StatusMessage'],
|
418
425
|
:code => response.body['Status'],
|
@@ -433,6 +440,25 @@ module VaultedBilling
|
|
433
440
|
end
|
434
441
|
end
|
435
442
|
|
443
|
+
def parse_avs_result(result)
|
444
|
+
return nil unless result
|
445
|
+
{
|
446
|
+
:result => result['ActualResult'],
|
447
|
+
:address => AvsResults[result['AddressResult']],
|
448
|
+
:country => AvsResults[result['CountryResult']],
|
449
|
+
:state => AvsResults[result['StateResult']],
|
450
|
+
:postal_code => AvsResults[result['PostalCodeResult']],
|
451
|
+
:phone => AvsResults[result['PhoneResult']],
|
452
|
+
:cardholder_name => AvsResults[result['CardholderNameResult']],
|
453
|
+
:city => AvsResults[result['CityResult']]
|
454
|
+
}
|
455
|
+
end
|
456
|
+
|
457
|
+
def parse_cvv_result(result)
|
458
|
+
return nil unless result
|
459
|
+
CVResults[result]
|
460
|
+
end
|
461
|
+
|
436
462
|
def parse_validation_errors(response)
|
437
463
|
errors = ChainableHash.new.merge(response.body || {})
|
438
464
|
if errors['ErrorResponse']['ValidationErrors'].present?
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module VaultedBilling
|
2
2
|
module Gateways
|
3
|
-
Dir[File.expand_path(File.join(File.dirname(__FILE__), 'gateways', '
|
3
|
+
Dir[File.expand_path(File.join(File.dirname(__FILE__), 'gateways', '*.rb'))].each do |file|
|
4
4
|
filename = File.basename(file, '.rb')
|
5
5
|
gateway_class = filename.camelize
|
6
6
|
autoload gateway_class, file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vaulted_billing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-10-27 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &2165677980 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '2.3'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2165677980
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: builder
|
27
|
-
requirement: &
|
27
|
+
requirement: &2165677480 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.1.2
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2165677480
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: multi_json
|
38
|
-
requirement: &
|
38
|
+
requirement: &2165677000 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '1.0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2165677000
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: multi_xml
|
49
|
-
requirement: &
|
49
|
+
requirement: &2165676400 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.3.0
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2165676400
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: countries
|
60
|
-
requirement: &
|
60
|
+
requirement: &2165675960 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *2165675960
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
|
-
requirement: &
|
71
|
+
requirement: &2165675180 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '2.4'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *2165675180
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: vcr
|
82
|
-
requirement: &
|
82
|
+
requirement: &2165674380 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '1.7'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *2165674380
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: webmock
|
93
|
-
requirement: &
|
93
|
+
requirement: &2165673920 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ~>
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '1.6'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *2165673920
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: factory_girl
|
104
|
-
requirement: &
|
104
|
+
requirement: &2165667440 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '1.3'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *2165667440
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: faker
|
115
|
-
requirement: &
|
115
|
+
requirement: &2165666980 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ~>
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: '0.9'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *2165666980
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: rake
|
126
|
-
requirement: &
|
126
|
+
requirement: &2165666520 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ~>
|
@@ -131,10 +131,10 @@ dependencies:
|
|
131
131
|
version: '0.9'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *2165666520
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: watchr
|
137
|
-
requirement: &
|
137
|
+
requirement: &2165666100 !ruby/object:Gem::Requirement
|
138
138
|
none: false
|
139
139
|
requirements:
|
140
140
|
- - ! '>='
|
@@ -142,10 +142,10 @@ dependencies:
|
|
142
142
|
version: '0'
|
143
143
|
type: :development
|
144
144
|
prerelease: false
|
145
|
-
version_requirements: *
|
145
|
+
version_requirements: *2165666100
|
146
146
|
- !ruby/object:Gem::Dependency
|
147
147
|
name: open4
|
148
|
-
requirement: &
|
148
|
+
requirement: &2165665620 !ruby/object:Gem::Requirement
|
149
149
|
none: false
|
150
150
|
requirements:
|
151
151
|
- - ! '>='
|
@@ -153,10 +153,10 @@ dependencies:
|
|
153
153
|
version: '0'
|
154
154
|
type: :development
|
155
155
|
prerelease: false
|
156
|
-
version_requirements: *
|
156
|
+
version_requirements: *2165665620
|
157
157
|
- !ruby/object:Gem::Dependency
|
158
158
|
name: appraisal
|
159
|
-
requirement: &
|
159
|
+
requirement: &2165665200 !ruby/object:Gem::Requirement
|
160
160
|
none: false
|
161
161
|
requirements:
|
162
162
|
- - ! '>='
|
@@ -164,7 +164,7 @@ dependencies:
|
|
164
164
|
version: '0'
|
165
165
|
type: :development
|
166
166
|
prerelease: false
|
167
|
-
version_requirements: *
|
167
|
+
version_requirements: *2165665200
|
168
168
|
description: Several card processors and gateways support offloading the storage of
|
169
169
|
credit card information onto their service. This offloads PCI compliance to the
|
170
170
|
gateway rather than keeping it with each retailer. This library abstracts the interface
|
@@ -184,6 +184,7 @@ files:
|
|
184
184
|
- lib/vaulted_billing/errors.rb
|
185
185
|
- lib/vaulted_billing/gateway.rb
|
186
186
|
- lib/vaulted_billing/gateways/authorize_net_cim.rb
|
187
|
+
- lib/vaulted_billing/gateways/bogus/failure.rb
|
187
188
|
- lib/vaulted_billing/gateways/bogus.rb
|
188
189
|
- lib/vaulted_billing/gateways/ipcommerce.rb
|
189
190
|
- lib/vaulted_billing/gateways/nmi_customer_vault.rb
|