tlconnor-activemerchant 1.20.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. data/CHANGELOG +805 -0
  2. data/CONTRIBUTORS +274 -0
  3. data/MIT-LICENSE +20 -0
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/active_merchant.rb +63 -0
  6. data/lib/active_merchant/billing.rb +9 -0
  7. data/lib/active_merchant/billing/avs_result.rb +98 -0
  8. data/lib/active_merchant/billing/base.rb +57 -0
  9. data/lib/active_merchant/billing/check.rb +68 -0
  10. data/lib/active_merchant/billing/credit_card.rb +264 -0
  11. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  12. data/lib/active_merchant/billing/credit_card_methods.rb +129 -0
  13. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  14. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  15. data/lib/active_merchant/billing/gateway.rb +170 -0
  16. data/lib/active_merchant/billing/gateways.rb +18 -0
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +694 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +944 -0
  19. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  20. data/lib/active_merchant/billing/gateways/beanstream.rb +167 -0
  21. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +388 -0
  22. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  23. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  24. data/lib/active_merchant/billing/gateways/bogus.rb +142 -0
  25. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  26. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  27. data/lib/active_merchant/billing/gateways/braintree_blue.rb +308 -0
  28. data/lib/active_merchant/billing/gateways/braintree_orange.rb +21 -0
  29. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  30. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  31. data/lib/active_merchant/billing/gateways/certo_direct.rb +279 -0
  32. data/lib/active_merchant/billing/gateways/cyber_source.rb +430 -0
  33. data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
  34. data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
  35. data/lib/active_merchant/billing/gateways/elavon.rb +135 -0
  36. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  37. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/eway_managed.rb +265 -0
  39. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  40. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  41. data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
  42. data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
  43. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
  44. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  45. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  46. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  47. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  48. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  49. data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
  50. data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
  51. data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
  52. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +157 -0
  53. data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -0
  54. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  55. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  56. data/lib/active_merchant/billing/gateways/moneris.rb +239 -0
  57. data/lib/active_merchant/billing/gateways/nab_transact.rb +244 -0
  58. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  59. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  60. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  61. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  62. data/lib/active_merchant/billing/gateways/ogone.rb +330 -0
  63. data/lib/active_merchant/billing/gateways/optimal_payment.rb +277 -0
  64. data/lib/active_merchant/billing/gateways/orbital.rb +344 -0
  65. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  66. data/lib/active_merchant/billing/gateways/pay_junction.rb +397 -0
  67. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  68. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  69. data/lib/active_merchant/billing/gateways/payflow.rb +261 -0
  70. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +208 -0
  71. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  72. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  73. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  74. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  75. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  76. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  77. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  78. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +354 -0
  79. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  80. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  81. data/lib/active_merchant/billing/gateways/paypal_express.rb +229 -0
  82. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  83. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  84. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  85. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  86. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  87. data/lib/active_merchant/billing/gateways/qbms.rb +297 -0
  88. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  89. data/lib/active_merchant/billing/gateways/quickpay.rb +298 -0
  90. data/lib/active_merchant/billing/gateways/realex.rb +315 -0
  91. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  92. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  93. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  94. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  95. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  96. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  97. data/lib/active_merchant/billing/gateways/samurai.rb +121 -0
  98. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  99. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  100. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  102. data/lib/active_merchant/billing/gateways/skip_jack.rb +458 -0
  103. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  104. data/lib/active_merchant/billing/gateways/stripe.rb +244 -0
  105. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  106. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  107. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  108. data/lib/active_merchant/billing/gateways/usa_epay.rb +23 -0
  109. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1496 -0
  110. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +206 -0
  111. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  112. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  113. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  114. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  115. data/lib/active_merchant/billing/integrations.rb +17 -0
  116. data/lib/active_merchant/billing/integrations/action_view_helper.rb +72 -0
  117. data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +38 -0
  118. data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +228 -0
  119. data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +340 -0
  120. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  121. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  122. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  123. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  124. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  125. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  126. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  127. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  128. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  129. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  130. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  131. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  132. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  133. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  134. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  135. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  136. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  137. data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
  138. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +31 -0
  139. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +55 -0
  140. data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
  141. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  142. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  143. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  144. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  145. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  146. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  147. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  148. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  149. data/lib/active_merchant/billing/integrations/helper.rb +113 -0
  150. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  151. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  152. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  153. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  154. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  155. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  156. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  157. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  158. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  159. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  160. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  161. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  162. data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
  163. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +100 -0
  164. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
  165. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  166. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  167. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  168. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  169. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  170. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  171. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  172. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  173. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  174. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  175. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +127 -0
  176. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  177. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  178. data/lib/active_merchant/billing/integrations/two_checkout.rb +22 -0
  179. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  180. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  181. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  182. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  183. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  184. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  185. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  186. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  187. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  188. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  189. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  190. data/lib/active_merchant/billing/response.rb +32 -0
  191. data/lib/active_merchant/version.rb +3 -0
  192. data/lib/activemerchant.rb +1 -0
  193. data/lib/support/gateway_support.rb +58 -0
  194. data/lib/support/outbound_hosts.rb +25 -0
  195. metadata +411 -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,239 @@
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
+
82
+ def test?
83
+ @options[:test] || super
84
+ end
85
+ private # :nodoc: all
86
+
87
+ def expdate(creditcard)
88
+ sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
89
+ end
90
+
91
+ def debit_commit(commit_type, money, creditcard, options)
92
+ requires!(options, :order_id)
93
+ commit(commit_type, debit_params(money, creditcard, options))
94
+ end
95
+
96
+ # Common params used amongst the +purchase+ and +authorization+ methods
97
+ def debit_params(money, creditcard, options = {})
98
+ {
99
+ :order_id => options[:order_id],
100
+ :cust_id => options[:customer],
101
+ :amount => amount(money),
102
+ :pan => creditcard.number,
103
+ :expdate => expdate(creditcard),
104
+ :crypt_type => options[:crypt_type] || @options[:crypt_type],
105
+ :cvv => creditcard.verification_value,
106
+ :billing_address => options[:address] || options[:billing_address]
107
+ }
108
+ end
109
+
110
+ # Common params used amongst the +credit+, +void+ and +capture+ methods
111
+ def crediting_params(authorization, options = {})
112
+ {
113
+ :txn_number => split_authorization(authorization).first,
114
+ :order_id => split_authorization(authorization).last,
115
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
116
+ }.merge(options)
117
+ end
118
+
119
+ # Splits an +authorization+ param and retrives the order id and
120
+ # transaction number in that order.
121
+ def split_authorization(authorization)
122
+ if authorization.nil? || authorization.empty? || authorization !~ /;/
123
+ raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")'
124
+ else
125
+ authorization.split(';')
126
+ end
127
+ end
128
+
129
+ def commit(action, parameters = {})
130
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters)))
131
+
132
+ Response.new(successful?(response), message_from(response[:message]), response,
133
+ :test => test?,
134
+ :authorization => authorization_from(response),
135
+ :avs_result => {:code => response[:avs_result_code]},
136
+ :cvv_result => response[:cvd_result_code] && response[:cvd_result_code].last
137
+ )
138
+ end
139
+
140
+ # Generates a Moneris authorization string of the form 'trans_id;receipt_id'.
141
+ def authorization_from(response = {})
142
+ if response[:trans_id] && response[:receipt_id]
143
+ "#{response[:trans_id]};#{response[:receipt_id]}"
144
+ end
145
+ end
146
+
147
+ # Tests for a successful response from Moneris' servers
148
+ def successful?(response)
149
+ response[:response_code] &&
150
+ response[:complete] &&
151
+ (0..49).include?(response[:response_code].to_i)
152
+ end
153
+
154
+ def parse(xml)
155
+ response = { :message => "Global Error Receipt", :complete => false }
156
+ hashify_xml!(xml, response)
157
+ response
158
+ end
159
+
160
+ def hashify_xml!(xml, response)
161
+ xml = REXML::Document.new(xml)
162
+ return if xml.root.nil?
163
+ xml.elements.each('//receipt/*') do |node|
164
+ response[node.name.underscore.to_sym] = normalize(node.text)
165
+ end
166
+ end
167
+
168
+ def post_data(action, parameters = {})
169
+ xml = REXML::Document.new
170
+ root = xml.add_element("request")
171
+ root.add_element("store_id").text = options[:login]
172
+ root.add_element("api_token").text = options[:password]
173
+ transaction = root.add_element(action)
174
+
175
+ # Must add the elements in the correct order
176
+ actions[action].each do |key|
177
+ transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
178
+ end
179
+
180
+ add_avs_info(transaction, parameters)
181
+ add_cvd_info(transaction, parameters)
182
+
183
+ xml.to_s
184
+ end
185
+
186
+ def add_avs_info(transaction, parameters)
187
+ if address = parameters[:billing_address]
188
+ street_number, street_name = address[:address1].split(' ', 2)
189
+
190
+ avs_info = transaction.add_element('avs_info')
191
+ avs_info.add_element('avs_street_number').text = street_number
192
+ avs_info.add_element('avs_street_name').text = street_name
193
+ avs_info.add_element('avs_zipcode').text = address[:zip]
194
+ end
195
+ end
196
+
197
+ def add_cvd_info(transaction, parameters)
198
+ if cvd_value = parameters[:cvv]
199
+ cvd_info = transaction.add_element('cvd_info')
200
+ cvd_info.add_element('cvd_indicator').text = '1'
201
+ cvd_info.add_element('cvd_value').text = cvd_value
202
+ end
203
+ end
204
+
205
+ def message_from(message)
206
+ return 'Unspecified error' if message.blank?
207
+ message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
208
+ end
209
+
210
+ # Make a Ruby type out of the response string
211
+ def normalize(field)
212
+ case field
213
+ when "true" then true
214
+ when "false" then false
215
+ when '', "null" then nil
216
+ else field
217
+ end
218
+ end
219
+
220
+ def actions
221
+ {
222
+ "purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
223
+ "preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
224
+ "command" => [:order_id],
225
+ "refund" => [:order_id, :amount, :txn_number, :crypt_type],
226
+ "indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
227
+ "completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
228
+ "purchasecorrection" => [:order_id, :txn_number, :crypt_type],
229
+ "cavvpurcha" => [:order_id, :cust_id, :amount, :pan, :expdate, :cav],
230
+ "cavvpreaut" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
231
+ "transact" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
232
+ "Batchcloseall" => [],
233
+ "opentotals" => [:ecr_number],
234
+ "batchclose" => [:ecr_number]
235
+ }
236
+ end
237
+ end
238
+ end
239
+ end