tomriley-active_merchant 1.4.2.3 → 1.4.2.4
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.
- data/CHANGELOG +14 -0
- data/CONTRIBUTERS +12 -0
- data/active_merchant.gemspec +3 -2
- data/init.rb +0 -1
- data/lib/active_merchant/billing/credit_card_methods.rb +1 -1
- data/lib/active_merchant/billing/expiry_date.rb +10 -4
- data/lib/active_merchant/billing/gateway.rb +4 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +12 -1
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +2 -1
- data/lib/active_merchant/billing/gateways/bogus.rb +19 -0
- data/lib/active_merchant/billing/gateways/eway.rb +6 -1
- data/lib/active_merchant/billing/gateways/first_pay.rb +172 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +283 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +259 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +22 -9
- data/lib/active_merchant/billing/gateways/{protx.rb → sage_pay.rb} +45 -12
- data/lib/active_merchant/billing/integrations/nochex/notification.rb +1 -1
- data/lib/active_merchant/billing/response.rb +9 -1
- data/test/fixtures.yml +16 -1
- data/test/remote/gateways/remote_first_pay_test.rb +87 -0
- data/test/remote/gateways/remote_merchant_ware_test.rb +113 -0
- data/test/remote/gateways/remote_ogone_test.rb +108 -0
- data/test/remote/gateways/remote_paypal_test.rb +12 -1
- data/test/remote/gateways/remote_protx_three_d_secure_test.rb +259 -0
- data/test/remote/gateways/{remote_protx_test.rb → remote_sage_pay_test.rb} +8 -8
- data/test/unit/credit_card_methods_test.rb +9 -0
- data/test/unit/expiry_date_test.rb +12 -1
- data/test/unit/gateways/bogus_test.rb +31 -0
- data/test/unit/gateways/first_pay_test.rb +125 -0
- data/test/unit/gateways/gateway_test.rb +6 -0
- data/test/unit/gateways/merchant_ware_test.rb +188 -0
- data/test/unit/gateways/ogone_test.rb +256 -0
- data/test/unit/gateways/paypal_test.rb +49 -0
- data/test/unit/gateways/sage_pay_test.rb +183 -0
- data/test/unit/integrations/notifications/nochex_notification_test.rb +1 -1
- data/test/unit/response_test.rb +16 -0
- metadata +16 -5
- data/test/unit/gateways/protx_test.rb +0 -139
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
require 'rexml/document'
|
|
2
|
+
|
|
3
|
+
module ActiveMerchant #:nodoc:
|
|
4
|
+
module Billing #:nodoc:
|
|
5
|
+
# = Ogone DirectLink Gateway
|
|
6
|
+
#
|
|
7
|
+
# DirectLink is the API version of the Ogone Payment Platform. It allows server to server
|
|
8
|
+
# communication between Ogone systems and your e-commerce website.
|
|
9
|
+
#
|
|
10
|
+
# This implementation follows the specification provided in the DirectLink integration
|
|
11
|
+
# guide version 2.4 (December 2008), available here:
|
|
12
|
+
# https://secure.ogone.com/ncol/Ogone_DirectLink_EN.pdf
|
|
13
|
+
#
|
|
14
|
+
# It also features aliases, which allow to store/unstore credit cards, as specified in
|
|
15
|
+
# the Alias Manager Option guide version 2.2 available here:
|
|
16
|
+
# https://secure.ogone.com/ncol/Ogone_Alias_EN.pdf
|
|
17
|
+
#
|
|
18
|
+
# It was last tested on Release 04.79 of Ogone e-Commerce (dated 11/02/2009).
|
|
19
|
+
#
|
|
20
|
+
# For any questions or comments, please contact Nicolas Jacobeus (nj@belighted.com).
|
|
21
|
+
#
|
|
22
|
+
# == Example use:
|
|
23
|
+
#
|
|
24
|
+
# gateway = ActiveMerchant::Billing::OgoneGateway.new(
|
|
25
|
+
# :login => "my_ogone_psp_id",
|
|
26
|
+
# :user => "my_ogone_user_id",
|
|
27
|
+
# :password => "my_ogone_pswd",
|
|
28
|
+
# :signature => "my_ogone_sha1_signature" # extra security, only if you configured your Ogone environment so
|
|
29
|
+
# )
|
|
30
|
+
#
|
|
31
|
+
# # set up credit card obj as in main ActiveMerchant example
|
|
32
|
+
# creditcard = ActiveMerchant::Billing::CreditCard.new(
|
|
33
|
+
# :type => 'visa',
|
|
34
|
+
# :number => '4242424242424242',
|
|
35
|
+
# :month => 8,
|
|
36
|
+
# :year => 2009,
|
|
37
|
+
# :first_name => 'Bob',
|
|
38
|
+
# :last_name => 'Bobsen'
|
|
39
|
+
# )
|
|
40
|
+
#
|
|
41
|
+
# # run request
|
|
42
|
+
# response = gateway.purchase(1000, creditcard, :order_id => "1") # charge 10 EUR
|
|
43
|
+
#
|
|
44
|
+
# If you don't provide an :order_id, the gateway will generate a random one for you.
|
|
45
|
+
#
|
|
46
|
+
# puts response.success? # Check whether the transaction was successful
|
|
47
|
+
# puts response.message # Retrieve the message returned by Ogone
|
|
48
|
+
# puts response.authorization # Retrieve the unique transaction ID returned by Ogone
|
|
49
|
+
#
|
|
50
|
+
# To use the alias feature, simply add :alias in the options hash:
|
|
51
|
+
#
|
|
52
|
+
# gateway.purchase(1000, creditcard, :order_id => "1", :alias => "myawesomecustomer") # associates the alias to that creditcard
|
|
53
|
+
# gateway.purchase(2000, nil, :order_id => "2", :alias => "myawesomecustomer") # don't need to know the creditcard for subsequent orders
|
|
54
|
+
#
|
|
55
|
+
class OgoneGateway < Gateway
|
|
56
|
+
|
|
57
|
+
URLS = {
|
|
58
|
+
:test => { :order => 'https://secure.ogone.com/ncol/test/orderdirect.asp',
|
|
59
|
+
:maintenance => 'https://secure.ogone.com/ncol/test/maintenancedirect.asp' },
|
|
60
|
+
:production => { :order => 'https://secure.ogone.com/ncol/prod/orderdirect.asp',
|
|
61
|
+
:maintenance => 'https://secure.ogone.com/ncol/prod/maintenancedirect.asp' }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
CVV_MAPPING = { 'OK' => 'M',
|
|
65
|
+
'KO' => 'N',
|
|
66
|
+
'NO' => 'P' }
|
|
67
|
+
|
|
68
|
+
AVS_MAPPING = { 'OK' => 'M',
|
|
69
|
+
'KO' => 'N',
|
|
70
|
+
'NO' => 'R' }
|
|
71
|
+
SUCCESS_MESSAGE = "The transaction was successful"
|
|
72
|
+
|
|
73
|
+
self.supported_countries = ['BE', 'DE', 'FR', 'NL', 'AT', 'CH']
|
|
74
|
+
# also supports Airplus and UATP
|
|
75
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover, :jcb, :maestro]
|
|
76
|
+
self.homepage_url = 'http://www.ogone.com/'
|
|
77
|
+
self.display_name = 'Ogone'
|
|
78
|
+
self.default_currency = 'EUR'
|
|
79
|
+
self.money_format = :cents
|
|
80
|
+
|
|
81
|
+
def initialize(options = {})
|
|
82
|
+
requires!(options, :login, :user, :password)
|
|
83
|
+
@options = options
|
|
84
|
+
super
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Verify and reserve the specified amount on the account, without actually doing the transaction.
|
|
88
|
+
def authorize(money, payment_source, options = {})
|
|
89
|
+
post = {}
|
|
90
|
+
add_invoice(post, options)
|
|
91
|
+
add_payment_source(post, payment_source, options)
|
|
92
|
+
add_address(post, payment_source, options)
|
|
93
|
+
add_customer_data(post, options)
|
|
94
|
+
add_money(post, money, options)
|
|
95
|
+
commit('RES', post)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Verify and transfer the specified amount.
|
|
99
|
+
def purchase(money, payment_source, options = {})
|
|
100
|
+
post = {}
|
|
101
|
+
add_invoice(post, options)
|
|
102
|
+
add_payment_source(post, payment_source, options)
|
|
103
|
+
add_address(post, payment_source, options)
|
|
104
|
+
add_customer_data(post, options)
|
|
105
|
+
add_money(post, money, options)
|
|
106
|
+
commit('SAL', post)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Complete a previously authorized transaction.
|
|
110
|
+
def capture(money, authorization, options = {})
|
|
111
|
+
post = {}
|
|
112
|
+
add_authorization(post, reference_from(authorization))
|
|
113
|
+
add_invoice(post, options)
|
|
114
|
+
add_customer_data(post, options)
|
|
115
|
+
add_money(post, money, options)
|
|
116
|
+
commit('SAL', post)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Cancels a previously authorized transaction.
|
|
120
|
+
def void(identification, options = {})
|
|
121
|
+
post = {}
|
|
122
|
+
add_authorization(post, reference_from(identification))
|
|
123
|
+
commit('DES', post)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Credit the specified account by a specific amount.
|
|
127
|
+
def credit(money, identification_or_credit_card, options = {})
|
|
128
|
+
if reference_transaction?(identification_or_credit_card)
|
|
129
|
+
# Referenced credit: refund of a settled transaction
|
|
130
|
+
perform_reference_credit(money, identification_or_credit_card, options)
|
|
131
|
+
else # must be a credit card or card reference
|
|
132
|
+
perform_non_referenced_credit(money, identification_or_credit_card, options)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
def reference_from(authorization)
|
|
138
|
+
authorization.split(";").first
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def reference_transaction?(identifier)
|
|
142
|
+
return false unless identifier.is_a?(String)
|
|
143
|
+
reference, action = identifier.split(";")
|
|
144
|
+
!action.nil?
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def perform_reference_credit(money, payment_target, options = {})
|
|
148
|
+
post = {}
|
|
149
|
+
add_authorization(post, reference_from(payment_target))
|
|
150
|
+
add_money(post, money, options)
|
|
151
|
+
commit('RFD', post)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def perform_non_referenced_credit(money, payment_target, options = {})
|
|
155
|
+
# Non-referenced credit: acts like a reverse purchase
|
|
156
|
+
post = {}
|
|
157
|
+
add_invoice(post, options)
|
|
158
|
+
add_payment_source(post, payment_target, options)
|
|
159
|
+
add_address(post, payment_target, options)
|
|
160
|
+
add_customer_data(post, options)
|
|
161
|
+
add_money(post, money, options)
|
|
162
|
+
commit('RFD', post)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def add_payment_source(post, payment_source, options)
|
|
166
|
+
if payment_source.is_a?(String)
|
|
167
|
+
add_alias(post, payment_source)
|
|
168
|
+
add_eci(post, '9')
|
|
169
|
+
else
|
|
170
|
+
add_alias(post, options[:store])
|
|
171
|
+
add_creditcard(post, payment_source)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def add_eci(post, eci)
|
|
176
|
+
add_pair post, 'ECI', eci
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def add_alias(post, _alias)
|
|
180
|
+
add_pair post, 'ALIAS', _alias
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def add_authorization(post, authorization)
|
|
184
|
+
add_pair post, 'PAYID', authorization
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def add_money(post, money, options)
|
|
188
|
+
add_pair post, 'currency', options[:currency] || currency(money)
|
|
189
|
+
add_pair post, 'amount', amount(money)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def add_customer_data(post, options)
|
|
193
|
+
add_pair post, 'EMAIL', options[:email]
|
|
194
|
+
add_pair post, 'REMOTE_ADDR', options[:ip]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def add_address(post, creditcard, options)
|
|
198
|
+
return unless options[:billing_address]
|
|
199
|
+
add_pair post, 'Owneraddress', options[:billing_address][:address1]
|
|
200
|
+
add_pair post, 'OwnerZip', options[:billing_address][:zip]
|
|
201
|
+
add_pair post, 'ownertown', options[:billing_address][:city]
|
|
202
|
+
add_pair post, 'ownercty', options[:billing_address][:country]
|
|
203
|
+
add_pair post, 'ownertelno', options[:billing_address][:phone]
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def add_invoice(post, options)
|
|
207
|
+
add_pair post, 'orderID', options[:order_id] || generate_unique_id[0...30]
|
|
208
|
+
add_pair post, 'COM', options[:description]
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def add_creditcard(post, creditcard)
|
|
212
|
+
add_pair post, 'CN', creditcard.name
|
|
213
|
+
add_pair post, 'CARDNO', creditcard.number
|
|
214
|
+
add_pair post, 'ED', "%02d%02s" % [creditcard.month, creditcard.year.to_s[-2..-1]]
|
|
215
|
+
add_pair post, 'CVC', creditcard.verification_value
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def parse(body)
|
|
219
|
+
xml = REXML::Document.new(body)
|
|
220
|
+
xml.root.attributes
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def commit(action, parameters)
|
|
224
|
+
add_pair parameters, 'PSPID', @options[:login]
|
|
225
|
+
add_pair parameters, 'USERID', @options[:user]
|
|
226
|
+
add_pair parameters, 'PSWD', @options[:password]
|
|
227
|
+
url = URLS[test? ? :test : :production][parameters['PAYID'] ? :maintenance : :order ]
|
|
228
|
+
response = parse(ssl_post(url, post_data(action, parameters)))
|
|
229
|
+
options = { :authorization => [response["PAYID"], action].join(";"),
|
|
230
|
+
:test => test?,
|
|
231
|
+
:avs_result => { :code => AVS_MAPPING[response["AAVCheck"]] },
|
|
232
|
+
:cvv_result => CVV_MAPPING[response["CVCCheck"]] }
|
|
233
|
+
Response.new(successful?(response), message_from(response), response, options)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def successful?(response)
|
|
237
|
+
response["NCERROR"] == "0"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def message_from(response)
|
|
241
|
+
successful?(response) ? SUCCESS_MESSAGE : response["NCERRORPLUS"].to_s.strip.gsub("|", ", ")
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def post_data(action, parameters = {})
|
|
245
|
+
add_pair parameters, 'Operation' , action
|
|
246
|
+
if @options[:signature] # the user wants a SHA-1 signature
|
|
247
|
+
string = ['orderID','amount','currency','CARDNO','PSPID','Operation','ALIAS'].map{|s|parameters[s]}.join + @options[:signature]
|
|
248
|
+
add_pair parameters, 'SHASign' , Digest::SHA1.hexdigest(string)
|
|
249
|
+
end
|
|
250
|
+
parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def add_pair(post, key, value, options = {})
|
|
254
|
+
post[key] = value if !value.blank? || options[:required]
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
@@ -11,14 +11,14 @@ module ActiveMerchant #:nodoc:
|
|
|
11
11
|
self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside'
|
|
12
12
|
self.display_name = 'PayPal Website Payments Pro (US)'
|
|
13
13
|
|
|
14
|
-
def authorize(money,
|
|
14
|
+
def authorize(money, credit_card_or_referenced_id, options = {})
|
|
15
15
|
requires!(options, :ip)
|
|
16
|
-
commit
|
|
16
|
+
commit define_transaction_type(credit_card_or_referenced_id), build_sale_or_authorization_request('Authorization', money, credit_card_or_referenced_id, options)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def purchase(money,
|
|
19
|
+
def purchase(money, credit_card_or_referenced_id, options = {})
|
|
20
20
|
requires!(options, :ip)
|
|
21
|
-
commit
|
|
21
|
+
commit define_transaction_type(credit_card_or_referenced_id), build_sale_or_authorization_request('Sale', money, credit_card_or_referenced_id, options)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def express
|
|
@@ -26,15 +26,28 @@ module ActiveMerchant #:nodoc:
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
private
|
|
29
|
-
|
|
29
|
+
|
|
30
|
+
def define_transaction_type(transaction_arg)
|
|
31
|
+
if transaction_arg.is_a?(String)
|
|
32
|
+
return 'DoReferenceTransaction'
|
|
33
|
+
else
|
|
34
|
+
return 'DoDirectPayment'
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def build_sale_or_authorization_request(action, money, credit_card_or_referenced_id, options)
|
|
39
|
+
transaction_type = define_transaction_type(credit_card_or_referenced_id)
|
|
40
|
+
reference_id = credit_card_or_referenced_id if transaction_type == "DoReferenceTransaction"
|
|
41
|
+
|
|
30
42
|
billing_address = options[:billing_address] || options[:address]
|
|
31
43
|
currency_code = options[:currency] || currency(money)
|
|
32
44
|
|
|
33
45
|
xml = Builder::XmlMarkup.new :indent => 2
|
|
34
|
-
xml.tag! '
|
|
35
|
-
xml.tag! '
|
|
46
|
+
xml.tag! transaction_type + 'Req', 'xmlns' => PAYPAL_NAMESPACE do
|
|
47
|
+
xml.tag! transaction_type + 'Request', 'xmlns:n2' => EBAY_NAMESPACE do
|
|
36
48
|
xml.tag! 'n2:Version', API_VERSION
|
|
37
|
-
xml.tag! 'n2:
|
|
49
|
+
xml.tag! 'n2:' + transaction_type + 'RequestDetails' do
|
|
50
|
+
xml.tag! 'n2:ReferenceID', reference_id if transaction_type == 'DoReferenceTransaction'
|
|
38
51
|
xml.tag! 'n2:PaymentAction', action
|
|
39
52
|
xml.tag! 'n2:PaymentDetails' do
|
|
40
53
|
xml.tag! 'n2:OrderTotal', amount(money), 'currencyID' => currency_code
|
|
@@ -54,7 +67,7 @@ module ActiveMerchant #:nodoc:
|
|
|
54
67
|
|
|
55
68
|
add_address(xml, 'n2:ShipToAddress', options[:shipping_address]) if options[:shipping_address]
|
|
56
69
|
end
|
|
57
|
-
add_credit_card(xml,
|
|
70
|
+
add_credit_card(xml, credit_card_or_referenced_id, billing_address, options) unless transaction_type == 'DoReferenceTransaction'
|
|
58
71
|
xml.tag! 'n2:IPAddress', options[:ip]
|
|
59
72
|
end
|
|
60
73
|
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
|
3
|
-
class
|
|
3
|
+
class SagePayGateway < Gateway
|
|
4
4
|
cattr_accessor :simulate
|
|
5
5
|
self.simulate = false
|
|
6
6
|
|
|
7
|
-
TEST_URL = 'https://
|
|
8
|
-
LIVE_URL = 'https://
|
|
9
|
-
SIMULATOR_URL = 'https://
|
|
7
|
+
TEST_URL = 'https://test.sagepay.com/gateway/service'
|
|
8
|
+
LIVE_URL = 'https://live.sagepay.com/gateway/service'
|
|
9
|
+
SIMULATOR_URL = 'https://test.sagepay.com/Simulator'
|
|
10
10
|
|
|
11
11
|
APPROVED = 'OK'
|
|
12
12
|
REGISTERED = 'REGISTERED'
|
|
@@ -47,10 +47,11 @@ module ActiveMerchant #:nodoc:
|
|
|
47
47
|
|
|
48
48
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :switch, :solo, :maestro, :diners_club]
|
|
49
49
|
self.supported_countries = ['GB']
|
|
50
|
+
self.supports_3d_secure = true
|
|
50
51
|
self.default_currency = 'GBP'
|
|
51
52
|
|
|
52
|
-
self.homepage_url = 'http://www.
|
|
53
|
-
self.display_name = '
|
|
53
|
+
self.homepage_url = 'http://www.sagepay.com'
|
|
54
|
+
self.display_name = 'SagePay'
|
|
54
55
|
|
|
55
56
|
def initialize(options = {})
|
|
56
57
|
requires!(options, :login)
|
|
@@ -61,6 +62,10 @@ module ActiveMerchant #:nodoc:
|
|
|
61
62
|
def test?
|
|
62
63
|
@options[:test] || super
|
|
63
64
|
end
|
|
65
|
+
|
|
66
|
+
def three_d_secure_enabled?
|
|
67
|
+
@options[:enable_3d_secure]
|
|
68
|
+
end
|
|
64
69
|
|
|
65
70
|
def purchase(money, credit_card, options = {})
|
|
66
71
|
requires!(options, :order_id)
|
|
@@ -71,7 +76,8 @@ module ActiveMerchant #:nodoc:
|
|
|
71
76
|
add_credit_card(post, credit_card)
|
|
72
77
|
add_address(post, options)
|
|
73
78
|
add_customer_data(post, options)
|
|
74
|
-
|
|
79
|
+
add_three_d_secure_flag(post, options)
|
|
80
|
+
|
|
75
81
|
commit(:purchase, post)
|
|
76
82
|
end
|
|
77
83
|
|
|
@@ -84,7 +90,8 @@ module ActiveMerchant #:nodoc:
|
|
|
84
90
|
add_credit_card(post, credit_card)
|
|
85
91
|
add_address(post, options)
|
|
86
92
|
add_customer_data(post, options)
|
|
87
|
-
|
|
93
|
+
add_three_d_secure_flag(post, options)
|
|
94
|
+
|
|
88
95
|
commit(:authorization, post)
|
|
89
96
|
end
|
|
90
97
|
|
|
@@ -152,6 +159,11 @@ module ActiveMerchant #:nodoc:
|
|
|
152
159
|
commit(:credit, post)
|
|
153
160
|
end
|
|
154
161
|
|
|
162
|
+
# Completes a 3D Secure transaction
|
|
163
|
+
def three_d_complete(pa_res, md)
|
|
164
|
+
commit(:three_d_complete, 'PARes' => pa_res, 'MD' => md)
|
|
165
|
+
end
|
|
166
|
+
|
|
155
167
|
private
|
|
156
168
|
def add_reference(post, identification)
|
|
157
169
|
order_id, transaction_id, authorization, security_key = identification.split(';')
|
|
@@ -186,6 +198,14 @@ module ActiveMerchant #:nodoc:
|
|
|
186
198
|
add_pair(post, :BillingPhone, options[:phone].gsub(/[^0-9+]/, '')[0,20]) unless options[:phone].blank?
|
|
187
199
|
add_pair(post, :ClientIPAddress, options[:ip])
|
|
188
200
|
end
|
|
201
|
+
|
|
202
|
+
def add_three_d_secure_flag(post, options)
|
|
203
|
+
if three_d_secure_enabled? && options[:skip_3d_secure] != true
|
|
204
|
+
add_pair(post, :Apply3DSecure, '0')
|
|
205
|
+
else
|
|
206
|
+
add_pair(post, :Apply3DSecure, '2')
|
|
207
|
+
end
|
|
208
|
+
end
|
|
189
209
|
|
|
190
210
|
def add_address(post, options)
|
|
191
211
|
if billing_address = options[:billing_address] || options[:address]
|
|
@@ -270,7 +290,11 @@ module ActiveMerchant #:nodoc:
|
|
|
270
290
|
:street_match => AVS_CVV_CODE[ response["AddressResult"] ],
|
|
271
291
|
:postal_match => AVS_CVV_CODE[ response["PostCodeResult"] ],
|
|
272
292
|
},
|
|
273
|
-
:cvv_result => AVS_CVV_CODE[ response["CV2Result"] ]
|
|
293
|
+
:cvv_result => AVS_CVV_CODE[ response["CV2Result"] ],
|
|
294
|
+
:three_d_secure => response["Status"] == '3DAUTH',
|
|
295
|
+
:pa_req => response["PAReq"],
|
|
296
|
+
:md => response["MD"],
|
|
297
|
+
:acs_url => response["ACSURL"]
|
|
274
298
|
)
|
|
275
299
|
end
|
|
276
300
|
|
|
@@ -300,12 +324,20 @@ module ActiveMerchant #:nodoc:
|
|
|
300
324
|
end
|
|
301
325
|
|
|
302
326
|
def build_url(action)
|
|
303
|
-
|
|
327
|
+
if action == :three_d_complete
|
|
328
|
+
endpoint = 'direct3dcallback'
|
|
329
|
+
else
|
|
330
|
+
endpoint = [ :purchase, :authorization, :authenticate ].include?(action) ? "vspdirect-register" : TRANSACTIONS[action].downcase
|
|
331
|
+
end
|
|
304
332
|
"#{test? ? TEST_URL : LIVE_URL}/#{endpoint}.vsp"
|
|
305
333
|
end
|
|
306
334
|
|
|
307
335
|
def build_simulator_url(action)
|
|
308
|
-
|
|
336
|
+
if action == :three_d_complete
|
|
337
|
+
endpoint = 'VSPDirectCallback.asp'
|
|
338
|
+
else
|
|
339
|
+
endpoint = [ :purchase, :authorization, :authenticate ].include?(action) ? "VSPDirectGateway.asp" : "VSPServerGateway.asp?Service=Vendor#{TRANSACTIONS[action].capitalize}Tx"
|
|
340
|
+
end
|
|
309
341
|
"#{SIMULATOR_URL}/#{endpoint}"
|
|
310
342
|
end
|
|
311
343
|
|
|
@@ -323,7 +355,7 @@ module ActiveMerchant #:nodoc:
|
|
|
323
355
|
parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
|
324
356
|
end
|
|
325
357
|
|
|
326
|
-
#
|
|
358
|
+
# SagePay returns data in the following format
|
|
327
359
|
# Key1=value1
|
|
328
360
|
# Key2=value2
|
|
329
361
|
def parse(body)
|
|
@@ -344,6 +376,7 @@ module ActiveMerchant #:nodoc:
|
|
|
344
376
|
[ first_name[0,20], last_name[0,20] ]
|
|
345
377
|
end
|
|
346
378
|
end
|
|
379
|
+
ProtxGateway = SagePayGateway
|
|
347
380
|
end
|
|
348
381
|
end
|
|
349
382
|
|