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.
Files changed (189) hide show
  1. data/CHANGELOG +690 -0
  2. data/CONTRIBUTORS +237 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +165 -0
  5. data/gem-public_cert.pem +20 -0
  6. data/lib/active_merchant.rb +47 -0
  7. data/lib/active_merchant/billing.rb +9 -0
  8. data/lib/active_merchant/billing/avs_result.rb +98 -0
  9. data/lib/active_merchant/billing/base.rb +57 -0
  10. data/lib/active_merchant/billing/check.rb +68 -0
  11. data/lib/active_merchant/billing/credit_card.rb +178 -0
  12. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  13. data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
  14. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  15. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  16. data/lib/active_merchant/billing/gateway.rb +170 -0
  17. data/lib/active_merchant/billing/gateways.rb +18 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net.rb +664 -0
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +858 -0
  20. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  21. data/lib/active_merchant/billing/gateways/beanstream.rb +139 -0
  22. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +282 -0
  23. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  24. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  25. data/lib/active_merchant/billing/gateways/bogus.rb +132 -0
  26. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  27. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  28. data/lib/active_merchant/billing/gateways/braintree_blue.rb +293 -0
  29. data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
  30. data/lib/active_merchant/billing/gateways/braspag.rb +188 -0
  31. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -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 +134 -0
  36. data/lib/active_merchant/billing/gateways/epay.rb +268 -0
  37. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/eway_managed.rb +231 -0
  39. data/lib/active_merchant/billing/gateways/exact.rb +222 -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 +156 -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 +209 -0
  57. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  58. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  59. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  60. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  61. data/lib/active_merchant/billing/gateways/ogone.rb +292 -0
  62. data/lib/active_merchant/billing/gateways/orbital.rb +321 -0
  63. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  64. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  65. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  66. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  67. data/lib/active_merchant/billing/gateways/payflow.rb +253 -0
  68. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  69. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  70. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  71. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  72. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  73. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  74. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  75. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  76. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +351 -0
  77. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  78. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  79. data/lib/active_merchant/billing/gateways/paypal_express.rb +177 -0
  80. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  81. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  82. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  83. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  84. data/lib/active_merchant/billing/gateways/qbms.rb +295 -0
  85. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  86. data/lib/active_merchant/billing/gateways/quickpay.rb +218 -0
  87. data/lib/active_merchant/billing/gateways/realex.rb +311 -0
  88. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  89. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  90. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  91. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  92. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  93. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  94. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  95. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  96. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +193 -0
  97. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  98. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  99. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  100. data/lib/active_merchant/billing/gateways/stripe.rb +212 -0
  101. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  102. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  103. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  104. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  105. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  106. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  107. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  108. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  109. data/lib/active_merchant/billing/integrations.rb +17 -0
  110. data/lib/active_merchant/billing/integrations/action_view_helper.rb +68 -0
  111. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  112. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  113. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  114. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  115. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  116. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  117. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  118. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  119. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  120. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  121. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  122. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  123. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  124. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  125. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  126. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  127. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  128. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  129. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  130. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  131. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  132. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  133. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  134. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  135. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  136. data/lib/active_merchant/billing/integrations/helper.rb +96 -0
  137. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  138. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  139. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  140. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  141. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  142. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  143. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  144. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  145. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  146. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  147. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  148. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  149. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  150. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  151. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  152. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  153. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  154. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  155. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  156. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  157. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  158. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  159. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
  160. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  161. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  162. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  163. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  164. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  165. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  166. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  167. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  168. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  169. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  170. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  171. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  172. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  173. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  174. data/lib/active_merchant/billing/response.rb +32 -0
  175. data/lib/active_merchant/common.rb +14 -0
  176. data/lib/active_merchant/common/connection.rb +177 -0
  177. data/lib/active_merchant/common/country.rb +328 -0
  178. data/lib/active_merchant/common/error.rb +26 -0
  179. data/lib/active_merchant/common/post_data.rb +24 -0
  180. data/lib/active_merchant/common/posts_data.rb +63 -0
  181. data/lib/active_merchant/common/requires_parameters.rb +16 -0
  182. data/lib/active_merchant/common/utils.rb +22 -0
  183. data/lib/active_merchant/common/validateable.rb +81 -0
  184. data/lib/active_merchant/version.rb +3 -0
  185. data/lib/activemerchant.rb +1 -0
  186. data/lib/certs/cacert.pem +7815 -0
  187. data/lib/support/gateway_support.rb +58 -0
  188. data/lib/support/outbound_hosts.rb +25 -0
  189. 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