start_activemerchant 1.50.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 (218) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1769 -0
  3. data/CONTRIBUTORS +540 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +226 -0
  6. data/lib/active_merchant.rb +67 -0
  7. data/lib/active_merchant/billing.rb +15 -0
  8. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  9. data/lib/active_merchant/billing/avs_result.rb +98 -0
  10. data/lib/active_merchant/billing/base.rb +72 -0
  11. data/lib/active_merchant/billing/check.rb +76 -0
  12. data/lib/active_merchant/billing/compatibility.rb +120 -0
  13. data/lib/active_merchant/billing/credit_card.rb +404 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +195 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +291 -0
  18. data/lib/active_merchant/billing/gateways.rb +14 -0
  19. data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
  20. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  21. data/lib/active_merchant/billing/gateways/authorize_net.rb +510 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
  24. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
  25. data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
  26. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  27. data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
  28. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -0
  29. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
  30. data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
  31. data/lib/active_merchant/billing/gateways/beanstream.rb +192 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +389 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +58 -0
  34. data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
  35. data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
  36. data/lib/active_merchant/billing/gateways/borgun.rb +211 -0
  37. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  39. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  40. data/lib/active_merchant/billing/gateways/braintree_blue.rb +574 -0
  41. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  42. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  43. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +238 -0
  45. data/lib/active_merchant/billing/gateways/cashnet.rb +202 -0
  46. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  47. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  48. data/lib/active_merchant/billing/gateways/cenpos.rb +262 -0
  49. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  50. data/lib/active_merchant/billing/gateways/checkout.rb +216 -0
  51. data/lib/active_merchant/billing/gateways/checkout_v2.rb +200 -0
  52. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  53. data/lib/active_merchant/billing/gateways/conekta.rb +210 -0
  54. data/lib/active_merchant/billing/gateways/cyber_source.rb +720 -0
  55. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  56. data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
  57. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  58. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  59. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  60. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  61. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  62. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  63. data/lib/active_merchant/billing/gateways/eway_rapid.rb +522 -0
  64. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  65. data/lib/active_merchant/billing/gateways/ezic.rb +206 -0
  66. data/lib/active_merchant/billing/gateways/fat_zebra.rb +213 -0
  67. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  68. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  69. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  70. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  71. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +413 -0
  72. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  73. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  74. data/lib/active_merchant/billing/gateways/garanti.rb +261 -0
  75. data/lib/active_merchant/billing/gateways/global_transport.rb +179 -0
  76. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  77. data/lib/active_merchant/billing/gateways/hps.rb +287 -0
  78. data/lib/active_merchant/billing/gateways/iats_payments.rb +277 -0
  79. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  80. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  81. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  82. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  83. data/lib/active_merchant/billing/gateways/inspire.rb +219 -0
  84. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  85. data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
  86. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  87. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  88. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  89. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  90. data/lib/active_merchant/billing/gateways/litle.rb +345 -0
  91. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  92. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  93. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  94. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  95. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  96. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  97. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  98. data/lib/active_merchant/billing/gateways/mercury.rb +326 -0
  99. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  100. data/lib/active_merchant/billing/gateways/migs.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  102. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  103. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  104. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  105. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  106. data/lib/active_merchant/billing/gateways/moneris_us.rb +298 -0
  107. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  108. data/lib/active_merchant/billing/gateways/nab_transact.rb +290 -0
  109. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  110. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  111. data/lib/active_merchant/billing/gateways/netbilling.rb +224 -0
  112. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  113. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  114. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  115. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  116. data/lib/active_merchant/billing/gateways/omise.rb +319 -0
  117. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  118. data/lib/active_merchant/billing/gateways/optimal_payment.rb +314 -0
  119. data/lib/active_merchant/billing/gateways/orbital.rb +834 -0
  120. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  121. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  122. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  123. data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
  124. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
  125. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  126. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  127. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  128. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  129. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  130. data/lib/active_merchant/billing/gateways/payflow.rb +308 -0
  131. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +220 -0
  132. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  133. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  134. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  135. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  136. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  137. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  138. data/lib/active_merchant/billing/gateways/paymill.rb +282 -0
  139. data/lib/active_merchant/billing/gateways/paypal.rb +129 -0
  140. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +679 -0
  141. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  142. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  143. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  144. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  145. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  146. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  147. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  148. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  149. data/lib/active_merchant/billing/gateways/payu_in.rb +247 -0
  150. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  151. data/lib/active_merchant/billing/gateways/pin.rb +207 -0
  152. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  153. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  154. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  155. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  156. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  157. data/lib/active_merchant/billing/gateways/quickbooks.rb +280 -0
  158. data/lib/active_merchant/billing/gateways/quickpay.rb +26 -0
  159. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
  160. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
  161. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
  162. data/lib/active_merchant/billing/gateways/qvalent.rb +179 -0
  163. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  164. data/lib/active_merchant/billing/gateways/redsys.rb +406 -0
  165. data/lib/active_merchant/billing/gateways/s5.rb +226 -0
  166. data/lib/active_merchant/billing/gateways/sage.rb +173 -0
  167. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +89 -0
  168. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +115 -0
  169. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  170. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  171. data/lib/active_merchant/billing/gateways/sage_pay.rb +399 -0
  172. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  173. data/lib/active_merchant/billing/gateways/secure_net.rb +263 -0
  174. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  175. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  176. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  177. data/lib/active_merchant/billing/gateways/skip_jack.rb +451 -0
  178. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  179. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  180. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  181. data/lib/active_merchant/billing/gateways/stripe.rb +489 -0
  182. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  183. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  184. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  185. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  186. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  187. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  188. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  189. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  190. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +259 -0
  191. data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
  192. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  193. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  194. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  195. data/lib/active_merchant/billing/gateways/wepay.rb +205 -0
  196. data/lib/active_merchant/billing/gateways/wirecard.rb +420 -0
  197. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  198. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +204 -0
  199. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  200. data/lib/active_merchant/billing/model.rb +30 -0
  201. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +24 -0
  202. data/lib/active_merchant/billing/payment_token.rb +21 -0
  203. data/lib/active_merchant/billing/rails.rb +3 -0
  204. data/lib/active_merchant/billing/response.rb +92 -0
  205. data/lib/active_merchant/connection.rb +172 -0
  206. data/lib/active_merchant/country.rb +332 -0
  207. data/lib/active_merchant/empty.rb +20 -0
  208. data/lib/active_merchant/errors.rb +35 -0
  209. data/lib/active_merchant/network_connection_retries.rb +79 -0
  210. data/lib/active_merchant/post_data.rb +24 -0
  211. data/lib/active_merchant/posts_data.rb +84 -0
  212. data/lib/active_merchant/version.rb +3 -0
  213. data/lib/activemerchant.rb +1 -0
  214. data/lib/certs/cacert.pem +3866 -0
  215. data/lib/support/gateway_support.rb +71 -0
  216. data/lib/support/outbound_hosts.rb +28 -0
  217. data/lib/support/ssl_verify.rb +93 -0
  218. metadata +387 -0
