activemerchant 1.44.1 → 1.45.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
- checksums.yaml.gz.sig +1 -3
- data.tar.gz.sig +0 -0
- data/CHANGELOG +48 -0
- data/CONTRIBUTORS +12 -0
- data/README.md +15 -5
- data/lib/active_merchant/billing.rb +2 -0
- data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
- data/lib/active_merchant/billing/gateway.rb +36 -4
- data/lib/active_merchant/billing/gateways/adyen.rb +6 -2
- data/lib/active_merchant/billing/gateways/authorize_net.rb +332 -255
- data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +9 -9
- data/lib/active_merchant/billing/gateways/borgun.rb +0 -1
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +8 -0
- data/lib/active_merchant/billing/gateways/cashnet.rb +17 -10
- data/lib/active_merchant/billing/gateways/checkout.rb +213 -0
- data/lib/active_merchant/billing/gateways/conekta.rb +1 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +1 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +3 -3
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +114 -13
- data/lib/active_merchant/billing/gateways/finansbank.rb +1 -1
- data/lib/active_merchant/billing/gateways/global_transport.rb +183 -0
- data/lib/active_merchant/billing/gateways/hps.rb +27 -20
- data/lib/active_merchant/billing/gateways/iats_payments.rb +68 -35
- data/lib/active_merchant/billing/gateways/litle.rb +36 -1
- data/lib/active_merchant/billing/gateways/merchant_one.rb +0 -1
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +8 -4
- data/lib/active_merchant/billing/gateways/mercury.rb +17 -10
- data/lib/active_merchant/billing/gateways/moneris.rb +11 -6
- data/lib/active_merchant/billing/gateways/moneris_us.rb +126 -33
- data/lib/active_merchant/billing/gateways/money_movers.rb +0 -1
- data/lib/active_merchant/billing/gateways/net_registry.rb +6 -1
- data/lib/active_merchant/billing/gateways/network_merchants.rb +5 -5
- data/lib/active_merchant/billing/gateways/nmi.rb +241 -5
- data/lib/active_merchant/billing/gateways/openpay.rb +1 -0
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -1
- data/lib/active_merchant/billing/gateways/orbital.rb +6 -4
- data/lib/active_merchant/billing/gateways/pay_junction.rb +9 -5
- data/lib/active_merchant/billing/gateways/payex.rb +19 -9
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +2 -2
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
- data/lib/active_merchant/billing/gateways/payscout.rb +0 -2
- data/lib/active_merchant/billing/gateways/pin.rb +1 -1
- data/lib/active_merchant/billing/gateways/psigate.rb +1 -2
- data/lib/active_merchant/billing/gateways/redsys.rb +37 -40
- data/lib/active_merchant/billing/gateways/secure_pay.rb +181 -9
- data/lib/active_merchant/billing/gateways/stripe.rb +106 -31
- data/lib/active_merchant/billing/gateways/tns.rb +227 -0
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +38 -10
- data/lib/active_merchant/billing/gateways/webpay.rb +14 -0
- data/lib/active_merchant/billing/payment_token.rb +21 -0
- data/lib/active_merchant/billing/response.rb +2 -1
- data/lib/active_merchant/country.rb +6 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +8 -3
- metadata.gz.sig +0 -0
- data/lib/active_merchant/billing/gateways/samurai.rb +0 -130
@@ -0,0 +1,225 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
# For more information visit {Bank Frick Acquiring Services}[http://www.bankfrickacquiring.com/merchantsolutions_en.html]
|
6
|
+
#
|
7
|
+
# Written by Piers Chambers (Varyonic.com)
|
8
|
+
class BankFrickGateway < Gateway
|
9
|
+
self.test_url = 'https://test.ctpe.io/payment/ctpe'
|
10
|
+
self.live_url = 'https://ctpe.io/payment/ctpe'
|
11
|
+
|
12
|
+
self.supported_countries = ['LI','US']
|
13
|
+
self.default_currency = 'EUR'
|
14
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
15
|
+
|
16
|
+
self.homepage_url = 'http://www.bankfrickacquiring.com/'
|
17
|
+
self.display_name = 'Bank Frick'
|
18
|
+
|
19
|
+
# The set of supported transactions for this gateway.
|
20
|
+
# More operations are supported by the gateway itself, but
|
21
|
+
# are not supported in this library.
|
22
|
+
SUPPORTED_TRANSACTIONS = {
|
23
|
+
'sale' => 'CC.DB',
|
24
|
+
'authonly' => 'CC.PA',
|
25
|
+
'capture' => 'CC.CP',
|
26
|
+
'refund' => 'CC.RF',
|
27
|
+
'void' => 'CC.RV',
|
28
|
+
}
|
29
|
+
|
30
|
+
def initialize(options={})
|
31
|
+
requires!(options, :sender, :channel, :userid, :userpwd)
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def purchase(money, payment, options={})
|
36
|
+
post = {}
|
37
|
+
add_invoice(post, money, options)
|
38
|
+
add_payment(post, payment)
|
39
|
+
add_address(post, payment, options)
|
40
|
+
add_customer_data(post, options)
|
41
|
+
|
42
|
+
commit('sale', post)
|
43
|
+
end
|
44
|
+
|
45
|
+
def authorize(money, payment, options={})
|
46
|
+
post = {}
|
47
|
+
add_invoice(post, money, options)
|
48
|
+
add_payment(post, payment)
|
49
|
+
add_address(post, payment, options)
|
50
|
+
add_customer_data(post, options)
|
51
|
+
|
52
|
+
commit('authonly', post)
|
53
|
+
end
|
54
|
+
|
55
|
+
def capture(money, authorization, options={})
|
56
|
+
post = {}
|
57
|
+
post[:authorization] = authorization
|
58
|
+
add_invoice(post, money, options)
|
59
|
+
|
60
|
+
commit('capture', post)
|
61
|
+
end
|
62
|
+
|
63
|
+
def refund(money, authorization, options={})
|
64
|
+
post = {}
|
65
|
+
post[:authorization] = authorization
|
66
|
+
add_invoice(post, money, options)
|
67
|
+
|
68
|
+
commit('refund', post)
|
69
|
+
end
|
70
|
+
|
71
|
+
def void(authorization, options={})
|
72
|
+
post = {}
|
73
|
+
post[:authorization] = authorization
|
74
|
+
|
75
|
+
commit('void', post)
|
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
|
+
private
|
86
|
+
|
87
|
+
def add_customer_data(post, options)
|
88
|
+
post[:email] = options[:email] || 'noone@example.com'
|
89
|
+
post[:ip] = options[:ip] || '0.0.0.0'
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_address(post, creditcard, options)
|
93
|
+
if address = options[:billing_address] || options[:address]
|
94
|
+
post[:address] = address[:address1].to_s
|
95
|
+
post[:company] = address[:company].to_s
|
96
|
+
post[:phone] = address[:phone].to_s.gsub(/[^0-9]/, '') || "0000000"
|
97
|
+
post[:zip] = address[:zip].to_s
|
98
|
+
post[:city] = address[:city].to_s
|
99
|
+
post[:country] = address[:country].to_s
|
100
|
+
post[:state] = address[:state].blank? ? 'n/a' : address[:state]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_invoice(post, money, options)
|
105
|
+
post[:order_id] = options[:order_id] if post.has_key? :order_id
|
106
|
+
post[:amount] = amount(money)
|
107
|
+
post[:currency] = (options[:currency] || currency(money))
|
108
|
+
post[:description] = options[:description]
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_payment(post, payment)
|
112
|
+
post[:first_name] = payment.first_name
|
113
|
+
post[:last_name] = payment.last_name
|
114
|
+
post[:brand] = payment.brand
|
115
|
+
post[:card_num] = payment.number
|
116
|
+
post[:card_code] = payment.verification_value if payment.verification_value?
|
117
|
+
post[:exp_year] = payment.year
|
118
|
+
post[:exp_month] = payment.month
|
119
|
+
end
|
120
|
+
|
121
|
+
def parse(body)
|
122
|
+
results = {}
|
123
|
+
xml = Nokogiri::XML(body)
|
124
|
+
resp = xml.xpath("//Response/Transaction/Identification")
|
125
|
+
resp.children.each do |element|
|
126
|
+
results[element.name.downcase.to_sym] = element.text
|
127
|
+
end
|
128
|
+
resp = xml.xpath("//Response/Transaction/Processing")
|
129
|
+
resp.children.each do |element|
|
130
|
+
results[element.name.downcase.to_sym] = element.text
|
131
|
+
end
|
132
|
+
results
|
133
|
+
end
|
134
|
+
|
135
|
+
def commit(action, parameters)
|
136
|
+
url = (test? ? test_url : live_url)
|
137
|
+
headers = {
|
138
|
+
'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'
|
139
|
+
}
|
140
|
+
response = parse(ssl_post(url, post_data(action, parameters), headers))
|
141
|
+
|
142
|
+
Response.new(
|
143
|
+
success_from(response),
|
144
|
+
message_from(response),
|
145
|
+
response,
|
146
|
+
authorization: authorization_from(response),
|
147
|
+
test: test?
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
def success_from(response)
|
152
|
+
response[:result] == 'ACK'
|
153
|
+
end
|
154
|
+
|
155
|
+
def message_from(response)
|
156
|
+
response[:return]
|
157
|
+
end
|
158
|
+
|
159
|
+
def authorization_from(response)
|
160
|
+
response[:uniqueid]
|
161
|
+
end
|
162
|
+
|
163
|
+
def post_data(action, parameters = {})
|
164
|
+
xml = build_xml_request(action, parameters)
|
165
|
+
"load=#{CGI.escape(xml)}"
|
166
|
+
end
|
167
|
+
|
168
|
+
def build_xml_request(action, data)
|
169
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
170
|
+
xml.Request(version: '1.0') do
|
171
|
+
xml.Header do
|
172
|
+
xml.Security(sender: @options[:sender], type: 'MERCHANT')
|
173
|
+
end
|
174
|
+
xml.Transaction(response: 'SYNC', channel: @options[:channel], mode: 'LIVE') do
|
175
|
+
xml.User(pwd: @options[:userpwd], login: @options[:userid])
|
176
|
+
xml.Identification do
|
177
|
+
xml.TransactionID data[:order_id] if data.has_key? :order_id
|
178
|
+
xml.ReferenceID data[:authorization] if data.has_key? :authorization
|
179
|
+
end
|
180
|
+
xml.Account do
|
181
|
+
xml.Holder "#{data[:first_name]} #{data[:last_name]}"
|
182
|
+
xml.Brand data[:brand]
|
183
|
+
xml.Number data[:card_num]
|
184
|
+
xml.Bank data[:bankname]
|
185
|
+
xml.Country data[:country]
|
186
|
+
xml.Authorization data[:authorization]
|
187
|
+
xml.Verification data[:card_code]
|
188
|
+
xml.Year data[:exp_year]
|
189
|
+
xml.Month data[:exp_month]
|
190
|
+
end if data.has_key? :card_num
|
191
|
+
xml.Payment(code: SUPPORTED_TRANSACTIONS[action]) do
|
192
|
+
xml.Presentation do
|
193
|
+
xml.Amount data[:amount]
|
194
|
+
xml.Currency data[:currency]
|
195
|
+
xml.Usage data[:description]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
xml.Customer do
|
199
|
+
xml.Contact do
|
200
|
+
xml.Email data[:email]
|
201
|
+
xml.Mobile data[:mobile]
|
202
|
+
xml.Ip data[:ip]
|
203
|
+
xml.Phone data[:phone]
|
204
|
+
end
|
205
|
+
xml.Address do
|
206
|
+
xml.Street data[:address]
|
207
|
+
xml.Zip data[:zip]
|
208
|
+
xml.City data[:city]
|
209
|
+
xml.State data[:state]
|
210
|
+
xml.Country data[:country]
|
211
|
+
end
|
212
|
+
xml.Name do
|
213
|
+
xml.Salutation data[:salutation]
|
214
|
+
xml.Title data[:title]
|
215
|
+
xml.Given data[:first_name]
|
216
|
+
xml.Family data[:last_name]
|
217
|
+
xml.Company data[:company]
|
218
|
+
end
|
219
|
+
end if data.has_key? :last_name
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -13,7 +13,7 @@ module ActiveMerchant #:nodoc:
|
|
13
13
|
REFUND_ERROR_MESSAGE = "Bogus Gateway: Use trans_id number ending in 1 for exception, 2 for error and anything else for success"
|
14
14
|
CHECK_ERROR_MESSAGE = "Bogus Gateway: Use bank account number ending in 1 for success, 2 for exception and anything else for error"
|
15
15
|
|
16
|
-
self.supported_countries = [
|
16
|
+
self.supported_countries = []
|
17
17
|
self.supported_cardtypes = [:bogus]
|
18
18
|
self.homepage_url = 'http://example.com'
|
19
19
|
self.display_name = 'Bogus'
|
@@ -24,7 +24,7 @@ module ActiveMerchant #:nodoc:
|
|
24
24
|
when /1$/
|
25
25
|
Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money}, :test => true, :authorization => AUTHORIZATION )
|
26
26
|
when /2$/
|
27
|
-
Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money, :error => FAILURE_MESSAGE }, :test => true)
|
27
|
+
Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money, :error => FAILURE_MESSAGE }, :test => true, :error_code => STANDARD_ERROR_CODE[:processing_error])
|
28
28
|
else
|
29
29
|
raise Error, error_message(paysource)
|
30
30
|
end
|
@@ -36,7 +36,7 @@ module ActiveMerchant #:nodoc:
|
|
36
36
|
when /1$/, AUTHORIZATION
|
37
37
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true, :authorization => AUTHORIZATION)
|
38
38
|
when /2$/
|
39
|
-
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }
|
39
|
+
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true, :error_code => STANDARD_ERROR_CODE[:processing_error])
|
40
40
|
else
|
41
41
|
raise Error, error_message(paysource)
|
42
42
|
end
|
@@ -53,7 +53,7 @@ module ActiveMerchant #:nodoc:
|
|
53
53
|
when /1$/
|
54
54
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true )
|
55
55
|
when /2$/
|
56
|
-
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
|
56
|
+
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true, :error_code => STANDARD_ERROR_CODE[:processing_error])
|
57
57
|
else
|
58
58
|
raise Error, error_message(paysource)
|
59
59
|
end
|
@@ -65,7 +65,7 @@ module ActiveMerchant #:nodoc:
|
|
65
65
|
when /1$/
|
66
66
|
raise Error, REFUND_ERROR_MESSAGE
|
67
67
|
when /2$/
|
68
|
-
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
|
68
|
+
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true, :error_code => STANDARD_ERROR_CODE[:processing_error])
|
69
69
|
else
|
70
70
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
71
71
|
end
|
@@ -77,7 +77,7 @@ module ActiveMerchant #:nodoc:
|
|
77
77
|
when /1$/
|
78
78
|
raise Error, CAPTURE_ERROR_MESSAGE
|
79
79
|
when /2$/
|
80
|
-
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
|
80
|
+
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true, :error_code => STANDARD_ERROR_CODE[:processing_error])
|
81
81
|
else
|
82
82
|
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
83
83
|
end
|
@@ -88,7 +88,7 @@ module ActiveMerchant #:nodoc:
|
|
88
88
|
when /1$/
|
89
89
|
raise Error, VOID_ERROR_MESSAGE
|
90
90
|
when /2$/
|
91
|
-
Response.new(false, FAILURE_MESSAGE, {:authorization => reference, :error => FAILURE_MESSAGE }, :test => true)
|
91
|
+
Response.new(false, FAILURE_MESSAGE, {:authorization => reference, :error => FAILURE_MESSAGE }, :test => true, :error_code => STANDARD_ERROR_CODE[:processing_error])
|
92
92
|
else
|
93
93
|
Response.new(true, SUCCESS_MESSAGE, {:authorization => reference}, :test => true)
|
94
94
|
end
|
@@ -99,7 +99,7 @@ module ActiveMerchant #:nodoc:
|
|
99
99
|
when /1$/
|
100
100
|
Response.new(true, SUCCESS_MESSAGE, {:billingid => '1'}, :test => true, :authorization => AUTHORIZATION)
|
101
101
|
when /2$/
|
102
|
-
Response.new(false, FAILURE_MESSAGE, {:billingid => nil, :error => FAILURE_MESSAGE }, :test => true)
|
102
|
+
Response.new(false, FAILURE_MESSAGE, {:billingid => nil, :error => FAILURE_MESSAGE }, :test => true, :error_code => STANDARD_ERROR_CODE[:processing_error])
|
103
103
|
else
|
104
104
|
raise Error, error_message(paysource)
|
105
105
|
end
|
@@ -110,7 +110,7 @@ module ActiveMerchant #:nodoc:
|
|
110
110
|
when /1$/
|
111
111
|
Response.new(true, SUCCESS_MESSAGE, {}, :test => true)
|
112
112
|
when /2$/
|
113
|
-
Response.new(false, FAILURE_MESSAGE, {:error => FAILURE_MESSAGE },:test => true)
|
113
|
+
Response.new(false, FAILURE_MESSAGE, {:error => FAILURE_MESSAGE },:test => true, :error_code => STANDARD_ERROR_CODE[:processing_error])
|
114
114
|
else
|
115
115
|
raise Error, UNSTORE_ERROR_MESSAGE
|
116
116
|
end
|
@@ -7,7 +7,6 @@ module ActiveMerchant #:nodoc:
|
|
7
7
|
|
8
8
|
self.test_url = 'https://gatewaytest.borgun.is/ws/Heimir.pub.ws:Authorization'
|
9
9
|
self.live_url = 'https://gateway01.borgun.is/ws/Heimir.pub.ws:Authorization'
|
10
|
-
self.ssl_version = :SSLv3
|
11
10
|
|
12
11
|
self.supported_countries = ['IS']
|
13
12
|
self.default_currency = 'ISK'
|
@@ -500,6 +500,14 @@ module ActiveMerchant #:nodoc:
|
|
500
500
|
parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address] && !options[:payment_method_token]
|
501
501
|
parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
|
502
502
|
parameters[:channel] = application_id if application_id.present? && application_id != "ActiveMerchant"
|
503
|
+
|
504
|
+
if options[:descriptor_name] || options[:descriptor_phone]
|
505
|
+
parameters[:descriptor] = {
|
506
|
+
name: options[:descriptor_name],
|
507
|
+
phone: options[:descriptor_phone]
|
508
|
+
}
|
509
|
+
end
|
510
|
+
|
503
511
|
parameters
|
504
512
|
end
|
505
513
|
end
|
@@ -18,7 +18,10 @@ module ActiveMerchant #:nodoc:
|
|
18
18
|
# * <tt>:password</tt> -- Password (REQUIRED)
|
19
19
|
# * <tt>:merchant_gateway_name</tt> -- Site name (REQUIRED)
|
20
20
|
# * <tt>:station</tt> -- Station (defaults to "WEB")
|
21
|
-
# * <tt>:
|
21
|
+
# * <tt>:custcode</tt> -- Customer code (defaults to
|
22
|
+
# "ActiveMerchant/#{ActiveMerchant::VERSION}")
|
23
|
+
# * <tt>:default_item_code</tt> -- Default item code (defaults to "FEE",
|
24
|
+
# can be overridden on a per-transaction basis with options[:item_code])
|
22
25
|
def initialize(options = {})
|
23
26
|
requires!(
|
24
27
|
options,
|
@@ -31,18 +34,20 @@ module ActiveMerchant #:nodoc:
|
|
31
34
|
super
|
32
35
|
end
|
33
36
|
|
34
|
-
def purchase(money, payment_object,
|
37
|
+
def purchase(money, payment_object, options = {})
|
35
38
|
post = {}
|
36
39
|
add_creditcard(post, payment_object)
|
37
|
-
add_invoice(post,
|
38
|
-
add_address(post,
|
39
|
-
add_customer_data(post,
|
40
|
+
add_invoice(post, options)
|
41
|
+
add_address(post, options)
|
42
|
+
add_customer_data(post, options)
|
40
43
|
commit('SALE', money, post)
|
41
44
|
end
|
42
45
|
|
43
|
-
def refund(money, identification,
|
44
|
-
|
45
|
-
|
46
|
+
def refund(money, identification, options = {})
|
47
|
+
post = {}
|
48
|
+
post[:origtx] = identification
|
49
|
+
add_invoice(post, options)
|
50
|
+
commit('REFUND', money, post)
|
46
51
|
end
|
47
52
|
|
48
53
|
private
|
@@ -69,8 +74,7 @@ module ActiveMerchant #:nodoc:
|
|
69
74
|
post[:operator] = @options[:operator]
|
70
75
|
post[:password] = @options[:password]
|
71
76
|
post[:station] = (@options[:station] || "WEB")
|
72
|
-
post[:
|
73
|
-
post[:custcode] = "ActiveMerchant/#{ActiveMerchant::VERSION}"
|
77
|
+
post[:custcode] = (@options[:custcode] || "ActiveMerchant/#{ActiveMerchant::VERSION}")
|
74
78
|
post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
75
79
|
end
|
76
80
|
|
@@ -79,10 +83,13 @@ module ActiveMerchant #:nodoc:
|
|
79
83
|
post[:cid] = creditcard.verification_value
|
80
84
|
post[:expdate] = expdate(creditcard)
|
81
85
|
post[:card_name_g] = creditcard.name
|
86
|
+
post[:fname] = creditcard.first_name
|
87
|
+
post[:lname] = creditcard.last_name
|
82
88
|
end
|
83
89
|
|
84
90
|
def add_invoice(post, options)
|
85
91
|
post[:order_number] = options[:order_id] if options[:order_id].present?
|
92
|
+
post[:itemcode] = (options[:item_code] || @options[:default_item_code])
|
86
93
|
end
|
87
94
|
|
88
95
|
def add_address(post, options)
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module ActiveMerchant #:nodoc:
|
5
|
+
module Billing #:nodoc:
|
6
|
+
class CheckoutGateway < Gateway
|
7
|
+
self.default_currency = 'USD'
|
8
|
+
self.money_format = :decimals
|
9
|
+
|
10
|
+
self.supported_countries = ['AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR', 'HR', 'HU', 'IE', 'IS', 'IT', 'LI', 'LT', 'LU', 'LV', 'MT', 'MU', 'NL', 'NO', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK', 'US']
|
11
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
|
12
|
+
|
13
|
+
self.homepage_url = 'https://www.checkout.com/'
|
14
|
+
self.display_name = 'Checkout.com'
|
15
|
+
|
16
|
+
self.live_url = 'https://api.checkout.com/Process/gateway.aspx'
|
17
|
+
|
18
|
+
ACTIONS = {
|
19
|
+
'purchase' => '1',
|
20
|
+
'authorize' => '4',
|
21
|
+
'capture' => '5',
|
22
|
+
'refund' => '2',
|
23
|
+
'void_purchase' => '3',
|
24
|
+
'void_authorize' => '9',
|
25
|
+
'void_capture' => '7'
|
26
|
+
}
|
27
|
+
|
28
|
+
def initialize(options = {})
|
29
|
+
@url = (options[:gateway_url] || self.live_url)
|
30
|
+
|
31
|
+
requires!(options, :merchant_id, :password)
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def purchase(amount, payment_method, options)
|
36
|
+
requires!(options, :order_id)
|
37
|
+
|
38
|
+
commit('purchase', amount, options) do |xml|
|
39
|
+
add_credentials(xml, options)
|
40
|
+
add_invoice(xml, amount, options)
|
41
|
+
add_payment_method(xml, payment_method)
|
42
|
+
add_billing_info(xml, options)
|
43
|
+
add_shipping_info(xml, options)
|
44
|
+
add_user_defined_fields(xml, options)
|
45
|
+
add_other_fields(xml, options)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def authorize(amount, payment_method, options)
|
50
|
+
requires!(options, :order_id)
|
51
|
+
|
52
|
+
commit('authorize', amount, options) do |xml|
|
53
|
+
add_credentials(xml, options)
|
54
|
+
add_invoice(xml, amount, options)
|
55
|
+
add_payment_method(xml, payment_method)
|
56
|
+
add_billing_info(xml, options)
|
57
|
+
add_shipping_info(xml, options)
|
58
|
+
add_user_defined_fields(xml, options)
|
59
|
+
add_other_fields(xml, options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def capture(amount, authorization, options = {})
|
64
|
+
commit('capture', amount, options) do |xml|
|
65
|
+
add_credentials(xml, options)
|
66
|
+
add_reference(xml, authorization)
|
67
|
+
add_invoice(xml, amount, options)
|
68
|
+
add_user_defined_fields(xml, options)
|
69
|
+
add_other_fields(xml, options)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def void(authorization, options = {})
|
74
|
+
_, _, orig_action, amount, currency = split_authorization(authorization)
|
75
|
+
commit("void_#{orig_action}") do |xml|
|
76
|
+
add_credentials(xml, options)
|
77
|
+
add_invoice(xml, amount.to_i, options.merge(currency: currency))
|
78
|
+
add_reference(xml, authorization)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def refund(amount, authorization, options = {})
|
83
|
+
commit('refund') do |xml|
|
84
|
+
add_credentials(xml, options)
|
85
|
+
add_invoice(xml, amount.to_i, options)
|
86
|
+
add_reference(xml, authorization)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def verify(credit_card, options={})
|
91
|
+
MultiResponse.run(:use_first_response) do |r|
|
92
|
+
r.process { authorize(100, credit_card, options) }
|
93
|
+
r.process(:ignore_result) { void(r.authorization, options) }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def add_credentials(xml, options)
|
100
|
+
xml.merchantid_ @options[:merchant_id]
|
101
|
+
xml.password_ @options[:password]
|
102
|
+
end
|
103
|
+
|
104
|
+
def add_invoice(xml, amount, options)
|
105
|
+
xml.bill_amount_ amount(amount)
|
106
|
+
xml.bill_currencycode_ options[:currency] || currency(amount)
|
107
|
+
xml.trackid_ options[:order_id] if options[:order_id]
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_payment_method(xml, payment_method)
|
111
|
+
xml.bill_cardholder_ payment_method.name
|
112
|
+
xml.bill_cc_ payment_method.number
|
113
|
+
xml.bill_expmonth_ format(payment_method.month, :two_digits)
|
114
|
+
xml.bill_expyear_ format(payment_method.year, :four_digits)
|
115
|
+
if payment_method.verification_value?
|
116
|
+
xml.bill_cvv2_ payment_method.verification_value
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_billing_info(xml, options)
|
121
|
+
if options[:billing_address]
|
122
|
+
xml.bill_address_ options[:billing_address][:address1]
|
123
|
+
xml.bill_city_ options[:billing_address][:city]
|
124
|
+
xml.bill_state_ options[:billing_address][:state]
|
125
|
+
xml.bill_postal_ options[:billing_address][:zip]
|
126
|
+
xml.bill_country_ options[:billing_address][:country]
|
127
|
+
xml.bill_phone_ options[:billing_address][:phone]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def add_shipping_info(xml, options)
|
132
|
+
if options[:shipping_address]
|
133
|
+
xml.ship_address_ options[:shipping_address][:address1]
|
134
|
+
xml.ship_address2_ options[:shipping_address][:address2]
|
135
|
+
xml.ship_city_ options[:shipping_address][:city]
|
136
|
+
xml.ship_state_ options[:shipping_address][:state]
|
137
|
+
xml.ship_postal_ options[:shipping_address][:zip]
|
138
|
+
xml.ship_country_ options[:shipping_address][:country]
|
139
|
+
xml.ship_phone_ options[:shipping_address][:phone]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def add_user_defined_fields(xml, options)
|
144
|
+
xml.udf1_ options[:udf1]
|
145
|
+
xml.udf2_ options[:udf2]
|
146
|
+
xml.udf3_ options[:udf3]
|
147
|
+
xml.udf4_ options[:udf4]
|
148
|
+
xml.udf5_ options[:udf5]
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_other_fields(xml, options)
|
152
|
+
xml.bill_email_ options[:email]
|
153
|
+
xml.bill_customerip_ options[:ip]
|
154
|
+
xml.merchantcustomerid_ options[:customer]
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_reference(xml, authorization)
|
158
|
+
transid, trackid, _, _, _ = split_authorization(authorization)
|
159
|
+
xml.transid transid
|
160
|
+
xml.trackid trackid if trackid
|
161
|
+
end
|
162
|
+
|
163
|
+
def commit(action, amount=nil, options={}, &builder)
|
164
|
+
response = parse_xml(ssl_post(@url, build_xml(action, &builder)))
|
165
|
+
Response.new(
|
166
|
+
(response[:responsecode] == "0"),
|
167
|
+
(response[:result] || response[:error_text] || "Unknown Response"),
|
168
|
+
response,
|
169
|
+
authorization: authorization_from(response, action, amount, options),
|
170
|
+
test: test?
|
171
|
+
)
|
172
|
+
end
|
173
|
+
|
174
|
+
def build_xml(action)
|
175
|
+
Nokogiri::XML::Builder.new do |xml|
|
176
|
+
xml.request do
|
177
|
+
xml.action_ ACTIONS[action]
|
178
|
+
yield xml
|
179
|
+
end
|
180
|
+
end.to_xml
|
181
|
+
end
|
182
|
+
|
183
|
+
def parse_xml(xml)
|
184
|
+
response = {}
|
185
|
+
|
186
|
+
Nokogiri::XML(CGI.unescapeHTML(xml)).xpath("//response").children.each do |node|
|
187
|
+
if node.text?
|
188
|
+
next
|
189
|
+
elsif (node.elements.size == 0)
|
190
|
+
response[node.name.downcase.to_sym] = node.text
|
191
|
+
else
|
192
|
+
node.elements.each do |childnode|
|
193
|
+
name = "#{node.name.downcase}_#{childnode.name.downcase}"
|
194
|
+
response[name.to_sym] = childnode.text
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
response
|
200
|
+
end
|
201
|
+
|
202
|
+
def authorization_from(response, action, amount, options)
|
203
|
+
currency = options[:currency] || currency(amount)
|
204
|
+
[response[:tranid], response[:trackid], action, amount, currency].join("|")
|
205
|
+
end
|
206
|
+
|
207
|
+
def split_authorization(authorization)
|
208
|
+
transid, trackid, action, amount, currency = authorization.split("|")
|
209
|
+
[transid, trackid, action, amount, currency]
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|