activemerchant 1.56.0 → 1.57.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 +42 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +52 -21
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -0
- data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +243 -0
- data/lib/active_merchant/billing/gateways/bpoint.rb +1 -1
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +11 -11
- data/lib/active_merchant/billing/gateways/bridge_pay.rb +37 -8
- data/lib/active_merchant/billing/gateways/card_stream.rb +36 -11
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +3 -0
- data/lib/active_merchant/billing/gateways/clearhaus.rb +2 -2
- data/lib/active_merchant/billing/gateways/creditcall.rb +1 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +12 -1
- data/lib/active_merchant/billing/gateways/element.rb +335 -0
- data/lib/active_merchant/billing/gateways/forte.rb +8 -0
- data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
- data/lib/active_merchant/billing/gateways/litle.rb +1 -1
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +2 -1
- data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +165 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +54 -12
- data/lib/active_merchant/billing/gateways/sage.rb +379 -128
- data/lib/active_merchant/billing/gateways/stripe.rb +13 -3
- data/lib/active_merchant/billing/gateways/trans_first.rb +26 -6
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +573 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +7 -0
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +11 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +7 -6
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +0 -89
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +0 -115
- data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +0 -149
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -97
@@ -6,8 +6,8 @@ module ActiveMerchant #:nodoc:
|
|
6
6
|
self.display_name = "BridgePay"
|
7
7
|
self.homepage_url = "http://www.bridgepaynetwork.com/"
|
8
8
|
|
9
|
-
self.test_url = "https://gatewaystage.itstgate.com/SmartPayments/
|
10
|
-
self.live_url = "https://gateway.itstgate.com/SmartPayments/
|
9
|
+
self.test_url = "https://gatewaystage.itstgate.com/SmartPayments/transact3.asmx"
|
10
|
+
self.live_url = "https://gateway.itstgate.com/SmartPayments/transact3.asmx"
|
11
11
|
|
12
12
|
self.supported_countries = ["CA", "US"]
|
13
13
|
self.default_currency = "USD"
|
@@ -75,6 +75,17 @@ module ActiveMerchant #:nodoc:
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
def store(creditcard, options={})
|
79
|
+
post = initialize_required_fields('')
|
80
|
+
post[:transaction] = 'Create'
|
81
|
+
post[:CardNumber] = creditcard.number
|
82
|
+
post[:CustomerPaymentInfoKey] = ''
|
83
|
+
post[:token] = ''
|
84
|
+
add_payment_method(post, creditcard)
|
85
|
+
|
86
|
+
commit(post)
|
87
|
+
end
|
88
|
+
|
78
89
|
def supports_scrubbing?
|
79
90
|
true
|
80
91
|
end
|
@@ -96,6 +107,8 @@ module ActiveMerchant #:nodoc:
|
|
96
107
|
post[:ExpDate] = expdate(payment_method)
|
97
108
|
post[:CardNum] = payment_method.number
|
98
109
|
post[:CVNum] = payment_method.verification_value
|
110
|
+
elsif payment_method.is_a?(String)
|
111
|
+
add_token(post, payment_method)
|
99
112
|
else
|
100
113
|
post[:CheckNum] = payment_method.number
|
101
114
|
post[:TransitNum] = payment_method.routing_number
|
@@ -105,6 +118,11 @@ module ActiveMerchant #:nodoc:
|
|
105
118
|
end
|
106
119
|
end
|
107
120
|
|
121
|
+
def add_token(post, payment_method)
|
122
|
+
payment_method = payment_method.split("|")
|
123
|
+
post[:ExtData] = "<Force>T</Force><CardVault><Transaction>Read</Transaction><CustomerPaymentInfoKey>#{payment_method[1]}</CustomerPaymentInfoKey><Token>#{payment_method[0]}</Token><ExpDate>#{payment_method[2]}</ExpDate></CardVault>"
|
124
|
+
end
|
125
|
+
|
108
126
|
def initialize_required_fields(transaction_type)
|
109
127
|
post = {}
|
110
128
|
post[:TransType] = transaction_type
|
@@ -164,9 +182,8 @@ module ActiveMerchant #:nodoc:
|
|
164
182
|
end
|
165
183
|
|
166
184
|
def commit(parameters)
|
167
|
-
url = url(parameters[:TransitNum] ? 'ProcessCheck' : 'ProcessCreditCard')
|
168
185
|
data = post_data(parameters)
|
169
|
-
raw = parse(ssl_post(url, data))
|
186
|
+
raw = parse(ssl_post(url(parameters), data))
|
170
187
|
|
171
188
|
Response.new(
|
172
189
|
success_from(raw),
|
@@ -177,9 +194,17 @@ module ActiveMerchant #:nodoc:
|
|
177
194
|
)
|
178
195
|
end
|
179
196
|
|
180
|
-
def url(
|
181
|
-
|
182
|
-
|
197
|
+
def url(params)
|
198
|
+
if params[:transaction]
|
199
|
+
"#{base_url}/ManageCardVault"
|
200
|
+
else
|
201
|
+
action = params[:TransitNum] ? 'ProcessCheck' : 'ProcessCreditCard'
|
202
|
+
"#{base_url}/#{action}"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def base_url
|
207
|
+
test? ? test_url : live_url
|
183
208
|
end
|
184
209
|
|
185
210
|
def success_from(response)
|
@@ -191,7 +216,11 @@ module ActiveMerchant #:nodoc:
|
|
191
216
|
end
|
192
217
|
|
193
218
|
def authorization_from(response)
|
194
|
-
|
219
|
+
if response[:token]
|
220
|
+
[response[:token], response[:customerpaymentinfokey], response[:expdate]].join("|")
|
221
|
+
else
|
222
|
+
[response[:authcode], response[:pnref]].join("|")
|
223
|
+
end
|
195
224
|
end
|
196
225
|
|
197
226
|
def split_authorization(authorization)
|
@@ -75,11 +75,12 @@ module ActiveMerchant #:nodoc:
|
|
75
75
|
|
76
76
|
def authorize(money, creditcard, options = {})
|
77
77
|
post = {}
|
78
|
+
add_pair(post, :captureDelay, -1)
|
78
79
|
add_amount(post, money, options)
|
79
80
|
add_invoice(post, creditcard, money, options)
|
80
81
|
add_creditcard(post, creditcard)
|
81
82
|
add_customer_data(post, options)
|
82
|
-
commit('
|
83
|
+
commit('SALE', post)
|
83
84
|
end
|
84
85
|
|
85
86
|
def purchase(money, creditcard, options = {})
|
@@ -94,8 +95,9 @@ module ActiveMerchant #:nodoc:
|
|
94
95
|
def capture(money, authorization, options = {})
|
95
96
|
post = {}
|
96
97
|
add_pair(post, :xref, authorization)
|
97
|
-
|
98
|
-
|
98
|
+
add_pair(post, :amount, amount(money), :required => true)
|
99
|
+
|
100
|
+
commit('CAPTURE', post)
|
99
101
|
end
|
100
102
|
|
101
103
|
def refund(money, authorization, options = {})
|
@@ -154,8 +156,8 @@ module ActiveMerchant #:nodoc:
|
|
154
156
|
add_pair(post, :item1GrossValue, amount(money))
|
155
157
|
end
|
156
158
|
|
157
|
-
add_pair(post, :threeDSRequired, (options[:threeds_required] || @threeds_required) ? 'Y' : 'N')
|
158
159
|
add_pair(post, :type, options[:type] || '1')
|
160
|
+
add_threeds_required(post, options)
|
159
161
|
end
|
160
162
|
|
161
163
|
def add_creditcard(post, credit_card)
|
@@ -175,6 +177,10 @@ module ActiveMerchant #:nodoc:
|
|
175
177
|
add_pair(post, :cardCVV, credit_card.verification_value)
|
176
178
|
end
|
177
179
|
|
180
|
+
def add_threeds_required(post, options)
|
181
|
+
add_pair(post, :threeDSRequired, (options[:threeds_required] || @threeds_required) ? 'Y' : 'N')
|
182
|
+
end
|
183
|
+
|
178
184
|
def add_hmac(post)
|
179
185
|
result = post.sort.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
180
186
|
result = Digest::SHA512.hexdigest("#{result}#{@options[:shared_secret]}")
|
@@ -194,11 +200,10 @@ module ActiveMerchant #:nodoc:
|
|
194
200
|
end
|
195
201
|
|
196
202
|
def commit(action, parameters)
|
197
|
-
|
203
|
+
parameters.update(:countryCode => self.supported_countries[0]) unless action == 'CAPTURE'
|
198
204
|
parameters.update(
|
199
205
|
:merchantID => @options[:login],
|
200
|
-
:action => action
|
201
|
-
:countryCode => self.supported_countries[0],
|
206
|
+
:action => action
|
202
207
|
)
|
203
208
|
# adds a signature to the post hash/array
|
204
209
|
add_hmac(parameters)
|
@@ -211,13 +216,32 @@ module ActiveMerchant #:nodoc:
|
|
211
216
|
:test => test?,
|
212
217
|
:authorization => response[:xref],
|
213
218
|
:cvv_result => CVV_CODE[response[:avscv2ResponseCode].to_s[0, 1]],
|
214
|
-
:avs_result =>
|
215
|
-
:postal_match => AVS_POSTAL_MATCH[response[:avscv2ResponseCode].to_s[1, 1]],
|
216
|
-
:street_match => AVS_STREET_MATCH[response[:avscv2ResponseCode].to_s[2, 1]]
|
217
|
-
}
|
219
|
+
:avs_result => avs_from(response)
|
218
220
|
)
|
219
221
|
end
|
220
222
|
|
223
|
+
def avs_from(response)
|
224
|
+
postal_match = AVS_POSTAL_MATCH[response[:avscv2ResponseCode].to_s[1, 1]]
|
225
|
+
street_match = AVS_STREET_MATCH[response[:avscv2ResponseCode].to_s[2, 1]]
|
226
|
+
|
227
|
+
code = if postal_match == "Y" && street_match == "Y"
|
228
|
+
"M"
|
229
|
+
elsif postal_match == "Y"
|
230
|
+
"P"
|
231
|
+
elsif street_match == "Y"
|
232
|
+
"A"
|
233
|
+
else
|
234
|
+
"I"
|
235
|
+
end
|
236
|
+
|
237
|
+
AVSResult.new({
|
238
|
+
:code => code,
|
239
|
+
:postal_match => postal_match,
|
240
|
+
:street_match => street_match
|
241
|
+
})
|
242
|
+
end
|
243
|
+
|
244
|
+
|
221
245
|
def currency_code(currency)
|
222
246
|
CURRENCY_CODES[currency]
|
223
247
|
end
|
@@ -229,6 +253,7 @@ module ActiveMerchant #:nodoc:
|
|
229
253
|
def add_pair(post, key, value, options = {})
|
230
254
|
post[key] = value if !value.blank? || options[:required]
|
231
255
|
end
|
256
|
+
|
232
257
|
end
|
233
258
|
end
|
234
259
|
end
|
@@ -78,6 +78,9 @@ module ActiveMerchant #:nodoc:
|
|
78
78
|
post[:value] = amount(money)
|
79
79
|
post[:trackId] = options[:order_id]
|
80
80
|
post[:currency] = options[:currency] || currency(money)
|
81
|
+
post[:descriptor] = {}
|
82
|
+
post[:descriptor][:name] = options[:descriptor_name] if options[:descriptor_name]
|
83
|
+
post[:descriptor][:city] = options[:descriptor_city] if options[:descriptor_city]
|
81
84
|
end
|
82
85
|
|
83
86
|
def add_payment_method(post, payment_method)
|
@@ -90,7 +90,7 @@ module ActiveMerchant #:nodoc:
|
|
90
90
|
# options - A standard ActiveMerchant options hash
|
91
91
|
def capture(amount, authorization, options={})
|
92
92
|
post = {}
|
93
|
-
|
93
|
+
add_invoice(post, amount, options)
|
94
94
|
|
95
95
|
commit("/authorizations/#{authorization}/captures", post)
|
96
96
|
end
|
@@ -145,7 +145,7 @@ module ActiveMerchant #:nodoc:
|
|
145
145
|
def add_invoice(post, money, options)
|
146
146
|
add_amount(post, money, options)
|
147
147
|
post[:reference] = options[:order_id] if options[:order_id]
|
148
|
-
post[:text_on_statement] = options[:
|
148
|
+
post[:text_on_statement] = options[:text_on_statement] if options[:text_on_statement]
|
149
149
|
end
|
150
150
|
|
151
151
|
def add_amount(post, amount, options)
|
@@ -120,7 +120,7 @@ module ActiveMerchant #:nodoc:
|
|
120
120
|
|
121
121
|
def add_card_details(xml, payment_method, options={})
|
122
122
|
xml.CardDetails do
|
123
|
-
xml.Manual(type: "
|
123
|
+
xml.Manual(type: "ecommerce") do
|
124
124
|
xml.PAN payment_method.number
|
125
125
|
xml.ExpiryDate exp_date(payment_method)
|
126
126
|
xml.CSC payment_method.verification_value unless empty?(payment_method.verification_value)
|
@@ -33,7 +33,7 @@ module ActiveMerchant #:nodoc:
|
|
33
33
|
self.test_url = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor'
|
34
34
|
self.live_url = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor'
|
35
35
|
|
36
|
-
XSD_VERSION = "1.
|
36
|
+
XSD_VERSION = "1.121"
|
37
37
|
|
38
38
|
# visa, master, american_express, discover
|
39
39
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
@@ -261,6 +261,7 @@ module ActiveMerchant #:nodoc:
|
|
261
261
|
def build_auth_request(money, creditcard_or_reference, options)
|
262
262
|
xml = Builder::XmlMarkup.new :indent => 2
|
263
263
|
add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
|
264
|
+
add_mdd_fields(xml, options)
|
264
265
|
add_auth_service(xml, creditcard_or_reference, options)
|
265
266
|
add_business_rules_data(xml, creditcard_or_reference, options)
|
266
267
|
xml.target!
|
@@ -291,6 +292,7 @@ module ActiveMerchant #:nodoc:
|
|
291
292
|
def build_purchase_request(money, payment_method_or_reference, options)
|
292
293
|
xml = Builder::XmlMarkup.new :indent => 2
|
293
294
|
add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
|
295
|
+
add_mdd_fields(xml, options)
|
294
296
|
if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
|
295
297
|
add_check_service(xml)
|
296
298
|
else
|
@@ -476,6 +478,15 @@ module ActiveMerchant #:nodoc:
|
|
476
478
|
end
|
477
479
|
end
|
478
480
|
|
481
|
+
def add_mdd_fields(xml, options)
|
482
|
+
xml.tag! 'merchantDefinedData' do
|
483
|
+
(1..20).each do |each|
|
484
|
+
key = "mdd_field_#{each}".to_sym
|
485
|
+
xml.tag!("field#{each}", options[key]) if options[key]
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
479
490
|
def add_check(xml, check)
|
480
491
|
xml.tag! 'check' do
|
481
492
|
xml.tag! 'accountNumber', check.account_number
|
@@ -0,0 +1,335 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module ActiveMerchant #:nodoc:
|
5
|
+
module Billing #:nodoc:
|
6
|
+
class ElementGateway < Gateway
|
7
|
+
self.test_url = 'https://certtransaction.elementexpress.com/express.asmx'
|
8
|
+
self.live_url = 'https://transaction.elementexpress.com/express.asmx'
|
9
|
+
|
10
|
+
self.supported_countries = ['US']
|
11
|
+
self.default_currency = 'USD'
|
12
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
13
|
+
|
14
|
+
self.homepage_url = 'http://www.elementps.com'
|
15
|
+
self.display_name = 'Element'
|
16
|
+
|
17
|
+
SERVICE_TEST_URL = 'https://certservices.elementexpress.com/express.asmx'
|
18
|
+
SERVICE_LIVE_URL = 'https://service.elementexpress.com/express.asmx'
|
19
|
+
|
20
|
+
def initialize(options={})
|
21
|
+
requires!(options, :account_id, :account_token, :application_id, :acceptor_id, :application_name, :application_version)
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def purchase(money, payment, options={})
|
26
|
+
action = payment.is_a?(Check) ? "CheckSale" : "CreditCardSale"
|
27
|
+
|
28
|
+
request = build_soap_request do |xml|
|
29
|
+
xml.send(action, xmlns: "https://transaction.elementexpress.com") do
|
30
|
+
add_credentials(xml)
|
31
|
+
add_payment_method(xml, payment)
|
32
|
+
add_transaction(xml, money)
|
33
|
+
add_terminal(xml, options)
|
34
|
+
add_address(xml, options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
commit(action, request, money)
|
39
|
+
end
|
40
|
+
|
41
|
+
def authorize(money, payment, options={})
|
42
|
+
request = build_soap_request do |xml|
|
43
|
+
xml.CreditCardAuthorization(xmlns: "https://transaction.elementexpress.com") do
|
44
|
+
add_credentials(xml)
|
45
|
+
add_payment_method(xml, payment)
|
46
|
+
add_transaction(xml, money)
|
47
|
+
add_terminal(xml, options)
|
48
|
+
add_address(xml, options)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
commit('CreditCardAuthorization', request, money)
|
53
|
+
end
|
54
|
+
|
55
|
+
def capture(money, authorization, options={})
|
56
|
+
trans_id, _ = split_authorization(authorization)
|
57
|
+
options.merge!({trans_id: trans_id})
|
58
|
+
|
59
|
+
request = build_soap_request do |xml|
|
60
|
+
xml.CreditCardAuthorizationCompletion(xmlns: "https://transaction.elementexpress.com") do
|
61
|
+
add_credentials(xml)
|
62
|
+
add_transaction(xml, money, options)
|
63
|
+
add_terminal(xml, options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
commit('CreditCardAuthorizationCompletion', request, money)
|
68
|
+
end
|
69
|
+
|
70
|
+
def refund(money, authorization, options={})
|
71
|
+
trans_id, _ = split_authorization(authorization)
|
72
|
+
options.merge!({trans_id: trans_id})
|
73
|
+
|
74
|
+
request = build_soap_request do |xml|
|
75
|
+
xml.CreditCardReturn(xmlns: "https://transaction.elementexpress.com") do
|
76
|
+
add_credentials(xml)
|
77
|
+
add_transaction(xml, money, options)
|
78
|
+
add_terminal(xml, options)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
commit('CreditCardReturn', request, money)
|
83
|
+
end
|
84
|
+
|
85
|
+
def void(authorization, options={})
|
86
|
+
trans_id, trans_amount = split_authorization(authorization)
|
87
|
+
options.merge!({trans_id: trans_id, trans_amount: trans_amount, reversal_type: "Full"})
|
88
|
+
|
89
|
+
request = build_soap_request do |xml|
|
90
|
+
xml.CreditCardReversal(xmlns: "https://transaction.elementexpress.com") do
|
91
|
+
add_credentials(xml)
|
92
|
+
add_transaction(xml, trans_amount, options)
|
93
|
+
add_terminal(xml, options)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
commit('CreditCardReversal', request, trans_amount)
|
98
|
+
end
|
99
|
+
|
100
|
+
def store(payment, options = {})
|
101
|
+
request = build_soap_request do |xml|
|
102
|
+
xml.PaymentAccountCreate(xmlns: "https://services.elementexpress.com") do
|
103
|
+
add_credentials(xml)
|
104
|
+
add_payment_method(xml, payment)
|
105
|
+
add_payment_account(xml, payment, options[:payment_account_reference_number] || SecureRandom.hex(20))
|
106
|
+
add_address(xml, options)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
commit('PaymentAccountCreate', request, nil)
|
111
|
+
end
|
112
|
+
|
113
|
+
def verify(credit_card, options={})
|
114
|
+
MultiResponse.run(:use_first_response) do |r|
|
115
|
+
r.process { authorize(100, credit_card, options) }
|
116
|
+
r.process(:ignore_result) { void(r.authorization, options) }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def supports_scrubbing?
|
121
|
+
true
|
122
|
+
end
|
123
|
+
|
124
|
+
def scrub(transcript)
|
125
|
+
transcript.
|
126
|
+
gsub(%r((<AccountToken>).+?(</AccountToken>))i, '\1[FILTERED]\2').
|
127
|
+
gsub(%r((<CardNumber>).+?(</CardNumber>))i, '\1[FILTERED]\2').
|
128
|
+
gsub(%r((<CVV>).+?(</CVV>))i, '\1[FILTERED]\2').
|
129
|
+
gsub(%r((<AccountNumber>).+?(</AccountNumber>))i, '\1[FILTERED]\2').
|
130
|
+
gsub(%r((<RoutingNumber>).+?(</RoutingNumber>))i, '\1[FILTERED]\2')
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def add_credentials(xml)
|
136
|
+
xml.credentials do
|
137
|
+
xml.AccountID @options[:account_id]
|
138
|
+
xml.AccountToken @options[:account_token]
|
139
|
+
xml.AcceptorID @options[:acceptor_id]
|
140
|
+
end
|
141
|
+
xml.application do
|
142
|
+
xml.ApplicationID @options[:application_id]
|
143
|
+
xml.ApplicationName @options[:application_name]
|
144
|
+
xml.ApplicationVersion @options[:application_version]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def add_payment_method(xml, payment)
|
149
|
+
if payment.is_a?(String)
|
150
|
+
add_payment_account_id(xml, payment)
|
151
|
+
elsif payment.is_a?(Check)
|
152
|
+
add_echeck(xml, payment)
|
153
|
+
else
|
154
|
+
add_credit_card(xml, payment)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def add_payment_account(xml, payment, payment_account_reference_number)
|
159
|
+
xml.paymentAccount do
|
160
|
+
xml.PaymentAccountType payment_account_type(payment)
|
161
|
+
xml.PaymentAccountReferenceNumber payment_account_reference_number
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def add_payment_account_id(xml, payment)
|
166
|
+
xml.extendedParameters do
|
167
|
+
xml.ExtendedParameters do
|
168
|
+
xml.Key "PaymentAccount"
|
169
|
+
xml.Value("xsi:type" => "PaymentAccount") do
|
170
|
+
xml.PaymentAccountID payment
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def add_transaction(xml, money, options = {})
|
177
|
+
xml.transaction do
|
178
|
+
xml.ReversalType options[:reversal_type] if options[:reversal_type]
|
179
|
+
xml.TransactionID options[:trans_id] if options[:trans_id]
|
180
|
+
xml.TransactionAmount amount(money.to_i) if money
|
181
|
+
xml.MarketCode "Default" if money
|
182
|
+
xml.ReferenceNumber options[:order_id] || SecureRandom.hex(20)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_terminal(xml, options)
|
187
|
+
xml.terminal do
|
188
|
+
xml.TerminalID "01"
|
189
|
+
xml.CardPresentCode "UseDefault"
|
190
|
+
xml.CardholderPresentCode "UseDefault"
|
191
|
+
xml.CardInputCode "UseDefault"
|
192
|
+
xml.CVVPresenceCode "UseDefault"
|
193
|
+
xml.TerminalCapabilityCode "UseDefault"
|
194
|
+
xml.TerminalEnvironmentCode "UseDefault"
|
195
|
+
xml.MotoECICode "NonAuthenticatedSecureECommerceTransaction"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def add_credit_card(xml, payment)
|
200
|
+
xml.card do
|
201
|
+
xml.CardNumber payment.number
|
202
|
+
xml.ExpirationMonth format(payment.month, :two_digits)
|
203
|
+
xml.ExpirationYear format(payment.year, :two_digits)
|
204
|
+
xml.CardholderName payment.first_name + " " + payment.last_name
|
205
|
+
xml.CVV payment.verification_value
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def add_echeck(xml, payment)
|
210
|
+
xml.demandDepositAccount do
|
211
|
+
xml.AccountNumber payment.account_number
|
212
|
+
xml.RoutingNumber payment.routing_number
|
213
|
+
xml.DDAAccountType payment.account_type.capitalize
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def add_address(xml, options)
|
218
|
+
if address = options[:billing_address] || options[:address]
|
219
|
+
xml.address do
|
220
|
+
xml.BillingAddress1 address[:address1] if address[:address1]
|
221
|
+
xml.BillingAddress2 address[:address2] if address[:address2]
|
222
|
+
xml.BillingCity address[:city] if address[:city]
|
223
|
+
xml.BillingState address[:state] if address[:state]
|
224
|
+
xml.BillingZipcode address[:zip] if address[:zip]
|
225
|
+
xml.BillingEmail address[:email] if address[:email]
|
226
|
+
xml.BillingPhone address[:phone_number] if address[:phone_number]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def parse(xml)
|
232
|
+
response = {}
|
233
|
+
|
234
|
+
doc = Nokogiri::XML(xml)
|
235
|
+
doc.remove_namespaces!
|
236
|
+
root = doc.root.xpath("//response/*")
|
237
|
+
|
238
|
+
if root.empty?
|
239
|
+
root = doc.root.xpath("//Response/*")
|
240
|
+
end
|
241
|
+
|
242
|
+
root.each do |node|
|
243
|
+
if (node.elements.empty?)
|
244
|
+
response[node.name.downcase] = node.text
|
245
|
+
else
|
246
|
+
node_name = node.name.downcase
|
247
|
+
response[node_name] = Hash.new
|
248
|
+
|
249
|
+
node.elements.each do |childnode|
|
250
|
+
response[node_name][childnode.name.downcase] = childnode.text
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
response
|
256
|
+
end
|
257
|
+
|
258
|
+
def commit(action, xml, amount)
|
259
|
+
response = parse(ssl_post(url(action), xml, headers(action)))
|
260
|
+
|
261
|
+
Response.new(
|
262
|
+
success_from(response),
|
263
|
+
message_from(response),
|
264
|
+
response,
|
265
|
+
authorization: authorization_from(action, response, amount),
|
266
|
+
test: test?
|
267
|
+
)
|
268
|
+
end
|
269
|
+
|
270
|
+
def authorization_from(action, response, amount)
|
271
|
+
if action == "PaymentAccountCreate"
|
272
|
+
response["paymentaccount"]["paymentaccountid"]
|
273
|
+
else
|
274
|
+
"#{response['transaction']['transactionid']}|#{amount}" if response['transaction']
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def success_from(response)
|
279
|
+
response["expressresponsecode"] == "0"
|
280
|
+
end
|
281
|
+
|
282
|
+
def message_from(response)
|
283
|
+
response["expressresponsemessage"]
|
284
|
+
end
|
285
|
+
|
286
|
+
def split_authorization(authorization)
|
287
|
+
authorization.split("|")
|
288
|
+
end
|
289
|
+
|
290
|
+
def build_soap_request
|
291
|
+
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
292
|
+
xml['soap'].Envelope('xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
293
|
+
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
|
294
|
+
'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/') do
|
295
|
+
|
296
|
+
xml['soap'].Body do
|
297
|
+
yield(xml)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
builder.to_xml
|
303
|
+
end
|
304
|
+
|
305
|
+
def payment_account_type(payment)
|
306
|
+
if payment.is_a?(Check)
|
307
|
+
payment_account_type = payment.account_type
|
308
|
+
else
|
309
|
+
payment_account_type = "CreditCard"
|
310
|
+
end
|
311
|
+
payment_account_type
|
312
|
+
end
|
313
|
+
|
314
|
+
def url(action)
|
315
|
+
if action == "PaymentAccountCreate"
|
316
|
+
url = (test? ? SERVICE_TEST_URL : SERVICE_LIVE_URL)
|
317
|
+
else
|
318
|
+
url = (test? ? test_url : live_url)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def interface(action)
|
323
|
+
return "transaction" if action != "PaymentAccountCreate"
|
324
|
+
return "services" if action == "PaymentAccountCreate"
|
325
|
+
end
|
326
|
+
|
327
|
+
def headers(action)
|
328
|
+
{
|
329
|
+
"Content-Type" => "text/xml; charset=utf-8",
|
330
|
+
"SOAPAction" => "https://#{interface(action)}.elementexpress.com/#{action}"
|
331
|
+
}
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|