@@ -0,0 +1,298 @@
1
+ require 'rexml/document'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+
6
+ # To learn more about the Moneris (US) gateway, please contact
7
+ # ussales@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 MonerisUsGateway < Gateway
13
+ self.test_url = 'https://esplusqa.moneris.com/gateway_us/servlet/MpgRequest'
14
+ self.live_url = 'https://esplus.moneris.com/gateway_us/servlet/MpgRequest'
15
+
16
+ self.supported_countries = ['US']
17
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover]
18
+ self.homepage_url = 'http://www.monerisusa.com/'
19
+ self.display_name = 'Moneris (US)'
20
+
21
+ # Initialize the Gateway
22
+ #
23
+ # The gateway requires that a valid login and password be passed
24
+ # in the +options+ hash.
25
+ #
26
+ # ==== Options
27
+ #
28
+ # * <tt>:login</tt> -- Your Store ID
29
+ # * <tt>:password</tt> -- Your API Token
30
+ # * <tt>:cvv_enabled</tt> -- Specify that you would like the CVV passed to the gateway.
31
+ # Only particular account types at Moneris will allow this.
32
+ # Defaults to false. (optional)
33
+ def initialize(options = {})
34
+ requires!(options, :login, :password)
35
+ @cvv_enabled = options[:cvv_enabled]
36
+ @avs_enabled = options[:avs_enabled]
37
+ options = { :crypt_type => 7 }.merge(options)
38
+ super
39
+ end
40
+
41
+ def verify(creditcard_or_datakey, options = {})
42
+ MultiResponse.run(:use_first_response) do |r|
43
+ r.process { authorize(100, creditcard_or_datakey, options) }
44
+ r.process(:ignore_result) { capture(0, r.authorization) }
45
+ end
46
+ end
47
+
48
+ # Referred to as "PreAuth" in the Moneris integration guide, this action
49
+ # verifies and locks funds on a customer's card, which then must be
50
+ # captured at a later date.
51
+ #
52
+ # Pass in +order_id+ and optionally a +customer+ parameter.
53
+ def authorize(money, creditcard_or_datakey, options = {})
54
+ requires!(options, :order_id)
55
+ post = {}
56
+ add_payment_source(post, creditcard_or_datakey, options)
57
+ post[:amount] = amount(money)
58
+ post[:order_id] = options[:order_id]
59
+ post[:address] = options[:billing_address] || options[:address]
60
+ post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
61
+ action = (post[:data_key].blank?) ? 'us_preauth' : 'us_res_preauth_cc'
62
+ commit(action, post)
63
+ end
64
+
65
+ # This action verifies funding on a customer's card and readies them for
66
+ # deposit in a merchant's account.
67
+ #
68
+ # Pass in <tt>order_id</tt> and optionally a <tt>customer</tt> parameter
69
+ def purchase(money, creditcard_or_datakey, options = {})
70
+ requires!(options, :order_id)
71
+ post = {}
72
+ add_payment_source(post, creditcard_or_datakey, options)
73
+ post[:amount] = amount(money)
74
+ post[:order_id] = options[:order_id]
75
+ post[:address] = options[:billing_address] || options[:address]
76
+ post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
77
+ action = (post[:data_key].blank?) ? 'us_purchase' : 'us_res_purchase_cc'
78
+ commit(action, post)
79
+ end
80
+
81
+ # This method retrieves locked funds from a customer's account (from a
82
+ # PreAuth) and prepares them for deposit in a merchant's account.
83
+ #
84
+ # Note: Moneris requires both the order_id and the transaction number of
85
+ # the original authorization. To maintain the same interface as the other
86
+ # gateways the two numbers are concatenated together with a ; separator as
87
+ # the authorization number returned by authorization
88
+ def capture(money, authorization, options = {})
89
+ commit 'us_completion', crediting_params(authorization, :comp_amount => amount(money))
90
+ end
91
+
92
+ # Voiding requires the original transaction ID and order ID of some open
93
+ # transaction. Closed transactions must be refunded. Note that the only
94
+ # methods which may be voided are +capture+ and +purchase+.
95
+ #
96
+ # Concatenate your transaction number and order_id by using a semicolon
97
+ # (';'). This is to keep the Moneris interface consistent with other
98
+ # gateways. (See +capture+ for details.)
99
+ def void(authorization, options = {})
100
+ commit 'us_purchasecorrection', crediting_params(authorization)
101
+ end
102
+
103
+ # Performs a refund. This method requires that the original transaction
104
+ # number and order number be included. Concatenate your transaction
105
+ # number and order_id by using a semicolon (';'). This is to keep the
106
+ # Moneris interface consistent with other gateways. (See +capture+ for
107
+ # details.)
108
+ def credit(money, authorization, options = {})
109
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
110
+ refund(money, authorization, options)
111
+ end
112
+
113
+ def refund(money, authorization, options = {})
114
+ commit 'us_refund', crediting_params(authorization, :amount => amount(money))
115
+ end
116
+
117
+ def store(credit_card, options = {})
118
+ post = {}
119
+ post[:pan] = credit_card.number
120
+ post[:expdate] = expdate(credit_card)
121
+ post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
122
+ commit('us_res_add_cc', post)
123
+ end
124
+
125
+ def unstore(data_key, options = {})
126
+ post = {}
127
+ post[:data_key] = data_key
128
+ commit('us_res_delete', post)
129
+ end
130
+
131
+ def update(data_key, credit_card, options = {})
132
+ post = {}
133
+ post[:pan] = credit_card.number
134
+ post[:expdate] = expdate(credit_card)
135
+ post[:data_key] = data_key
136
+ post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
137
+ commit('us_res_update_cc', post)
138
+ end
139
+
140
+ private # :nodoc: all
141
+
142
+ def expdate(creditcard)
143
+ sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
144
+ end
145
+
146
+ def add_payment_source(post, source, options)
147
+ if source.is_a?(String)
148
+ post[:data_key] = source
149
+ post[:cust_id] = options[:customer]
150
+ else
151
+ post[:pan] = source.number
152
+ post[:expdate] = expdate(source)
153
+ post[:cvd_value] = source.verification_value if source.verification_value?
154
+ post[:cust_id] = options[:customer] || source.name
155
+ end
156
+ end
157
+
158
+ # Common params used amongst the +credit+, +void+ and +capture+ methods
159
+ def crediting_params(authorization, options = {})
160
+ {
161
+ :txn_number => split_authorization(authorization).first,
162
+ :order_id => split_authorization(authorization).last,
163
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
164
+ }.merge(options)
165
+ end
166
+
167
+ # Splits an +authorization+ param and retrieves the order id and
168
+ # transaction number in that order.
169
+ def split_authorization(authorization)
170
+ if authorization.nil? || authorization.empty? || authorization !~ /;/
171
+ raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")'
172
+ else
173
+ authorization.split(';')
174
+ end
175
+ end
176
+
177
+ def commit(action, parameters = {})
178
+ data = post_data(action, parameters)
179
+ url = test? ? self.test_url : self.live_url
180
+ raw = ssl_post(url, data)
181
+ response = parse(raw)
182
+
183
+ Response.new(successful?(response), message_from(response[:message]), response,
184
+ :test => test?,
185
+ :avs_result => { :code => response[:avs_result_code] },
186
+ :cvv_result => response[:cvd_result_code] && response[:cvd_result_code][-1,1],
187
+ :authorization => authorization_from(response)
188
+ )
189
+ end
190
+
191
+ # Generates a Moneris authorization string of the form 'trans_id;receipt_id'.
192
+ def authorization_from(response = {})
193
+ if response[:trans_id] && response[:receipt_id]
194
+ "#{response[:trans_id]};#{response[:receipt_id]}"
195
+ end
196
+ end
197
+
198
+ # Tests for a successful response from Moneris' servers
199
+ def successful?(response)
200
+ response[:response_code] &&
201
+ response[:complete] &&
202
+ (0..49).include?(response[:response_code].to_i)
203
+ end
204
+
205
+ def parse(xml)
206
+ response = { :message => "Global Error Receipt", :complete => false }
207
+ hashify_xml!(xml, response)
208
+ response
209
+ end
210
+
211
+ def hashify_xml!(xml, response)
212
+ xml = REXML::Document.new(xml)
213
+ return if xml.root.nil?
214
+ xml.elements.each('//receipt/*') do |node|
215
+ response[node.name.underscore.to_sym] = normalize(node.text)
216
+ end
217
+ end
218
+
219
+ def post_data(action, parameters = {})
220
+ xml = REXML::Document.new
221
+ root = xml.add_element("request")
222
+ root.add_element("store_id").text = options[:login]
223
+ root.add_element("api_token").text = options[:password]
224
+ root.add_element(transaction_element(action, parameters))
225
+
226
+ xml.to_s
227
+ end
228
+
229
+ def transaction_element(action, parameters)
230
+ transaction = REXML::Element.new(action)
231
+
232
+ # Must add the elements in the correct order
233
+ actions[action].each do |key|
234
+ case key
235
+ when :avs_info
236
+ transaction.add_element(avs_element(parameters[:address])) if @avs_enabled && parameters[:address]
237
+ when :cvd_info
238
+ transaction.add_element(cvd_element(parameters[:cvd_value])) if @cvv_enabled
239
+ else
240
+ transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
241
+ end
242
+ end
243
+
244
+ transaction
245
+ end
246
+
247
+ def avs_element(address)
248
+ full_address = "#{address[:address1]} #{address[:address2]}"
249
+ tokens = full_address.split(/\s+/)
250
+
251
+ element = REXML::Element.new('avs_info')
252
+ element.add_element('avs_street_number').text = tokens.select{|x| x =~ /\d/}.join(' ')
253
+ element.add_element('avs_street_name').text = tokens.reject{|x| x =~ /\d/}.join(' ')
254
+ element.add_element('avs_zipcode').text = address[:zip]
255
+ element
256
+ end
257
+
258
+ def cvd_element(cvd_value)
259
+ element = REXML::Element.new('cvd_info')
260
+ if cvd_value
261
+ element.add_element('cvd_indicator').text = "1"
262
+ element.add_element('cvd_value').text = cvd_value
263
+ else
264
+ element.add_element('cvd_indicator').text = "0"
265
+ end
266
+ element
267
+ end
268
+
269
+ def message_from(message)
270
+ return 'Unspecified error' if message.blank?
271
+ message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
272
+ end
273
+
274
+ def actions
275
+ {
276
+ "us_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type, :avs_info, :cvd_info],
277
+ "us_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type, :avs_info, :cvd_info],
278
+ "us_command" => [:order_id],
279
+ "us_refund" => [:order_id, :amount, :txn_number, :crypt_type],
280
+ "us_indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
281
+ "us_completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
282
+ "us_purchasecorrection" => [:order_id, :txn_number, :crypt_type],
283
+ "us_cavvpurcha" => [:order_id, :cust_id, :amount, :pan, :expdate, :cav],
284
+ "us_cavvpreaut" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
285
+ "us_transact" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
286
+ "us_Batchcloseall" => [],
287
+ "us_opentotals" => [:ecr_number],
288
+ "us_batchclose" => [:ecr_number],
289
+ "us_res_add_cc" => [:pan, :expdate, :crypt_type],
290
+ "us_res_delete" => [:data_key],
291
+ "us_res_update_cc" => [:data_key, :pan, :expdate, :crypt_type],
292
+ "us_res_purchase_cc" => [:data_key, :order_id, :cust_id, :amount, :crypt_type],
293
+ "us_res_preauth_cc" => [:data_key, :order_id, :cust_id, :amount, :crypt_type]
294
+ }
295
+ end
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,152 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class MoneyMoversGateway < Gateway
4
+ self.live_url = self.test_url = 'https://secure.mmoagateway.com/api/transact.php'
5
+
6
+ APPROVED, DECLINED, ERROR = 1, 2, 3
7
+
8
+ self.homepage_url = 'http://mmoa.us/'
9
+ self.display_name = 'MoneyMovers'
10
+ self.supported_countries = ['US']
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
12
+
13
+ def initialize(options = {})
14
+ requires!(options, :login, :password)
15
+ @options = options
16
+ super
17
+ end
18
+
19
+ def purchase(money, creditcard, options = {})
20
+ post = {}
21
+ add_invoice(post, options)
22
+ add_creditcard(post, creditcard)
23
+ add_address(post, options)
24
+ add_customer_data(post, options)
25
+ commit('sale', money, post)
26
+ end
27
+
28
+ def authorize(money, creditcard, options = {})
29
+ post = {}
30
+ add_invoice(post, options)
31
+ add_creditcard(post, creditcard)
32
+ add_address(post, options)
33
+ add_customer_data(post, options)
34
+ commit('auth', money, post)
35
+ end
36
+
37
+ def capture(money, authorization, options = {})
38
+ options[:transactionid] = authorization
39
+ commit('capture', money, options)
40
+ end
41
+
42
+ def void(authorization, options = {})
43
+ options[:transactionid] = authorization
44
+ commit('void', nil, options)
45
+ end
46
+
47
+ def refund(money, authorization, options = {})
48
+ commit('refund', money, options.merge(:transactionid => authorization))
49
+ end
50
+
51
+ def credit(money, authorization, options = {})
52
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
53
+ refund(money, authorization, options)
54
+ end
55
+
56
+ private
57
+
58
+ def add_customer_data(post, options)
59
+ post[:firstname] = options[:first_name]
60
+ post[:lastname] = options[:last_name]
61
+
62
+ post[:email] = options[:email]
63
+ end
64
+
65
+ def add_address(post, options)
66
+ if address = (options[:billing_address] || options[:address])
67
+ post[:company] = address[:company]
68
+ post[:address1] = address[:address1]
69
+ post[:address2] = address[:address2]
70
+ post[:city] = address[:city]
71
+ post[:state] = address[:state]
72
+ post[:zip] = address[:zip]
73
+ post[:country] = address[:country]
74
+ post[:phone] = address[:phone]
75
+ end
76
+ if address = options[:shipping_address]
77
+ post[:shipping_firstname] = address[:first_name]
78
+ post[:shipping_lastname] = address[:last_name]
79
+ post[:shipping_company] = address[:company]
80
+ post[:shipping_address1] = address[:address1]
81
+ post[:shipping_address2] = address[:address2]
82
+ post[:shipping_city] = address[:city]
83
+ post[:shipping_state] = address[:state]
84
+ post[:shipping_zip] = address[:zip]
85
+ post[:shipping_country] = address[:country]
86
+ post[:shipping_email] = address[:email]
87
+ end
88
+ end
89
+
90
+ def add_invoice(post, options)
91
+ post[:orderid] = options[:order_id]
92
+ post[:orderdescription] = options[:description]
93
+ end
94
+
95
+ def add_creditcard(post, creditcard)
96
+ post[:ccnumber] = creditcard.number
97
+ post[:ccexp] = expdate(creditcard)
98
+ post[:cvv] = creditcard.verification_value
99
+ end
100
+
101
+ def parse(body)
102
+ body.split('&').inject({}) do |memo, x|
103
+ k, v = x.split('=')
104
+ memo[k] = v
105
+ memo
106
+ end
107
+ end
108
+
109
+ def commit(action, money, parameters)
110
+ parameters[:amount] = amount(money)
111
+
112
+ data = ssl_post(self.live_url, post_data(action, parameters))
113
+ response = parse(data)
114
+ message = message_from(response)
115
+
116
+ Response.new(success?(response), message, response,
117
+ :test => test?,
118
+ :authorization => response['transactionid'],
119
+ :avs_result => {:code => response['avsresponse']},
120
+ :cvv_result => response['cvvresponse']
121
+ )
122
+ end
123
+
124
+ def success?(response)
125
+ response['response'] == '1'
126
+ end
127
+
128
+ def test?
129
+ (@options[:login].eql?('demo')) && (@options[:password].eql?('password'))
130
+ end
131
+
132
+ def message_from(response)
133
+ case response['response'].to_i
134
+ when APPROVED
135
+ "Transaction Approved"
136
+ when DECLINED
137
+ "Transaction Declined"
138
+ else
139
+ "Error in transaction data or system error"
140
+ end
141
+ end
142
+
143
+ def post_data(action, parameters = {})
144
+ parameters[:type] = action
145
+ parameters[:username] = @options[:login]
146
+ parameters[:password] = @options[:password]
147
+ parameters.map{|k, v| "#{k}=#{CGI.escape(v.to_s)}"}.join('&')
148
+ end
149
+ end
150
+ end
151
+ end
152
+
@@ -0,0 +1,290 @@
1
+ require 'rexml/document'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ # The National Australia Bank provide a payment gateway that seems to
6
+ # be a rebadged Securepay Australia service, though some differences exist.
7
+ class NabTransactGateway < Gateway
8
+ API_VERSION = 'xml-4.2'
9
+ PERIODIC_API_VERSION = "spxml-4.2"
10
+
11
+ class_attribute :test_periodic_url, :live_periodic_url
12
+
13
+ self.test_url = 'https://transact.nab.com.au/test/xmlapi/payment'
14
+ self.live_url = 'https://transact.nab.com.au/live/xmlapi/payment'
15
+ self.test_periodic_url = 'https://transact.nab.com.au/xmlapidemo/periodic'
16
+ self.live_periodic_url = 'https://transact.nab.com.au/xmlapi/periodic'
17
+
18
+ self.supported_countries = ['AU']
19
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
20
+
21
+ self.homepage_url = 'http://transact.nab.com.au'
22
+ self.display_name = 'NAB Transact'
23
+ self.money_format = :cents
24
+ self.default_currency = 'AUD'
25
+
26
+ #Transactions currently accepted by NAB Transact XML API
27
+ TRANSACTIONS = {
28
+ :purchase => 0, #Standard Payment
29
+ :refund => 4, #Refund
30
+ :void => 6, #Client Reversal (Void)
31
+ :unmatched_refund => 666, #Unmatched Refund
32
+ :authorization => 10, #Preauthorise
33
+ :capture => 11 #Preauthorise Complete (Advice)
34
+ }
35
+
36
+ PERIODIC_TYPES = {
37
+ :addcrn => 5,
38
+ :deletecrn => 5,
39
+ :trigger => 8
40
+ }
41
+
42
+ SUCCESS_CODES = [ '00', '08', '11', '16', '77' ]
43
+
44
+
45
+ def initialize(options = {})
46
+ requires!(options, :login, :password)
47
+ super
48
+ end
49
+
50
+ def purchase(money, credit_card_or_stored_id, options = {})
51
+ if credit_card_or_stored_id.respond_to?(:number)
52
+ commit :purchase, build_purchase_request(money, credit_card_or_stored_id, options)
53
+ else
54
+ commit_periodic(:trigger, build_purchase_using_stored_card_request(money, credit_card_or_stored_id, options))
55
+ end
56
+ end
57
+
58
+ def credit(money, credit_card, options = {})
59
+ commit :unmatched_refund, build_purchase_request(money, credit_card, options)
60
+ end
61
+
62
+ def refund(money, authorization, options = {})
63
+ commit :refund, build_reference_request(money, authorization, options)
64
+ end
65
+
66
+ def authorize(money, credit_card, options = {})
67
+ commit :authorization, build_purchase_request(money, credit_card, options)
68
+ end
69
+
70
+ def capture(money, authorization, options = {})
71
+ commit :capture, build_reference_request(money, authorization, options)
72
+ end
73
+
74
+ def store(credit_card, options = {})
75
+ commit_periodic(:addcrn, build_store_request(credit_card, options))
76
+ end
77
+
78
+ def unstore(identification, options = {})
79
+ commit_periodic(:deletecrn, build_unstore_request(identification, options))
80
+ end
81
+
82
+ private
83
+
84
+ def add_metadata(xml, options)
85
+ if options[:merchant_name] || options[:merchant_location]
86
+ xml.tag! 'metadata' do
87
+ xml.tag! 'meta', :name => 'ca_name', :value => options[:merchant_name] if options[:merchant_name]
88
+ xml.tag! 'meta', :name => 'ca_location', :value => options[:merchant_location] if options[:merchant_location]
89
+ end
90
+ end
91
+ end
92
+
93
+ def build_purchase_request(money, credit_card, options)
94
+ xml = Builder::XmlMarkup.new
95
+ xml.tag! 'amount', amount(money)
96
+ xml.tag! 'currency', options[:currency] || currency(money)
97
+ xml.tag! 'purchaseOrderNo', options[:order_id].to_s.gsub(/[ ']/, '')
98
+
99
+ xml.tag! 'CreditCardInfo' do
100
+ xml.tag! 'cardNumber', credit_card.number
101
+ xml.tag! 'expiryDate', expdate(credit_card)
102
+ xml.tag! 'cvv', credit_card.verification_value if credit_card.verification_value?
103
+ end
104
+
105
+ add_metadata(xml, options)
106
+
107
+ xml.target!
108
+ end
109
+
110
+ def build_reference_request(money, reference, options)
111
+ xml = Builder::XmlMarkup.new
112
+
113
+ transaction_id, order_id, preauth_id, original_amount = reference.split('*')
114
+
115
+ xml.tag! 'amount', (money ? amount(money) : original_amount)
116
+ xml.tag! 'currency', options[:currency] || currency(money)
117
+ xml.tag! 'txnID', transaction_id
118
+ xml.tag! 'purchaseOrderNo', order_id
119
+ xml.tag! 'preauthID', preauth_id
120
+
121
+ add_metadata(xml, options)
122
+
123
+ xml.target!
124
+ end
125
+
126
+ #Generate payment request XML
127
+ # - API is set to allow multiple Txn's but currently only allows one
128
+ # - txnSource = 23 - (XML)
129
+ def build_request(action, body)
130
+ xml = Builder::XmlMarkup.new
131
+ xml.instruct!
132
+ xml.tag! 'NABTransactMessage' do
133
+ xml.tag! 'MessageInfo' do
134
+ xml.tag! 'messageID', SecureRandom.hex(15)
135
+ xml.tag! 'messageTimestamp', generate_timestamp
136
+ xml.tag! 'timeoutValue', request_timeout
137
+ xml.tag! 'apiVersion', API_VERSION
138
+ end
139
+
140
+ xml.tag! 'MerchantInfo' do
141
+ xml.tag! 'merchantID', @options[:login]
142
+ xml.tag! 'password', @options[:password]
143
+ end
144
+
145
+ xml.tag! 'RequestType', 'Payment'
146
+ xml.tag! 'Payment' do
147
+ xml.tag! 'TxnList', "count" => 1 do
148
+ xml.tag! 'Txn', "ID" => 1 do
149
+ xml.tag! 'txnType', TRANSACTIONS[action]
150
+ xml.tag! 'txnSource', 23
151
+ xml << body
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ xml.target!
158
+ end
159
+
160
+ def build_periodic_request(action, body)
161
+ xml = Builder::XmlMarkup.new
162
+ xml.instruct!
163
+ xml.tag! 'NABTransactMessage' do
164
+ xml.tag! 'MessageInfo' do
165
+ xml.tag! 'messageID', SecureRandom.hex(15)
166
+ xml.tag! 'messageTimestamp', generate_timestamp
167
+ xml.tag! 'timeoutValue', request_timeout
168
+ xml.tag! 'apiVersion', PERIODIC_API_VERSION
169
+ end
170
+
171
+ xml.tag! 'MerchantInfo' do
172
+ xml.tag! 'merchantID', @options[:login]
173
+ xml.tag! 'password', @options[:password]
174
+ end
175
+
176
+ xml.tag! 'RequestType', 'Periodic'
177
+ xml.tag! 'Periodic' do
178
+ xml.tag! 'PeriodicList', "count" => 1 do
179
+ xml.tag! 'PeriodicItem', "ID" => 1 do
180
+ xml.tag! 'actionType', action.to_s
181
+ xml.tag! 'periodicType', PERIODIC_TYPES[action] if PERIODIC_TYPES[action]
182
+ xml << body
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ xml.target!
189
+ end
190
+
191
+ def build_purchase_using_stored_card_request(money, identification, options)
192
+ xml = Builder::XmlMarkup.new
193
+
194
+ xml.tag! 'crn', identification
195
+ xml.tag! 'currency', options[:currency] || currency(money)
196
+ xml.tag! 'amount', amount(money)
197
+
198
+ xml.target!
199
+ end
200
+
201
+ def build_store_request(credit_card, options)
202
+ xml = Builder::XmlMarkup.new
203
+
204
+ xml.tag! 'crn', options[:billing_id] || SecureRandom.hex(10)
205
+ xml.tag! 'CreditCardInfo' do
206
+ xml.tag! 'cardNumber', credit_card.number
207
+ xml.tag! 'expiryDate', expdate(credit_card)
208
+ xml.tag! 'cvv', credit_card.verification_value if credit_card.verification_value?
209
+ end
210
+
211
+ xml.target!
212
+ end
213
+
214
+ def build_unstore_request(identification, options)
215
+ xml = Builder::XmlMarkup.new
216
+
217
+ xml.tag! 'crn', identification
218
+ xml.target!
219
+ end
220
+
221
+ def commit(action, request)
222
+ response = parse(ssl_post(test? ? self.test_url : self.live_url, build_request(action, request)))
223
+
224
+ Response.new(success?(response), message_from(response), response,
225
+ :test => test?,
226
+ :authorization => authorization_from(action, response)
227
+ )
228
+ end
229
+
230
+ def commit_periodic(action, request)
231
+ response = parse(ssl_post(test? ? self.test_periodic_url : self.live_periodic_url, build_periodic_request(action, request)))
232
+ Response.new(success?(response), message_from(response), response,
233
+ :test => test?,
234
+ :authorization => authorization_from(action, response)
235
+ )
236
+ end
237
+
238
+ def success?(response)
239
+ SUCCESS_CODES.include?(response[:response_code])
240
+ end
241
+
242
+ def authorization_from(action, response)
243
+ if action == :addcrn
244
+ response[:crn]
245
+ else
246
+ [response[:txn_id], response[:purchase_order_no], response[:preauth_id], response[:amount]].join('*')
247
+ end
248
+ end
249
+
250
+ def message_from(response)
251
+ response[:response_text] || response[:status_description]
252
+ end
253
+
254
+ def expdate(credit_card)
255
+ "#{format(credit_card.month, :two_digits)}/#{format(credit_card.year, :two_digits)}"
256
+ end
257
+
258
+ def parse(body)
259
+ xml = REXML::Document.new(body)
260
+
261
+ response = {}
262
+
263
+ xml.root.elements.to_a.each do |node|
264
+ parse_element(response, node)
265
+ end
266
+
267
+ response
268
+ end
269
+
270
+ def parse_element(response, node)
271
+ if node.has_elements?
272
+ node.elements.each{|element| parse_element(response, element) }
273
+ else
274
+ response[node.name.underscore.to_sym] = node.text
275
+ end
276
+ end
277
+
278
+ # YYYYDDMMHHNNSSKKK000sOOO
279
+ def generate_timestamp
280
+ time = Time.now.utc
281
+ time.strftime("%Y%d%m%H%M%S#{time.usec}+000")
282
+ end
283
+
284
+ def request_timeout
285
+ @options[:request_timeout] || 60
286
+ end
287
+
288
+ end
289
+ end
290
+ end