johnreitano-activemerchant 1.5.2
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 +508 -0
- data/CONTRIBUTORS +134 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +136 -0
- data/gem-public_cert.pem +20 -0
- data/lib/active_merchant/billing/avs_result.rb +98 -0
- data/lib/active_merchant/billing/base.rb +57 -0
- data/lib/active_merchant/billing/check.rb +68 -0
- data/lib/active_merchant/billing/credit_card.rb +159 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
- data/lib/active_merchant/billing/cvv_result.rb +38 -0
- data/lib/active_merchant/billing/expiry_date.rb +34 -0
- data/lib/active_merchant/billing/gateway.rb +163 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +654 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +736 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +244 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +98 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +594 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +593 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
- data/lib/active_merchant/billing/gateways/eway.rb +277 -0
- data/lib/active_merchant/billing/gateways/exact.rb +222 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +172 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +270 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +449 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +283 -0
- data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +279 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
- data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
- data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
- data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +326 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +130 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
- data/lib/active_merchant/billing/gateways/realex.rb +200 -0
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
- data/lib/active_merchant/billing/gateways/sage.rb +146 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +309 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +265 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
- data/lib/active_merchant/billing/gateways/transax.rb +25 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
- data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
- data/lib/active_merchant/billing/gateways.rb +18 -0
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +79 -0
- data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
- data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
- data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
- data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
- data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
- data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
- data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
- data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
- data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
- data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
- data/lib/active_merchant/billing/integrations/helper.rb +93 -0
- data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
- data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
- data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
- data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
- data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
- data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
- data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
- data/lib/active_merchant/billing/integrations/notification.rb +62 -0
- data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
- data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
- data/lib/active_merchant/billing/integrations/quickpay.rb +17 -0
- data/lib/active_merchant/billing/integrations/return.rb +35 -0
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
- data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
- data/lib/active_merchant/billing/integrations.rb +29 -0
- data/lib/active_merchant/billing/response.rb +32 -0
- data/lib/active_merchant/billing.rb +9 -0
- data/lib/active_merchant/lib/connection.rb +170 -0
- data/lib/active_merchant/lib/country.rb +319 -0
- data/lib/active_merchant/lib/error.rb +4 -0
- data/lib/active_merchant/lib/post_data.rb +22 -0
- data/lib/active_merchant/lib/posts_data.rb +47 -0
- data/lib/active_merchant/lib/requires_parameters.rb +16 -0
- data/lib/active_merchant/lib/utils.rb +18 -0
- data/lib/active_merchant/lib/validateable.rb +76 -0
- data/lib/active_merchant.rb +46 -0
- data/lib/certs/cacert.pem +7815 -0
- data/lib/support/gateway_support.rb +58 -0
- metadata +218 -0
@@ -0,0 +1,283 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class MerchantWareGateway < Gateway
|
4
|
+
URL = 'https://ps1.merchantware.net/MerchantWARE/ws/RetailTransaction/TXRetail.asmx'
|
5
|
+
|
6
|
+
self.supported_countries = ['US']
|
7
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
8
|
+
self.homepage_url = 'http://merchantwarehouse.com/merchantware'
|
9
|
+
self.display_name = 'MerchantWARE'
|
10
|
+
|
11
|
+
ENV_NAMESPACES = { "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
|
12
|
+
"xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
|
13
|
+
"xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/"
|
14
|
+
}
|
15
|
+
TX_NAMESPACE = "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail"
|
16
|
+
|
17
|
+
ACTIONS = {
|
18
|
+
:purchase => "IssueKeyedSale",
|
19
|
+
:authorize => "IssueKeyedPreAuth",
|
20
|
+
:capture => "IssuePostAuth",
|
21
|
+
:void => "IssueVoid",
|
22
|
+
:credit => "IssueKeyedRefund",
|
23
|
+
:reference_credit => "IssueRefundByReference"
|
24
|
+
}
|
25
|
+
|
26
|
+
# Creates a new MerchantWareGateway
|
27
|
+
#
|
28
|
+
# The gateway requires that a valid login, password, and name be passed
|
29
|
+
# in the +options+ hash.
|
30
|
+
#
|
31
|
+
# ==== Options
|
32
|
+
#
|
33
|
+
# * <tt>:login</tt> - The MerchantWARE SiteID.
|
34
|
+
# * <tt>:password</tt> - The MerchantWARE Key.
|
35
|
+
# * <tt>:name</tt> - The MerchantWARE Name.
|
36
|
+
def initialize(options = {})
|
37
|
+
requires!(options, :login, :password, :name)
|
38
|
+
@options = options
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
# Authorize a credit card for a given amount.
|
43
|
+
#
|
44
|
+
# ==== Parameters
|
45
|
+
# * <tt>money</tt> - The amount to be authorized as an Integer value in cents.
|
46
|
+
# * <tt>credit_card</tt> - The CreditCard details for the transaction.
|
47
|
+
# * <tt>options</tt>
|
48
|
+
# * <tt>:order_id</tt> - A unique reference for this order (required).
|
49
|
+
# * <tt>:billing_address</tt> - The billing address for the cardholder.
|
50
|
+
def authorize(money, credit_card, options = {})
|
51
|
+
request = build_purchase_request(:authorize, money, credit_card, options)
|
52
|
+
commit(:authorize, request)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Authorize and immediately capture funds from a credit card.
|
56
|
+
#
|
57
|
+
# ==== Parameters
|
58
|
+
# * <tt>money</tt> - The amount to be authorized as anInteger value in cents.
|
59
|
+
# * <tt>credit_card</tt> - The CreditCard details for the transaction.
|
60
|
+
# * <tt>options</tt>
|
61
|
+
# * <tt>:order_id</tt> - A unique reference for this order (required).
|
62
|
+
# * <tt>:billing_address</tt> - The billing address for the cardholder.
|
63
|
+
def purchase(money, credit_card, options = {})
|
64
|
+
request = build_purchase_request(:purchase, money, credit_card, options)
|
65
|
+
commit(:purchase, request)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Capture authorized funds from a credit card.
|
69
|
+
#
|
70
|
+
# ==== Parameters
|
71
|
+
# * <tt>money</tt> - The amount to be captured as anInteger value in cents.
|
72
|
+
# * <tt>authorization</tt> - The authorization string returned from the initial authorization.
|
73
|
+
def capture(money, authorization, options = {})
|
74
|
+
request = build_capture_request(:capture, money, authorization, options)
|
75
|
+
commit(:capture, request)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Void a transaction.
|
79
|
+
#
|
80
|
+
# ==== Parameters
|
81
|
+
# * <tt>authorization</tt> - The authorization string returned from the initial authorization or purchase.
|
82
|
+
def void(authorization, options = {})
|
83
|
+
reference, options[:order_id] = split_reference(authorization)
|
84
|
+
|
85
|
+
request = soap_request(:void) do |xml|
|
86
|
+
add_reference(xml, reference)
|
87
|
+
end
|
88
|
+
commit(:void, request)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Refund an amount back a cardholder
|
92
|
+
#
|
93
|
+
# ==== Parameters
|
94
|
+
#
|
95
|
+
# * <tt>money</tt> - The amount to be refunded as an Integer value in cents.
|
96
|
+
# * <tt>identification</tt> - The credit card you want to refund or the authorization for the existing transaction you are refunding.
|
97
|
+
# * <tt>options</tt>
|
98
|
+
# * <tt>:order_id</tt> - A unique reference for this order (required when performing a non-referenced credit)
|
99
|
+
def credit(money, identification, options = {})
|
100
|
+
if identification.is_a?(String)
|
101
|
+
perform_reference_credit(money, identification, options)
|
102
|
+
else
|
103
|
+
perform_credit(money, identification, options)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def soap_request(action)
|
110
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
111
|
+
xml.instruct!
|
112
|
+
xml.tag! "env:Envelope", ENV_NAMESPACES do
|
113
|
+
xml.tag! "env:Body" do
|
114
|
+
xml.tag! ACTIONS[action], "xmlns" => TX_NAMESPACE do
|
115
|
+
add_credentials(xml)
|
116
|
+
yield xml
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
xml.target!
|
121
|
+
end
|
122
|
+
|
123
|
+
def build_purchase_request(action, money, credit_card, options)
|
124
|
+
requires!(options, :order_id)
|
125
|
+
|
126
|
+
request = soap_request(action) do |xml|
|
127
|
+
add_invoice(xml, options)
|
128
|
+
add_amount(xml, money)
|
129
|
+
add_credit_card(xml, credit_card)
|
130
|
+
add_address(xml, options)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def build_capture_request(action, money, identification, options)
|
135
|
+
reference, options[:order_id] = split_reference(identification)
|
136
|
+
|
137
|
+
request = soap_request(action) do |xml|
|
138
|
+
add_reference(xml, reference)
|
139
|
+
add_invoice(xml, options)
|
140
|
+
add_amount(xml, money)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def perform_reference_credit(money, identification, options)
|
145
|
+
reference, options[:order_id] = split_reference(identification)
|
146
|
+
|
147
|
+
request = soap_request(:reference_credit) do |xml|
|
148
|
+
add_reference(xml, reference)
|
149
|
+
add_invoice(xml, options)
|
150
|
+
add_amount(xml, money, "strOverrideAmount")
|
151
|
+
end
|
152
|
+
|
153
|
+
commit(:reference_credit, request)
|
154
|
+
end
|
155
|
+
|
156
|
+
def perform_credit(money, credit_card, options)
|
157
|
+
requires!(options, :order_id)
|
158
|
+
|
159
|
+
request = soap_request(:credit) do |xml|
|
160
|
+
add_invoice(xml, options)
|
161
|
+
add_amount(xml, money)
|
162
|
+
add_credit_card(xml, credit_card)
|
163
|
+
end
|
164
|
+
|
165
|
+
commit(:credit, request)
|
166
|
+
end
|
167
|
+
|
168
|
+
def add_credentials(xml)
|
169
|
+
xml.tag! "strSiteId", @options[:login]
|
170
|
+
xml.tag! "strKey", @options[:password]
|
171
|
+
xml.tag! "strName", @options[:name]
|
172
|
+
end
|
173
|
+
|
174
|
+
def expdate(credit_card)
|
175
|
+
year = sprintf("%.4i", credit_card.year)
|
176
|
+
month = sprintf("%.2i", credit_card.month)
|
177
|
+
|
178
|
+
"#{month}#{year[-2..-1]}"
|
179
|
+
end
|
180
|
+
|
181
|
+
def add_invoice(xml, options)
|
182
|
+
xml.tag! "strOrderNumber", options[:order_id].to_s.gsub(/[^\w]/, '').slice(0, 25)
|
183
|
+
end
|
184
|
+
|
185
|
+
def add_amount(xml, money, tag = "strAmount")
|
186
|
+
xml.tag! tag, amount(money)
|
187
|
+
end
|
188
|
+
|
189
|
+
def add_reference(xml, reference)
|
190
|
+
xml.tag! "strReferenceCode", reference
|
191
|
+
end
|
192
|
+
|
193
|
+
def add_address(xml, options)
|
194
|
+
if address = options[:billing_address] || options[:address]
|
195
|
+
xml.tag! "strAVSStreetAddress", address[:address1]
|
196
|
+
xml.tag! "strAVSZipCode", address[:zip]
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def add_credit_card(xml, credit_card)
|
201
|
+
xml.tag! "strPAN", credit_card.number
|
202
|
+
xml.tag! "strExpDate", expdate(credit_card)
|
203
|
+
xml.tag! "strCardHolder", credit_card.name
|
204
|
+
xml.tag! "strCVCode", credit_card.verification_value if credit_card.verification_value?
|
205
|
+
end
|
206
|
+
|
207
|
+
def split_reference(reference)
|
208
|
+
reference.to_s.split(";")
|
209
|
+
end
|
210
|
+
|
211
|
+
def parse(action, data)
|
212
|
+
response = {}
|
213
|
+
xml = REXML::Document.new(data)
|
214
|
+
|
215
|
+
root = REXML::XPath.first(xml, "//#{ACTIONS[action]}Response/#{ACTIONS[action]}Result")
|
216
|
+
|
217
|
+
root.elements.each do |element|
|
218
|
+
response[element.name] = element.text
|
219
|
+
end
|
220
|
+
|
221
|
+
status, code, message = response["ApprovalStatus"].split(";")
|
222
|
+
response[:status] = status
|
223
|
+
|
224
|
+
if response[:success] = status == "APPROVED"
|
225
|
+
response[:message] = status
|
226
|
+
else
|
227
|
+
response[:message] = message
|
228
|
+
response[:failure_code] = code
|
229
|
+
end
|
230
|
+
|
231
|
+
response
|
232
|
+
end
|
233
|
+
|
234
|
+
def parse_error(http_response)
|
235
|
+
response = {}
|
236
|
+
response[:http_code] = http_response.code
|
237
|
+
response[:http_message] = http_response.message
|
238
|
+
response[:success] = false
|
239
|
+
|
240
|
+
document = REXML::Document.new(http_response.body)
|
241
|
+
|
242
|
+
node = REXML::XPath.first(document, "//soap:Fault")
|
243
|
+
|
244
|
+
node.elements.each do |element|
|
245
|
+
response[element.name] = element.text
|
246
|
+
end
|
247
|
+
|
248
|
+
response[:message] = response["faultstring"].to_s.gsub("\n", " ")
|
249
|
+
response
|
250
|
+
rescue REXML::ParseException => e
|
251
|
+
response[:http_body] = http_response.body
|
252
|
+
response[:message] = "Failed to parse the failed response"
|
253
|
+
response
|
254
|
+
end
|
255
|
+
|
256
|
+
def commit(action, request)
|
257
|
+
begin
|
258
|
+
data = ssl_post(URL, request,
|
259
|
+
"Content-Type" => 'text/xml; charset=utf-8',
|
260
|
+
"SOAPAction" => "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail/#{ACTIONS[action]}"
|
261
|
+
)
|
262
|
+
response = parse(action, data)
|
263
|
+
rescue ActiveMerchant::ResponseError => e
|
264
|
+
response = parse_error(e.response)
|
265
|
+
end
|
266
|
+
|
267
|
+
Response.new(response[:success], response[:message], response,
|
268
|
+
:test => test?,
|
269
|
+
:authorization => authorization_from(response),
|
270
|
+
:avs_result => { :code => response["AVSResponse"] },
|
271
|
+
:cvv_result => response["CVResponse"]
|
272
|
+
)
|
273
|
+
end
|
274
|
+
|
275
|
+
def authorization_from(response)
|
276
|
+
if response[:success]
|
277
|
+
[ response["ReferenceID"], response["OrderNumber"] ].join(";")
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/modern_payments_cim'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class ModernPaymentsGateway < Gateway
|
6
|
+
self.supported_countries = ModernPaymentsCimGateway.supported_countries
|
7
|
+
self.supported_cardtypes = ModernPaymentsCimGateway.supported_cardtypes
|
8
|
+
self.homepage_url = ModernPaymentsCimGateway.homepage_url
|
9
|
+
self.display_name = ModernPaymentsCimGateway.display_name
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
requires!(options, :login, :password)
|
13
|
+
@options = options
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def purchase(money, credit_card, options = {})
|
18
|
+
customer_response = cim.create_customer(options)
|
19
|
+
return customer_response unless customer_response.success?
|
20
|
+
|
21
|
+
customer_id = customer_response.params["create_customer_result"]
|
22
|
+
|
23
|
+
card_response = cim.modify_customer_credit_card(customer_id, credit_card)
|
24
|
+
return card_response unless card_response.success?
|
25
|
+
|
26
|
+
cim.authorize_credit_card_payment(customer_id, money)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def cim
|
31
|
+
@cim ||= ModernPaymentsCimGateway.new(@options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,220 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class ModernPaymentsCimGateway < Gateway #:nodoc:
|
4
|
+
TEST_URL = "https://secure.modpay.com/netservices/test/ModpayTest.asmx"
|
5
|
+
LIVE_URL = 'https://secure.modpay.com/ws/modpay.asmx'
|
6
|
+
|
7
|
+
LIVE_XMLNS = "https://secure.modpay.com/ws/"
|
8
|
+
TEST_XMLNS = "https://secure.modpay.com/netservices/test/"
|
9
|
+
|
10
|
+
self.supported_countries = ['US']
|
11
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
12
|
+
self.homepage_url = 'http://www.modpay.com'
|
13
|
+
self.display_name = 'Modern Payments'
|
14
|
+
|
15
|
+
SUCCESS_MESSAGE = "Transaction accepted"
|
16
|
+
FAILURE_MESSAGE = "Transaction failed"
|
17
|
+
ERROR_MESSAGE = "Transaction error"
|
18
|
+
|
19
|
+
PAYMENT_METHOD = {
|
20
|
+
:check => 1,
|
21
|
+
:credit_card => 2
|
22
|
+
}
|
23
|
+
|
24
|
+
def initialize(options = {})
|
25
|
+
requires!(options, :login, :password)
|
26
|
+
@options = options
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_customer(options = {})
|
31
|
+
post = {}
|
32
|
+
add_customer_data(post, options)
|
33
|
+
add_address(post, options)
|
34
|
+
|
35
|
+
commit('CreateCustomer', post)
|
36
|
+
end
|
37
|
+
|
38
|
+
def modify_customer_credit_card(customer_id, credit_card)
|
39
|
+
raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
|
40
|
+
|
41
|
+
post = {}
|
42
|
+
add_customer_id(post, customer_id)
|
43
|
+
add_credit_card(post, credit_card)
|
44
|
+
|
45
|
+
commit('ModifyCustomerCreditCard', post)
|
46
|
+
end
|
47
|
+
|
48
|
+
def authorize_credit_card_payment(customer_id, amount)
|
49
|
+
raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
|
50
|
+
|
51
|
+
post = {}
|
52
|
+
add_customer_id(post, customer_id)
|
53
|
+
add_amount(post, amount)
|
54
|
+
|
55
|
+
commit('AuthorizeCreditCardPayment', post)
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_payment(customer_id, amount, options = {})
|
59
|
+
raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
|
60
|
+
|
61
|
+
post = {}
|
62
|
+
add_customer_id(post, customer_id)
|
63
|
+
add_amount(post, amount)
|
64
|
+
add_payment_details(post, options)
|
65
|
+
|
66
|
+
commit('CreatePayment', post)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
def add_payment_details(post, options)
|
71
|
+
post[:pmtDate] = (options[:payment_date] || Time.now.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
72
|
+
post[:pmtType] = PAYMENT_METHOD[options[:payment_method] || :credit_card]
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_amount(post, money)
|
76
|
+
post[:pmtAmount] = amount(money)
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_customer_id(post, customer_id)
|
80
|
+
post[:custId] = customer_id
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_customer_data(post, options)
|
84
|
+
post[:acctNum] = options[:customer]
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_address(post, options)
|
88
|
+
address = options[:billing_address] || options[:address] || {}
|
89
|
+
|
90
|
+
if name = address[:name]
|
91
|
+
segments = name.split(' ')
|
92
|
+
post[:lastName] = segments.pop
|
93
|
+
post[:firstName] = segments.join(' ')
|
94
|
+
else
|
95
|
+
post[:firstName] = address[:first_name]
|
96
|
+
post[:lastName] = address[:last_name]
|
97
|
+
end
|
98
|
+
|
99
|
+
post[:address] = address[:address1]
|
100
|
+
post[:city] = address[:city]
|
101
|
+
post[:state] = address[:state]
|
102
|
+
post[:zip] = address[:zip]
|
103
|
+
post[:phone] = address[:phone]
|
104
|
+
post[:fax] = address[:fax]
|
105
|
+
post[:email] = options[:email]
|
106
|
+
end
|
107
|
+
|
108
|
+
def add_credit_card(post, credit_card)
|
109
|
+
post[:ccName] = credit_card.name
|
110
|
+
post[:ccNum] = credit_card.number
|
111
|
+
post[:expMonth] = credit_card.month
|
112
|
+
post[:expYear] = credit_card.year
|
113
|
+
end
|
114
|
+
|
115
|
+
def build_request(action, params)
|
116
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
117
|
+
xml.instruct!
|
118
|
+
xml.tag! 'env:Envelope',
|
119
|
+
{ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
|
120
|
+
'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
|
121
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance' } do
|
122
|
+
|
123
|
+
xml.tag! 'env:Body' do
|
124
|
+
xml.tag! action, { "xmlns" => xmlns(action) } do
|
125
|
+
xml.tag! "clientId", @options[:login]
|
126
|
+
xml.tag! "clientCode", @options[:password]
|
127
|
+
params.each {|key, value| xml.tag! key, value }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
xml.target!
|
132
|
+
end
|
133
|
+
|
134
|
+
def xmlns(action)
|
135
|
+
if test? && action == 'AuthorizeCreditCardPayment'
|
136
|
+
TEST_XMLNS
|
137
|
+
else
|
138
|
+
LIVE_XMLNS
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def url(action)
|
143
|
+
if test? && action == 'AuthorizeCreditCardPayment'
|
144
|
+
TEST_URL
|
145
|
+
else
|
146
|
+
LIVE_URL
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def commit(action, params)
|
151
|
+
data = ssl_post(url(action), build_request(action, params),
|
152
|
+
{ 'Content-Type' =>'text/xml; charset=utf-8',
|
153
|
+
'SOAPAction' => "#{xmlns(action)}#{action}" }
|
154
|
+
)
|
155
|
+
|
156
|
+
response = parse(action, data)
|
157
|
+
Response.new(successful?(action, response), message_from(action, response), response,
|
158
|
+
:test => test?,
|
159
|
+
:authorization => authorization_from(action, response),
|
160
|
+
:avs_result => { :code => response[:avs_code] }
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
def authorization_from(action, response)
|
165
|
+
response[authorization_key(action)]
|
166
|
+
end
|
167
|
+
|
168
|
+
def authorization_key(action)
|
169
|
+
action == "AuthorizeCreditCardPayment" ? :trans_id : "#{action.underscore}_result".to_sym
|
170
|
+
end
|
171
|
+
|
172
|
+
def successful?(action, response)
|
173
|
+
key = authorization_key(action)
|
174
|
+
|
175
|
+
if key == :trans_id
|
176
|
+
response[:approved] == "true"
|
177
|
+
else
|
178
|
+
response[key].to_i > 0
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def message_from(action, response)
|
183
|
+
if response[:faultcode]
|
184
|
+
ERROR_MESSAGE
|
185
|
+
elsif successful?(action, response)
|
186
|
+
SUCCESS_MESSAGE
|
187
|
+
else
|
188
|
+
FAILURE_MESSAGE
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def parse(action, xml)
|
193
|
+
response = {}
|
194
|
+
response[:action] = action
|
195
|
+
|
196
|
+
xml = REXML::Document.new(xml)
|
197
|
+
if root = REXML::XPath.first(xml, "//#{action}Response")
|
198
|
+
root.elements.to_a.each do |node|
|
199
|
+
parse_element(response, node)
|
200
|
+
end
|
201
|
+
elsif root = REXML::XPath.first(xml, "//soap:Fault")
|
202
|
+
root.elements.to_a.each do |node|
|
203
|
+
response[node.name.underscore.to_sym] = node.text
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
response
|
208
|
+
end
|
209
|
+
|
210
|
+
def parse_element(response, node)
|
211
|
+
if node.has_elements?
|
212
|
+
node.elements.each{|e| parse_element(response, e) }
|
213
|
+
else
|
214
|
+
response[node.name.underscore.to_sym] = node.text.to_s.strip
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|