virtual_merchant 0.3.8 → 0.3.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|