activemerchant 1.28.0 → 1.29.1
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 +41 -0
- data/CONTRIBUTORS +12 -0
- data/README.md +6 -0
- data/lib/active_merchant/billing/gateway.rb +2 -1
- data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +77 -78
- data/lib/active_merchant/billing/gateways/balanced.rb +0 -1
- data/lib/active_merchant/billing/gateways/banwire.rb +1 -2
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +19 -20
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +35 -36
- data/lib/active_merchant/billing/gateways/blue_pay.rb +135 -140
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +12 -4
- data/lib/active_merchant/billing/gateways/card_stream.rb +54 -59
- data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +19 -14
- data/lib/active_merchant/billing/gateways/data_cash.rb +106 -112
- data/lib/active_merchant/billing/gateways/efsnet.rb +29 -34
- data/lib/active_merchant/billing/gateways/elavon.rb +7 -1
- data/lib/active_merchant/billing/gateways/epay.rb +0 -1
- data/lib/active_merchant/billing/gateways/eway.rb +88 -93
- data/lib/active_merchant/billing/gateways/eway_managed.rb +47 -51
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +300 -0
- data/lib/active_merchant/billing/gateways/exact.rb +45 -54
- data/lib/active_merchant/billing/gateways/federated_canada.rb +3 -4
- data/lib/active_merchant/billing/gateways/first_pay.rb +37 -38
- data/lib/active_merchant/billing/gateways/garanti.rb +1 -2
- data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +5 -8
- data/lib/active_merchant/billing/gateways/inspire.rb +52 -52
- data/lib/active_merchant/billing/gateways/instapay.rb +10 -11
- data/lib/active_merchant/billing/gateways/iridium.rb +38 -39
- data/lib/active_merchant/billing/gateways/itransact.rb +7 -9
- data/lib/active_merchant/billing/gateways/jetpay.rb +45 -46
- data/lib/active_merchant/billing/gateways/linkpoint.rb +104 -108
- data/lib/active_merchant/billing/gateways/litle.rb +1 -5
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +153 -155
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +49 -50
- data/lib/active_merchant/billing/gateways/mercury.rb +272 -0
- data/lib/active_merchant/billing/gateways/metrics_global.rb +9 -10
- data/lib/active_merchant/billing/gateways/migs.rb +5 -3
- data/lib/active_merchant/billing/gateways/modern_payments.rb +6 -7
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +40 -41
- data/lib/active_merchant/billing/gateways/moneris.rb +46 -50
- data/lib/active_merchant/billing/gateways/moneris_us.rb +52 -55
- data/lib/active_merchant/billing/gateways/nab_transact.rb +0 -5
- data/lib/active_merchant/billing/gateways/net_registry.rb +20 -21
- data/lib/active_merchant/billing/gateways/netaxept.rb +30 -36
- data/lib/active_merchant/billing/gateways/netbilling.rb +2 -2
- data/lib/active_merchant/billing/gateways/ogone.rb +0 -5
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +1 -6
- data/lib/active_merchant/billing/gateways/orbital/avs_result.rb +93 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +25 -21
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +1 -6
- data/lib/active_merchant/billing/gateways/pay_junction.rb +62 -63
- data/lib/active_merchant/billing/gateways/pay_secure.rb +29 -30
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +0 -5
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +33 -38
- data/lib/active_merchant/billing/gateways/payment_express.rb +48 -51
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +7 -11
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +7 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +3 -0
- data/lib/active_merchant/billing/gateways/paystation.rb +62 -64
- data/lib/active_merchant/billing/gateways/payway.rb +2 -9
- data/lib/active_merchant/billing/gateways/plugnpay.rb +0 -1
- data/lib/active_merchant/billing/gateways/psigate.rb +102 -94
- data/lib/active_merchant/billing/gateways/psl_card.rb +66 -67
- data/lib/active_merchant/billing/gateways/qbms.rb +0 -6
- data/lib/active_merchant/billing/gateways/quantum.rb +2 -8
- data/lib/active_merchant/billing/gateways/quickpay.rb +2 -3
- data/lib/active_merchant/billing/gateways/realex.rb +6 -16
- data/lib/active_merchant/billing/gateways/redsys.rb +394 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +25 -26
- data/lib/active_merchant/billing/gateways/sage.rb +15 -16
- data/lib/active_merchant/billing/gateways/sage_pay.rb +51 -56
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +1 -2
- data/lib/active_merchant/billing/gateways/samurai.rb +1 -4
- data/lib/active_merchant/billing/gateways/secure_net.rb +0 -1
- data/lib/active_merchant/billing/gateways/secure_pay.rb +5 -8
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +0 -5
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +17 -18
- data/lib/active_merchant/billing/gateways/skip_jack.rb +29 -34
- data/lib/active_merchant/billing/gateways/smart_ps.rb +55 -56
- data/lib/active_merchant/billing/gateways/stripe.rb +8 -3
- data/lib/active_merchant/billing/gateways/trans_first.rb +28 -29
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +85 -87
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +27 -28
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +0 -5
- data/lib/active_merchant/billing/gateways/verifi.rb +86 -87
- data/lib/active_merchant/billing/gateways/viaklix.rb +42 -47
- data/lib/active_merchant/billing/gateways/vindicia.rb +30 -28
- data/lib/active_merchant/billing/gateways/webpay.rb +45 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +0 -6
- data/lib/active_merchant/billing/gateways/worldpay.rb +4 -9
- data/lib/active_merchant/billing/gateways.rb +6 -7
- data/lib/active_merchant/billing/integrations/a1agregator/helper.rb +31 -0
- data/lib/active_merchant/billing/integrations/a1agregator/notification.rb +186 -0
- data/lib/active_merchant/billing/integrations/a1agregator/status.rb +38 -0
- data/lib/active_merchant/billing/integrations/a1agregator.rb +26 -0
- data/lib/active_merchant/billing/integrations/liqpay/helper.rb +43 -0
- data/lib/active_merchant/billing/integrations/liqpay/notification.rb +89 -0
- data/lib/active_merchant/billing/integrations/liqpay/return.rb +83 -0
- data/lib/active_merchant/billing/integrations/liqpay.rb +30 -0
- data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +17 -1
- data/lib/active_merchant/billing/integrations/notification.rb +4 -0
- data/lib/active_merchant/billing/integrations/pay_fast/common.rb +42 -0
- data/lib/active_merchant/billing/integrations/pay_fast/helper.rb +50 -0
- data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +134 -0
- data/lib/active_merchant/billing/integrations/pay_fast/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/pay_fast.rb +70 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +64 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +10 -7
- data/lib/active_merchant/billing/integrations/webmoney/notification.rb +12 -0
- data/lib/active_merchant/billing/response.rb +17 -4
- data/lib/active_merchant/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +46 -27
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
class MercuryGateway < Gateway
|
|
4
|
+
URLS = {
|
|
5
|
+
:test => 'https://w1.mercurydev.net/ws/ws.asmx',
|
|
6
|
+
:live => 'https://w1.mercurypay.com/ws/ws.asmx'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
self.homepage_url = 'http://www.mercurypay.com'
|
|
10
|
+
self.display_name = 'Mercury'
|
|
11
|
+
self.supported_countries = ['US']
|
|
12
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
|
13
|
+
self.default_currency = 'USD'
|
|
14
|
+
|
|
15
|
+
def initialize(options = {})
|
|
16
|
+
requires!(options, :login, :password)
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def purchase(money, credit_card, options = {})
|
|
21
|
+
requires!(options, :order_id)
|
|
22
|
+
|
|
23
|
+
request = build_non_authorized_request('Sale', money, credit_card, options)
|
|
24
|
+
commit('Sale', request)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def credit(money, credit_card, options = {})
|
|
28
|
+
requires!(options, :order_id)
|
|
29
|
+
|
|
30
|
+
request = build_non_authorized_request('Return', money, credit_card, options)
|
|
31
|
+
commit('Return', request)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def authorize(money, credit_card, options = {})
|
|
35
|
+
requires!(options, :order_id)
|
|
36
|
+
|
|
37
|
+
options[:authorized] ||= money
|
|
38
|
+
request = build_non_authorized_request('PreAuth', money, credit_card, options)
|
|
39
|
+
commit('PreAuth', request)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def capture(money, authorization, options = {})
|
|
43
|
+
requires!(options, :credit_card)
|
|
44
|
+
options[:authorized] ||= money
|
|
45
|
+
request = build_authorized_request('PreAuthCapture', money, authorization, options[:credit_card], options)
|
|
46
|
+
commit('PreAuthCapture', request)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def refund(money, authorization, options = {})
|
|
50
|
+
requires!(options, :credit_card)
|
|
51
|
+
|
|
52
|
+
request = build_authorized_request('VoidSale', money, authorization, options[:credit_card], options)
|
|
53
|
+
commit(options[:void], request)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def build_non_authorized_request(action, money, credit_card, options)
|
|
59
|
+
xml = Builder::XmlMarkup.new
|
|
60
|
+
|
|
61
|
+
xml.tag! "TStream" do
|
|
62
|
+
xml.tag! "Transaction" do
|
|
63
|
+
xml.tag! 'TranType', 'Credit'
|
|
64
|
+
xml.tag! 'TranCode', action
|
|
65
|
+
if action == 'PreAuth' || action == 'Sale'
|
|
66
|
+
xml.tag! "PartialAuth", "Allow"
|
|
67
|
+
end
|
|
68
|
+
add_invoice(xml, options[:order_id], nil, options)
|
|
69
|
+
add_customer_data(xml, options)
|
|
70
|
+
add_amount(xml, money, options)
|
|
71
|
+
add_credit_card(xml, credit_card, action)
|
|
72
|
+
add_address(xml, options)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
xml = xml.target!
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def build_authorized_request(action, money, authorization, credit_card, options)
|
|
79
|
+
xml = Builder::XmlMarkup.new
|
|
80
|
+
|
|
81
|
+
invoice_no, ref_no, auth_code, acq_ref_data, process_data = split_authorization(authorization)
|
|
82
|
+
|
|
83
|
+
xml.tag! "TStream" do
|
|
84
|
+
xml.tag! "Transaction" do
|
|
85
|
+
xml.tag! 'TranType', 'Credit'
|
|
86
|
+
xml.tag! 'TranCode', action
|
|
87
|
+
if action == 'PreAuthCapture'
|
|
88
|
+
xml.tag! "PartialAuth", "Allow"
|
|
89
|
+
end
|
|
90
|
+
add_invoice(xml, invoice_no, ref_no, options)
|
|
91
|
+
add_customer_data(xml, options)
|
|
92
|
+
add_amount(xml, money, options)
|
|
93
|
+
add_credit_card(xml, credit_card, action)
|
|
94
|
+
add_address(xml, options)
|
|
95
|
+
xml.tag! 'TranInfo' do
|
|
96
|
+
xml.tag! "AuthCode", auth_code
|
|
97
|
+
xml.tag! "AcqRefData", acq_ref_data
|
|
98
|
+
xml.tag! "ProcessData", process_data
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
xml = xml.target!
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def add_invoice(xml, invoice_no, ref_no, options)
|
|
106
|
+
if /^\d+$/ !~ invoice_no.to_s
|
|
107
|
+
raise ArgumentError.new("#{invoice_no} is not numeric as required by Mercury")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
xml.tag! 'InvoiceNo', invoice_no
|
|
111
|
+
xml.tag! 'RefNo', ref_no || invoice_no
|
|
112
|
+
xml.tag! 'OperatorID', options[:merchant] if options[:merchant]
|
|
113
|
+
xml.tag! 'Memo', options[:description] if options[:description]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def add_customer_data(xml, options)
|
|
117
|
+
xml.tag! 'IpAddress', options[:ip] if options[:ip]
|
|
118
|
+
if options[:customer]
|
|
119
|
+
xml.tag! "TranInfo" do
|
|
120
|
+
xml.tag! 'CustomerCode', options[:customer]
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
xml.tag! 'MerchantID', @options[:login]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def add_amount(xml, money, options = {})
|
|
127
|
+
xml.tag! 'Amount' do
|
|
128
|
+
xml.tag! 'Purchase', amount(money)
|
|
129
|
+
xml.tag! 'Tax', options[:tax] if options[:tax]
|
|
130
|
+
xml.tag! 'Authorize', amount(options[:authorized]) if options[:authorized]
|
|
131
|
+
xml.tag! 'Gratuity', amount(options[:tip]) if options[:tip]
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
CARD_CODES = {
|
|
136
|
+
'visa' => 'VISA',
|
|
137
|
+
'master' => 'M/C',
|
|
138
|
+
'american_express' => 'AMEX',
|
|
139
|
+
'discover' => 'DCVR',
|
|
140
|
+
'diners_club' => 'DCLB',
|
|
141
|
+
'jcb' => 'JCB'
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
def add_credit_card(xml, credit_card, action)
|
|
145
|
+
xml.tag! 'Account' do
|
|
146
|
+
xml.tag! 'AcctNo', credit_card.number
|
|
147
|
+
xml.tag! 'ExpDate', expdate(credit_card)
|
|
148
|
+
end
|
|
149
|
+
xml.tag! 'CardType', CARD_CODES[credit_card.brand] if credit_card.brand
|
|
150
|
+
|
|
151
|
+
include_cvv = !%w(Return PreAuthCapture).include?(action)
|
|
152
|
+
xml.tag! 'CVVData', credit_card.verification_value if(include_cvv && credit_card.verification_value)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def expdate(credit_card)
|
|
156
|
+
year = sprintf("%.4i", credit_card.year)
|
|
157
|
+
month = sprintf("%.2i", credit_card.month)
|
|
158
|
+
|
|
159
|
+
"#{month}#{year[-2..-1]}"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def add_address(xml, options)
|
|
163
|
+
if billing_address = options[:billing_address] || options[:address]
|
|
164
|
+
xml.tag! 'AVS' do
|
|
165
|
+
xml.tag! 'Address', billing_address[:address1]
|
|
166
|
+
xml.tag! 'Zip', billing_address[:zip]
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def parse(action, body)
|
|
172
|
+
response = {}
|
|
173
|
+
hashify_xml!(unescape_xml(body), response)
|
|
174
|
+
response
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def hashify_xml!(xml, response)
|
|
178
|
+
xml = REXML::Document.new(xml)
|
|
179
|
+
|
|
180
|
+
xml.elements.each("//CmdResponse/*") do |node|
|
|
181
|
+
response[node.name.underscore.to_sym] = node.text
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
xml.elements.each("//TranResponse/*") do |node|
|
|
185
|
+
if node.name.to_s == "Amount"
|
|
186
|
+
node.elements.each do |amt|
|
|
187
|
+
response[amt.name.underscore.to_sym] = amt.text
|
|
188
|
+
end
|
|
189
|
+
else
|
|
190
|
+
response[node.name.underscore.to_sym] = node.text
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def endpoint_url
|
|
196
|
+
URLS[test? ? :test : :live]
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def build_soap_request(body)
|
|
200
|
+
xml = Builder::XmlMarkup.new
|
|
201
|
+
|
|
202
|
+
xml.instruct!
|
|
203
|
+
xml.tag! 'soap:Envelope', ENVELOPE_NAMESPACES do
|
|
204
|
+
xml.tag! 'soap:Body' do
|
|
205
|
+
xml.tag! 'CreditTransaction', 'xmlns' => homepage_url do
|
|
206
|
+
xml.tag! 'tran' do
|
|
207
|
+
xml << escape_xml(body)
|
|
208
|
+
end
|
|
209
|
+
xml.tag! 'pw', @options[:password]
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
xml.target!
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def build_header
|
|
217
|
+
{
|
|
218
|
+
"SOAPAction" => "http://www.mercurypay.com/CreditTransaction",
|
|
219
|
+
"Content-Type" => "text/xml; charset=utf-8"
|
|
220
|
+
}
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
SUCCESS_CODES = [ 'Approved', 'Success' ]
|
|
224
|
+
|
|
225
|
+
def commit(action, request)
|
|
226
|
+
response = parse(action, ssl_post(endpoint_url, build_soap_request(request), build_header))
|
|
227
|
+
|
|
228
|
+
success = SUCCESS_CODES.include?(response[:cmd_status])
|
|
229
|
+
message = success ? 'Success' : message_from(response)
|
|
230
|
+
|
|
231
|
+
Response.new(success, message, response,
|
|
232
|
+
:test => test?,
|
|
233
|
+
:authorization => authorization_from(response),
|
|
234
|
+
:avs_result => { :code => response[:avs_result] },
|
|
235
|
+
:cvv_result => response[:cvv_result])
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def message_from(response)
|
|
239
|
+
response[:text_response]
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def authorization_from(response)
|
|
243
|
+
[
|
|
244
|
+
response[:invoice_no],
|
|
245
|
+
response[:ref_no],
|
|
246
|
+
response[:auth_code],
|
|
247
|
+
response[:acq_ref_data],
|
|
248
|
+
response[:process_data]
|
|
249
|
+
].join(";")
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def split_authorization(authorization)
|
|
253
|
+
invoice_no, ref_no, auth_code, acq_ref_data, process_data = authorization.split(";")
|
|
254
|
+
[invoice_no, ref_no, auth_code, acq_ref_data, process_data]
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
ENVELOPE_NAMESPACES = {
|
|
258
|
+
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
|
|
259
|
+
'xmlns:soap' => "http://schemas.xmlsoap.org/soap/envelope/",
|
|
260
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
def escape_xml(xml)
|
|
264
|
+
"\n<![CDATA[\n#{xml}\n]]>\n"
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def unescape_xml(escaped_xml)
|
|
268
|
+
escaped_xml.gsub(/\>/,'>').gsub(/\</,'<')
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
@@ -48,11 +48,10 @@ module ActiveMerchant #:nodoc:
|
|
|
48
48
|
#
|
|
49
49
|
# * <tt>:login</tt> -- The username required to access the Metrics Global control panel. (REQUIRED)
|
|
50
50
|
# * <tt>:password</tt> -- The password required to access the Metrics Global control panel. (REQUIRED)
|
|
51
|
-
# * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
|
|
51
|
+
# * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
|
|
52
52
|
# Otherwise, perform transactions against the production server.
|
|
53
53
|
def initialize(options = {})
|
|
54
54
|
requires!(options, :login, :password)
|
|
55
|
-
@options = options
|
|
56
55
|
super
|
|
57
56
|
end
|
|
58
57
|
|
|
@@ -156,7 +155,7 @@ module ActiveMerchant #:nodoc:
|
|
|
156
155
|
end
|
|
157
156
|
|
|
158
157
|
private
|
|
159
|
-
|
|
158
|
+
|
|
160
159
|
def commit(action, money, parameters)
|
|
161
160
|
parameters[:amount] = amount(money) unless action == 'VOID'
|
|
162
161
|
|
|
@@ -177,8 +176,8 @@ module ActiveMerchant #:nodoc:
|
|
|
177
176
|
# (TESTMODE) Successful Sale
|
|
178
177
|
test_mode = test? || message =~ /TESTMODE/
|
|
179
178
|
|
|
180
|
-
Response.new(success?(response), message, response,
|
|
181
|
-
:test => test_mode,
|
|
179
|
+
Response.new(success?(response), message, response,
|
|
180
|
+
:test => test_mode,
|
|
182
181
|
:authorization => response[:transaction_id],
|
|
183
182
|
:fraud_review => fraud_review?(response),
|
|
184
183
|
:avs_result => { :code => response[:avs_result_code] },
|
|
@@ -199,7 +198,7 @@ module ActiveMerchant #:nodoc:
|
|
|
199
198
|
|
|
200
199
|
results = {
|
|
201
200
|
:response_code => fields[RESPONSE_CODE].to_i,
|
|
202
|
-
:response_reason_code => fields[RESPONSE_REASON_CODE],
|
|
201
|
+
:response_reason_code => fields[RESPONSE_REASON_CODE],
|
|
203
202
|
:response_reason_text => fields[RESPONSE_REASON_TEXT],
|
|
204
203
|
:avs_result_code => fields[AVS_RESULT_CODE],
|
|
205
204
|
:transaction_id => fields[TRANSACTION_ID],
|
|
@@ -252,7 +251,7 @@ module ActiveMerchant #:nodoc:
|
|
|
252
251
|
post[:customer_ip] = options[:ip]
|
|
253
252
|
end
|
|
254
253
|
end
|
|
255
|
-
|
|
254
|
+
|
|
256
255
|
# x_duplicate_window won't be sent by default, because sending it changes the response.
|
|
257
256
|
# "If this field is present in the request with or without a value, an enhanced duplicate transaction response will be sent."
|
|
258
257
|
def add_duplicate_window(post)
|
|
@@ -271,7 +270,7 @@ module ActiveMerchant #:nodoc:
|
|
|
271
270
|
post[:country] = address[:country].to_s
|
|
272
271
|
post[:state] = address[:state].blank? ? 'n/a' : address[:state]
|
|
273
272
|
end
|
|
274
|
-
|
|
273
|
+
|
|
275
274
|
if address = options[:shipping_address]
|
|
276
275
|
post[:ship_to_first_name] = address[:first_name].to_s
|
|
277
276
|
post[:ship_to_last_name] = address[:last_name].to_s
|
|
@@ -296,11 +295,11 @@ module ActiveMerchant #:nodoc:
|
|
|
296
295
|
end
|
|
297
296
|
end
|
|
298
297
|
|
|
299
|
-
def message_from(results)
|
|
298
|
+
def message_from(results)
|
|
300
299
|
if results[:response_code] == DECLINED
|
|
301
300
|
return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code])
|
|
302
301
|
if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code])
|
|
303
|
-
return AVSResult.messages[ results[:avs_result_code] ]
|
|
302
|
+
return AVSResult.messages[ results[:avs_result_code] ]
|
|
304
303
|
end
|
|
305
304
|
end
|
|
306
305
|
|
|
@@ -46,8 +46,6 @@ module ActiveMerchant #:nodoc:
|
|
|
46
46
|
# * <tt>:advanced_password</tt> -- The MiGS AMA User's password
|
|
47
47
|
def initialize(options = {})
|
|
48
48
|
requires!(options, :login, :password)
|
|
49
|
-
@test = options[:login].start_with?('TEST')
|
|
50
|
-
@options = options
|
|
51
49
|
super
|
|
52
50
|
end
|
|
53
51
|
|
|
@@ -180,6 +178,10 @@ module ActiveMerchant #:nodoc:
|
|
|
180
178
|
response_object(response_hash)
|
|
181
179
|
end
|
|
182
180
|
|
|
181
|
+
def test?
|
|
182
|
+
@options[:login].start_with?('TEST')
|
|
183
|
+
end
|
|
184
|
+
|
|
183
185
|
private
|
|
184
186
|
|
|
185
187
|
def add_advanced_user(post)
|
|
@@ -219,7 +221,7 @@ module ActiveMerchant #:nodoc:
|
|
|
219
221
|
|
|
220
222
|
def response_object(response)
|
|
221
223
|
Response.new(success?(response), response[:Message], response,
|
|
222
|
-
:test =>
|
|
224
|
+
:test => test?,
|
|
223
225
|
:authorization => response[:TransactionNo],
|
|
224
226
|
:fraud_review => fraud_review?(response),
|
|
225
227
|
:avs_result => { :code => response[:AVSResultCode] },
|
|
@@ -7,27 +7,26 @@ module ActiveMerchant #:nodoc:
|
|
|
7
7
|
self.supported_cardtypes = ModernPaymentsCimGateway.supported_cardtypes
|
|
8
8
|
self.homepage_url = ModernPaymentsCimGateway.homepage_url
|
|
9
9
|
self.display_name = ModernPaymentsCimGateway.display_name
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
self.abstract_class = true
|
|
12
12
|
|
|
13
13
|
def initialize(options = {})
|
|
14
14
|
requires!(options, :login, :password)
|
|
15
|
-
@options = options
|
|
16
15
|
super
|
|
17
16
|
end
|
|
18
|
-
|
|
17
|
+
|
|
19
18
|
def purchase(money, credit_card, options = {})
|
|
20
19
|
customer_response = cim.create_customer(options)
|
|
21
20
|
return customer_response unless customer_response.success?
|
|
22
|
-
|
|
21
|
+
|
|
23
22
|
customer_id = customer_response.params["create_customer_result"]
|
|
24
|
-
|
|
23
|
+
|
|
25
24
|
card_response = cim.modify_customer_credit_card(customer_id, credit_card)
|
|
26
25
|
return card_response unless card_response.success?
|
|
27
|
-
|
|
26
|
+
|
|
28
27
|
cim.authorize_credit_card_payment(customer_id, money)
|
|
29
28
|
end
|
|
30
|
-
|
|
29
|
+
|
|
31
30
|
private
|
|
32
31
|
def cim
|
|
33
32
|
@cim ||= ModernPaymentsCimGateway.new(@options)
|
|
@@ -3,66 +3,65 @@ module ActiveMerchant #:nodoc:
|
|
|
3
3
|
class ModernPaymentsCimGateway < Gateway #:nodoc:
|
|
4
4
|
self.test_url = "https://secure.modpay.com/netservices/test/ModpayTest.asmx"
|
|
5
5
|
self.live_url = 'https://secure.modpay.com/ws/modpay.asmx'
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
LIVE_XMLNS = "https://secure.modpay.com/ws/"
|
|
8
8
|
TEST_XMLNS = "https://secure.modpay.com/netservices/test/"
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
self.supported_countries = ['US']
|
|
11
11
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
|
12
12
|
self.homepage_url = 'http://www.modpay.com'
|
|
13
13
|
self.display_name = 'Modern Payments'
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
SUCCESS_MESSAGE = "Transaction accepted"
|
|
16
16
|
FAILURE_MESSAGE = "Transaction failed"
|
|
17
17
|
ERROR_MESSAGE = "Transaction error"
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
PAYMENT_METHOD = {
|
|
20
20
|
:check => 1,
|
|
21
21
|
:credit_card => 2
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
def initialize(options = {})
|
|
25
25
|
requires!(options, :login, :password)
|
|
26
|
-
@options = options
|
|
27
26
|
super
|
|
28
|
-
end
|
|
29
|
-
|
|
27
|
+
end
|
|
28
|
+
|
|
30
29
|
def create_customer(options = {})
|
|
31
30
|
post = {}
|
|
32
31
|
add_customer_data(post, options)
|
|
33
32
|
add_address(post, options)
|
|
34
|
-
|
|
33
|
+
|
|
35
34
|
commit('CreateCustomer', post)
|
|
36
35
|
end
|
|
37
|
-
|
|
36
|
+
|
|
38
37
|
def modify_customer_credit_card(customer_id, credit_card)
|
|
39
38
|
raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
|
|
40
|
-
|
|
39
|
+
|
|
41
40
|
post = {}
|
|
42
41
|
add_customer_id(post, customer_id)
|
|
43
42
|
add_credit_card(post, credit_card)
|
|
44
|
-
|
|
43
|
+
|
|
45
44
|
commit('ModifyCustomerCreditCard', post)
|
|
46
45
|
end
|
|
47
|
-
|
|
46
|
+
|
|
48
47
|
def authorize_credit_card_payment(customer_id, amount)
|
|
49
48
|
raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
|
|
50
|
-
|
|
49
|
+
|
|
51
50
|
post = {}
|
|
52
51
|
add_customer_id(post, customer_id)
|
|
53
52
|
add_amount(post, amount)
|
|
54
|
-
|
|
53
|
+
|
|
55
54
|
commit('AuthorizeCreditCardPayment', post)
|
|
56
55
|
end
|
|
57
|
-
|
|
56
|
+
|
|
58
57
|
def create_payment(customer_id, amount, options = {})
|
|
59
58
|
raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
|
|
60
|
-
|
|
59
|
+
|
|
61
60
|
post = {}
|
|
62
61
|
add_customer_id(post, customer_id)
|
|
63
62
|
add_amount(post, amount)
|
|
64
63
|
add_payment_details(post, options)
|
|
65
|
-
|
|
64
|
+
|
|
66
65
|
commit('CreatePayment', post)
|
|
67
66
|
end
|
|
68
67
|
|
|
@@ -71,22 +70,22 @@ module ActiveMerchant #:nodoc:
|
|
|
71
70
|
post[:pmtDate] = (options[:payment_date] || Time.now.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
72
71
|
post[:pmtType] = PAYMENT_METHOD[options[:payment_method] || :credit_card]
|
|
73
72
|
end
|
|
74
|
-
|
|
73
|
+
|
|
75
74
|
def add_amount(post, money)
|
|
76
75
|
post[:pmtAmount] = amount(money)
|
|
77
76
|
end
|
|
78
|
-
|
|
77
|
+
|
|
79
78
|
def add_customer_id(post, customer_id)
|
|
80
79
|
post[:custId] = customer_id
|
|
81
80
|
end
|
|
82
|
-
|
|
81
|
+
|
|
83
82
|
def add_customer_data(post, options)
|
|
84
83
|
post[:acctNum] = options[:customer]
|
|
85
84
|
end
|
|
86
|
-
|
|
85
|
+
|
|
87
86
|
def add_address(post, options)
|
|
88
87
|
address = options[:billing_address] || options[:address] || {}
|
|
89
|
-
|
|
88
|
+
|
|
90
89
|
if name = address[:name]
|
|
91
90
|
segments = name.split(' ')
|
|
92
91
|
post[:lastName] = segments.pop
|
|
@@ -95,7 +94,7 @@ module ActiveMerchant #:nodoc:
|
|
|
95
94
|
post[:firstName] = address[:first_name]
|
|
96
95
|
post[:lastName] = address[:last_name]
|
|
97
96
|
end
|
|
98
|
-
|
|
97
|
+
|
|
99
98
|
post[:address] = address[:address1]
|
|
100
99
|
post[:city] = address[:city]
|
|
101
100
|
post[:state] = address[:state]
|
|
@@ -104,14 +103,14 @@ module ActiveMerchant #:nodoc:
|
|
|
104
103
|
post[:fax] = address[:fax]
|
|
105
104
|
post[:email] = options[:email]
|
|
106
105
|
end
|
|
107
|
-
|
|
106
|
+
|
|
108
107
|
def add_credit_card(post, credit_card)
|
|
109
108
|
post[:ccName] = credit_card.name
|
|
110
109
|
post[:ccNum] = credit_card.number
|
|
111
110
|
post[:expMonth] = credit_card.month
|
|
112
111
|
post[:expYear] = credit_card.year
|
|
113
112
|
end
|
|
114
|
-
|
|
113
|
+
|
|
115
114
|
def build_request(action, params)
|
|
116
115
|
xml = Builder::XmlMarkup.new :indent => 2
|
|
117
116
|
xml.instruct!
|
|
@@ -130,7 +129,7 @@ module ActiveMerchant #:nodoc:
|
|
|
130
129
|
end
|
|
131
130
|
xml.target!
|
|
132
131
|
end
|
|
133
|
-
|
|
132
|
+
|
|
134
133
|
def xmlns(action)
|
|
135
134
|
if test? && action == 'AuthorizeCreditCardPayment'
|
|
136
135
|
TEST_XMLNS
|
|
@@ -138,7 +137,7 @@ module ActiveMerchant #:nodoc:
|
|
|
138
137
|
LIVE_XMLNS
|
|
139
138
|
end
|
|
140
139
|
end
|
|
141
|
-
|
|
140
|
+
|
|
142
141
|
def url(action)
|
|
143
142
|
if test? && action == 'AuthorizeCreditCardPayment'
|
|
144
143
|
self.test_url
|
|
@@ -146,39 +145,39 @@ module ActiveMerchant #:nodoc:
|
|
|
146
145
|
self.live_url
|
|
147
146
|
end
|
|
148
147
|
end
|
|
149
|
-
|
|
148
|
+
|
|
150
149
|
def commit(action, params)
|
|
151
|
-
data = ssl_post(url(action), build_request(action, params),
|
|
152
|
-
{ 'Content-Type' =>'text/xml; charset=utf-8',
|
|
150
|
+
data = ssl_post(url(action), build_request(action, params),
|
|
151
|
+
{ 'Content-Type' =>'text/xml; charset=utf-8',
|
|
153
152
|
'SOAPAction' => "#{xmlns(action)}#{action}" }
|
|
154
153
|
)
|
|
155
154
|
|
|
156
155
|
response = parse(action, data)
|
|
157
|
-
Response.new(successful?(action, response), message_from(action, response), response,
|
|
158
|
-
:test => test?,
|
|
156
|
+
Response.new(successful?(action, response), message_from(action, response), response,
|
|
157
|
+
:test => test?,
|
|
159
158
|
:authorization => authorization_from(action, response),
|
|
160
159
|
:avs_result => { :code => response[:avs_code] }
|
|
161
160
|
)
|
|
162
161
|
end
|
|
163
|
-
|
|
162
|
+
|
|
164
163
|
def authorization_from(action, response)
|
|
165
164
|
response[authorization_key(action)]
|
|
166
165
|
end
|
|
167
|
-
|
|
166
|
+
|
|
168
167
|
def authorization_key(action)
|
|
169
168
|
action == "AuthorizeCreditCardPayment" ? :trans_id : "#{action.underscore}_result".to_sym
|
|
170
169
|
end
|
|
171
|
-
|
|
170
|
+
|
|
172
171
|
def successful?(action, response)
|
|
173
172
|
key = authorization_key(action)
|
|
174
|
-
|
|
173
|
+
|
|
175
174
|
if key == :trans_id
|
|
176
175
|
response[:approved] == "true"
|
|
177
176
|
else
|
|
178
177
|
response[key].to_i > 0
|
|
179
178
|
end
|
|
180
179
|
end
|
|
181
|
-
|
|
180
|
+
|
|
182
181
|
def message_from(action, response)
|
|
183
182
|
if response[:faultcode]
|
|
184
183
|
ERROR_MESSAGE
|
|
@@ -188,11 +187,11 @@ module ActiveMerchant #:nodoc:
|
|
|
188
187
|
FAILURE_MESSAGE
|
|
189
188
|
end
|
|
190
189
|
end
|
|
191
|
-
|
|
190
|
+
|
|
192
191
|
def parse(action, xml)
|
|
193
192
|
response = {}
|
|
194
193
|
response[:action] = action
|
|
195
|
-
|
|
194
|
+
|
|
196
195
|
xml = REXML::Document.new(xml)
|
|
197
196
|
if root = REXML::XPath.first(xml, "//#{action}Response")
|
|
198
197
|
root.elements.to_a.each do |node|
|
|
@@ -206,7 +205,7 @@ module ActiveMerchant #:nodoc:
|
|
|
206
205
|
|
|
207
206
|
response
|
|
208
207
|
end
|
|
209
|
-
|
|
208
|
+
|
|
210
209
|
def parse_element(response, node)
|
|
211
210
|
if node.has_elements?
|
|
212
211
|
node.elements.each{|e| parse_element(response, e) }
|