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,307 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ #
6
+ # == Monei gateway
7
+ # This class implements Monei gateway for Active Merchant. For more information about Monei
8
+ # gateway please go to http://www.monei.net
9
+ #
10
+ # === Setup
11
+ # In order to set-up the gateway you need four paramaters: sender_id, channel_id, login and pwd.
12
+ # Request that data to Monei.
13
+ class MoneiGateway < Gateway
14
+ self.test_url = 'https://test.monei-api.net/payment/ctpe'
15
+ self.live_url = 'https://monei-api.net/payment/ctpe'
16
+
17
+ self.supported_countries = ['ES']
18
+ self.default_currency = 'EUR'
19
+ self.supported_cardtypes = [:visa, :master, :maestro, :jcb, :american_express]
20
+
21
+ self.homepage_url = 'http://www.monei.net/'
22
+ self.display_name = 'Monei'
23
+
24
+ # Constructor
25
+ #
26
+ # options - Hash containing the gateway credentials, ALL MANDATORY
27
+ # :sender_id Sender ID
28
+ # :channel_id Channel ID
29
+ # :login User login
30
+ # :pwd User password
31
+ #
32
+ def initialize(options={})
33
+ requires!(options, :sender_id, :channel_id, :login, :pwd)
34
+ super
35
+ end
36
+
37
+ # Public: Performs purchase operation
38
+ #
39
+ # money - Amount of purchase
40
+ # credit_card - Credit card
41
+ # options - Hash containing purchase options
42
+ # :order_id Merchant created id for the purchase
43
+ # :billing_address Hash with billing address information
44
+ # :description Merchant created purchase description (optional)
45
+ # :currency Sale currency to override money object or default (optional)
46
+ #
47
+ # Returns Active Merchant response object
48
+ def purchase(money, credit_card, options)
49
+ execute_new_order(:purchase, money, credit_card, options)
50
+ end
51
+
52
+ # Public: Performs authorization operation
53
+ #
54
+ # money - Amount to authorize
55
+ # credit_card - Credit card
56
+ # options - Hash containing authorization options
57
+ # :order_id Merchant created id for the authorization
58
+ # :billing_address Hash with billing address information
59
+ # :description Merchant created authorization description (optional)
60
+ # :currency Sale currency to override money object or default (optional)
61
+ #
62
+ # Returns Active Merchant response object
63
+ def authorize(money, credit_card, options={})
64
+ execute_new_order(:authorize, money, credit_card, options)
65
+ end
66
+
67
+ # Public: Performs capture operation on previous authorization
68
+ #
69
+ # money - Amount to capture
70
+ # authorization - Reference to previous authorization, obtained from response object returned by authorize
71
+ # options - Hash containing capture options
72
+ # :order_id Merchant created id for the authorization (optional)
73
+ # :description Merchant created authorization description (optional)
74
+ # :currency Sale currency to override money object or default (optional)
75
+ #
76
+ # Note: you should pass either order_id or description
77
+ #
78
+ # Returns Active Merchant response object
79
+ def capture(money, authorization, options={})
80
+ execute_dependant(:capture, money, authorization, options)
81
+ end
82
+
83
+ # Public: Refunds from previous purchase
84
+ #
85
+ # money - Amount to refund
86
+ # authorization - Reference to previous purchase, obtained from response object returned by purchase
87
+ # options - Hash containing refund options
88
+ # :order_id Merchant created id for the authorization (optional)
89
+ # :description Merchant created authorization description (optional)
90
+ # :currency Sale currency to override money object or default (optional)
91
+ #
92
+ # Note: you should pass either order_id or description
93
+ #
94
+ # Returns Active Merchant response object
95
+ def refund(money, authorization, options={})
96
+ execute_dependant(:refund, money, authorization, options)
97
+ end
98
+
99
+ # Public: Voids previous authorization
100
+ #
101
+ # authorization - Reference to previous authorization, obtained from response object returned by authorize
102
+ # options - Hash containing capture options
103
+ # :order_id Merchant created id for the authorization (optional)
104
+ #
105
+ # Returns Active Merchant response object
106
+ def void(authorization, options={})
107
+ execute_dependant(:void, nil, authorization, options)
108
+ end
109
+
110
+ # Public: Verifies credit card. Does this by doing a authorization of 1.00 Euro and then voiding it.
111
+ #
112
+ # credit_card - Credit card
113
+ # options - Hash containing authorization options
114
+ # :order_id Merchant created id for the authorization
115
+ # :billing_address Hash with billing address information
116
+ # :description Merchant created authorization description (optional)
117
+ # :currency Sale currency to override money object or default (optional)
118
+ #
119
+ # Returns Active Merchant response object of Authorization operation
120
+ def verify(credit_card, options={})
121
+ MultiResponse.run(:use_first_response) do |r|
122
+ r.process { authorize(100, credit_card, options) }
123
+ r.process(:ignore_result) { void(r.authorization, options) }
124
+ end
125
+ end
126
+
127
+ private
128
+
129
+ # Private: Execute purchase or authorize operation
130
+ def execute_new_order(action, money, credit_card, options)
131
+ request = build_request do |xml|
132
+ add_identification_new_order(xml, options)
133
+ add_payment(xml, action, money, options)
134
+ add_account(xml, credit_card)
135
+ add_customer(xml, credit_card, options)
136
+ end
137
+
138
+ commit(request)
139
+ end
140
+
141
+ # Private: Execute operation that depends on athorization code from previous purchase or authorize operation
142
+ def execute_dependant(action, money, authorization, options)
143
+ request = build_request do |xml|
144
+ add_identification_authorization(xml, authorization, options)
145
+ add_payment(xml, action, money, options)
146
+ end
147
+
148
+ commit(request)
149
+ end
150
+
151
+ # Private: Build XML wrapping code yielding to code to fill the transaction information
152
+ def build_request
153
+ builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
154
+ xml.Request(:version => "1.0") do
155
+ xml.Header { xml.Security(:sender => @options[:sender_id]) }
156
+ xml.Transaction(:mode => test? ? 'CONNECTOR_TEST' : 'LIVE', :response => 'SYNC', :channel => @options[:channel_id]) do
157
+ xml.User(:login => @options[:login], :pwd => @options[:pwd])
158
+ yield xml
159
+ end
160
+ end
161
+ end
162
+ builder.to_xml
163
+ end
164
+
165
+ # Private: Add identification part to XML for new orders
166
+ def add_identification_new_order(xml, options)
167
+ requires!(options, :order_id)
168
+ xml.Identification do
169
+ xml.TransactionID options[:order_id]
170
+ end
171
+ end
172
+
173
+ # Private: Add identification part to XML for orders that depend on authorization from previous operation
174
+ def add_identification_authorization(xml, authorization, options)
175
+ xml.Identification do
176
+ xml.ReferenceID authorization
177
+ xml.TransactionID options[:order_id]
178
+ end
179
+ end
180
+
181
+ # Private: Add payment part to XML
182
+ def add_payment(xml, action, money, options)
183
+ code = tanslate_payment_code(action)
184
+
185
+ xml.Payment(:code => code) do
186
+ xml.Presentation do
187
+ xml.Amount amount(money)
188
+ xml.Currency options[:currency] || currency(money)
189
+ xml.Usage options[:description] || options[:order_id]
190
+ end unless money.nil?
191
+ end
192
+ end
193
+
194
+ # Private: Add account part to XML
195
+ def add_account(xml, credit_card)
196
+ xml.Account do
197
+ xml.Holder credit_card.name
198
+ xml.Number credit_card.number
199
+ xml.Brand credit_card.brand.upcase
200
+ xml.Expiry(:month => credit_card.month, :year => credit_card.year)
201
+ xml.Verification credit_card.verification_value
202
+ end
203
+ end
204
+
205
+ # Private: Add customer part to XML
206
+ def add_customer(xml, credit_card, options)
207
+ requires!(options, :billing_address)
208
+ address = options[:billing_address]
209
+ xml.Customer do
210
+ xml.Name do
211
+ xml.Given credit_card.first_name
212
+ xml.Family credit_card.last_name
213
+ end
214
+ xml.Address do
215
+ xml.Street address[:address1].to_s
216
+ xml.Zip address[:zip].to_s
217
+ xml.City address[:city].to_s
218
+ xml.State address[:state].to_s if address.has_key? :state
219
+ xml.Country address[:country].to_s
220
+ end
221
+ xml.Contact do
222
+ xml.Email options[:email] || 'noemail@monei.net'
223
+ xml.Ip options[:ip] || '0.0.0.0'
224
+ end
225
+ end
226
+ end
227
+
228
+ # Private: Parse XML response from Monei servers
229
+ def parse(body)
230
+ xml = Nokogiri::XML(body)
231
+ {
232
+ :unique_id => xml.xpath("//Response/Transaction/Identification/UniqueID").text,
233
+ :status => translate_status_code(xml.xpath("//Response/Transaction/Processing/Status/@code").text),
234
+ :reason => translate_status_code(xml.xpath("//Response/Transaction/Processing/Reason/@code").text),
235
+ :message => xml.xpath("//Response/Transaction/Processing/Return").text
236
+ }
237
+ end
238
+
239
+ # Private: Send XML transaction to Monei servers and create AM response
240
+ def commit(xml)
241
+ url = (test? ? test_url : live_url)
242
+
243
+ response = parse(ssl_post(url, post_data(xml), 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'))
244
+
245
+ Response.new(
246
+ success_from(response),
247
+ message_from(response),
248
+ response,
249
+ authorization: authorization_from(response),
250
+ test: test?,
251
+ error_code: error_code_from(response)
252
+ )
253
+ end
254
+
255
+ # Private: Decide success from servers response
256
+ def success_from(response)
257
+ response[:status] == :success || response[:status] == :new
258
+ end
259
+
260
+ # Private: Get message from servers response
261
+ def message_from(response)
262
+ response[:message]
263
+ end
264
+
265
+ # Private: Get error code from servers response
266
+ def error_code_from(response)
267
+ success_from(response) ? nil : STANDARD_ERROR_CODE[:card_declined]
268
+ end
269
+
270
+ # Private: Get authorization code from servers response
271
+ def authorization_from(response)
272
+ response[:unique_id]
273
+ end
274
+
275
+ # Private: Encode POST parameters
276
+ def post_data(xml)
277
+ "load=#{CGI.escape(xml)}"
278
+ end
279
+
280
+ # Private: Translate Monei status code to native ruby symbols
281
+ def translate_status_code(code)
282
+ {
283
+ '00' => :success,
284
+ '40' => :neutral,
285
+ '59' => :waiting_bank,
286
+ '60' => :rejected_bank,
287
+ '64' => :waiting_risk,
288
+ '65' => :rejected_risk,
289
+ '70' => :rejected_validation,
290
+ '80' => :waiting,
291
+ '90' => :new
292
+ }[code]
293
+ end
294
+
295
+ # Private: Translate AM operations to Monei operations codes
296
+ def tanslate_payment_code(action)
297
+ {
298
+ :purchase => 'CC.DB',
299
+ :authorize => 'CC.PA',
300
+ :capture => 'CC.CP',
301
+ :refund => 'CC.RF',
302
+ :void => 'CC.RV'
303
+ }[action]
304
+ end
305
+ end
306
+ end
307
+ end
@@ -0,0 +1,309 @@
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
+ self.test_url = 'https://esqa.moneris.com/gateway2/servlet/MpgRequest'
14
+ self.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
+ # 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
+ # Referred to as "PreAuth" in the Moneris integration guide, this action
42
+ # verifies and locks funds on a customer's card, which then must be
43
+ # captured at a later date.
44
+ #
45
+ # Pass in +order_id+ and optionally a +customer+ parameter.
46
+ def authorize(money, creditcard_or_datakey, options = {})
47
+ requires!(options, :order_id)
48
+ post = {}
49
+ add_payment_source(post, creditcard_or_datakey, options)
50
+ post[:amount] = amount(money)
51
+ post[:order_id] = options[:order_id]
52
+ post[:address] = options[:billing_address] || options[:address]
53
+ post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
54
+ action = (post[:data_key].blank?) ? 'preauth' : 'res_preauth_cc'
55
+ commit(action, post)
56
+ end
57
+
58
+ # This action verifies funding on a customer's card and readies them for
59
+ # deposit in a merchant's account.
60
+ #
61
+ # Pass in <tt>order_id</tt> and optionally a <tt>customer</tt> parameter
62
+ def purchase(money, creditcard_or_datakey, options = {})
63
+ requires!(options, :order_id)
64
+ post = {}
65
+ add_payment_source(post, creditcard_or_datakey, options)
66
+ post[:amount] = amount(money)
67
+ post[:order_id] = options[:order_id]
68
+ post[:address] = options[:billing_address] || options[:address]
69
+ post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
70
+ action = (post[:data_key].blank?) ? 'purchase' : 'res_purchase_cc'
71
+ commit(action, post)
72
+ end
73
+
74
+ # This method retrieves locked funds from a customer's account (from a
75
+ # PreAuth) and prepares them for deposit in a merchant's account.
76
+ #
77
+ # Note: Moneris requires both the order_id and the transaction number of
78
+ # the original authorization. To maintain the same interface as the other
79
+ # gateways the two numbers are concatenated together with a ; separator as
80
+ # the authorization number returned by authorization
81
+ def capture(money, authorization, options = {})
82
+ commit 'completion', crediting_params(authorization, :comp_amount => amount(money))
83
+ end
84
+
85
+ # Voiding requires the original transaction ID and order ID of some open
86
+ # transaction. Closed transactions must be refunded.
87
+ #
88
+ # Moneris supports the voiding of an unsettled capture or purchase via
89
+ # its <tt>purchasecorrection</tt> command. This action can only occur
90
+ # on the same day as the capture/purchase prior to 22:00-23:00 EST. If
91
+ # you want to do this, pass <tt>:purchasecorrection => true</tt> as
92
+ # an option.
93
+ #
94
+ # Fun, Historical Trivia:
95
+ # Voiding an authorization in Moneris is a relatively new feature
96
+ # (September, 2011). It is actually done by doing a $0 capture.
97
+ #
98
+ # Concatenate your transaction number and order_id by using a semicolon
99
+ # (';'). This is to keep the Moneris interface consistent with other
100
+ # gateways. (See +capture+ for details.)
101
+ def void(authorization, options = {})
102
+ if options[:purchasecorrection]
103
+ commit 'purchasecorrection', crediting_params(authorization)
104
+ else
105
+ capture(0, authorization, options)
106
+ end
107
+ end
108
+
109
+ # Performs a refund. This method requires that the original transaction
110
+ # number and order number be included. Concatenate your transaction
111
+ # number and order_id by using a semicolon (';'). This is to keep the
112
+ # Moneris interface consistent with other gateways. (See +capture+ for
113
+ # details.)
114
+ def credit(money, authorization, options = {})
115
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
116
+ refund(money, authorization, options)
117
+ end
118
+
119
+ def refund(money, authorization, options = {})
120
+ commit 'refund', crediting_params(authorization, :amount => amount(money))
121
+ end
122
+
123
+ def store(credit_card, options = {})
124
+ post = {}
125
+ post[:pan] = credit_card.number
126
+ post[:expdate] = expdate(credit_card)
127
+ post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
128
+ commit('res_add_cc', post)
129
+ end
130
+
131
+ def unstore(data_key, options = {})
132
+ post = {}
133
+ post[:data_key] = data_key
134
+ commit('res_delete', post)
135
+ end
136
+
137
+ def update(data_key, credit_card, options = {})
138
+ post = {}
139
+ post[:pan] = credit_card.number
140
+ post[:expdate] = expdate(credit_card)
141
+ post[:data_key] = data_key
142
+ post[:crypt_type] = options[:crypt_type] || @options[:crypt_type]
143
+ commit('res_update_cc', post)
144
+ end
145
+
146
+ private # :nodoc: all
147
+
148
+ def expdate(creditcard)
149
+ sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month)
150
+ end
151
+
152
+ def add_payment_source(post, source, options)
153
+ if source.is_a?(String)
154
+ post[:data_key] = source
155
+ post[:cust_id] = options[:customer]
156
+ else
157
+ if source.respond_to?(:track_data) && source.track_data.present?
158
+ post[:pos_code] = '00'
159
+ post[:track2] = source.track_data
160
+ else
161
+ post[:pan] = source.number
162
+ post[:expdate] = expdate(source)
163
+ post[:cvd_value] = source.verification_value if source.verification_value?
164
+ end
165
+ post[:cust_id] = options[:customer] || source.name
166
+ end
167
+ end
168
+
169
+ # Common params used amongst the +credit+, +void+ and +capture+ methods
170
+ def crediting_params(authorization, options = {})
171
+ {
172
+ :txn_number => split_authorization(authorization).first,
173
+ :order_id => split_authorization(authorization).last,
174
+ :crypt_type => options[:crypt_type] || @options[:crypt_type]
175
+ }.merge(options)
176
+ end
177
+
178
+ # Splits an +authorization+ param and retrieves the order id and
179
+ # transaction number in that order.
180
+ def split_authorization(authorization)
181
+ if authorization.nil? || authorization.empty? || authorization !~ /;/
182
+ raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")'
183
+ else
184
+ authorization.split(';')
185
+ end
186
+ end
187
+
188
+ def commit(action, parameters = {})
189
+ data = post_data(action, parameters)
190
+ url = test? ? self.test_url : self.live_url
191
+ raw = ssl_post(url, data)
192
+ response = parse(raw)
193
+
194
+ Response.new(successful?(response), message_from(response[:message]), response,
195
+ :test => test?,
196
+ :avs_result => { :code => response[:avs_result_code] },
197
+ :cvv_result => response[:cvd_result_code] && response[:cvd_result_code][-1,1],
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
+ response[:response_code] &&
212
+ response[:complete] &&
213
+ (0..49).include?(response[:response_code].to_i)
214
+ end
215
+
216
+ def parse(xml)
217
+ response = { :message => "Global Error Receipt", :complete => false }
218
+ hashify_xml!(xml, response)
219
+ response
220
+ end
221
+
222
+ def hashify_xml!(xml, response)
223
+ xml = REXML::Document.new(xml)
224
+ return if xml.root.nil?
225
+ xml.elements.each('//receipt/*') do |node|
226
+ response[node.name.underscore.to_sym] = normalize(node.text)
227
+ end
228
+ end
229
+
230
+ def post_data(action, parameters = {})
231
+ xml = REXML::Document.new
232
+ root = xml.add_element("request")
233
+ root.add_element("store_id").text = options[:login]
234
+ root.add_element("api_token").text = options[:password]
235
+ root.add_element(transaction_element(action, parameters))
236
+
237
+ xml.to_s
238
+ end
239
+
240
+ def transaction_element(action, parameters)
241
+ transaction = REXML::Element.new(action)
242
+
243
+ # Must add the elements in the correct order
244
+ actions[action].each do |key|
245
+ case key
246
+ when :avs_info
247
+ transaction.add_element(avs_element(parameters[:address])) if @avs_enabled && parameters[:address]
248
+ when :cvd_info
249
+ transaction.add_element(cvd_element(parameters[:cvd_value])) if @cvv_enabled
250
+ else
251
+ transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
252
+ end
253
+ end
254
+
255
+ transaction
256
+ end
257
+
258
+ def avs_element(address)
259
+ full_address = "#{address[:address1]} #{address[:address2]}"
260
+ tokens = full_address.split(/\s+/)
261
+
262
+ element = REXML::Element.new('avs_info')
263
+ element.add_element('avs_street_number').text = tokens.select{|x| x =~ /\d/}.join(' ')
264
+ element.add_element('avs_street_name').text = tokens.reject{|x| x =~ /\d/}.join(' ')
265
+ element.add_element('avs_zipcode').text = address[:zip]
266
+ element
267
+ end
268
+
269
+ def cvd_element(cvd_value)
270
+ element = REXML::Element.new('cvd_info')
271
+ if cvd_value
272
+ element.add_element('cvd_indicator').text = "1"
273
+ element.add_element('cvd_value').text = cvd_value
274
+ else
275
+ element.add_element('cvd_indicator').text = "0"
276
+ end
277
+ element
278
+ end
279
+
280
+ def message_from(message)
281
+ return 'Unspecified error' if message.blank?
282
+ message.gsub(/[^\w]/, ' ').split.join(" ").capitalize
283
+ end
284
+
285
+ def actions
286
+ {
287
+ "purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type, :avs_info, :cvd_info, :track2, :pos_code],
288
+ "preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type, :avs_info, :cvd_info, :track2, :pos_code],
289
+ "command" => [:order_id],
290
+ "refund" => [:order_id, :amount, :txn_number, :crypt_type],
291
+ "indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
292
+ "completion" => [:order_id, :comp_amount, :txn_number, :crypt_type],
293
+ "purchasecorrection" => [:order_id, :txn_number, :crypt_type],
294
+ "cavvpurcha" => [:order_id, :cust_id, :amount, :pan, :expdate, :cav],
295
+ "cavvpreaut" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv],
296
+ "transact" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
297
+ "Batchcloseall" => [],
298
+ "opentotals" => [:ecr_number],
299
+ "batchclose" => [:ecr_number],
300
+ "res_add_cc" => [:pan, :expdate, :crypt_type],
301
+ "res_delete" => [:data_key],
302
+ "res_update_cc" => [:data_key, :pan, :expdate, :crypt_type],
303
+ "res_purchase_cc" => [:data_key, :order_id, :cust_id, :amount, :crypt_type],
304
+ "res_preauth_cc" => [:data_key, :order_id, :cust_id, :amount, :crypt_type]
305
+ }
306
+ end
307
+ end
308
+ end
309
+ end