kount_complete 2.0.0 → 2.0.5
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.
- checksums.yaml +4 -4
- data/lib/kount.rb +27 -28
- data/lib/kount/Response.rb +354 -344
- data/lib/kount/cart.rb +36 -36
- data/lib/kount/client.rb +133 -128
- data/lib/kount/payment_types.rb +52 -52
- data/lib/kount/request.rb +39 -41
- data/lib/kount/request/inquiry.rb +88 -90
- data/lib/kount/request/update.rb +28 -28
- data/lib/kount/security_mash.rb +82 -82
- data/lib/kount/utils/khash.rb +59 -47
- metadata +3 -4
@@ -1,90 +1,88 @@
|
|
1
|
-
module Kount
|
2
|
-
##
|
3
|
-
# This class extends the Request class.
|
4
|
-
class Inquiry < Request
|
5
|
-
attr_accessor :cart
|
6
|
-
|
7
|
-
# Initialize an Inquiry object
|
8
|
-
#
|
9
|
-
# Example usage
|
10
|
-
# {:MACK => "Y", :AUTH => "A"}
|
11
|
-
#
|
12
|
-
# @param initial_params [Hash] Initial params for request
|
13
|
-
def initialize(initial_params = {})
|
14
|
-
super(initial_params)
|
15
|
-
@cart = Cart.new
|
16
|
-
# We want Request to default to MODE Q unless a different mode has
|
17
|
-
# been passed.
|
18
|
-
add_params(MODE: 'Q') unless initial_params.key?(:MODE)
|
19
|
-
end
|
20
|
-
|
21
|
-
# @param version [String] RIS version
|
22
|
-
# @param merchant_id [String] Merchant ID
|
23
|
-
# @param response_format [String] Response format (JSON)
|
24
|
-
# @param ksalt [String] Kount supplied secret salt for KHASH
|
25
|
-
def prepare_params(version, merchant_id, response_format, ksalt)
|
26
|
-
super(version, merchant_id, response_format, ksalt)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
params.merge!(PTOK:
|
52
|
-
|
53
|
-
params
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
#
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
90
|
-
end
|
1
|
+
module Kount
|
2
|
+
##
|
3
|
+
# This class extends the Request class.
|
4
|
+
class Inquiry < Request
|
5
|
+
attr_accessor :cart
|
6
|
+
|
7
|
+
# Initialize an Inquiry object
|
8
|
+
#
|
9
|
+
# Example usage
|
10
|
+
# {:MACK => "Y", :AUTH => "A"}
|
11
|
+
#
|
12
|
+
# @param initial_params [Hash] Initial params for request
|
13
|
+
def initialize(initial_params = {})
|
14
|
+
super(initial_params)
|
15
|
+
@cart = Cart.new
|
16
|
+
# We want Request to default to MODE Q unless a different mode has
|
17
|
+
# been passed.
|
18
|
+
add_params(MODE: 'Q') unless initial_params.key?(:MODE)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param version [String] RIS version
|
22
|
+
# @param merchant_id [String] Merchant ID
|
23
|
+
# @param response_format [String] Response format (JSON)
|
24
|
+
# @param ksalt [String] Kount supplied secret salt for KHASH
|
25
|
+
def prepare_params(version, merchant_id, response_format, ksalt)
|
26
|
+
super(version, merchant_id, response_format, ksalt)
|
27
|
+
params.merge! collect_cart_items
|
28
|
+
# The Kount::Request has no knowledge of the KSALT or merchant_id, both
|
29
|
+
# of which are needed for KHASH. Request form params have everything we
|
30
|
+
# need at this point to do the KHASH if needed.
|
31
|
+
fixup_payment_params(ksalt, merchant_id)
|
32
|
+
params
|
33
|
+
end
|
34
|
+
|
35
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
36
|
+
def fixup_payment_params(ksalt, merchant_id)
|
37
|
+
ptok = params[:PTOK]
|
38
|
+
case params[:PTYP]
|
39
|
+
when 'CARD', 'TOKEN'
|
40
|
+
#ptok = Kount::SecurityMash.hash_credit_card(ptok, ksalt)
|
41
|
+
ptok = Kount::Khash.hash_payment_token(ptok, ksalt)
|
42
|
+
params.merge!(PTOK: ptok, PENC: 'KHASH')
|
43
|
+
when 'GIFT', 'OTHER'
|
44
|
+
#ptok = Kount::SecurityMash.hash_gift_card(ptok, ksalt, merchant_id)
|
45
|
+
ptok = Kount::Khash.hash_gift_card(ptok, ksalt, merchant_id)
|
46
|
+
params.merge!(PTOK: ptok, PENC: 'KHASH')
|
47
|
+
when 'CHEK', 'OTHER'
|
48
|
+
ptok = Kount::Khash.hash_check_payment(ptok, ksalt)
|
49
|
+
params.merge!(PTOK: ptok, PENC: 'KHASH')
|
50
|
+
when 'NONE'
|
51
|
+
params.merge!(PTOK: nil, PENC: nil)
|
52
|
+
else
|
53
|
+
params[:PENC] ||= 'NONE'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Pulls the cart data into the request params hash
|
58
|
+
def collect_cart_items
|
59
|
+
{
|
60
|
+
PROD_TYPE: cart.get_item(:TYPE),
|
61
|
+
PROD_DESC: cart.get_item(:DESC),
|
62
|
+
PROD_ITEM: cart.get_item(:ITEM),
|
63
|
+
PROD_PRICE: cart.get_item(:PRICE),
|
64
|
+
PROD_QUANT: cart.get_item(:QUANT)
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
# Puts the cart object into the request for processing
|
69
|
+
# @param cart [Kount::Cart] Cart object
|
70
|
+
def add_cart(cart)
|
71
|
+
@cart = cart
|
72
|
+
end
|
73
|
+
|
74
|
+
# Add UDF to request
|
75
|
+
# @param name [String] UDF label name
|
76
|
+
# @param value [String] UDF value
|
77
|
+
def add_udf(name, value)
|
78
|
+
@params.merge!("UDF[#{name}]" => value)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Convenience method to create the payment params
|
82
|
+
# @param type [String] Payment type
|
83
|
+
# @param token [String] Payment token
|
84
|
+
def add_payment(type, token = '')
|
85
|
+
add_params(PTYP: type, PTOK: token)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/kount/request/update.rb
CHANGED
@@ -1,28 +1,28 @@
|
|
1
|
-
module Kount
|
2
|
-
##
|
3
|
-
# This class extends the Request class and is used in the
|
4
|
-
# process of sending updates to an existing transaction
|
5
|
-
# generated by a previous Inquiry request.
|
6
|
-
class Update < Request
|
7
|
-
# Initialize an Update object
|
8
|
-
#
|
9
|
-
# Example usage
|
10
|
-
# {:MACK => "Y", :AUTH => "A"}
|
11
|
-
#
|
12
|
-
# @param initial_params [Hash] Initial params for request
|
13
|
-
def initialize(initial_params = {})
|
14
|
-
super(initial_params)
|
15
|
-
# Default to mode U unless mode X is explicitly set
|
16
|
-
add_params(MODE: 'U') unless initial_params[:MODE] == 'X'
|
17
|
-
end
|
18
|
-
|
19
|
-
# @param version [String] RIS version
|
20
|
-
# @param merchant_id [String] Merchant ID
|
21
|
-
# @param response_format [String] Response format (JSON)
|
22
|
-
# @param ksalt [String] Kount supplied secret salt for KHASH
|
23
|
-
def prepare_params(version, merchant_id, response_format, ksalt)
|
24
|
-
super(version, merchant_id, response_format, ksalt)
|
25
|
-
params
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
1
|
+
module Kount
|
2
|
+
##
|
3
|
+
# This class extends the Request class and is used in the
|
4
|
+
# process of sending updates to an existing transaction
|
5
|
+
# generated by a previous Inquiry request.
|
6
|
+
class Update < Request
|
7
|
+
# Initialize an Update object
|
8
|
+
#
|
9
|
+
# Example usage
|
10
|
+
# {:MACK => "Y", :AUTH => "A"}
|
11
|
+
#
|
12
|
+
# @param initial_params [Hash] Initial params for request
|
13
|
+
def initialize(initial_params = {})
|
14
|
+
super(initial_params)
|
15
|
+
# Default to mode U unless mode X is explicitly set
|
16
|
+
add_params(MODE: 'U') unless initial_params[:MODE] == 'X'
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param version [String] RIS version
|
20
|
+
# @param merchant_id [String] Merchant ID
|
21
|
+
# @param response_format [String] Response format (JSON)
|
22
|
+
# @param ksalt [String] Kount supplied secret salt for KHASH
|
23
|
+
def prepare_params(version, merchant_id, response_format, ksalt)
|
24
|
+
super(version, merchant_id, response_format, ksalt)
|
25
|
+
params
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/kount/security_mash.rb
CHANGED
@@ -1,82 +1,82 @@
|
|
1
|
-
require 'digest/sha1'
|
2
|
-
module Kount
|
3
|
-
##
|
4
|
-
# This class implements the Kount KHASH for cards and gift cards.
|
5
|
-
|
6
|
-
class SecurityMash
|
7
|
-
# @param plain_text [String] String to be hashed
|
8
|
-
# @param ptyp [String] Payment type code: CARD, GIFT, or OTHER
|
9
|
-
# @return [String] KHASH version of string
|
10
|
-
def self.hash_token(plain_text, ptyp, ksalt, merchant_id = '')
|
11
|
-
if ptyp == 'CARD'
|
12
|
-
hash_credit_card(plain_text, ksalt)
|
13
|
-
else
|
14
|
-
hash_gift_card(plain_text, ksalt, merchant_id)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# Hash a credit card number.
|
19
|
-
# Preserves first six characters of the input so that hashed cards can be
|
20
|
-
# categorized by Bank Identification Number (BIN).
|
21
|
-
#
|
22
|
-
# Example usage:
|
23
|
-
# hashed = Kount::SecurityMash.hash_credit_card("4111111111111111")
|
24
|
-
# Expect: 411111WMS5YA6FUZA1KC
|
25
|
-
# hashed = Kount::SecurityMash.hash_credit_card("5199185454061655")
|
26
|
-
# Expect: 5199182NOQRXNKTTFL11
|
27
|
-
# hashed = Kount::SecurityMash.hash_credit_card("4259344583883")
|
28
|
-
# Expect: 425934FEXQI1QS6TH2O5
|
29
|
-
#
|
30
|
-
# @param plain_text [String] String to be hashed
|
31
|
-
# @return [String] KHASH version of string
|
32
|
-
def self.hash_credit_card(plain_text, ksalt)
|
33
|
-
return plain_text if khashed?(plain_text)
|
34
|
-
first_six = plain_text[0..5]
|
35
|
-
mashed = mash(plain_text, 14, ksalt)
|
36
|
-
"#{first_six}#{mashed}"
|
37
|
-
end
|
38
|
-
|
39
|
-
# Hash a gift card number.
|
40
|
-
# Use the six characters of the merchant id so that hashed cards can be
|
41
|
-
# unique across the entire domain.
|
42
|
-
#
|
43
|
-
# Example usage:
|
44
|
-
# hashed = Kount::SecurityMash.hash_gift_card("123456", "3245876")
|
45
|
-
# Expect: 1234569HXH32Y5NNJCGB
|
46
|
-
|
47
|
-
# @param plain_text [String] String to be hashed
|
48
|
-
# @return [String] KHASH version of string
|
49
|
-
def self.hash_gift_card(plain_text, ksalt, merchant_id)
|
50
|
-
mashed = mash(plain_text, 14, ksalt)
|
51
|
-
"#{merchant_id}#{mashed}"
|
52
|
-
end
|
53
|
-
|
54
|
-
# Compute a base64 hash of the provided data.
|
55
|
-
#
|
56
|
-
# @param data [String] Data to hash
|
57
|
-
# @param len [int] Length of hash to retain
|
58
|
-
# @return [String] Hashed data
|
59
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
60
|
-
def self.mash(data, len, m)
|
61
|
-
a = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
62
|
-
r = Digest::SHA1.hexdigest("#{data}.#{m}")
|
63
|
-
c = ''
|
64
|
-
len = 17 if len > 17
|
65
|
-
limit = 2 * len
|
66
|
-
i = 0
|
67
|
-
while i < limit
|
68
|
-
c << a[r[i..i + 6].to_i(16) % 36]
|
69
|
-
i += 2
|
70
|
-
end
|
71
|
-
c
|
72
|
-
end
|
73
|
-
|
74
|
-
# end mash
|
75
|
-
|
76
|
-
# @param val [String] Token that may or may not be khashed
|
77
|
-
# @return [Boolean] True if token is already khashed
|
78
|
-
def self.khashed?(val)
|
79
|
-
true if val =~ /(\d{6}[A-Z0-9]{14})/
|
80
|
-
end
|
81
|
-
end # end KountSecurityMash
|
82
|
-
end
|
1
|
+
require 'digest/sha1'
|
2
|
+
module Kount
|
3
|
+
##
|
4
|
+
# This class implements the Kount KHASH for cards and gift cards.
|
5
|
+
|
6
|
+
class SecurityMash
|
7
|
+
# @param plain_text [String] String to be hashed
|
8
|
+
# @param ptyp [String] Payment type code: CARD, GIFT, or OTHER
|
9
|
+
# @return [String] KHASH version of string
|
10
|
+
def self.hash_token(plain_text, ptyp, ksalt, merchant_id = '')
|
11
|
+
if ptyp == 'CARD'
|
12
|
+
hash_credit_card(plain_text, ksalt)
|
13
|
+
else
|
14
|
+
hash_gift_card(plain_text, ksalt, merchant_id)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Hash a credit card number.
|
19
|
+
# Preserves first six characters of the input so that hashed cards can be
|
20
|
+
# categorized by Bank Identification Number (BIN).
|
21
|
+
#
|
22
|
+
# Example usage:
|
23
|
+
# hashed = Kount::SecurityMash.hash_credit_card("4111111111111111")
|
24
|
+
# Expect: 411111WMS5YA6FUZA1KC
|
25
|
+
# hashed = Kount::SecurityMash.hash_credit_card("5199185454061655")
|
26
|
+
# Expect: 5199182NOQRXNKTTFL11
|
27
|
+
# hashed = Kount::SecurityMash.hash_credit_card("4259344583883")
|
28
|
+
# Expect: 425934FEXQI1QS6TH2O5
|
29
|
+
#
|
30
|
+
# @param plain_text [String] String to be hashed
|
31
|
+
# @return [String] KHASH version of string
|
32
|
+
def self.hash_credit_card(plain_text, ksalt)
|
33
|
+
return plain_text if khashed?(plain_text)
|
34
|
+
first_six = plain_text[0..5]
|
35
|
+
mashed = mash(plain_text, 14, ksalt)
|
36
|
+
"#{first_six}#{mashed}"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Hash a gift card number.
|
40
|
+
# Use the six characters of the merchant id so that hashed cards can be
|
41
|
+
# unique across the entire domain.
|
42
|
+
#
|
43
|
+
# Example usage:
|
44
|
+
# hashed = Kount::SecurityMash.hash_gift_card("123456", "3245876")
|
45
|
+
# Expect: 1234569HXH32Y5NNJCGB
|
46
|
+
|
47
|
+
# @param plain_text [String] String to be hashed
|
48
|
+
# @return [String] KHASH version of string
|
49
|
+
def self.hash_gift_card(plain_text, ksalt, merchant_id)
|
50
|
+
mashed = mash(plain_text, 14, ksalt)
|
51
|
+
"#{merchant_id}#{mashed}"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Compute a base64 hash of the provided data.
|
55
|
+
#
|
56
|
+
# @param data [String] Data to hash
|
57
|
+
# @param len [int] Length of hash to retain
|
58
|
+
# @return [String] Hashed data
|
59
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
60
|
+
def self.mash(data, len, m)
|
61
|
+
a = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
62
|
+
r = Digest::SHA1.hexdigest("#{data}.#{m}")
|
63
|
+
c = ''
|
64
|
+
len = 17 if len > 17
|
65
|
+
limit = 2 * len
|
66
|
+
i = 0
|
67
|
+
while i < limit
|
68
|
+
c << a[r[i..i + 6].to_i(16) % 36]
|
69
|
+
i += 2
|
70
|
+
end
|
71
|
+
c
|
72
|
+
end
|
73
|
+
|
74
|
+
# end mash
|
75
|
+
|
76
|
+
# @param val [String] Token that may or may not be khashed
|
77
|
+
# @return [Boolean] True if token is already khashed
|
78
|
+
def self.khashed?(val)
|
79
|
+
true if val =~ /(\d{6}[A-Z0-9]{14})/
|
80
|
+
end
|
81
|
+
end # end KountSecurityMash
|
82
|
+
end
|
data/lib/kount/utils/khash.rb
CHANGED
@@ -1,47 +1,59 @@
|
|
1
|
-
module Kount
|
2
|
-
class Khash
|
3
|
-
# @param plain_text [String] String to be hashed
|
4
|
-
# @param ptyp [String] Payment type code: CARD, GIFT, or OTHER
|
5
|
-
# @return [String] KHASH version of string
|
6
|
-
def self.hash_token(plain_text, ptyp, ksalt, merchant_id = '')
|
7
|
-
if
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
first_six
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
mashed = getkhash(plain_text, 14, ksalt)
|
44
|
-
"#{
|
45
|
-
end
|
46
|
-
|
47
|
-
|
1
|
+
module Kount
|
2
|
+
class Khash
|
3
|
+
# @param plain_text [String] String to be hashed
|
4
|
+
# @param ptyp [String] Payment type code: CARD, GIFT, or OTHER
|
5
|
+
# @return [String] KHASH version of string
|
6
|
+
def self.hash_token(plain_text, ptyp, ksalt, merchant_id = '')
|
7
|
+
# changed if-else to case-when to follow ruby coding standard
|
8
|
+
|
9
|
+
case ptyp
|
10
|
+
when 'CARD'
|
11
|
+
HashPaymentToken(plain_text, ksalt)
|
12
|
+
when 'CHEK'
|
13
|
+
HashCheckPayment(plain_text, ksalt)
|
14
|
+
else
|
15
|
+
HashGiftCard(plain_text, ksalt, merchant_id)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.getkhash(data, len, m)
|
20
|
+
a = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
21
|
+
r = Digest::SHA1.hexdigest("#{data}.#{m}")
|
22
|
+
c = ''
|
23
|
+
len = 17 if len > 17
|
24
|
+
limit = 2 * len
|
25
|
+
i = 0
|
26
|
+
while i < limit
|
27
|
+
c << a[r[i..i + 6].to_i(16) % 36]
|
28
|
+
i += 2
|
29
|
+
end
|
30
|
+
c
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.hash_payment_token(plain_text, ksalt)
|
34
|
+
return plain_text if khashed?(plain_text)
|
35
|
+
first_six = plain_text[0..5]
|
36
|
+
mashed = getkhash(plain_text, 14, ksalt)
|
37
|
+
"#{first_six}#{mashed}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.hash_check_payment(plain_text, ksalt)
|
41
|
+
return plain_text if khashed?(plain_text)
|
42
|
+
first_six = plain_text[0..5]
|
43
|
+
mashed = getkhash(plain_text, 14, ksalt)
|
44
|
+
"#{first_six}#{mashed}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.hash_gift_card(plain_text, ksalt, merchant_id)
|
48
|
+
mashed = getkhash(plain_text, 14, ksalt)
|
49
|
+
"#{merchant_id}#{mashed}"
|
50
|
+
end
|
51
|
+
|
52
|
+
# @param val [String] Token that may or may not be khashed
|
53
|
+
# @return [Boolean] True if token is already khashed
|
54
|
+
def self.khashed?(val)
|
55
|
+
true if val =~ /(\d{6}[A-Z0-9]{14})/
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|