mattbauer-activemerchant 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. data/CHANGELOG +459 -0
  2. data/CONTRIBUTERS +118 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README +134 -0
  5. data/Rakefile +153 -0
  6. data/gem-public_cert.pem +20 -0
  7. data/init.rb +3 -0
  8. data/lib/active_merchant.rb +60 -0
  9. data/lib/active_merchant/billing/avs_result.rb +98 -0
  10. data/lib/active_merchant/billing/base.rb +57 -0
  11. data/lib/active_merchant/billing/check.rb +68 -0
  12. data/lib/active_merchant/billing/credit_card.rb +159 -0
  13. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  14. data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
  15. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  16. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  17. data/lib/active_merchant/billing/gateway.rb +158 -0
  18. data/lib/active_merchant/billing/gateways.rb +3 -0
  19. data/lib/active_merchant/billing/gateways/authorize_net.rb +657 -0
  20. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +703 -0
  21. data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
  22. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +233 -0
  23. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  24. data/lib/active_merchant/billing/gateways/bogus.rb +98 -0
  25. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  26. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  27. data/lib/active_merchant/billing/gateways/cyber_source.rb +406 -0
  28. data/lib/active_merchant/billing/gateways/data_cash.rb +595 -0
  29. data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
  30. data/lib/active_merchant/billing/gateways/elavon.rb +106 -0
  31. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  32. data/lib/active_merchant/billing/gateways/exact.rb +222 -0
  33. data/lib/active_merchant/billing/gateways/first_pay.rb +172 -0
  34. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  35. data/lib/active_merchant/billing/gateways/linkpoint.rb +396 -0
  36. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
  37. data/lib/active_merchant/billing/gateways/merchant_ware.rb +283 -0
  38. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  39. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +214 -0
  40. data/lib/active_merchant/billing/gateways/moneris.rb +295 -0
  41. data/lib/active_merchant/billing/gateways/moneris_usa.rb +258 -0
  42. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  43. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  44. data/lib/active_merchant/billing/gateways/ogone.rb +259 -0
  45. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  46. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  47. data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
  48. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  49. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  50. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  51. data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
  52. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  53. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  54. data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
  55. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  56. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +325 -0
  57. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
  58. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  59. data/lib/active_merchant/billing/gateways/paypal_express.rb +130 -0
  60. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
  61. data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
  62. data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
  63. data/lib/active_merchant/billing/gateways/psl_card.rb +306 -0
  64. data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
  65. data/lib/active_merchant/billing/gateways/realex.rb +200 -0
  66. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  67. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  68. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +110 -0
  69. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  70. data/lib/active_merchant/billing/gateways/sage_pay.rb +308 -0
  71. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  72. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
  73. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  74. data/lib/active_merchant/billing/gateways/skip_jack.rb +442 -0
  75. data/lib/active_merchant/billing/gateways/smart_ps.rb +254 -0
  76. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  77. data/lib/active_merchant/billing/gateways/transax.rb +26 -0
  78. data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
  79. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  80. data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
  81. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  82. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  83. data/lib/active_merchant/billing/integrations.rb +22 -0
  84. data/lib/active_merchant/billing/integrations/action_view_helper.rb +79 -0
  85. data/lib/active_merchant/billing/integrations/bogus.rb +22 -0
  86. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  87. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  88. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  89. data/lib/active_merchant/billing/integrations/chronopay.rb +22 -0
  90. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +81 -0
  91. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +156 -0
  92. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  93. data/lib/active_merchant/billing/integrations/gestpay.rb +26 -0
  94. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  95. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  96. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +83 -0
  97. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  98. data/lib/active_merchant/billing/integrations/helper.rb +93 -0
  99. data/lib/active_merchant/billing/integrations/hi_trust.rb +26 -0
  100. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  101. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  102. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  103. data/lib/active_merchant/billing/integrations/nochex.rb +87 -0
  104. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  105. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  106. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  107. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  108. data/lib/active_merchant/billing/integrations/paypal.rb +40 -0
  109. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  110. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  111. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  112. data/lib/active_merchant/billing/integrations/quickpay.rb +18 -0
  113. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  114. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  115. data/lib/active_merchant/billing/integrations/return.rb +35 -0
  116. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  117. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  118. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  119. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  120. data/lib/active_merchant/billing/response.rb +32 -0
  121. data/lib/active_merchant/lib/connection.rb +170 -0
  122. data/lib/active_merchant/lib/country.rb +319 -0
  123. data/lib/active_merchant/lib/error.rb +4 -0
  124. data/lib/active_merchant/lib/post_data.rb +22 -0
  125. data/lib/active_merchant/lib/posts_data.rb +47 -0
  126. data/lib/active_merchant/lib/requires_parameters.rb +16 -0
  127. data/lib/active_merchant/lib/utils.rb +18 -0
  128. data/lib/active_merchant/lib/validateable.rb +76 -0
  129. data/lib/certs/cacert.pem +7815 -0
  130. data/lib/support/gateway_support.rb +58 -0
  131. data/script/destroy +14 -0
  132. data/script/generate +14 -0
  133. data/test/fixtures.yml +353 -0
  134. data/test/remote/gateways/remote_authorize_net_cim_test.rb +459 -0
  135. data/test/remote/gateways/remote_authorize_net_test.rb +145 -0
  136. data/test/remote/gateways/remote_beanstream_interac_test.rb +53 -0
  137. data/test/remote/gateways/remote_beanstream_test.rb +150 -0
  138. data/test/remote/gateways/remote_braintree_test.rb +154 -0
  139. data/test/remote/gateways/remote_card_stream_test.rb +148 -0
  140. data/test/remote/gateways/remote_cyber_source_test.rb +144 -0
  141. data/test/remote/gateways/remote_data_cash_test.rb +357 -0
  142. data/test/remote/gateways/remote_efsnet_test.rb +81 -0
  143. data/test/remote/gateways/remote_elavon_test.rb +66 -0
  144. data/test/remote/gateways/remote_eway_test.rb +74 -0
  145. data/test/remote/gateways/remote_exact_test.rb +60 -0
  146. data/test/remote/gateways/remote_first_pay_test.rb +87 -0
  147. data/test/remote/gateways/remote_instapay_test.rb +61 -0
  148. data/test/remote/gateways/remote_linkpoint_test.rb +112 -0
  149. data/test/remote/gateways/remote_merchant_e_solutions_test.rb +173 -0
  150. data/test/remote/gateways/remote_merchant_ware_test.rb +113 -0
  151. data/test/remote/gateways/remote_modern_payments_cim_test.rb +58 -0
  152. data/test/remote/gateways/remote_modern_payments_test.rb +43 -0
  153. data/test/remote/gateways/remote_moneris_test.rb +118 -0
  154. data/test/remote/gateways/remote_moneris_usa_test.rb +115 -0
  155. data/test/remote/gateways/remote_net_registry_test.rb +85 -0
  156. data/test/remote/gateways/remote_netbilling_test.rb +70 -0
  157. data/test/remote/gateways/remote_ogone_test.rb +108 -0
  158. data/test/remote/gateways/remote_pay_junction_test.rb +143 -0
  159. data/test/remote/gateways/remote_pay_secure_test.rb +39 -0
  160. data/test/remote/gateways/remote_payflow_express_test.rb +50 -0
  161. data/test/remote/gateways/remote_payflow_test.rb +237 -0
  162. data/test/remote/gateways/remote_payflow_uk_test.rb +173 -0
  163. data/test/remote/gateways/remote_payment_express_test.rb +136 -0
  164. data/test/remote/gateways/remote_paypal_express_test.rb +49 -0
  165. data/test/remote/gateways/remote_paypal_test.rb +178 -0
  166. data/test/remote/gateways/remote_plugnpay_test.rb +72 -0
  167. data/test/remote/gateways/remote_psigate_test.rb +50 -0
  168. data/test/remote/gateways/remote_psl_card_test.rb +125 -0
  169. data/test/remote/gateways/remote_quickpay_test.rb +190 -0
  170. data/test/remote/gateways/remote_realex_test.rb +224 -0
  171. data/test/remote/gateways/remote_sage_bankcard_test.rb +109 -0
  172. data/test/remote/gateways/remote_sage_pay_test.rb +219 -0
  173. data/test/remote/gateways/remote_sage_test.rb +87 -0
  174. data/test/remote/gateways/remote_sage_virtual_check_test.rb +62 -0
  175. data/test/remote/gateways/remote_secure_pay_au_test.rb +40 -0
  176. data/test/remote/gateways/remote_secure_pay_tech_test.rb +37 -0
  177. data/test/remote/gateways/remote_secure_pay_test.rb +28 -0
  178. data/test/remote/gateways/remote_skipjack_test.rb +105 -0
  179. data/test/remote/gateways/remote_trans_first_test.rb +34 -0
  180. data/test/remote/gateways/remote_transax_test.rb +112 -0
  181. data/test/remote/gateways/remote_trust_commerce_test.rb +152 -0
  182. data/test/remote/gateways/remote_usa_epay_test.rb +46 -0
  183. data/test/remote/gateways/remote_verifi_test.rb +107 -0
  184. data/test/remote/gateways/remote_viaklix_test.rb +43 -0
  185. data/test/remote/gateways/remote_wirecard_test.rb +111 -0
  186. data/test/remote/integrations/remote_gestpay_integration_test.rb +37 -0
  187. data/test/remote/integrations/remote_paypal_integration_test.rb +26 -0
  188. data/test/test_helper.rb +182 -0
  189. data/test/unit/avs_result_test.rb +59 -0
  190. data/test/unit/base_test.rb +55 -0
  191. data/test/unit/check_test.rb +88 -0
  192. data/test/unit/connection_test.rb +129 -0
  193. data/test/unit/country_code_test.rb +33 -0
  194. data/test/unit/country_test.rb +64 -0
  195. data/test/unit/credit_card_formatting_test.rb +19 -0
  196. data/test/unit/credit_card_methods_test.rb +179 -0
  197. data/test/unit/credit_card_test.rb +318 -0
  198. data/test/unit/cvv_result_test.rb +33 -0
  199. data/test/unit/expiry_date_test.rb +32 -0
  200. data/test/unit/gateways/authorize_net_cim_test.rb +638 -0
  201. data/test/unit/gateways/authorize_net_test.rb +290 -0
  202. data/test/unit/gateways/beanstream_interac_test.rb +51 -0
  203. data/test/unit/gateways/beanstream_test.rb +108 -0
  204. data/test/unit/gateways/bogus_test.rb +46 -0
  205. data/test/unit/gateways/braintree_test.rb +126 -0
  206. data/test/unit/gateways/card_stream_test.rb +90 -0
  207. data/test/unit/gateways/cyber_source_test.rb +188 -0
  208. data/test/unit/gateways/data_cash_test.rb +133 -0
  209. data/test/unit/gateways/efsnet_test.rb +123 -0
  210. data/test/unit/gateways/elavon_test.rb +139 -0
  211. data/test/unit/gateways/eway_test.rb +118 -0
  212. data/test/unit/gateways/exact_test.rb +156 -0
  213. data/test/unit/gateways/first_pay_test.rb +125 -0
  214. data/test/unit/gateways/gateway_test.rb +48 -0
  215. data/test/unit/gateways/instapay_test.rb +102 -0
  216. data/test/unit/gateways/linkpoint_test.rb +167 -0
  217. data/test/unit/gateways/merchant_e_solutions_test.rb +169 -0
  218. data/test/unit/gateways/merchant_ware_test.rb +188 -0
  219. data/test/unit/gateways/modern_payments_cim_test.rb +171 -0
  220. data/test/unit/gateways/moneris_test.rb +185 -0
  221. data/test/unit/gateways/moneris_usa_test.rb +183 -0
  222. data/test/unit/gateways/net_registry_test.rb +416 -0
  223. data/test/unit/gateways/netbilling_test.rb +54 -0
  224. data/test/unit/gateways/ogone_test.rb +256 -0
  225. data/test/unit/gateways/pay_junction_test.rb +123 -0
  226. data/test/unit/gateways/pay_secure_test.rb +71 -0
  227. data/test/unit/gateways/payflow_express_test.rb +173 -0
  228. data/test/unit/gateways/payflow_express_uk_test.rb +86 -0
  229. data/test/unit/gateways/payflow_test.rb +305 -0
  230. data/test/unit/gateways/payflow_uk_test.rb +30 -0
  231. data/test/unit/gateways/payment_express_test.rb +195 -0
  232. data/test/unit/gateways/paypal_express_test.rb +382 -0
  233. data/test/unit/gateways/paypal_test.rb +569 -0
  234. data/test/unit/gateways/plugnpay_test.rb +86 -0
  235. data/test/unit/gateways/psigate_test.rb +169 -0
  236. data/test/unit/gateways/psl_card_test.rb +64 -0
  237. data/test/unit/gateways/quickpay_test.rb +112 -0
  238. data/test/unit/gateways/realex_test.rb +151 -0
  239. data/test/unit/gateways/sage_bankcard_test.rb +162 -0
  240. data/test/unit/gateways/sage_pay_test.rb +139 -0
  241. data/test/unit/gateways/sage_virtual_check_test.rb +71 -0
  242. data/test/unit/gateways/secure_pay_au_test.rb +207 -0
  243. data/test/unit/gateways/secure_pay_tech_test.rb +44 -0
  244. data/test/unit/gateways/secure_pay_test.rb +87 -0
  245. data/test/unit/gateways/skip_jack_test.rb +133 -0
  246. data/test/unit/gateways/trans_first_test.rb +112 -0
  247. data/test/unit/gateways/trust_commerce_test.rb +90 -0
  248. data/test/unit/gateways/usa_epay_test.rb +128 -0
  249. data/test/unit/gateways/verifi_test.rb +96 -0
  250. data/test/unit/gateways/viaklix_test.rb +78 -0
  251. data/test/unit/gateways/wirecard_test.rb +250 -0
  252. data/test/unit/generators/test_gateway_generator.rb +46 -0
  253. data/test/unit/generators/test_generator_helper.rb +20 -0
  254. data/test/unit/generators/test_integration_generator.rb +53 -0
  255. data/test/unit/integrations/action_view_helper_test.rb +50 -0
  256. data/test/unit/integrations/bogus_module_test.rb +20 -0
  257. data/test/unit/integrations/chronopay_module_test.rb +13 -0
  258. data/test/unit/integrations/gestpay_module_test.rb +14 -0
  259. data/test/unit/integrations/helpers/bogus_helper_test.rb +28 -0
  260. data/test/unit/integrations/helpers/chronopay_helper_test.rb +67 -0
  261. data/test/unit/integrations/helpers/gestpay_helper_test.rb +100 -0
  262. data/test/unit/integrations/helpers/hi_trust_helper_test.rb +16 -0
  263. data/test/unit/integrations/helpers/nochex_helper_test.rb +53 -0
  264. data/test/unit/integrations/helpers/paypal_helper_test.rb +171 -0
  265. data/test/unit/integrations/helpers/quickpay_helper_test.rb +40 -0
  266. data/test/unit/integrations/helpers/two_checkout_helper_test.rb +92 -0
  267. data/test/unit/integrations/hi_trust_module_test.rb +13 -0
  268. data/test/unit/integrations/nochex_module_test.rb +13 -0
  269. data/test/unit/integrations/notifications/chronopay_notification_test.rb +66 -0
  270. data/test/unit/integrations/notifications/gestpay_notification_test.rb +60 -0
  271. data/test/unit/integrations/notifications/hi_trust_notification_test.rb +59 -0
  272. data/test/unit/integrations/notifications/nochex_notification_test.rb +51 -0
  273. data/test/unit/integrations/notifications/notification_test.rb +54 -0
  274. data/test/unit/integrations/notifications/paypal_notification_test.rb +85 -0
  275. data/test/unit/integrations/notifications/quickpay_notification_test.rb +69 -0
  276. data/test/unit/integrations/notifications/two_checkout_notification_test.rb +55 -0
  277. data/test/unit/integrations/paypal_module_test.rb +28 -0
  278. data/test/unit/integrations/quickpay_module_test.rb +9 -0
  279. data/test/unit/integrations/returns/chronopay_return_test.rb +11 -0
  280. data/test/unit/integrations/returns/gestpay_return_test.rb +10 -0
  281. data/test/unit/integrations/returns/hi_trust_return_test.rb +24 -0
  282. data/test/unit/integrations/returns/nochex_return_test.rb +10 -0
  283. data/test/unit/integrations/returns/paypal_return_test.rb +10 -0
  284. data/test/unit/integrations/returns/return_test.rb +11 -0
  285. data/test/unit/integrations/returns/two_checkout_return_test.rb +24 -0
  286. data/test/unit/integrations/two_checkout_module_test.rb +13 -0
  287. data/test/unit/post_data_test.rb +55 -0
  288. data/test/unit/posts_data_test.rb +48 -0
  289. data/test/unit/response_test.rb +28 -0
  290. data/test/unit/utils_test.rb +7 -0
  291. data/test/unit/validateable_test.rb +60 -0
  292. metadata +396 -0
