tlconnor-activemerchant 1.20.4 → 1.23.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +86 -6
- data/CONTRIBUTORS +33 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +2 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +4 -4
- data/lib/active_merchant/billing/gateways/blue_pay.rb +492 -11
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +46 -19
- data/lib/active_merchant/billing/gateways/certo_direct.rb +1 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +2 -0
- data/lib/active_merchant/billing/gateways/epay.rb +3 -1
- data/lib/active_merchant/billing/gateways/itransact.rb +450 -0
- data/lib/active_merchant/billing/gateways/litle.rb +275 -0
- data/lib/active_merchant/billing/gateways/migs.rb +259 -0
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +4 -30
- data/lib/active_merchant/billing/gateways/moneris_us.rb +211 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
- data/lib/active_merchant/billing/gateways/ogone.rb +104 -12
- data/lib/active_merchant/billing/gateways/orbital.rb +15 -6
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +1 -4
- data/lib/active_merchant/billing/gateways/payflow.rb +8 -3
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +4 -1
- data/lib/active_merchant/billing/gateways/payflow_express.rb +4 -2
- data/lib/active_merchant/billing/gateways/payment_express.rb +60 -13
- data/lib/active_merchant/billing/gateways/paypal.rb +3 -18
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +333 -3
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +245 -0
- data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +43 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +14 -65
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +8 -3
- data/lib/active_merchant/billing/gateways/realex.rb +5 -7
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +3 -2
- data/lib/active_merchant/billing/gateways/stripe.rb +1 -9
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +2 -2
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -5
- data/lib/active_merchant/billing/gateways/viaklix.rb +7 -2
- data/lib/active_merchant/billing/gateways/vindicia.rb +359 -0
- data/lib/active_merchant/billing/integrations/dotpay.rb +22 -0
- data/lib/active_merchant/billing/integrations/dotpay/helper.rb +77 -0
- data/lib/active_merchant/billing/integrations/dotpay/notification.rb +86 -0
- data/lib/active_merchant/billing/integrations/dotpay/return.rb +11 -0
- data/lib/active_merchant/billing/integrations/epay.rb +21 -0
- data/lib/active_merchant/billing/integrations/epay/helper.rb +55 -0
- data/lib/active_merchant/billing/integrations/epay/notification.rb +110 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +2 -1
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +2 -3
- data/lib/active_merchant/billing/integrations/robokassa.rb +49 -0
- data/lib/active_merchant/billing/integrations/robokassa/common.rb +19 -0
- data/lib/active_merchant/billing/integrations/robokassa/helper.rb +50 -0
- data/lib/active_merchant/billing/integrations/robokassa/notification.rb +55 -0
- data/lib/active_merchant/billing/integrations/robokassa/return.rb +17 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +25 -3
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +58 -26
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +71 -46
- data/lib/active_merchant/billing/integrations/verkkomaksut.rb +20 -0
- data/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb +87 -0
- data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +59 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +28 -5
@@ -0,0 +1,100 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Billing
|
3
|
+
module MigsCodes
|
4
|
+
TXN_RESPONSE_CODES = {
|
5
|
+
'?' => 'Response Unknown',
|
6
|
+
'0' => 'Transaction Successful',
|
7
|
+
'1' => 'Transaction Declined - Bank Error',
|
8
|
+
'2' => 'Bank Declined Transaction',
|
9
|
+
'3' => 'Transaction Declined - No Reply from Bank',
|
10
|
+
'4' => 'Transaction Declined - Expired Card',
|
11
|
+
'5' => 'Transaction Declined - Insufficient funds',
|
12
|
+
'6' => 'Transaction Declined - Error Communicating with Bank',
|
13
|
+
'7' => 'Payment Server Processing Error - Typically caused by invalid input data such as an invalid credit card number. Processing errors can also occur',
|
14
|
+
'8' => 'Transaction Declined - Transaction Type Not Supported',
|
15
|
+
'9' => 'Bank Declined Transaction (Do not contact Bank)',
|
16
|
+
'A' => 'Transaction Aborted',
|
17
|
+
'C' => 'Transaction Cancelled',
|
18
|
+
'D' => 'Deferred Transaction',
|
19
|
+
'E' => 'Issuer Returned a Referral Response',
|
20
|
+
'F' => '3D Secure Authentication Failed',
|
21
|
+
'I' => 'Card Security Code Failed',
|
22
|
+
'L' => 'Shopping Transaction Locked (This indicates that there is another transaction taking place using the same shopping transaction number)',
|
23
|
+
'N' => 'Cardholder is not enrolled in 3D Secure (Authentication Only)',
|
24
|
+
'P' => 'Transaction is Pending',
|
25
|
+
'R' => 'Retry Limits Exceeded, Transaction Not Processed',
|
26
|
+
'S' => 'Duplicate OrderInfo used. (This is only relevant for Payment Servers that enforce the uniqueness of this field)',
|
27
|
+
'U' => 'Card Security Code Failed'
|
28
|
+
}
|
29
|
+
|
30
|
+
ISSUER_RESPONSE_CODES = {
|
31
|
+
'00' => 'Approved',
|
32
|
+
'01' => 'Refer to Card Issuer',
|
33
|
+
'02' => 'Refer to Card Issuer',
|
34
|
+
'03' => 'Invalid Merchant',
|
35
|
+
'04' => 'Pick Up Card',
|
36
|
+
'05' => 'Do Not Honor',
|
37
|
+
'07' => 'Pick Up Card',
|
38
|
+
'12' => 'Invalid Transaction',
|
39
|
+
'14' => 'Invalid Card Number (No such Number)',
|
40
|
+
'15' => 'No Such Issuer',
|
41
|
+
'33' => 'Expired Card',
|
42
|
+
'34' => 'Suspected Fraud',
|
43
|
+
'36' => 'Restricted Card',
|
44
|
+
'39' => 'No Credit Account',
|
45
|
+
'41' => 'Card Reported Lost',
|
46
|
+
'43' => 'Stolen Card',
|
47
|
+
'51' => 'Insufficient Funds',
|
48
|
+
'54' => 'Expired Card',
|
49
|
+
'57' => 'Transaction Not Permitted',
|
50
|
+
'59' => 'Suspected Fraud',
|
51
|
+
'62' => 'Restricted Card',
|
52
|
+
'65' => 'Exceeds withdrawal frequency limit',
|
53
|
+
'91' => 'Cannot Contact Issuer'
|
54
|
+
}
|
55
|
+
|
56
|
+
VERIFIED_3D_CODES = {
|
57
|
+
'Y' => 'The cardholder was successfully authenticated.',
|
58
|
+
'E' => 'The cardholder is not enrolled.',
|
59
|
+
'N' => 'The cardholder was not verified.',
|
60
|
+
'U' => 'The cardholder\'s Issuer was unable to authenticate due to a system error at the Issuer.',
|
61
|
+
'F' => 'An error exists in the format of the request from the merchant. For example, the request did not contain all required fields, or the format of some fields was invalid.',
|
62
|
+
'A' => 'Authentication of your Merchant ID and Password to the Directory Server Failed (see "What does a Payment Authentication Status of "A" mean?" on page 85).',
|
63
|
+
'D' => 'Error communicating with the Directory Server, for example, the Payment Server could not connect to the directory server or there was a versioning mismatch.',
|
64
|
+
'C' => 'The card type is not supported for authentication.',
|
65
|
+
'M' => 'This indicates that attempts processing was used. Verification is marked with status M - ACS attempts processing used. Payment is performed with authentication. Attempts is when a cardholder has successfully passed the directory server but decides not to continue with the authentication process and cancels.',
|
66
|
+
'S' => 'The signature on the response received from the Issuer could not be validated. This should be considered a failure.',
|
67
|
+
'T' => 'ACS timed out. The Issuer\'s ACS did not respond to the Authentication request within the time out period.',
|
68
|
+
'P' => 'Error parsing input from Issuer.',
|
69
|
+
'I' => 'Internal Payment Server system error. This could be caused by a temporary DB failure or an error in the security module or by some error in an internal system.'
|
70
|
+
}
|
71
|
+
|
72
|
+
class CreditCardType
|
73
|
+
attr_accessor :am_code, :migs_code, :migs_long_code, :name
|
74
|
+
def initialize(am_code, migs_code, migs_long_code, name)
|
75
|
+
@am_code = am_code
|
76
|
+
@migs_code = migs_code
|
77
|
+
@migs_long_code = migs_long_code
|
78
|
+
@name = name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
CARD_TYPES = [
|
83
|
+
# The following are 4 different representations of credit card types
|
84
|
+
# am_code: The active merchant code
|
85
|
+
# migs_code: Used in response for purchase/authorize/status
|
86
|
+
# migs_long_code: Used to pre-select card for server_purchase_url
|
87
|
+
# name: The nice display name
|
88
|
+
%w(american_express AE Amex American\ Express),
|
89
|
+
%w(diners_club DC Dinersclub Diners\ Club),
|
90
|
+
%w(jcb JC JCB JCB\ Card),
|
91
|
+
%w(maestro MS Maestro Maestro\ Card),
|
92
|
+
%w(master MC Mastercard MasterCard),
|
93
|
+
%w(na PL PrivateLabelCard Private\ Label\ Card),
|
94
|
+
%w(visa VC Visa Visa\ Card')
|
95
|
+
].map do |am_code, migs_code, migs_long_code, name|
|
96
|
+
CreditCardType.new(am_code, migs_code, migs_long_code, name)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -101,9 +101,7 @@ module ActiveMerchant #:nodoc:
|
|
101
101
|
:amount => amount(money),
|
102
102
|
:pan => creditcard.number,
|
103
103
|
:expdate => expdate(creditcard),
|
104
|
-
:crypt_type => options[:crypt_type] || @options[:crypt_type]
|
105
|
-
:cvv => creditcard.verification_value,
|
106
|
-
:billing_address => options[:address] || options[:billing_address]
|
104
|
+
:crypt_type => options[:crypt_type] || @options[:crypt_type]
|
107
105
|
}
|
108
106
|
end
|
109
107
|
|
@@ -131,9 +129,7 @@ module ActiveMerchant #:nodoc:
|
|
131
129
|
|
132
130
|
Response.new(successful?(response), message_from(response[:message]), response,
|
133
131
|
:test => test?,
|
134
|
-
:authorization => authorization_from(response)
|
135
|
-
:avs_result => {:code => response[:avs_result_code]},
|
136
|
-
:cvv_result => response[:cvd_result_code] && response[:cvd_result_code].last
|
132
|
+
:authorization => authorization_from(response)
|
137
133
|
)
|
138
134
|
end
|
139
135
|
|
@@ -176,32 +172,10 @@ module ActiveMerchant #:nodoc:
|
|
176
172
|
actions[action].each do |key|
|
177
173
|
transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
|
178
174
|
end
|
179
|
-
|
180
|
-
add_avs_info(transaction, parameters)
|
181
|
-
add_cvd_info(transaction, parameters)
|
182
|
-
|
175
|
+
|
183
176
|
xml.to_s
|
184
177
|
end
|
185
|
-
|
186
|
-
def add_avs_info(transaction, parameters)
|
187
|
-
if address = parameters[:billing_address]
|
188
|
-
street_number, street_name = address[:address1].split(' ', 2)
|
189
|
-
|
190
|
-
avs_info = transaction.add_element('avs_info')
|
191
|
-
avs_info.add_element('avs_street_number').text = street_number
|
192
|
-
avs_info.add_element('avs_street_name').text = street_name
|
193
|
-
avs_info.add_element('avs_zipcode').text = address[:zip]
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def add_cvd_info(transaction, parameters)
|
198
|
-
if cvd_value = parameters[:cvv]
|
199
|
-
cvd_info = transaction.add_element('cvd_info')
|
200
|
-
cvd_info.add_element('cvd_indicator').text = '1'
|
201
|
-
cvd_info.add_element('cvd_value').text = cvd_value
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
178
|
+
|
205
179
|
def message_from(message)
|
206
180
|
return 'Unspecified error' if message.blank?
|
207
181
|
message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
|
6
|
+
# To learn more about the Moneris (US) gateway, please contact
|
7
|
+
# ussales@moneris.com for a copy of their integration guide. For
|
8
|
+
# information on remote testing, please see "Test Environment Penny Value
|
9
|
+
# Response Table", and "Test Environment eFraud (AVS and CVD) Penny
|
10
|
+
# Response Values", available at Moneris' {eSelect Plus Documentation
|
11
|
+
# Centre}[https://www3.moneris.com/connect/en/documents/index.html].
|
12
|
+
class MonerisUsGateway < Gateway
|
13
|
+
TEST_URL = 'https://esplusqa.moneris.com/gateway_us/servlet/MpgRequest'
|
14
|
+
LIVE_URL = 'https://esplus.moneris.com/gateway_us/servlet/MpgRequest'
|
15
|
+
|
16
|
+
self.supported_countries = ['US']
|
17
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover]
|
18
|
+
self.homepage_url = 'http://www.monerisusa.com/'
|
19
|
+
self.display_name = 'Moneris (US)'
|
20
|
+
|
21
|
+
# login is your Store ID
|
22
|
+
# password is your API Token
|
23
|
+
def initialize(options = {})
|
24
|
+
requires!(options, :login, :password)
|
25
|
+
@options = { :crypt_type => 7 }.update(options)
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
# Referred to as "PreAuth" in the Moneris integration guide, this action
|
30
|
+
# verifies and locks funds on a customer's card, which then must be
|
31
|
+
# captured at a later date.
|
32
|
+
#
|
33
|
+
# Pass in +order_id+ and optionally a +customer+ parameter.
|
34
|
+
def authorize(money, creditcard, options = {})
|
35
|
+
debit_commit 'us_preauth', money, creditcard, options
|
36
|
+
end
|
37
|
+
|
38
|
+
# This action verifies funding on a customer's card, and readies them for
|
39
|
+
# deposit in a merchant's account.
|
40
|
+
#
|
41
|
+
# Pass in <tt>order_id</tt> and optionally a <tt>customer</tt> parameter
|
42
|
+
def purchase(money, creditcard, options = {})
|
43
|
+
debit_commit 'us_purchase', money, creditcard, options
|
44
|
+
end
|
45
|
+
|
46
|
+
# This method retrieves locked funds from a customer's account (from a
|
47
|
+
# PreAuth) and prepares them for deposit in a merchant's account.
|
48
|
+
#
|
49
|
+
# Note: Moneris requires both the order_id and the transaction number of
|
50
|
+
# the original authorization. To maintain the same interface as the other
|
51
|
+
# gateways the two numbers are concatenated together with a ; separator as
|
52
|
+
# the authorization number returned by authorization
|
53
|
+
def capture(money, authorization, options = {})
|
54
|
+
commit 'us_completion', crediting_params(authorization, :comp_amount => amount(money))
|
55
|
+
end
|
56
|
+
|
57
|
+
# Voiding requires the original transaction ID and order ID of some open
|
58
|
+
# transaction. Closed transactions must be refunded. Note that the only
|
59
|
+
# methods which may be voided are +capture+ and +purchase+.
|
60
|
+
#
|
61
|
+
# Concatenate your transaction number and order_id by using a semicolon
|
62
|
+
# (';'). This is to keep the Moneris interface consistent with other
|
63
|
+
# gateways. (See +capture+ for details.)
|
64
|
+
def void(authorization, options = {})
|
65
|
+
commit 'us_purchasecorrection', crediting_params(authorization)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Performs a refund. This method requires that the original transaction
|
69
|
+
# number and order number be included. Concatenate your transaction
|
70
|
+
# number and order_id by using a semicolon (';'). This is to keep the
|
71
|
+
# Moneris interface consistent with other gateways. (See +capture+ for
|
72
|
+
# details.)
|
73
|
+
def credit(money, authorization, options = {})
|
74
|
+
deprecated CREDIT_DEPRECATION_MESSAGE
|
75
|
+
refund(money, authorization, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def refund(money, authorization, options = {})
|
79
|
+
commit 'us_refund', crediting_params(authorization, :amount => amount(money))
|
80
|
+
end
|
81
|
+
|
82
|
+
def test?
|
83
|
+
@options[:test] || super
|
84
|
+
end
|
85
|
+
private # :nodoc: all
|
86
|
+
|
87
|
+
def expdate(creditcard)
|
88
|
+
sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
|
89
|
+
end
|
90
|
+
|
91
|
+
def debit_commit(commit_type, money, creditcard, options)
|
92
|
+
requires!(options, :order_id)
|
93
|
+
commit(commit_type, debit_params(money, creditcard, options))
|
94
|
+
end
|
95
|
+
|
96
|
+
# Common params used amongst the +purchase+ and +authorization+ methods
|
97
|
+
def debit_params(money, creditcard, options = {})
|
98
|
+
{
|
99
|
+
:order_id => options[:order_id],
|
100
|
+
:cust_id => options[:customer],
|
101
|
+
:amount => amount(money),
|
102
|
+
:pan => creditcard.number,
|
103
|
+
:expdate => expdate(creditcard),
|
104
|
+
:crypt_type => options[:crypt_type] || @options[:crypt_type]
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
# Common params used amongst the +credit+, +void+ and +capture+ methods
|
109
|
+
def crediting_params(authorization, options = {})
|
110
|
+
{
|
111
|
+
:txn_number => split_authorization(authorization).first,
|
112
|
+
:order_id => split_authorization(authorization).last,
|
113
|
+
:crypt_type => options[:crypt_type] || @options[:crypt_type]
|
114
|
+
}.merge(options)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Splits an +authorization+ param and retrives the order id and
|
118
|
+
# transaction number in that order.
|
119
|
+
def split_authorization(authorization)
|
120
|
+
if authorization.nil? || authorization.empty? || authorization !~ /;/
|
121
|
+
raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")'
|
122
|
+
else
|
123
|
+
authorization.split(';')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def commit(action, parameters = {})
|
128
|
+
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters)))
|
129
|
+
|
130
|
+
Response.new(successful?(response), message_from(response[:message]), response,
|
131
|
+
:test => test?,
|
132
|
+
:authorization => authorization_from(response)
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Generates a Moneris authorization string of the form 'trans_id;receipt_id'.
|
137
|
+
def authorization_from(response = {})
|
138
|
+
if response[:trans_id] && response[:receipt_id]
|
139
|
+
"#{response[:trans_id]};#{response[:receipt_id]}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Tests for a successful response from Moneris' servers
|
144
|
+
def successful?(response)
|
145
|
+
response[:response_code] &&
|
146
|
+
response[:complete] &&
|
147
|
+
(0..49).include?(response[:response_code].to_i)
|
148
|
+
end
|
149
|
+
|
150
|
+
def parse(xml)
|
151
|
+
response = { :message => "Global Error Receipt", :complete => false }
|
152
|
+
hashify_xml!(xml, response)
|
153
|
+
response
|
154
|
+
end
|
155
|
+
|
156
|
+
def hashify_xml!(xml, response)
|
157
|
+
xml = REXML::Document.new(xml)
|
158
|
+
return if xml.root.nil?
|
159
|
+
xml.elements.each('//receipt/*') do |node|
|
160
|
+
response[node.name.underscore.to_sym] = normalize(node.text)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def post_data(action, parameters = {})
|
165
|
+
xml = REXML::Document.new
|
166
|
+
root = xml.add_element("request")
|
167
|
+
root.add_element("store_id").text = options[:login]
|
168
|
+
root.add_element("api_token").text = options[:password]
|
169
|
+
transaction = root.add_element(action)
|
170
|
+
|
171
|
+
# Must add the elements in the correct order
|
172
|
+
actions[action].each do |key|
|
173
|
+
transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
|
174
|
+
end
|
175
|
+
|
176
|
+
xml.to_s
|
177
|
+
end
|
178
|
+
|
179
|
+
def message_from(message)
|
180
|
+
return 'Unspecified error' if message.blank?
|
181
|
+
message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
|
182
|
+
end
|
183
|
+
|
184
|
+
# Make a Ruby type out of the response string
|
185
|
+
def normalize(field)
|
186
|
+
case field
|
187
|
+
when "true" then true
|
188
|
+
when "false" then false
|
189
|
+
when '', "null" then nil
|
190
|
+
else field
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def actions
|
195
|
+
{
|
196
|
+
"us_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
197
|
+
"us_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
198
|
+
"us_refund" => [:order_id, :amount, :txn_number, :crypt_type],
|
199
|
+
"us_ind_refund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
200
|
+
"us_completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
|
201
|
+
"us_purchasecorrection" => [:order_id, :txn_number, :crypt_type],
|
202
|
+
"us_cavv_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
|
203
|
+
"us_cavv_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
|
204
|
+
"us_batchcloseall" => [],
|
205
|
+
"us_opentotals" => [:ecr_number],
|
206
|
+
"us_batchclose" => [:ecr_number]
|
207
|
+
}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -59,7 +59,7 @@ module ActiveMerchant #:nodoc:
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def purchase(money, credit_card_or_stored_id, options = {})
|
62
|
-
if credit_card_or_stored_id.
|
62
|
+
if credit_card_or_stored_id.respond_to?(:number)
|
63
63
|
#Credit card for instant payment
|
64
64
|
commit :purchase, build_purchase_request(money, credit_card_or_stored_id, options)
|
65
65
|
else
|
@@ -9,17 +9,23 @@ module ActiveMerchant #:nodoc:
|
|
9
9
|
# communication between Ogone systems and your e-commerce website.
|
10
10
|
#
|
11
11
|
# This implementation follows the specification provided in the DirectLink integration
|
12
|
-
# guide version 4.
|
12
|
+
# guide version 4.3.0 (25 April 2012), available here:
|
13
13
|
# https://secure.ogone.com/ncol/Ogone_DirectLink_EN.pdf
|
14
14
|
#
|
15
15
|
# It also features aliases, which allow to store/unstore credit cards, as specified in
|
16
|
-
# the Alias Manager Option guide version 3.2.
|
16
|
+
# the Alias Manager Option guide version 3.2.1 (25 April 2012) available here:
|
17
17
|
# https://secure.ogone.com/ncol/Ogone_Alias_EN.pdf
|
18
18
|
#
|
19
|
-
# It
|
19
|
+
# It also implements the 3-D Secure feature, as specified in the DirectLink with
|
20
|
+
# 3-D Secure guide version 3.0 (25 April 2012) available here:
|
21
|
+
# https://secure.ogone.com/ncol/Ogone_DirectLink-3-D_EN.pdf
|
22
|
+
#
|
23
|
+
# It was last tested on Release 4.92 of Ogone DirectLink + AliasManager + Direct Link 3D
|
24
|
+
# (25 April 2012).
|
20
25
|
#
|
21
26
|
# For any questions or comments, please contact one of the following:
|
22
|
-
# -
|
27
|
+
# - Joel Cogen (joel.cogen@belighted.com)
|
28
|
+
# - Nicolas Jacobeus (nicolas.jacobeus@belighted.com),
|
23
29
|
# - Sébastien Grosjean (public@zencocoon.com),
|
24
30
|
# - Rémy Coutable (remy@jilion.com).
|
25
31
|
#
|
@@ -52,17 +58,46 @@ module ActiveMerchant #:nodoc:
|
|
52
58
|
# puts response.success? # Check whether the transaction was successful
|
53
59
|
# puts response.message # Retrieve the message returned by Ogone
|
54
60
|
# puts response.authorization # Retrieve the unique transaction ID returned by Ogone
|
61
|
+
# puts response.order_id # Retrieve the order ID
|
55
62
|
#
|
56
63
|
# == Alias feature
|
57
64
|
#
|
58
|
-
# To use the alias feature, simply add :
|
65
|
+
# To use the alias feature, simply add :billing_id in the options hash:
|
59
66
|
#
|
60
67
|
# # Associate the alias to that credit card
|
61
|
-
# gateway.purchase(1000, creditcard, :order_id => "1", :
|
68
|
+
# gateway.purchase(1000, creditcard, :order_id => "1", :billing_id => "myawesomecustomer")
|
62
69
|
#
|
63
70
|
# # You can use the alias instead of the credit card for subsequent orders
|
64
71
|
# gateway.purchase(2000, "myawesomecustomer", :order_id => "2")
|
65
72
|
#
|
73
|
+
# # You can also create an alias without making a purchase using store
|
74
|
+
# gateway.store(creditcard, :billing_id => "myawesomecustomer")
|
75
|
+
#
|
76
|
+
# # When using store, you can also let Ogone generate the alias for you
|
77
|
+
# response = gateway.store(creditcard)
|
78
|
+
# puts response.billing_id # Retrieve the generated alias
|
79
|
+
#
|
80
|
+
# == 3-D Secure feature
|
81
|
+
#
|
82
|
+
# To use the 3-D Secure feature, simply add :d3d => true in the options hash:
|
83
|
+
# gateway.purchase(2000, "myawesomecustomer", :order_id => "2", :d3d => true)
|
84
|
+
#
|
85
|
+
# Specific 3-D Secure request options are (please refer to the documentation for more infos about these options):
|
86
|
+
# :win_3ds => :main_window (default), :pop_up or :pop_ix.
|
87
|
+
# :http_accept => "*/*" (default), or any other HTTP_ACCEPT header value.
|
88
|
+
# :http_user_agent => The cardholder's User-Agent string
|
89
|
+
# :accept_url => URL of the web page to show the customer when the payment is authorized.
|
90
|
+
# (or waiting to be authorized).
|
91
|
+
# :decline_url => URL of the web page to show the customer when the acquirer rejects the authorization
|
92
|
+
# more than the maximum permitted number of authorization attempts (10 by default, but can
|
93
|
+
# be changed in the "Global transaction parameters" tab, "Payment retry" section of the
|
94
|
+
# Technical Information page).
|
95
|
+
# :exception_url => URL of the web page to show the customer when the payment result is uncertain.
|
96
|
+
# :paramplus => Field to submit the miscellaneous parameters and their values that you wish to be
|
97
|
+
# returned in the post sale request or final redirection.
|
98
|
+
# :complus => Field to submit a value you wish to be returned in the post sale request or output.
|
99
|
+
# :language => Customer's language, for example: "en_EN"
|
100
|
+
#
|
66
101
|
class OgoneGateway < Gateway
|
67
102
|
|
68
103
|
URLS = {
|
@@ -80,8 +115,16 @@ module ActiveMerchant #:nodoc:
|
|
80
115
|
|
81
116
|
SUCCESS_MESSAGE = "The transaction was successful"
|
82
117
|
|
118
|
+
THREE_D_SECURE_DISPLAY_WAYS = { :main_window => 'MAINW', # display the identification page in the main window
|
119
|
+
# (default value).
|
120
|
+
:pop_up => 'POPUP', # display the identification page in a pop-up window
|
121
|
+
# and return to the main window at the end.
|
122
|
+
:pop_ix => 'POPIX' } # display the identification page in a pop-up window
|
123
|
+
# and remain in the pop-up window.
|
124
|
+
|
83
125
|
OGONE_NO_SIGNATURE_DEPRECATION_MESSAGE = "Signature usage will be required from a future release of ActiveMerchant's Ogone Gateway. Please update your Ogone account to use it."
|
84
126
|
OGONE_LOW_ENCRYPTION_DEPRECATION_MESSAGE = "SHA512 signature encryptor will be required from a future release of ActiveMerchant's Ogone Gateway. Please update your Ogone account to use it."
|
127
|
+
OGONE_STORE_OPTION_DEPRECATION_MESSAGE = "The 'store' option has been renamed to 'billing_id', and its usage is deprecated."
|
85
128
|
|
86
129
|
self.supported_countries = ['BE', 'DE', 'FR', 'NL', 'AT', 'CH']
|
87
130
|
# also supports Airplus and UATP
|
@@ -152,6 +195,14 @@ module ActiveMerchant #:nodoc:
|
|
152
195
|
perform_reference_credit(money, reference, options)
|
153
196
|
end
|
154
197
|
|
198
|
+
# Store a credit card by creating an Ogone Alias
|
199
|
+
def store(payment_source, options = {})
|
200
|
+
options.merge!(:alias_operation => 'BYOGONE') unless options.has_key?(:billing_id) || options.has_key?(:store)
|
201
|
+
response = authorize(1, payment_source, options)
|
202
|
+
void(response.authorization) if response.success?
|
203
|
+
response
|
204
|
+
end
|
205
|
+
|
155
206
|
def test?
|
156
207
|
@options[:test] || super
|
157
208
|
end
|
@@ -164,7 +215,7 @@ module ActiveMerchant #:nodoc:
|
|
164
215
|
|
165
216
|
def reference_transaction?(identifier)
|
166
217
|
return false unless identifier.is_a?(String)
|
167
|
-
|
218
|
+
_, action = identifier.split(";")
|
168
219
|
!action.nil?
|
169
220
|
end
|
170
221
|
|
@@ -188,21 +239,44 @@ module ActiveMerchant #:nodoc:
|
|
188
239
|
|
189
240
|
def add_payment_source(post, payment_source, options)
|
190
241
|
if payment_source.is_a?(String)
|
191
|
-
add_alias(post, payment_source)
|
242
|
+
add_alias(post, payment_source, options[:alias_operation])
|
192
243
|
add_eci(post, options[:eci] || '9')
|
193
244
|
else
|
194
|
-
|
245
|
+
if options.has_key?(:store)
|
246
|
+
deprecated OGONE_STORE_OPTION_DEPRECATION_MESSAGE
|
247
|
+
options[:billing_id] ||= options[:store]
|
248
|
+
end
|
249
|
+
add_alias(post, options[:billing_id], options[:alias_operation])
|
195
250
|
add_eci(post, options[:eci] || '7')
|
251
|
+
add_d3d(post, options) if options[:d3d]
|
196
252
|
add_creditcard(post, payment_source)
|
197
253
|
end
|
198
254
|
end
|
199
255
|
|
256
|
+
def add_d3d(post, options)
|
257
|
+
add_pair post, 'FLAG3D', 'Y'
|
258
|
+
win_3ds = THREE_D_SECURE_DISPLAY_WAYS.key?(options[:win_3ds]) ?
|
259
|
+
THREE_D_SECURE_DISPLAY_WAYS[options[:win_3ds]] :
|
260
|
+
THREE_D_SECURE_DISPLAY_WAYS[:main_window]
|
261
|
+
add_pair post, 'WIN3DS', win_3ds
|
262
|
+
|
263
|
+
add_pair post, 'HTTP_ACCEPT', options[:http_accept] || "*/*"
|
264
|
+
add_pair post, 'HTTP_USER_AGENT', options[:http_user_agent] if options[:http_user_agent]
|
265
|
+
add_pair post, 'ACCEPTURL', options[:accept_url] if options[:accept_url]
|
266
|
+
add_pair post, 'DECLINEURL', options[:decline_url] if options[:decline_url]
|
267
|
+
add_pair post, 'EXCEPTIONURL', options[:exception_url] if options[:exception_url]
|
268
|
+
add_pair post, 'PARAMPLUS', options[:paramplus] if options[:paramplus]
|
269
|
+
add_pair post, 'COMPLUS', options[:complus] if options[:complus]
|
270
|
+
add_pair post, 'LANGUAGE', options[:language] if options[:language]
|
271
|
+
end
|
272
|
+
|
200
273
|
def add_eci(post, eci)
|
201
274
|
add_pair post, 'ECI', eci.to_s
|
202
275
|
end
|
203
276
|
|
204
|
-
def add_alias(post, _alias)
|
277
|
+
def add_alias(post, _alias, alias_operation = nil)
|
205
278
|
add_pair post, 'ALIAS', _alias
|
279
|
+
add_pair post, 'ALIASOPERATION', alias_operation unless alias_operation.nil?
|
206
280
|
end
|
207
281
|
|
208
282
|
def add_authorization(post, authorization)
|
@@ -242,7 +316,15 @@ module ActiveMerchant #:nodoc:
|
|
242
316
|
|
243
317
|
def parse(body)
|
244
318
|
xml_root = REXML::Document.new(body).root
|
245
|
-
convert_attributes_to_hash(xml_root.attributes)
|
319
|
+
response = convert_attributes_to_hash(xml_root.attributes)
|
320
|
+
|
321
|
+
# Add HTML_ANSWER element (3-D Secure specific to the response's params)
|
322
|
+
# Note: HTML_ANSWER is not an attribute so we add it "by hand" to the response
|
323
|
+
if html_answer = REXML::XPath.first(xml_root, "//HTML_ANSWER")
|
324
|
+
response["HTML_ANSWER"] = html_answer.text
|
325
|
+
end
|
326
|
+
|
327
|
+
response
|
246
328
|
end
|
247
329
|
|
248
330
|
def commit(action, parameters)
|
@@ -259,7 +341,7 @@ module ActiveMerchant #:nodoc:
|
|
259
341
|
:avs_result => { :code => AVS_MAPPING[response["AAVCheck"]] },
|
260
342
|
:cvv_result => CVV_MAPPING[response["CVCCheck"]]
|
261
343
|
}
|
262
|
-
|
344
|
+
OgoneResponse.new(successful?(response), message_from(response), response, options)
|
263
345
|
end
|
264
346
|
|
265
347
|
def successful?(response)
|
@@ -326,5 +408,15 @@ module ActiveMerchant #:nodoc:
|
|
326
408
|
response_hash
|
327
409
|
end
|
328
410
|
end
|
411
|
+
|
412
|
+
class OgoneResponse < Response
|
413
|
+
def order_id
|
414
|
+
@params['orderID']
|
415
|
+
end
|
416
|
+
|
417
|
+
def billing_id
|
418
|
+
@params['ALIAS']
|
419
|
+
end
|
420
|
+
end
|
329
421
|
end
|
330
422
|
end
|