gonow-activemerchant 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +690 -0
- data/CONTRIBUTORS +237 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +165 -0
- data/gem-public_cert.pem +20 -0
- data/lib/active_merchant.rb +47 -0
- data/lib/active_merchant/billing.rb +9 -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 +178 -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 +170 -0
- data/lib/active_merchant/billing/gateways.rb +18 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +664 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +858 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +139 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +282 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +132 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +293 -0
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
- data/lib/active_merchant/billing/gateways/braspag.rb +188 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +430 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
- data/lib/active_merchant/billing/gateways/epay.rb +268 -0
- data/lib/active_merchant/billing/gateways/eway.rb +277 -0
- data/lib/active_merchant/billing/gateways/eway_managed.rb +231 -0
- data/lib/active_merchant/billing/gateways/exact.rb +222 -0
- data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
- data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
- data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
- data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +156 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -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 +209 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
- data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +292 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +321 -0
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -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/paybox_direct.rb +207 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +253 -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_express.rb +222 -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 +235 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +351 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +177 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +295 -0
- data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +218 -0
- data/lib/active_merchant/billing/gateways/realex.rb +311 -0
- data/lib/active_merchant/billing/gateways/sage.rb +146 -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_pay.rb +320 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
- data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +193 -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 +271 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +212 -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 +423 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +233 -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/worldpay.rb +280 -0
- data/lib/active_merchant/billing/integrations.rb +17 -0
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +68 -0
- data/lib/active_merchant/billing/integrations/bogus.rb +23 -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/chronopay.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/direc_pay.rb +41 -0
- data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
- data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
- data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
- data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
- data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
- data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
- data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
- data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
- data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
- data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
- data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
- data/lib/active_merchant/billing/integrations/gestpay.rb +25 -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/helper.rb +96 -0
- data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -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/moneybookers.rb +26 -0
- data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
- data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
- data/lib/active_merchant/billing/integrations/nochex.rb +88 -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/notification.rb +62 -0
- data/lib/active_merchant/billing/integrations/paypal.rb +39 -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/quickpay.rb +21 -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/return.rb +42 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -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/valitor.rb +33 -0
- data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
- data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
- data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
- data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
- data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
- data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
- data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
- data/lib/active_merchant/billing/response.rb +32 -0
- data/lib/active_merchant/common.rb +14 -0
- data/lib/active_merchant/common/connection.rb +177 -0
- data/lib/active_merchant/common/country.rb +328 -0
- data/lib/active_merchant/common/error.rb +26 -0
- data/lib/active_merchant/common/post_data.rb +24 -0
- data/lib/active_merchant/common/posts_data.rb +63 -0
- data/lib/active_merchant/common/requires_parameters.rb +16 -0
- data/lib/active_merchant/common/utils.rb +22 -0
- data/lib/active_merchant/common/validateable.rb +81 -0
- data/lib/active_merchant/version.rb +3 -0
- data/lib/activemerchant.rb +1 -0
- data/lib/certs/cacert.pem +7815 -0
- data/lib/support/gateway_support.rb +58 -0
- data/lib/support/outbound_hosts.rb +25 -0
- metadata +276 -0
@@ -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
|
+
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
|
6
|
+
# To learn more about the Moneris gateway, please contact
|
7
|
+
# eselectplus@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 MonerisGateway < Gateway
|
13
|
+
TEST_URL = 'https://esqa.moneris.com/gateway2/servlet/MpgRequest'
|
14
|
+
LIVE_URL = 'https://www3.moneris.com/gateway2/servlet/MpgRequest'
|
15
|
+
|
16
|
+
self.supported_countries = ['CA']
|
17
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover]
|
18
|
+
self.homepage_url = 'http://www.moneris.com/'
|
19
|
+
self.display_name = 'Moneris'
|
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 '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 '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 '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 '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 'refund', crediting_params(authorization, :amount => amount(money))
|
80
|
+
end
|
81
|
+
private # :nodoc: all
|
82
|
+
|
83
|
+
def expdate(creditcard)
|
84
|
+
sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
|
85
|
+
end
|
86
|
+
|
87
|
+
def debit_commit(commit_type, money, creditcard, options)
|
88
|
+
requires!(options, :order_id)
|
89
|
+
commit(commit_type, debit_params(money, creditcard, options))
|
90
|
+
end
|
91
|
+
|
92
|
+
# Common params used amongst the +purchase+ and +authorization+ methods
|
93
|
+
def debit_params(money, creditcard, options = {})
|
94
|
+
{
|
95
|
+
:order_id => options[:order_id],
|
96
|
+
:cust_id => options[:customer],
|
97
|
+
:amount => amount(money),
|
98
|
+
:pan => creditcard.number,
|
99
|
+
:expdate => expdate(creditcard),
|
100
|
+
:crypt_type => options[:crypt_type] || @options[:crypt_type]
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
# Common params used amongst the +credit+, +void+ and +capture+ methods
|
105
|
+
def crediting_params(authorization, options = {})
|
106
|
+
{
|
107
|
+
:txn_number => split_authorization(authorization).first,
|
108
|
+
:order_id => split_authorization(authorization).last,
|
109
|
+
:crypt_type => options[:crypt_type] || @options[:crypt_type]
|
110
|
+
}.merge(options)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Splits an +authorization+ param and retrives the order id and
|
114
|
+
# transaction number in that order.
|
115
|
+
def split_authorization(authorization)
|
116
|
+
if authorization.nil? || authorization.empty? || authorization !~ /;/
|
117
|
+
raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")'
|
118
|
+
else
|
119
|
+
authorization.split(';')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def commit(action, parameters = {})
|
124
|
+
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters)))
|
125
|
+
|
126
|
+
Response.new(successful?(response), message_from(response[:message]), response,
|
127
|
+
:test => test?,
|
128
|
+
:authorization => authorization_from(response)
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Generates a Moneris authorization string of the form 'trans_id;receipt_id'.
|
133
|
+
def authorization_from(response = {})
|
134
|
+
if response[:trans_id] && response[:receipt_id]
|
135
|
+
"#{response[:trans_id]};#{response[:receipt_id]}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Tests for a successful response from Moneris' servers
|
140
|
+
def successful?(response)
|
141
|
+
response[:response_code] &&
|
142
|
+
response[:complete] &&
|
143
|
+
(0..49).include?(response[:response_code].to_i)
|
144
|
+
end
|
145
|
+
|
146
|
+
def parse(xml)
|
147
|
+
response = { :message => "Global Error Receipt", :complete => false }
|
148
|
+
hashify_xml!(xml, response)
|
149
|
+
response
|
150
|
+
end
|
151
|
+
|
152
|
+
def hashify_xml!(xml, response)
|
153
|
+
xml = REXML::Document.new(xml)
|
154
|
+
return if xml.root.nil?
|
155
|
+
xml.elements.each('//receipt/*') do |node|
|
156
|
+
response[node.name.underscore.to_sym] = normalize(node.text)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def post_data(action, parameters = {})
|
161
|
+
xml = REXML::Document.new
|
162
|
+
root = xml.add_element("request")
|
163
|
+
root.add_element("store_id").text = options[:login]
|
164
|
+
root.add_element("api_token").text = options[:password]
|
165
|
+
transaction = root.add_element(action)
|
166
|
+
|
167
|
+
# Must add the elements in the correct order
|
168
|
+
actions[action].each do |key|
|
169
|
+
transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
|
170
|
+
end
|
171
|
+
|
172
|
+
xml.to_s
|
173
|
+
end
|
174
|
+
|
175
|
+
def message_from(message)
|
176
|
+
return 'Unspecified error' if message.blank?
|
177
|
+
message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
|
178
|
+
end
|
179
|
+
|
180
|
+
# Make a Ruby type out of the response string
|
181
|
+
def normalize(field)
|
182
|
+
case field
|
183
|
+
when "true" then true
|
184
|
+
when "false" then false
|
185
|
+
when '', "null" then nil
|
186
|
+
else field
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def actions
|
191
|
+
{
|
192
|
+
"purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
193
|
+
"preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
194
|
+
"command" => [:order_id],
|
195
|
+
"refund" => [:order_id, :amount, :txn_number, :crypt_type],
|
196
|
+
"indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
197
|
+
"completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
|
198
|
+
"purchasecorrection" => [:order_id, :txn_number, :crypt_type],
|
199
|
+
"cavvpurcha" => [:order_id, :cust_id, :amount, :pan, :expdate, :cav],
|
200
|
+
"cavvpreaut" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
|
201
|
+
"transact" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
|
202
|
+
"Batchcloseall" => [],
|
203
|
+
"opentotals" => [:ecr_number],
|
204
|
+
"batchclose" => [:ecr_number]
|
205
|
+
}
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Billing
|
3
|
+
# Gateway for netregistry.com.au.
|
4
|
+
#
|
5
|
+
# Note that NetRegistry itself uses gateway service providers. At the
|
6
|
+
# time of this writing, there are at least two (Quest and Ingenico).
|
7
|
+
# This module has only been tested with Quest.
|
8
|
+
#
|
9
|
+
# Also note that NetRegistry does not offer a test mode, nor does it
|
10
|
+
# have support for the authorize/capture/void functionality by default
|
11
|
+
# (you may arrange for this as described in "Programming for
|
12
|
+
# NetRegistry's E-commerce Gateway." [http://rubyurl.com/hNG]), and no
|
13
|
+
# #void functionality is documented. As a result, the #authorize and
|
14
|
+
# #capture have not yet been tested through a live gateway, and #void
|
15
|
+
# will raise an error.
|
16
|
+
#
|
17
|
+
# If you have this functionality enabled, please consider contributing
|
18
|
+
# to ActiveMerchant by writing tests/code for these methods, and
|
19
|
+
# submitting a patch.
|
20
|
+
#
|
21
|
+
# In addition to the standard ActiveMerchant functionality, the
|
22
|
+
# response will contain a 'receipt' parameter
|
23
|
+
# (response.params['receipt']) if a receipt was issued by the gateway.
|
24
|
+
class NetRegistryGateway < Gateway
|
25
|
+
URL = 'https://4tknox.au.com/cgi-bin/themerchant.au.com/ecom/external2.pl'
|
26
|
+
|
27
|
+
FILTERED_PARAMS = [ 'card_no', 'card_expiry', 'receipt_array' ]
|
28
|
+
|
29
|
+
self.supported_countries = ['AU']
|
30
|
+
|
31
|
+
# Note that support for Diners, Amex, and JCB require extra
|
32
|
+
# steps in setting up your account, as detailed in
|
33
|
+
# "Programming for NetRegistry's E-commerce Gateway."
|
34
|
+
# [http://rubyurl.com/hNG]
|
35
|
+
self.supported_cardtypes = [:visa, :master, :diners_club, :american_express, :jcb]
|
36
|
+
self.display_name = 'NetRegistry'
|
37
|
+
self.homepage_url = 'http://www.netregistry.com.au'
|
38
|
+
|
39
|
+
TRANSACTIONS = {
|
40
|
+
:authorization => 'preauth',
|
41
|
+
:purchase => 'purchase',
|
42
|
+
:capture => 'completion',
|
43
|
+
:status => 'status',
|
44
|
+
:credit => 'refund'
|
45
|
+
}
|
46
|
+
|
47
|
+
# Create a new NetRegistry gateway.
|
48
|
+
#
|
49
|
+
# Options :login and :password must be given.
|
50
|
+
def initialize(options = {})
|
51
|
+
requires!(options, :login, :password)
|
52
|
+
@options = options
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
# Note that #authorize and #capture only work if your account
|
57
|
+
# vendor is St George, and if your account has been setup as
|
58
|
+
# described in "Programming for NetRegistry's E-commerce
|
59
|
+
# Gateway." [http://rubyurl.com/hNG]
|
60
|
+
def authorize(money, credit_card, options = {})
|
61
|
+
params = {
|
62
|
+
'AMOUNT' => amount(money),
|
63
|
+
'CCNUM' => credit_card.number,
|
64
|
+
'CCEXP' => expiry(credit_card)
|
65
|
+
}
|
66
|
+
add_request_details(params, options)
|
67
|
+
commit(:authorization, params)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Note that #authorize and #capture only work if your account
|
71
|
+
# vendor is St George, and if your account has been setup as
|
72
|
+
# described in "Programming for NetRegistry's E-commerce
|
73
|
+
# Gateway." [http://rubyurl.com/hNG]
|
74
|
+
def capture(money, authorization, options = {})
|
75
|
+
requires!(options, :credit_card)
|
76
|
+
credit_card = options[:credit_card]
|
77
|
+
|
78
|
+
params = {
|
79
|
+
'PREAUTHNUM' => authorization,
|
80
|
+
'AMOUNT' => amount(money),
|
81
|
+
'CCNUM' => credit_card.number,
|
82
|
+
'CCEXP' => expiry(credit_card)
|
83
|
+
}
|
84
|
+
add_request_details(params, options)
|
85
|
+
commit(:capture, params)
|
86
|
+
end
|
87
|
+
|
88
|
+
def purchase(money, credit_card, options = {})
|
89
|
+
params = {
|
90
|
+
'AMOUNT' => amount(money),
|
91
|
+
'CCNUM' => credit_card.number,
|
92
|
+
'CCEXP' => expiry(credit_card)
|
93
|
+
}
|
94
|
+
add_request_details(params, options)
|
95
|
+
commit(:purchase, params)
|
96
|
+
end
|
97
|
+
|
98
|
+
def credit(money, identification, options = {})
|
99
|
+
params = {
|
100
|
+
'AMOUNT' => amount(money),
|
101
|
+
'TXNREF' => identification
|
102
|
+
}
|
103
|
+
add_request_details(params, options)
|
104
|
+
commit(:credit, params)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Specific to NetRegistry.
|
108
|
+
#
|
109
|
+
# Run a 'status' command. This lets you view the status of a
|
110
|
+
# completed transaction.
|
111
|
+
#
|
112
|
+
def status(identification)
|
113
|
+
params = {
|
114
|
+
'TXNREF' => identification
|
115
|
+
}
|
116
|
+
|
117
|
+
commit(:status, params)
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
def add_request_details(params, options)
|
122
|
+
params['COMMENT'] = options[:description] unless options[:description].blank?
|
123
|
+
end
|
124
|
+
|
125
|
+
# Return the expiry for the given creditcard in the required
|
126
|
+
# format for a command.
|
127
|
+
def expiry(credit_card)
|
128
|
+
month = format(credit_card.month, :two_digits)
|
129
|
+
year = format(credit_card.year , :two_digits)
|
130
|
+
"#{month}/#{year}"
|
131
|
+
end
|
132
|
+
|
133
|
+
# Post the a request with the given parameters and return the
|
134
|
+
# response object.
|
135
|
+
#
|
136
|
+
# Login and password are added automatically, and the comment is
|
137
|
+
# omitted if nil.
|
138
|
+
def commit(action, params)
|
139
|
+
# get gateway response
|
140
|
+
response = parse( ssl_post(URL, post_data(action, params)) )
|
141
|
+
|
142
|
+
Response.new(response['status'] == 'approved', message_from(response), response,
|
143
|
+
:authorization => authorization_from(response, action)
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
def post_data(action, params)
|
148
|
+
params['COMMAND'] = TRANSACTIONS[action]
|
149
|
+
params['LOGIN'] = "#{@options[:login]}/#{@options[:password]}"
|
150
|
+
URI.encode(params.map{|k,v| "#{k}=#{v}"}.join('&'))
|
151
|
+
end
|
152
|
+
|
153
|
+
def parse(response)
|
154
|
+
params = {}
|
155
|
+
|
156
|
+
lines = response.split("\n")
|
157
|
+
|
158
|
+
# Just incase there is no real response returned
|
159
|
+
params['status'] = lines[0]
|
160
|
+
params['response_text'] = lines[1]
|
161
|
+
|
162
|
+
started = false
|
163
|
+
lines.each do |line|
|
164
|
+
if started
|
165
|
+
key, val = line.chomp.split(/=/, 2)
|
166
|
+
params[key] = val unless FILTERED_PARAMS.include?(key)
|
167
|
+
end
|
168
|
+
|
169
|
+
started = line.chomp =~ /^\.$/ unless started
|
170
|
+
end
|
171
|
+
|
172
|
+
params
|
173
|
+
end
|
174
|
+
|
175
|
+
def message_from(response)
|
176
|
+
response['response_text']
|
177
|
+
end
|
178
|
+
|
179
|
+
def authorization_from(response, command)
|
180
|
+
case command
|
181
|
+
when :purchase
|
182
|
+
response['txn_ref']
|
183
|
+
when :authorization
|
184
|
+
response['transaction_no']
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|