virtual_merchant 0.3.8 → 0.3.9
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/virtual_merchant/credit_card.rb +59 -52
- data/lib/virtual_merchant/gateway.rb +33 -8
- data/lib/virtual_merchant/logger.rb +13 -8
- data/lib/virtual_merchant/xml_generator.rb +11 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b66fbdd061c01dd0fe3616af2b274b50d4cf15af
|
4
|
+
data.tar.gz: ea8a7a2f2f335dfa46a052d88d39461c950e3542
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bba7caef29bc7de60a0099180a51e5a8a323a2c851d6125b3dfa7d685e38898428658b668bd3efd98b86042e0cf6339e337a84e01e0d34e47a2e68331eb9f462
|
7
|
+
data.tar.gz: a2ba8491b977ce3dd4484f73a309bb17e07b5cd73b3bace09dcefb0d6a9480a790a2bb98a352bf96ff32b8197043dec722d0ddee50c51215cedbd22b4c223743
|
@@ -1,7 +1,8 @@
|
|
1
|
+
require 'virtual_merchant/swipe_extractor'
|
1
2
|
module VirtualMerchant
|
2
3
|
class CreditCard
|
3
4
|
attr_accessor :name_on_card, :number, :expiration, :security_code, :swipe, :track2,
|
4
|
-
:encrypted_track_1, :encrypted_track_2, :last_four, :encrypted, :swiped
|
5
|
+
:encrypted_track_1, :encrypted_track_2, :last_four, :encrypted, :swiped, :valid, :errors
|
5
6
|
|
6
7
|
def self.from_swipe(swipe)
|
7
8
|
if swipe.class == Hash && swipe[:encrypted]
|
@@ -16,6 +17,7 @@ module VirtualMerchant
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def initialize(info)
|
20
|
+
@errors = {}
|
19
21
|
if info[:encrypted]
|
20
22
|
self.from_encrypted(info)
|
21
23
|
elsif info[:swipe]
|
@@ -26,6 +28,7 @@ module VirtualMerchant
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def from_encrypted (info)
|
31
|
+
@errors = {}
|
29
32
|
@encrypted = true
|
30
33
|
@encrypted_track_1 = info[:track_1]
|
31
34
|
@encrypted_track_2 = info[:track_2]
|
@@ -33,22 +36,35 @@ module VirtualMerchant
|
|
33
36
|
end
|
34
37
|
|
35
38
|
def from_swipe(swipe_raw)
|
36
|
-
@
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
@errors = {}
|
40
|
+
if check_swipe(swipe_raw)
|
41
|
+
@valid = true
|
42
|
+
@swiped = true
|
43
|
+
@swipe = swipe_raw
|
44
|
+
@track2 = SwipeExtractor.get_track_2(swipe)
|
45
|
+
@number = SwipeExtractor.get_card_number(swipe)
|
46
|
+
@expiration = SwipeExtractor.get_expiration(swipe)
|
47
|
+
@name_on_card = SwipeExtractor.get_name(swipe)
|
48
|
+
@last_four = SwipeExtractor.get_last_four(@number)
|
49
|
+
else
|
50
|
+
@valid = false
|
51
|
+
end
|
43
52
|
end
|
44
53
|
|
45
54
|
def from_manual(info)
|
46
|
-
@
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
55
|
+
@errors = {}
|
56
|
+
if info[:number] && check_luhn(info[:number].to_s.gsub(/\s+/, ""))
|
57
|
+
@name_on_card = info[:name_on_card] if info[:name_on_card]
|
58
|
+
@number = info[:number].to_s.gsub(/\s+/, "")
|
59
|
+
@expiration = info[:expiration].to_s if info[:expiration]
|
60
|
+
@security_code = info[:security_code].to_s if info[:security_code]
|
61
|
+
@track2 = info[:track_2] if info[:track_2]
|
62
|
+
@last_four = SwipeExtractor.get_last_four(@number)
|
63
|
+
@valid = true
|
64
|
+
else
|
65
|
+
errors[5000] = "The Credit Card Number supplied in the authorization request appears to be invalid."
|
66
|
+
@valid = false
|
67
|
+
end
|
52
68
|
end
|
53
69
|
|
54
70
|
def encrypted?
|
@@ -59,50 +75,41 @@ module VirtualMerchant
|
|
59
75
|
self.swiped
|
60
76
|
end
|
61
77
|
|
62
|
-
def
|
63
|
-
|
64
|
-
card_number = card_number.split(' ').join('')
|
65
|
-
end
|
66
|
-
|
67
|
-
def extract_expiration(swipe)
|
68
|
-
secondCarrot = swipe.index("^", swipe.index("^")+1)
|
69
|
-
card_expiration_year = swipe[secondCarrot+1..secondCarrot+2]
|
70
|
-
card_expiration_month = swipe[(secondCarrot + 3)..(secondCarrot + 4)]
|
71
|
-
card_expiration = card_expiration_month.to_s + card_expiration_year.to_s
|
78
|
+
def valid?
|
79
|
+
self.valid
|
72
80
|
end
|
73
81
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
last_name_on_card = swipe[swipe.index('^')+1..swipe.index('/')-1]
|
79
|
-
else
|
80
|
-
if !swipe.index(" ")
|
81
|
-
first_name_on_card = "Gift"
|
82
|
-
last_name_on_card = "Card"
|
83
|
-
else
|
84
|
-
first_name_on_card = swipe.slice(swipe.index('^') + 1, swipe.index(' '))
|
85
|
-
last_name_on_card = swipe.slice(swipe.index(" ") + 1, secondCarrot)
|
86
|
-
end
|
82
|
+
def check_swipe(swipe_raw)
|
83
|
+
if swipe_raw.index('%') == nil
|
84
|
+
@errors[5012] = "The track data sent appears to be invalid."
|
85
|
+
return false
|
87
86
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
def extract_track_2(swipe)
|
92
|
-
# Magtek reader: Track 2 starts with a semi-colon and goes to the end
|
93
|
-
# I think that is standard for all readers, but not positive. -LQ
|
94
|
-
track2 = swipe.slice(swipe.index(";"), swipe.length)
|
95
|
-
if track2.index("+")
|
96
|
-
# Some AMEX have extra stuff at the end of track 2 that causes
|
97
|
-
#virtual merchant to return an INVLD DATA5623 message.
|
98
|
-
#Soooo... let's slice that off
|
99
|
-
track2 = track2.slice(0, track2.index("+"))
|
87
|
+
if swipe_raw.index(';') == nil
|
88
|
+
@errors[5013] = "Transaction requires Track2 data to be sent."
|
89
|
+
return false
|
100
90
|
end
|
101
|
-
|
91
|
+
track1 = swipe_raw[1.. swipe_raw.index('?')-1]
|
92
|
+
if track1 == nil || track1 == "E"
|
93
|
+
@errors[5012] = "The track data sent appears to be invalid."
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
track2 = swipe_raw[swipe_raw.index(';')+1.. swipe_raw.length-2]
|
97
|
+
if track2 == nil || track2 == "E"
|
98
|
+
@errors[5013] = "Transaction requires Track2 data to be sent."
|
99
|
+
return false
|
100
|
+
end
|
101
|
+
return true
|
102
102
|
end
|
103
103
|
|
104
|
-
def
|
105
|
-
|
104
|
+
def check_luhn(code)
|
105
|
+
s1 = s2 = 0
|
106
|
+
code.to_s.reverse.chars.each_slice(2) do |odd, even|
|
107
|
+
s1 += odd.to_i
|
108
|
+
double = even.to_i * 2
|
109
|
+
double -= 9 if double >= 10
|
110
|
+
s2 += double
|
111
|
+
end
|
112
|
+
(s1 + s2) % 10 == 0
|
106
113
|
end
|
107
114
|
|
108
115
|
def blurred_number
|
@@ -6,13 +6,21 @@ class Gateway
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def ccsale(card, amount, custom_fields)
|
9
|
-
|
10
|
-
|
9
|
+
if card.valid?
|
10
|
+
xml = VirtualMerchant::XMLGenerator.generate(card, amount, creds, custom_fields, "ccsale")
|
11
|
+
process(xml, amount)
|
12
|
+
else
|
13
|
+
gen_cc_errors(card)
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
17
|
def ccauth(card, amount, custom_fields)
|
14
|
-
|
15
|
-
|
18
|
+
if card.valid?
|
19
|
+
xml = VirtualMerchant::XMLGenerator.generate(card, amount, creds, custom_fields, "ccauthonly")
|
20
|
+
process(xml, amount)
|
21
|
+
else
|
22
|
+
gen_cc_errors(card)
|
23
|
+
end
|
16
24
|
end
|
17
25
|
|
18
26
|
def cccomplete(amount, transaction_id)
|
@@ -27,13 +35,21 @@ class Gateway
|
|
27
35
|
end
|
28
36
|
|
29
37
|
def ccaddrecurring(card, amount, custom_fields)
|
30
|
-
|
31
|
-
|
38
|
+
if card.valid?
|
39
|
+
xml = VirtualMerchant::XMLGenerator.generate(card, amount, creds, custom_fields, "ccaddrecurring")
|
40
|
+
process(xml, amount)
|
41
|
+
else
|
42
|
+
gen_cc_errors(card)
|
43
|
+
end
|
32
44
|
end
|
33
45
|
|
34
46
|
def cccredit(card, amount, custom_fields)
|
35
|
-
|
36
|
-
|
47
|
+
if card.valid?
|
48
|
+
xml = VirtualMerchant::XMLGenerator.generate(card, amount, creds, custom_fields, 'cccredit')
|
49
|
+
process(xml, amount)
|
50
|
+
else
|
51
|
+
gen_cc_errors(card)
|
52
|
+
end
|
37
53
|
end
|
38
54
|
|
39
55
|
def ccvoid(transaction_id)
|
@@ -58,4 +74,13 @@ class Gateway
|
|
58
74
|
'https://www.myvirtualmerchant.com/VirtualMerchant/processxml.do'
|
59
75
|
end
|
60
76
|
end
|
77
|
+
|
78
|
+
def gen_cc_errors(card)
|
79
|
+
card.errors.each do |code, msg|
|
80
|
+
xml = VirtualMerchant::XMLGenerator.error(code, msg)
|
81
|
+
response = VirtualMerchant::Response.new(xml)
|
82
|
+
VirtualMerchant::Logger.log_response(response)
|
83
|
+
response
|
84
|
+
end
|
85
|
+
end
|
61
86
|
end
|
@@ -1,14 +1,12 @@
|
|
1
1
|
module VirtualMerchant
|
2
2
|
class Logger
|
3
|
-
@@on
|
3
|
+
@@on = false
|
4
|
+
@@log_xml = false
|
4
5
|
|
5
|
-
def self.on!
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.off!
|
10
|
-
@@on = false
|
11
|
-
end
|
6
|
+
def self.on!() @@on = true end
|
7
|
+
def self.off!() @@on = false end
|
8
|
+
def self.xml_on!() @@log_xml = true end
|
9
|
+
def self.xml_off!() @@log_xml = false end
|
12
10
|
|
13
11
|
def self.log_response(response)
|
14
12
|
return unless @@on
|
@@ -21,5 +19,12 @@ module VirtualMerchant
|
|
21
19
|
p "result_message " + response.result_message
|
22
20
|
p "!!!!!!!!!!!!!!!!!!!!!!!! End Credit Response !!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
23
21
|
end
|
22
|
+
|
23
|
+
def self.xml(msg, xml)
|
24
|
+
return unless @@log_xml
|
25
|
+
puts msg
|
26
|
+
pp xml
|
27
|
+
end
|
28
|
+
|
24
29
|
end
|
25
30
|
end
|
@@ -8,6 +8,7 @@ module VirtualMerchant
|
|
8
8
|
<ssl_pin>#{creds.pin}</ssl_pin>
|
9
9
|
<ssl_txn_id>#{transaction_id}</ssl_txn_id>
|
10
10
|
</txn>"
|
11
|
+
VirtualMerchant::Logger.xml('VOID OUTPUT', xml)
|
11
12
|
return xml
|
12
13
|
end
|
13
14
|
|
@@ -25,6 +26,7 @@ module VirtualMerchant
|
|
25
26
|
xml += "<#{key}>#{value}</#{key}>"
|
26
27
|
end
|
27
28
|
xml += "</txn>"
|
29
|
+
VirtualMerchant::Logger.xml('NORMAL OUTPUT', xml)
|
28
30
|
xml
|
29
31
|
end
|
30
32
|
|
@@ -37,6 +39,7 @@ module VirtualMerchant
|
|
37
39
|
xml += "<ssl_amount>#{amount.total}</ssl_amount>"
|
38
40
|
end
|
39
41
|
xml += "</txn>"
|
42
|
+
VirtualMerchant::Logger.xml('MODIFY TRANSACTION OUTPUT', xml)
|
40
43
|
xml
|
41
44
|
end
|
42
45
|
|
@@ -90,5 +93,13 @@ module VirtualMerchant
|
|
90
93
|
end
|
91
94
|
xml
|
92
95
|
end
|
96
|
+
|
97
|
+
def self.error(code, message)
|
98
|
+
xml = "<txn>
|
99
|
+
<errorCode>#{code}</errorCode>
|
100
|
+
<errorMessage>#{message}</errorMessage>
|
101
|
+
</txn>"
|
102
|
+
xml
|
103
|
+
end
|
93
104
|
end
|
94
105
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: virtual_merchant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Quarella
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Makes it easy to charge credit cards with the VirtualMerchant API.
|
14
14
|
email: leequarella@gmail.com
|
@@ -21,10 +21,10 @@ files:
|
|
21
21
|
- lib/virtual_merchant/communication.rb
|
22
22
|
- lib/virtual_merchant/credentials.rb
|
23
23
|
- lib/virtual_merchant/credit_card.rb
|
24
|
+
- lib/virtual_merchant/gateway.rb
|
24
25
|
- lib/virtual_merchant/logger.rb
|
25
26
|
- lib/virtual_merchant/response.rb
|
26
27
|
- lib/virtual_merchant/xml_generator.rb
|
27
|
-
- lib/virtual_merchant/gateway.rb
|
28
28
|
homepage: https://github.com/leequarella/VirtualMerchant-Ruby
|
29
29
|
licenses:
|
30
30
|
- MIT
|
@@ -35,17 +35,17 @@ require_paths:
|
|
35
35
|
- lib
|
36
36
|
required_ruby_version: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ">="
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
46
|
requirements: []
|
47
47
|
rubyforge_project:
|
48
|
-
rubygems_version: 2.
|
48
|
+
rubygems_version: 2.2.2
|
49
49
|
signing_key:
|
50
50
|
specification_version: 4
|
51
51
|
summary: Virtual Merchant API
|