activemerchant 1.49.0 → 1.50.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.
- checksums.yaml +4 -4
- data/CHANGELOG +47 -0
- data/CONTRIBUTORS +4 -0
- data/README.md +5 -1
- data/lib/active_merchant/billing/credit_card.rb +9 -0
- data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +17 -6
- data/lib/active_merchant/billing/gateways/beanstream.rb +4 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +0 -4
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +4 -0
- data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
- data/lib/active_merchant/billing/gateways/cashnet.rb +19 -8
- data/lib/active_merchant/billing/gateways/cenpos.rb +15 -29
- data/lib/active_merchant/billing/gateways/conekta.rb +3 -2
- data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +19 -12
- data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
- data/lib/active_merchant/billing/gateways/omise.rb +319 -0
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +5 -4
- data/lib/active_merchant/billing/gateways/orbital.rb +7 -0
- data/lib/active_merchant/billing/gateways/payu_in.rb +243 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +11 -357
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
- data/lib/active_merchant/billing/gateways/s5.rb +226 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +7 -1
- data/lib/active_merchant/billing/gateways/secure_net.rb +1 -1
- data/lib/active_merchant/billing/gateways/stripe.rb +8 -5
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +2 -2
- data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
- data/lib/active_merchant/connection.rb +3 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +15 -27
- checksums.yaml.gz.sig +0 -2
- data.tar.gz.sig +0 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +0 -209
- metadata.gz.sig +0 -1
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class S5Gateway < Gateway
|
6
|
+
self.test_url = 'https://test.ctpe.io/payment/ctpe'
|
7
|
+
self.live_url = 'https://ctpe.io/payment/ctpe'
|
8
|
+
|
9
|
+
self.supported_countries = ['DK']
|
10
|
+
self.default_currency = 'EUR'
|
11
|
+
self.supported_cardtypes = [:visa, :master, :maestro]
|
12
|
+
|
13
|
+
self.homepage_url = 'http://www.s5.dk/'
|
14
|
+
self.display_name = 'S5'
|
15
|
+
|
16
|
+
SUPPORTED_TRANSACTIONS = {
|
17
|
+
'sale' => 'CC.DB',
|
18
|
+
'authonly' => 'CC.PA',
|
19
|
+
'capture' => 'CC.CP',
|
20
|
+
'refund' => 'CC.RF',
|
21
|
+
'void' => 'CC.RV',
|
22
|
+
}
|
23
|
+
|
24
|
+
def initialize(options={})
|
25
|
+
requires!(options, :sender, :channel, :login, :password)
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def purchase(money, payment, options={})
|
30
|
+
request = build_xml_request do |xml|
|
31
|
+
add_payment(xml, money, 'sale', options)
|
32
|
+
add_account(xml, payment)
|
33
|
+
add_customer(xml, payment, options)
|
34
|
+
add_recurrence_mode(xml, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
commit(request)
|
38
|
+
end
|
39
|
+
|
40
|
+
def refund(money, authorization, options={})
|
41
|
+
request = build_xml_request do |xml|
|
42
|
+
add_identification(xml, authorization)
|
43
|
+
add_payment(xml, money, 'refund', options)
|
44
|
+
end
|
45
|
+
|
46
|
+
commit(request)
|
47
|
+
end
|
48
|
+
|
49
|
+
def authorize(money, payment, options={})
|
50
|
+
request = build_xml_request do |xml|
|
51
|
+
add_payment(xml, money, 'authonly', options)
|
52
|
+
add_account(xml, payment)
|
53
|
+
add_customer(xml, payment, options)
|
54
|
+
add_recurrence_mode(xml, options)
|
55
|
+
end
|
56
|
+
|
57
|
+
commit(request)
|
58
|
+
end
|
59
|
+
|
60
|
+
def capture(money, authorization, options={})
|
61
|
+
request = build_xml_request do |xml|
|
62
|
+
add_identification(xml, authorization)
|
63
|
+
add_payment(xml, money, 'capture', options)
|
64
|
+
end
|
65
|
+
|
66
|
+
commit(request)
|
67
|
+
end
|
68
|
+
|
69
|
+
def void(authorization, options={})
|
70
|
+
request = build_xml_request do |xml|
|
71
|
+
add_identification(xml, authorization)
|
72
|
+
add_payment(xml, nil, 'void', options)
|
73
|
+
end
|
74
|
+
|
75
|
+
commit(request)
|
76
|
+
end
|
77
|
+
|
78
|
+
def verify(credit_card, options={})
|
79
|
+
MultiResponse.run(:use_first_response) do |r|
|
80
|
+
r.process { authorize(100, credit_card, options) }
|
81
|
+
r.process(:ignore_result) { void(r.authorization, options) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def supports_scrubbing?
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
def scrub(transcript)
|
90
|
+
transcript.
|
91
|
+
gsub(%r((pwd=).+(/>))i, '\1[FILTERED]\2').
|
92
|
+
gsub(%r((<Number>).+(</Number>))i, '\1[FILTERED]\2').
|
93
|
+
gsub(%r((<Verification>).+(</Verification>))i, '\1[FILTERED]\2')
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def add_identification(xml, authorization)
|
99
|
+
xml.Identification do
|
100
|
+
xml.ReferenceID authorization
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_payment(xml, money, action, options)
|
105
|
+
xml.Payment(code: SUPPORTED_TRANSACTIONS[action]) do
|
106
|
+
xml.Memo "return_code=#{options[:memo]}" if options[:memo]
|
107
|
+
xml.Presentation do
|
108
|
+
xml.Amount amount(money)
|
109
|
+
xml.Currency options[:currency] || currency(money)
|
110
|
+
xml.Usage options[:description]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_account(xml, creditcard)
|
116
|
+
xml.Account do
|
117
|
+
xml.Number creditcard.number
|
118
|
+
xml.Holder "#{creditcard.first_name} #{creditcard.last_name}"
|
119
|
+
xml.Brand creditcard.brand
|
120
|
+
xml.Expiry(year: creditcard.year, month: creditcard.month)
|
121
|
+
xml.Verification creditcard.verification_value
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_customer(xml, creditcard, options)
|
126
|
+
address = options[:billing_address]
|
127
|
+
xml.Customer do
|
128
|
+
xml.Contact do
|
129
|
+
xml.Email options[:email]
|
130
|
+
xml.Ip options[:ip]
|
131
|
+
xml.Phone address[:phone] if address
|
132
|
+
end
|
133
|
+
add_address(xml, address)
|
134
|
+
xml.Name do
|
135
|
+
xml.Given creditcard.first_name
|
136
|
+
xml.Family creditcard.last_name
|
137
|
+
xml.Company options[:company]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def add_address(xml, address)
|
143
|
+
return unless address
|
144
|
+
|
145
|
+
xml.Address do
|
146
|
+
xml.Street "#{address[:address1]} #{address[:address2]}"
|
147
|
+
xml.Zip address[:zip]
|
148
|
+
xml.City address[:city]
|
149
|
+
xml.State address[:state]
|
150
|
+
xml.Country address[:country]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def add_recurrence_mode(xml, options)
|
155
|
+
if options[:recurring] == true
|
156
|
+
xml.Recurrence(mode: "REPEATED")
|
157
|
+
else
|
158
|
+
xml.Recurrence(mode: "INITIAL")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def parse(body)
|
163
|
+
results = {}
|
164
|
+
xml = Nokogiri::XML(body)
|
165
|
+
resp = xml.xpath("//Response/Transaction/Identification")
|
166
|
+
resp.children.each do |element|
|
167
|
+
results[element.name.downcase.to_sym] = element.text
|
168
|
+
end
|
169
|
+
resp = xml.xpath("//Response/Transaction/Processing")
|
170
|
+
resp.children.each do |element|
|
171
|
+
results[element.name.downcase.to_sym] = element.text
|
172
|
+
end
|
173
|
+
results
|
174
|
+
end
|
175
|
+
|
176
|
+
def commit(xml)
|
177
|
+
url = (test? ? test_url : live_url)
|
178
|
+
headers = {
|
179
|
+
'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'
|
180
|
+
}
|
181
|
+
|
182
|
+
response = parse(ssl_post(url, post_data(xml), headers))
|
183
|
+
|
184
|
+
Response.new(
|
185
|
+
success_from(response),
|
186
|
+
message_from(response),
|
187
|
+
response,
|
188
|
+
authorization: authorization_from(response),
|
189
|
+
test: test?
|
190
|
+
)
|
191
|
+
end
|
192
|
+
|
193
|
+
def success_from(response)
|
194
|
+
response[:result] == 'ACK'
|
195
|
+
end
|
196
|
+
|
197
|
+
def message_from(response)
|
198
|
+
response[:return]
|
199
|
+
end
|
200
|
+
|
201
|
+
def authorization_from(response)
|
202
|
+
response[:uniqueid]
|
203
|
+
end
|
204
|
+
|
205
|
+
def post_data(xml)
|
206
|
+
"load=#{xml}"
|
207
|
+
end
|
208
|
+
|
209
|
+
def build_xml_request
|
210
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
211
|
+
xml.Request(version: '1.0') do
|
212
|
+
xml.Header do
|
213
|
+
xml.Security(sender: @options[:sender])
|
214
|
+
end
|
215
|
+
xml.Transaction(mode: @options[:mode] || 'LIVE', channel: @options[:channel]) do
|
216
|
+
xml.User(login: @options[:login], pwd: @options[:password])
|
217
|
+
yield(xml)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
builder.to_xml
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
@@ -138,6 +138,13 @@ module ActiveMerchant #:nodoc:
|
|
138
138
|
commit(:unstore, post)
|
139
139
|
end
|
140
140
|
|
141
|
+
def verify(credit_card, options={})
|
142
|
+
MultiResponse.run(:use_first_response) do |r|
|
143
|
+
r.process { authorize(100, credit_card, options) }
|
144
|
+
r.process(:ignore_result) { void(r.authorization, options) }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
141
148
|
private
|
142
149
|
def add_reference(post, identification)
|
143
150
|
order_id, transaction_id, authorization, security_key = identification.split(';')
|
@@ -390,4 +397,3 @@ module ActiveMerchant #:nodoc:
|
|
390
397
|
|
391
398
|
end
|
392
399
|
end
|
393
|
-
|
@@ -203,7 +203,7 @@ module ActiveMerchant #:nodoc:
|
|
203
203
|
add_merchant_key(xml, options)
|
204
204
|
xml.tag! 'METHOD', 'CC'
|
205
205
|
xml.tag! 'NOTE', options[:description] if options[:description]
|
206
|
-
xml.tag! 'ORDERID', options[:order_id]
|
206
|
+
xml.tag! 'ORDERID', truncate(options[:order_id], 25)
|
207
207
|
xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
|
208
208
|
end
|
209
209
|
|
@@ -49,7 +49,6 @@ module ActiveMerchant #:nodoc:
|
|
49
49
|
requires!(options, :login)
|
50
50
|
@api_key = options[:login]
|
51
51
|
@fee_refund_api_key = options[:fee_refund_login]
|
52
|
-
@version = options[:version]
|
53
52
|
|
54
53
|
super
|
55
54
|
end
|
@@ -110,6 +109,7 @@ module ActiveMerchant #:nodoc:
|
|
110
109
|
post = {}
|
111
110
|
add_amount(post, money, options)
|
112
111
|
post[:refund_application_fee] = true if options[:refund_application_fee]
|
112
|
+
post[:reverse_transfer] = options[:reverse_transfer] if options[:reverse_transfer]
|
113
113
|
|
114
114
|
MultiResponse.run(:first) do |r|
|
115
115
|
r.process { commit(:post, "charges/#{CGI.escape(identification)}/refund", post, options) }
|
@@ -123,7 +123,7 @@ module ActiveMerchant #:nodoc:
|
|
123
123
|
|
124
124
|
def verify(payment, options = {})
|
125
125
|
MultiResponse.run(:use_first_response) do |r|
|
126
|
-
r.process { authorize(50, payment, options) }
|
126
|
+
r.process { authorize(50, payment, options.merge(currency: "USD")) }
|
127
127
|
r.process(:ignore_result) { void(r.authorization, options) }
|
128
128
|
end
|
129
129
|
end
|
@@ -243,7 +243,7 @@ module ActiveMerchant #:nodoc:
|
|
243
243
|
add_customer_data(post, options)
|
244
244
|
add_metadata(post, options)
|
245
245
|
post[:description] = options[:description]
|
246
|
-
post[:
|
246
|
+
post[:statement_descriptor] = options[:statement_description]
|
247
247
|
add_customer(post, payment, options)
|
248
248
|
add_flags(post, options)
|
249
249
|
end
|
@@ -381,20 +381,23 @@ module ActiveMerchant #:nodoc:
|
|
381
381
|
|
382
382
|
def headers(options = {})
|
383
383
|
key = options[:key] || @api_key
|
384
|
-
version = options[:version] || @version
|
385
384
|
idempotency_key = options[:idempotency_key]
|
386
385
|
|
387
386
|
headers = {
|
388
387
|
"Authorization" => "Basic " + Base64.encode64(key.to_s + ":").strip,
|
389
388
|
"User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
|
389
|
+
"Stripe-Version" => api_version(options),
|
390
390
|
"X-Stripe-Client-User-Agent" => user_agent,
|
391
391
|
"X-Stripe-Client-User-Metadata" => {:ip => options[:ip]}.to_json
|
392
392
|
}
|
393
|
-
headers.merge!("Stripe-Version" => version) if version
|
394
393
|
headers.merge!("Idempotency-Key" => idempotency_key) if idempotency_key
|
395
394
|
headers
|
396
395
|
end
|
397
396
|
|
397
|
+
def api_version(options)
|
398
|
+
options[:version] || @options[:version] || "2015-04-07"
|
399
|
+
end
|
400
|
+
|
398
401
|
def api_request(method, endpoint, parameters = nil, options = {})
|
399
402
|
raw_response = response = nil
|
400
403
|
begin
|
@@ -178,7 +178,8 @@ module ActiveMerchant #:nodoc:
|
|
178
178
|
post[:card] = credit_card.number
|
179
179
|
post[:cvv2] = credit_card.verification_value if credit_card.verification_value?
|
180
180
|
post[:expir] = expdate(credit_card)
|
181
|
-
post[:name] = credit_card.name
|
181
|
+
post[:name] = credit_card.name unless credit_card.name.blank?
|
182
|
+
post[:cardpresent] = true if credit_card.manual_entry
|
182
183
|
end
|
183
184
|
end
|
184
185
|
|
@@ -256,4 +257,3 @@ module ActiveMerchant #:nodoc:
|
|
256
257
|
end
|
257
258
|
end
|
258
259
|
end
|
259
|
-
|
@@ -0,0 +1,280 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module ActiveMerchant
|
4
|
+
module Billing
|
5
|
+
class VancoGateway < Gateway
|
6
|
+
include Empty
|
7
|
+
|
8
|
+
self.test_url = 'https://www.vancodev.com/cgi-bin/wstest2.vps'
|
9
|
+
self.live_url = 'https://www.vancoservices.com/cgi-bin/ws2.vps'
|
10
|
+
|
11
|
+
self.supported_countries = ['US']
|
12
|
+
self.default_currency = 'USD'
|
13
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
14
|
+
|
15
|
+
self.homepage_url = 'http://vancopayments.com/'
|
16
|
+
self.display_name = 'Vanco Payment Solutions'
|
17
|
+
|
18
|
+
def initialize(options={})
|
19
|
+
requires!(options, :user_id, :password, :client_id)
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def purchase(money, payment_method, options={})
|
24
|
+
MultiResponse.run do |r|
|
25
|
+
r.process { commit(login_request) }
|
26
|
+
r.process { commit(purchase_request(money, payment_method, r.params["response_sessionid"], options)) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def refund(money, authorization, options={})
|
31
|
+
MultiResponse.run do |r|
|
32
|
+
r.process { commit(login_request) }
|
33
|
+
r.process { commit(refund_request(money, authorization, r.params["response_sessionid"])) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def supports_scrubbing?
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
def scrub(transcript)
|
42
|
+
transcript.
|
43
|
+
gsub(%r((<Password>).+(</Password>))i, '\1[FILTERED]\2').
|
44
|
+
gsub(%r((<CardCVV2>).+(</CardCVV2>))i, '\1[FILTERED]\2').
|
45
|
+
gsub(%r((<AccountNumber>).+(</AccountNumber>))i, '\1[FILTERED]\2')
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def parse(xml)
|
51
|
+
response = {}
|
52
|
+
|
53
|
+
doc = Nokogiri::XML(xml)
|
54
|
+
doc.root.xpath('*').each do |node|
|
55
|
+
if (node.elements.empty?)
|
56
|
+
response[node.name.downcase.to_sym] = node.text
|
57
|
+
else
|
58
|
+
node.elements.each do |childnode|
|
59
|
+
childnode_to_response(response, node, childnode)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
response
|
65
|
+
end
|
66
|
+
|
67
|
+
def childnode_to_response(response, node, childnode)
|
68
|
+
name = "#{node.name.downcase}_#{childnode.name.downcase}"
|
69
|
+
if name == "response_errors" && !childnode.elements.empty?
|
70
|
+
add_errors_to_response(response, childnode.to_s)
|
71
|
+
else
|
72
|
+
response[name.downcase.to_sym] = childnode.text
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_errors_to_response(response, errors_xml)
|
77
|
+
errors_hash = Hash.from_xml(errors_xml).values.first
|
78
|
+
response[:response_errors] = errors_hash
|
79
|
+
|
80
|
+
error = errors_hash["Error"]
|
81
|
+
if error.kind_of?(Hash)
|
82
|
+
response[:error_message] = error["ErrorDescription"]
|
83
|
+
response[:error_codes] = error["ErrorCode"]
|
84
|
+
elsif error.kind_of?(Array)
|
85
|
+
error_str = error.map { |e| e["ErrorDescription"]}.join(". ")
|
86
|
+
error_codes = error.map { |e| e["ErrorCode"]}.join(", ")
|
87
|
+
response[:error_message] = "#{error_str}."
|
88
|
+
response[:error_codes] = error_codes
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def commit(request)
|
93
|
+
response = parse(ssl_post(url, request, headers))
|
94
|
+
|
95
|
+
succeeded = success_from(response)
|
96
|
+
Response.new(
|
97
|
+
succeeded,
|
98
|
+
message_from(succeeded, response),
|
99
|
+
response,
|
100
|
+
authorization: authorization_from(response),
|
101
|
+
test: test?
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
def success_from(response)
|
106
|
+
!response[:response_errors]
|
107
|
+
end
|
108
|
+
|
109
|
+
def message_from(succeeded, response)
|
110
|
+
return "Success" if succeeded
|
111
|
+
response[:error_message]
|
112
|
+
end
|
113
|
+
|
114
|
+
def authorization_from(response)
|
115
|
+
[
|
116
|
+
response[:response_customerref],
|
117
|
+
response[:response_paymentmethodref],
|
118
|
+
response[:response_transactionref]
|
119
|
+
].join("|")
|
120
|
+
end
|
121
|
+
|
122
|
+
def split_authorization(authorization)
|
123
|
+
authorization.to_s.split('|')
|
124
|
+
end
|
125
|
+
|
126
|
+
def purchase_request(money, payment_method, session_id, options)
|
127
|
+
build_xml_request do |doc|
|
128
|
+
add_auth(doc, "EFTAddCompleteTransaction", session_id)
|
129
|
+
|
130
|
+
doc.Request do
|
131
|
+
doc.RequestVars do
|
132
|
+
add_client_id(doc)
|
133
|
+
add_amount(doc, money, options)
|
134
|
+
add_payment_method(doc, payment_method, options)
|
135
|
+
add_purchase_noise(doc)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def refund_request(money, authorization, session_id)
|
142
|
+
build_xml_request do |doc|
|
143
|
+
add_auth(doc, "EFTAddCredit", session_id)
|
144
|
+
|
145
|
+
doc.Request do
|
146
|
+
doc.RequestVars do
|
147
|
+
add_client_id(doc)
|
148
|
+
add_amount(doc, money, options)
|
149
|
+
add_reference(doc, authorization)
|
150
|
+
add_refund_noise(doc)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def add_request(doc, request_type)
|
157
|
+
doc.RequestType(request_type)
|
158
|
+
doc.RequestID(SecureRandom.hex(15))
|
159
|
+
doc.RequestTime(Time.now)
|
160
|
+
doc.Version(2)
|
161
|
+
end
|
162
|
+
|
163
|
+
def add_auth(doc, request_type, session_id)
|
164
|
+
doc.Auth do
|
165
|
+
add_request(doc, request_type)
|
166
|
+
doc.SessionID(session_id)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def add_reference(doc, authorization)
|
171
|
+
customer_ref, payment_method_ref, transaction_ref = split_authorization(authorization)
|
172
|
+
doc.CustomerRef(customer_ref)
|
173
|
+
doc.PaymentMethodRef(payment_method_ref)
|
174
|
+
doc.TransactionRef(transaction_ref)
|
175
|
+
end
|
176
|
+
|
177
|
+
def add_amount(doc, money, options)
|
178
|
+
if empty?(options[:fund_id])
|
179
|
+
doc.Amount(amount(money))
|
180
|
+
else
|
181
|
+
doc.Funds do
|
182
|
+
doc.Fund do
|
183
|
+
doc.FundID(options[:fund_id])
|
184
|
+
doc.FundAmount(amount(money))
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def add_payment_method(doc, payment_method, options)
|
191
|
+
if card_brand(payment_method) == 'check'
|
192
|
+
add_echeck(doc, payment_method)
|
193
|
+
else
|
194
|
+
add_credit_card(doc, payment_method, options)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def add_credit_card(doc, credit_card, options)
|
199
|
+
address = options[:billing_address]
|
200
|
+
|
201
|
+
doc.AccountNumber(credit_card.number)
|
202
|
+
doc.CustomerName("#{credit_card.last_name}, #{credit_card.first_name}")
|
203
|
+
doc.CardExpMonth(format(credit_card.month, :two_digits))
|
204
|
+
doc.CardExpYear(format(credit_card.year, :two_digits))
|
205
|
+
doc.CardCVV2(credit_card.verification_value)
|
206
|
+
doc.CardBillingName(credit_card.name)
|
207
|
+
doc.CardBillingAddr1(address[:address1])
|
208
|
+
doc.CardBillingAddr2(address[:address2])
|
209
|
+
doc.CardBillingCity(address[:city])
|
210
|
+
doc.CardBillingState(address[:state])
|
211
|
+
doc.CardBillingZip(address[:zip])
|
212
|
+
doc.CardBillingCountryCode(address[:country])
|
213
|
+
doc.AccountType("CC")
|
214
|
+
end
|
215
|
+
|
216
|
+
def add_echeck(doc, echeck)
|
217
|
+
if echeck.account_type == "savings"
|
218
|
+
doc.AccountType("S")
|
219
|
+
else
|
220
|
+
doc.AccountType("C")
|
221
|
+
end
|
222
|
+
|
223
|
+
doc.CustomerName("#{echeck.last_name}, #{echeck.first_name}")
|
224
|
+
doc.AccountNumber(echeck.account_number)
|
225
|
+
doc.RoutingNumber(echeck.routing_number)
|
226
|
+
doc.TransactionTypeCode("TEL")
|
227
|
+
end
|
228
|
+
|
229
|
+
def add_purchase_noise(doc)
|
230
|
+
doc.StartDate("0000-00-00")
|
231
|
+
doc.FrequencyCode("O")
|
232
|
+
end
|
233
|
+
|
234
|
+
def add_refund_noise(doc)
|
235
|
+
doc.ContactName("Bilbo Baggins")
|
236
|
+
doc.ContactPhone("1234567890")
|
237
|
+
doc.ContactExtension("None")
|
238
|
+
doc.ReasonForCredit("Refund requested")
|
239
|
+
end
|
240
|
+
|
241
|
+
def add_client_id(doc)
|
242
|
+
doc.ClientID(@options[:client_id])
|
243
|
+
end
|
244
|
+
|
245
|
+
def login_request
|
246
|
+
build_xml_request do |doc|
|
247
|
+
doc.Auth do
|
248
|
+
add_request(doc, "Login")
|
249
|
+
end
|
250
|
+
|
251
|
+
doc.Request do
|
252
|
+
doc.RequestVars do
|
253
|
+
doc.UserID(@options[:user_id])
|
254
|
+
doc.Password(@options[:password])
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def build_xml_request
|
261
|
+
builder = Nokogiri::XML::Builder.new
|
262
|
+
builder.__send__("VancoWS") do |doc|
|
263
|
+
yield(doc)
|
264
|
+
end
|
265
|
+
builder.to_xml
|
266
|
+
end
|
267
|
+
|
268
|
+
def url
|
269
|
+
(test? ? test_url : live_url)
|
270
|
+
end
|
271
|
+
|
272
|
+
def headers
|
273
|
+
{
|
274
|
+
'Content-Type' => 'text/xml'
|
275
|
+
}
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|