@@ -0,0 +1,295 @@
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]
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 action create a recurring purchase on a customer's card with the
47
+ # desired interval, frequency, limit, starting date. It can also peform
48
+ # an immediate verification of funding on a customer's card and ready them
49
+ # for deposit in a merchant's account. This immediate amount can differ from
50
+ # the recurring amount
51
+ #
52
+ # ==== Parameters
53
+ #
54
+ # * <tt>money</tt> -- The amount to be purchased. Either an Integer value in cents or a Money object.
55
+ # * <tt>creditcard</tt> -- The CreditCard details for the transaction.
56
+ # * <tt>:interval</tt> - :day, :week, or :month
57
+ # * <tt>:frequency</tt> - The number of intervals you wish to pass between billing cycles
58
+ # * <tt>:limit</tt> - The number of times to recur this transaction
59
+ # * <tt>:starts_on</tt> - This is the date on which the first charge will be billed. The value must be in the
60
+ # future. It cannot be the day on which the transaction is being sent. If the
61
+ # transaction is to be billed immediately the start_now feature must be set to true
62
+ # and the start_date should be set at the desired interval after today.
63
+ # * <tt>:start_now</tt> - When a charge is to be made against the card immediately start_now should be
64
+ # set to ‘true’. If the billing is to start in the future then this value is to be set to
65
+ # ‘false’. When start_now is set to ‘true’ the amount to be billed immediately may
66
+ # differ from the recur amount billed on a regular basis thereafter.
67
+ # * <tt>options</tt> -- A hash of optional parameters. Set :recur_amount to either an Integer
68
+ # value in cents or a Money object to have the recurring amount differ from the immediate amount. Note
69
+ # this only works if start_now is set to false. Otherwise it is ignored.
70
+ def recurring_purchase(money, creditcard, interval, frequency, limit, starts_on, start_now, options = {})
71
+ requires!(options, :order_id)
72
+ params = debit_params(money, creditcard, options)
73
+ recur_params = {
74
+ :recur_unit => interval,
75
+ :start_now => start_now,
76
+ :start_date => starts_on,
77
+ :num_recurs => limit,
78
+ :period => frequency,
79
+ :recur_amount => amount(options[:recurring_money] || money)
80
+ }
81
+ commit('purchase', params, recur_params)
82
+ end
83
+
84
+ # This action updates a recurring purchase on a customer's card. It requires
85
+ # the authorization code and can change the following: customer id, add more
86
+ # recurring payments, the total number of recurring payments, terminate
87
+ # the recurring payments, put them on hold (suspend), the amount and change
88
+ # the credit card.
89
+ #
90
+ # ==== Parameters
91
+ #
92
+ # * <tt>authorization</tt> -- The authorization code used to initially create the recurring payment
93
+ # * <tt>options</tt> -- The possible options are:
94
+ # <Tt>:customer</tt> - the customer id to use
95
+ # <Tt>:extend_limit</tt> - add additional recurring payments
96
+ # <Tt>:limit</tt> - change the total number of recurring payments
97
+ # <Tt>:recurring_money</tt> - change the recurring payment amount
98
+ # <Tt>:terminate</tt> - set to true to stop recurring payments
99
+ # <Tt>:hold</tt> - set to true to hold recurring payments (suspend them)
100
+ # <Tt>:creditcard</tt> - a credit card object to associated with the recurring payments
101
+ def recurring_update(authorization, options = {})
102
+ params = {
103
+ :order_id => split_authorization(authorization).last,
104
+ :cust_id => options[:customer],
105
+ :add_num_recurs => options[:extend_limit],
106
+ :total_num_recurs => options[:limit],
107
+ :recur_amount => amount(options[:recurring_money]),
108
+ :terminate => options[:terminate].nil? ? false : options[:terminate],
109
+ :hold => options[:hold].nil? ? false : options[:hold]
110
+ }
111
+ if options[:creditcard]
112
+ params.merge!(
113
+ :pan => options[:creditcard].number,
114
+ :expdate => expdate(options[:creditcard])
115
+ )
116
+ end
117
+ commit 'recur_update', params
118
+ end
119
+
120
+ # This method retrieves locked funds from a customer's account (from a
121
+ # PreAuth) and prepares them for deposit in a merchant's account.
122
+ #
123
+ # Note: Moneris requires both the order_id and the transaction number of
124
+ # the original authorization. To maintain the same interface as the other
125
+ # gateways the two numbers are concatenated together with a ; separator as
126
+ # the authorization number returned by authorization
127
+ def capture(money, authorization, options = {})
128
+ commit 'completion', crediting_params(authorization, :comp_amount => amount(money))
129
+ end
130
+
131
+ # Voiding requires the original transaction ID and order ID of some open
132
+ # transaction. Closed transactions must be refunded. Note that the only
133
+ # methods which may be voided are +capture+ and +purchase+.
134
+ #
135
+ # Concatenate your transaction number and order_id by using a semicolon
136
+ # (';'). This is to keep the Moneris interface consistent with other
137
+ # gateways. (See +capture+ for details.)
138
+ def void(authorization, options = {})
139
+ commit 'purchasecorrection', crediting_params(authorization)
140
+ end
141
+
142
+ # Performs a refund. This method requires that the original transaction
143
+ # number and order number be included. Concatenate your transaction
144
+ # number and order_id by using a semicolon (';'). This is to keep the
145
+ # Moneris interface consistent with other gateways. (See +capture+ for
146
+ # details.)
147
+ def credit(money, authorization, options = {})
148
+ commit 'refund', crediting_params(authorization, :amount => amount(money))
149
+ end
150
+
151
+ private # :nodoc: all
152
+
153
+ def expdate(creditcard)
154
+ sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
155
+ end
156
+
157
+ def debit_commit(commit_type, money, creditcard, options)
158
+ requires!(options, :order_id)
159
+ commit(commit_type, debit_params(money, creditcard, options))
160
+ end
161
+
162
+ # Common params used amongst the +purchase+ and +authorization+ methods
163
+ def debit_params(money, creditcard, options = {})
164
+ {
165
+ :order_id => options[:order_id],
166
+ :cust_id => options[:customer],
167
+ :amount => amount(money),
168
+ :pan => creditcard.number,
169
+ :expdate => expdate(creditcard),
170
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
171
+ }
172
+ end
173
+
174
+ # Common params used amongst the +credit+, +void+ and +capture+ methods
175
+ def crediting_params(authorization, options = {})
176
+ {
177
+ :txn_number => split_authorization(authorization).first,
178
+ :order_id => split_authorization(authorization).last,
179
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
180
+ }.merge(options)
181
+ end
182
+
183
+ # Splits an +authorization+ param and retrives the order id and
184
+ # transaction number in that order.
185
+ def split_authorization(authorization)
186
+ if authorization.nil? || authorization.empty? || authorization !~ /;/
187
+ raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")'
188
+ else
189
+ authorization.split(';')
190
+ end
191
+ end
192
+
193
+ def commit(action, parameters = {}, recurring_parameters = nil)
194
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters, recurring_parameters)))
195
+
196
+ Response.new(successful?(response), message_from(response[:message]), response,
197
+ :test => test?,
198
+ :authorization => authorization_from(response)
199
+ )
200
+ end
201
+
202
+ # Generates a Moneris authorization string of the form 'trans_id;receipt_id'.
203
+ def authorization_from(response = {})
204
+ if response[:trans_id] && response[:receipt_id]
205
+ "#{response[:trans_id]};#{response[:receipt_id]}"
206
+ end
207
+ end
208
+
209
+ # Tests for a successful response from Moneris' servers
210
+ def successful?(response)
211
+ successful_action?(response) || successful_recurring?(response)
212
+ end
213
+
214
+ def successful_action?(response)
215
+ response[:response_code] &&
216
+ response[:complete] &&
217
+ (0..49).include?(response[:response_code].to_i)
218
+ end
219
+
220
+ def successful_recurring?(response)
221
+ response[:recur_success]
222
+ end
223
+
224
+ def parse(xml)
225
+ response = { :message => "Global Error Receipt", :complete => false }
226
+ hashify_xml!(xml, response)
227
+ response
228
+ end
229
+
230
+ def hashify_xml!(xml, response)
231
+ xml = REXML::Document.new(xml)
232
+ return if xml.root.nil?
233
+ xml.elements.each('//receipt/*') do |node|
234
+ response[node.name.underscore.to_sym] = normalize(node.text)
235
+ end
236
+ end
237
+
238
+ def post_data(action, parameters = {}, recurring_parameters = nil)
239
+ xml = REXML::Document.new
240
+ root = xml.add_element("request")
241
+ root.add_element("store_id").text = options[:login]
242
+ root.add_element("api_token").text = options[:password]
243
+ transaction = root.add_element(action)
244
+
245
+ # Must add the elements in the correct order
246
+ actions[action].each do |key|
247
+ transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
248
+ end
249
+
250
+ if recurring_parameters
251
+ recur = transaction.add_element('recur')
252
+ actions['recur'].each do |key|
253
+ recur.add_element(key.to_s).text = recurring_parameters[key] unless recurring_parameters[key].blank?
254
+ end
255
+ end
256
+ xml.to_s
257
+ end
258
+
259
+ def message_from(message)
260
+ return 'Unspecified error' if message.blank?
261
+ message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
262
+ end
263
+
264
+ # Make a Ruby type out of the response string
265
+ def normalize(field)
266
+ case field
267
+ when "true" then true
268
+ when "false" then false
269
+ when '', "null" then nil
270
+ else field
271
+ end
272
+ end
273
+
274
+ def actions
275
+ {
276
+ "purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
277
+ "preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
278
+ "command" => [:order_id],
279
+ "refund" => [:order_id, :amount, :txn_number, :crypt_type],
280
+ "indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
281
+ "completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
282
+ "purchasecorrection" => [:order_id, :txn_number, :crypt_type],
283
+ "cavvpurcha" => [:order_id, :cust_id, :amount, :pan, :expdate, :cav],
284
+ "cavvpreaut" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
285
+ "transact" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
286
+ "Batchcloseall" => [],
287
+ "opentotals" => [:ecr_number],
288
+ "batchclose" => [:ecr_number],
289
+ "recur" => [:recur_unit, :start_now, :start_date, :num_recurs, :period, :recur_amount],
290
+ "recur_update" => [:order_id, :cust_id, :recur_amount, :pan, :expdate, :add_num_recurs, :total_num_recurs, :hold, :terminate]
291
+ }
292
+ end
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,258 @@
1
+ require 'rexml/document'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+
6
+ # To learn more about the Moneris USA 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
+ # [https://esplusqa.moneris.com/connect/en/documents/index.html].
12
+ class MonerisUsaGateway < Gateway
13
+ TEST_URL = 'https://esplusqa.moneris.com/gateway_us/servlet/MpgRequest'
14
+ LIVE_URL = 'https://esplus.moneris.com/gateway_us/servlet/MpgRequest'
15
+
16
+ self.supported_countries = ['US']
17
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
18
+ self.homepage_url = 'http://www.monerisusa.com/'
19
+ self.display_name = 'Moneris USA'
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 'us_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 'us_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 'us_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 'us_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
+ commit 'us_refund', crediting_params(authorization, :amount => amount(money))
75
+ end
76
+
77
+ # This action create a recurring purchase on a customer's card with the
78
+ # desired interval, frequency, limit, starting date. It can also peform
79
+ # an immediate verification of funding on a customer's card and ready them
80
+ # for deposit in a merchant's account. This immediate amount can differ from
81
+ # the recurring amount
82
+ #
83
+ # ==== Parameters
84
+ #
85
+ # * <tt>money</tt> -- The amount to be purchased. Either an Integer value in cents or a Money object.
86
+ # * <tt>creditcard</tt> -- The CreditCard details for the transaction.
87
+ # * <tt>:interval</tt> - :day, :week, or :month
88
+ # * <tt>:frequency</tt> - The number of intervals you wish to pass between billing cycles
89
+ # * <tt>:limit</tt> - The number of times to recur this transaction
90
+ # * <tt>:starts_on</tt> - This is the date on which the first charge will be billed. The value must be in the
91
+ # future. It cannot be the day on which the transaction is being sent. If the
92
+ # transaction is to be billed immediately the start_now feature must be set to true
93
+ # and the start_date should be set at the desired interval after today.
94
+ # * <tt>:start_now</tt> - When a charge is to be made against the card immediately start_now should be
95
+ # set to ‘true’. If the billing is to start in the future then this value is to be set to
96
+ # ‘false’. When start_now is set to ‘true’ the amount to be billed immediately may
97
+ # differ from the recur amount billed on a regular basis thereafter.
98
+ # * <tt>options</tt> -- A hash of optional parameters. Set :recur_amount to either an Integer
99
+ # value in cents or a Money object to have the recurring amount differ from the immediate amount. Note
100
+ # this only works if start_now is set to false. Otherwise it is ignored.
101
+ def recurring_purchase(money, creditcard, interval, frequency, limit, starts_on, start_now, options = {})
102
+ requires!(options, :order_id)
103
+ params = debit_params(money, creditcard, options)
104
+ recur_params = {
105
+ :recur_unit => interval,
106
+ :start_now => start_now,
107
+ :start_date => starts_on,
108
+ :num_recurs => limit,
109
+ :period => frequency,
110
+ :recur_amount => amount(options[:recurring_money] || money)
111
+ }
112
+ commit('us_purchase', params, recur_params)
113
+ end
114
+
115
+ private # :nodoc: all
116
+
117
+ def expdate(creditcard)
118
+ sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
119
+ end
120
+
121
+ def debit_commit(commit_type, money, creditcard, options)
122
+ requires!(options, :order_id)
123
+ commit(commit_type, debit_params(money, creditcard, options))
124
+ end
125
+
126
+ # Common params used amongst the +purchase+ and +authorization+ methods
127
+ def debit_params(money, creditcard, options = {})
128
+ {
129
+ :order_id => options[:order_id],
130
+ :cust_id => options[:customer],
131
+ :amount => amount(money),
132
+ :pan => creditcard.number,
133
+ :expdate => expdate(creditcard),
134
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
135
+ }
136
+ end
137
+
138
+ # Common params used amongst the +credit+, +void+ and +capture+ methods
139
+ def crediting_params(authorization, options = {})
140
+ {
141
+ :txn_number => split_authorization(authorization).first,
142
+ :order_id => split_authorization(authorization).last,
143
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
144
+ }.merge(options)
145
+ end
146
+
147
+ # Splits an +authorization+ param and retrives the order id and
148
+ # transaction number in that order.
149
+ def split_authorization(authorization)
150
+ if authorization.nil? || authorization.empty? || authorization !~ /;/
151
+ raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")'
152
+ else
153
+ authorization.split(';')
154
+ end
155
+ end
156
+
157
+ def commit(action, parameters = {}, recurring_parameters = nil)
158
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, post_data(action, parameters, recurring_parameters)))
159
+
160
+ Response.new(successful?(response), message_from(response[:message]), response,
161
+ :test => test?,
162
+ :authorization => authorization_from(response)
163
+ )
164
+ end
165
+
166
+ # Generates a Moneris authorization string of the form 'trans_id;receipt_id'.
167
+ def authorization_from(response = {})
168
+ if response[:trans_id] && response[:receipt_id]
169
+ "#{response[:trans_id]};#{response[:receipt_id]}"
170
+ end
171
+ end
172
+
173
+ # Tests for a successful response from Moneris' servers
174
+ def successful?(response)
175
+ successful_action?(response) || successful_recurring?(response)
176
+ end
177
+
178
+ def successful_action?(response)
179
+ response[:response_code] &&
180
+ response[:complete] &&
181
+ (0..49).include?(response[:response_code].to_i)
182
+ end
183
+
184
+ def successful_recurring?(response)
185
+ response[:recur_success]
186
+ end
187
+
188
+ def parse(xml)
189
+ response = { :message => "Global Error Receipt", :complete => false }
190
+ hashify_xml!(xml, response)
191
+ response
192
+ end
193
+
194
+ def hashify_xml!(xml, response)
195
+ xml = REXML::Document.new(xml)
196
+ return if xml.root.nil?
197
+ xml.elements.each('//receipt/*') do |node|
198
+ response[node.name.underscore.to_sym] = normalize(node.text)
199
+ end
200
+ end
201
+
202
+ def post_data(action, parameters = {}, recurring_parameters = nil)
203
+ xml = REXML::Document.new
204
+ root = xml.add_element("request")
205
+ root.add_element("store_id").text = options[:login]
206
+ root.add_element("api_token").text = options[:password]
207
+ transaction = root.add_element(action)
208
+
209
+ # Must add the elements in the correct order
210
+ actions[action].each do |key|
211
+ transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
212
+ end
213
+
214
+ if recurring_parameters
215
+ recur = transaction.add_element('recur')
216
+ actions['recur'].each do |key|
217
+ recur.add_element(key.to_s).text = recurring_parameters[key] unless recurring_parameters[key].blank?
218
+ end
219
+ end
220
+
221
+ xml.to_s
222
+ end
223
+
224
+ def message_from(message)
225
+ return 'Unspecified error' if message.blank?
226
+ message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
227
+ end
228
+
229
+ # Make a Ruby type out of the response string
230
+ def normalize(field)
231
+ case field
232
+ when "true" then true
233
+ when "false" then false
234
+ when '', "null" then nil
235
+ else field
236
+ end
237
+ end
238
+
239
+ def actions
240
+ {
241
+ "us_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
242
+ "us_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
243
+ "command" => [:order_id],
244
+ "us_refund" => [:order_id, :amount, :txn_number, :crypt_type],
245
+ "indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
246
+ "us_completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
247
+ "us_purchasecorrection" => [:order_id, :txn_number, :crypt_type],
248
+ "us_cavv_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :cav],
249
+ "us_cavv_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
250
+ "us_batchcloseall" => [],
251
+ "us_opentotals" => [:ecr_number],
252
+ "us_batchclose" => [:ecr_number],
253
+ "recur" => [:recur_unit, :start_now, :start_date, :num_recurs, :period, :recur_amount]
254
+ }
255
+ end
256
+ end
257
+ end
258
+ end