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,245 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class MerchantPartnersGateway < Gateway
6
+ self.display_name = "Merchant Partners"
7
+ self.homepage_url = "http://www.merchantpartners.com/"
8
+
9
+ self.live_url = "https://trans.merchantpartners.com/cgi-bin/ProcessXML.cgi"
10
+
11
+ self.supported_countries = ["US"]
12
+ self.default_currency = "USD"
13
+ self.money_format = :dollars
14
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
15
+
16
+ def initialize(options={})
17
+ requires!(options, :account_id, :merchant_pin)
18
+ super
19
+ end
20
+
21
+ def purchase(amount, payment_method, options={})
22
+ post = {}
23
+ add_invoice(post, amount, options)
24
+ add_payment_method(post, payment_method)
25
+ add_customer_data(post, options)
26
+
27
+ commit(payment_method.is_a?(String) ? :stored_purchase : :purchase, post)
28
+ end
29
+
30
+ def authorize(amount, payment_method, options={})
31
+ post = {}
32
+ add_invoice(post, amount, options)
33
+ add_payment_method(post, payment_method)
34
+ add_customer_data(post, options)
35
+
36
+ commit(:authorize, post)
37
+ end
38
+
39
+ def capture(amount, authorization, options={})
40
+ post = {}
41
+ add_invoice(post, amount, options)
42
+ add_reference(post, authorization)
43
+ add_customer_data(post, options)
44
+
45
+ commit(:capture, post)
46
+ end
47
+
48
+ def void(authorization, options={})
49
+ post = {}
50
+ add_reference(post, authorization)
51
+
52
+ commit(:void, post)
53
+ end
54
+
55
+ def refund(amount, authorization, options={})
56
+ post = {}
57
+ add_invoice(post, amount, options)
58
+ add_reference(post, authorization)
59
+ add_customer_data(post, options)
60
+
61
+ commit(:refund, post)
62
+ end
63
+
64
+ def credit(amount, payment_method, options={})
65
+ post = {}
66
+ add_invoice(post, amount, options)
67
+ add_payment_method(post, payment_method)
68
+
69
+ commit(payment_method.is_a?(String) ? :stored_credit : :credit, post)
70
+ end
71
+
72
+ def verify(credit_card, options={})
73
+ MultiResponse.run(:use_first_response) do |r|
74
+ r.process { authorize(100, credit_card, options) }
75
+ r.process(:ignore_result) { void(r.authorization, options) }
76
+ end
77
+ end
78
+
79
+ def store(payment_method, options = {})
80
+ post = {}
81
+ add_payment_method(post, payment_method)
82
+ add_customer_data(post, options)
83
+
84
+ post[:profileactiontype] = options[:profileactiontype] || STORE_TX_TYPES[:store_only]
85
+
86
+ commit(:store, post)
87
+ end
88
+
89
+ def supports_scrubbing?
90
+ true
91
+ end
92
+
93
+ def scrub(transcript)
94
+ transcript.
95
+ gsub(%r((<ccnum>)[^<]+(<))i, '\1[FILTERED]\2').
96
+ gsub(%r((<cvv2>)[^<]+(<))i, '\1[FILTERED]\2').
97
+ gsub(%r((<merchantpin>)[^<]+(<))i, '\1[FILTERED]\2')
98
+ end
99
+
100
+ def test?
101
+ @options[:account_id].eql?('TEST0')
102
+ end
103
+
104
+ private
105
+
106
+ def add_invoice(post, money, options)
107
+ post[:amount] = amount(money)
108
+ post[:merchantordernumber] = options[:order_id]
109
+ post[:currency] = options[:currency] || currency(money)
110
+ end
111
+
112
+ def add_payment_method(post, payment_method)
113
+ if(payment_method.is_a?(String))
114
+ user_profile_id, last_4 = split_authorization(payment_method)
115
+ post[:userprofileid] = user_profile_id
116
+ post[:last4digits] = last_4
117
+ else
118
+ post[:ccname] = payment_method.name
119
+ post[:ccnum] = payment_method.number
120
+ post[:cvv2] = payment_method.verification_value
121
+ post[:expmon] = format(payment_method.month, :two_digits)
122
+ post[:expyear] = format(payment_method.year, :four_digits)
123
+ post[:swipedata] = payment_method.track_data if payment_method.track_data
124
+ end
125
+ end
126
+
127
+ def add_customer_data(post, options)
128
+ post[:email] = options[:email] if options[:email]
129
+ post[:ipaddress] = options[:ip] if options[:ip]
130
+ if(billing_address = options[:billing_address])
131
+ post[:billaddr1] = billing_address[:address1]
132
+ post[:billaddr2] = billing_address[:address2]
133
+ post[:billcity] = billing_address[:city]
134
+ post[:billstate] = billing_address[:state]
135
+ post[:billcountry] = billing_address[:country]
136
+ post[:bilzip] = billing_address[:zip]
137
+ post[:phone] = billing_address[:phone]
138
+ end
139
+ end
140
+
141
+ def add_reference(post, authorization)
142
+ post[:historykeyid] = authorization
143
+ end
144
+
145
+ ACTIONS = {
146
+ purchase: "2",
147
+ authorize: "1",
148
+ capture: "3",
149
+ void: "5",
150
+ refund: "4",
151
+ credit: "6",
152
+ store: "7",
153
+ stored_purchase: "8",
154
+ stored_credit: "13"
155
+ }
156
+
157
+ STORE_TX_TYPES = {
158
+ store_only: "3"
159
+ }
160
+
161
+ def commit(action, post)
162
+ post[:acctid] = @options[:account_id]
163
+ post[:merchantpin] = @options[:merchant_pin]
164
+ post[:service] = ACTIONS[action] if ACTIONS[action]
165
+
166
+ data = build_request(post)
167
+ response_data = parse(ssl_post(live_url, data, headers))
168
+ succeeded = success_from(response_data)
169
+
170
+ Response.new(
171
+ succeeded,
172
+ message_from(succeeded, response_data),
173
+ response_data,
174
+ authorization: authorization_from(post, response_data),
175
+ :avs_result => AVSResult.new(code: response_data["avs_response"]),
176
+ :cvv_result => CVVResult.new(response_data["cvv2_response"]),
177
+ test: test?
178
+ )
179
+ end
180
+
181
+ def headers
182
+ {
183
+ "Content-Type" => "application/xml"
184
+ }
185
+ end
186
+
187
+ def build_request(post)
188
+ Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
189
+ xml.interface_driver {
190
+ xml.trans_catalog {
191
+ xml.transaction(name: "creditcard") {
192
+ xml.inputs {
193
+ post.each do |field, value|
194
+ xml.send(field, value)
195
+ end
196
+ }
197
+ }
198
+ }
199
+ }
200
+ end.to_xml
201
+ end
202
+
203
+ def parse(body)
204
+ response = {}
205
+ Nokogiri::XML(CGI.unescapeHTML(body)).xpath("//trans_catalog/transaction/outputs").children.each do |node|
206
+ parse_element(response, node)
207
+ end
208
+ response
209
+ end
210
+
211
+ def parse_element(response, node)
212
+ if node.elements.size == 0
213
+ response[node.name.downcase.underscore.to_sym] = node.text
214
+ else
215
+ node.elements.each{|element| parse_element(response, element) }
216
+ end
217
+ end
218
+
219
+ def success_from(response)
220
+ response[:status] == "Approved"
221
+ end
222
+
223
+ def message_from(succeeded, response)
224
+ succeeded ? "Succeeded" : error_message_from(response)
225
+ end
226
+
227
+ def authorization_from(request, response)
228
+ request[:service] == ACTIONS[:store] ?
229
+ "#{response[:userprofileid]}|#{response[:last4digits]}" :
230
+ response[:historyid]
231
+ end
232
+
233
+ def split_authorization(authorization)
234
+ authorization.split("|")
235
+ end
236
+
237
+ def error_message_from(response)
238
+ if(response[:status] == "Declined")
239
+ match = response[:result].match(/DECLINED:\d{10}:(.+):/)
240
+ match[1] if match
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,319 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class MerchantWareGateway < Gateway
4
+ class_attribute :v4_live_url
5
+
6
+ self.live_url = self.test_url = 'https://ps1.merchantware.net/MerchantWARE/ws/RetailTransaction/TXRetail.asmx'
7
+ self.v4_live_url = 'https://ps1.merchantware.net/Merchantware/ws/RetailTransaction/v4/Credit.asmx'
8
+
9
+ self.supported_countries = ['US']
10
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
11
+ self.homepage_url = 'http://merchantwarehouse.com/merchantware'
12
+ self.display_name = 'MerchantWARE'
13
+
14
+ ENV_NAMESPACES = { "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
15
+ "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
16
+ "xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/"
17
+ }
18
+ ENV_NAMESPACES_V4 = { "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
19
+ "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
20
+ "xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/"
21
+ }
22
+
23
+ TX_NAMESPACE = "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail"
24
+ TX_NAMESPACE_V4 = "http://schemas.merchantwarehouse.com/merchantware/40/Credit/"
25
+
26
+ ACTIONS = {
27
+ :purchase => "IssueKeyedSale",
28
+ :authorize => "IssueKeyedPreAuth",
29
+ :capture => "IssuePostAuth",
30
+ :void => "VoidPreAuthorization",
31
+ :credit => "IssueKeyedRefund",
32
+ :reference_credit => "IssueRefundByReference"
33
+ }
34
+
35
+ # Creates a new MerchantWareGateway
36
+ #
37
+ # The gateway requires that a valid login, password, and name be passed
38
+ # in the +options+ hash.
39
+ #
40
+ # ==== Options
41
+ #
42
+ # * <tt>:login</tt> - The MerchantWARE SiteID.
43
+ # * <tt>:password</tt> - The MerchantWARE Key.
44
+ # * <tt>:name</tt> - The MerchantWARE Name.
45
+ def initialize(options = {})
46
+ requires!(options, :login, :password, :name)
47
+ super
48
+ end
49
+
50
+ # Authorize a credit card for a given amount.
51
+ #
52
+ # ==== Parameters
53
+ # * <tt>money</tt> - The amount to be authorized as an Integer value in cents.
54
+ # * <tt>credit_card</tt> - The CreditCard details for the transaction.
55
+ # * <tt>options</tt>
56
+ # * <tt>:order_id</tt> - A unique reference for this order (required).
57
+ # * <tt>:billing_address</tt> - The billing address for the cardholder.
58
+ def authorize(money, credit_card, options = {})
59
+ request = build_purchase_request(:authorize, money, credit_card, options)
60
+ commit(:authorize, request)
61
+ end
62
+
63
+ # Authorize and immediately capture funds from a credit card.
64
+ #
65
+ # ==== Parameters
66
+ # * <tt>money</tt> - The amount to be authorized as anInteger value in cents.
67
+ # * <tt>credit_card</tt> - The CreditCard details for the transaction.
68
+ # * <tt>options</tt>
69
+ # * <tt>:order_id</tt> - A unique reference for this order (required).
70
+ # * <tt>:billing_address</tt> - The billing address for the cardholder.
71
+ def purchase(money, credit_card, options = {})
72
+ request = build_purchase_request(:purchase, money, credit_card, options)
73
+ commit(:purchase, request)
74
+ end
75
+
76
+ # Capture authorized funds from a credit card.
77
+ #
78
+ # ==== Parameters
79
+ # * <tt>money</tt> - The amount to be captured as anInteger value in cents.
80
+ # * <tt>authorization</tt> - The authorization string returned from the initial authorization.
81
+ def capture(money, authorization, options = {})
82
+ request = build_capture_request(:capture, money, authorization, options)
83
+ commit(:capture, request)
84
+ end
85
+
86
+ # Void a transaction.
87
+ #
88
+ # ==== Parameters
89
+ # * <tt>authorization</tt> - The authorization string returned from the initial authorization or purchase.
90
+ def void(authorization, options = {})
91
+ reference, options[:order_id] = split_reference(authorization)
92
+ request = v4_soap_request(:void) do |xml|
93
+ add_reference_token(xml, reference)
94
+ end
95
+ commit(:void, request, true)
96
+ end
97
+
98
+ # Refund an amount back a cardholder
99
+ #
100
+ # ==== Parameters
101
+ #
102
+ # * <tt>money</tt> - The amount to be refunded as an Integer value in cents.
103
+ # * <tt>identification</tt> - The credit card you want to refund or the authorization for the existing transaction you are refunding.
104
+ # * <tt>options</tt>
105
+ # * <tt>:order_id</tt> - A unique reference for this order (required when performing a non-referenced credit)
106
+ def credit(money, identification, options = {})
107
+ if identification.is_a?(String)
108
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
109
+ refund(money, identification, options)
110
+ else
111
+ perform_credit(money, identification, options)
112
+ end
113
+ end
114
+
115
+ def refund(money, reference, options = {})
116
+ perform_reference_credit(money, reference, options)
117
+ end
118
+
119
+ private
120
+
121
+ def soap_request(action)
122
+ xml = Builder::XmlMarkup.new :indent => 2
123
+ xml.instruct!
124
+ xml.tag! "env:Envelope", ENV_NAMESPACES do
125
+ xml.tag! "env:Body" do
126
+ xml.tag! ACTIONS[action], "xmlns" => TX_NAMESPACE do
127
+ add_credentials(xml)
128
+ yield xml
129
+ end
130
+ end
131
+ end
132
+ xml.target!
133
+ end
134
+
135
+ def v4_soap_request(action)
136
+ xml = Builder::XmlMarkup.new :indent => 2
137
+ xml.instruct!
138
+ xml.tag! "soap:Envelope", ENV_NAMESPACES_V4 do
139
+ xml.tag! "soap:Body" do
140
+ xml.tag! ACTIONS[:void], "xmlns" => TX_NAMESPACE_V4 do
141
+ xml.tag! "merchantName", @options[:name]
142
+ xml.tag! "merchantSiteId", @options[:login]
143
+ xml.tag! "merchantKey", @options[:password]
144
+ yield xml
145
+ end
146
+ end
147
+ end
148
+ xml.target!
149
+ end
150
+
151
+ def build_purchase_request(action, money, credit_card, options)
152
+ requires!(options, :order_id)
153
+
154
+ soap_request(action) do |xml|
155
+ add_invoice(xml, options)
156
+ add_amount(xml, money)
157
+ add_credit_card(xml, credit_card)
158
+ add_address(xml, options)
159
+ end
160
+ end
161
+
162
+ def build_capture_request(action, money, identification, options)
163
+ reference, options[:order_id] = split_reference(identification)
164
+
165
+ soap_request(action) do |xml|
166
+ add_reference(xml, reference)
167
+ add_invoice(xml, options)
168
+ add_amount(xml, money)
169
+ end
170
+ end
171
+
172
+ def perform_reference_credit(money, identification, options)
173
+ reference, options[:order_id] = split_reference(identification)
174
+
175
+ request = soap_request(:reference_credit) do |xml|
176
+ add_reference(xml, reference)
177
+ add_invoice(xml, options)
178
+ add_amount(xml, money, "strOverrideAmount")
179
+ end
180
+
181
+ commit(:reference_credit, request)
182
+ end
183
+
184
+ def perform_credit(money, credit_card, options)
185
+ requires!(options, :order_id)
186
+
187
+ request = soap_request(:credit) do |xml|
188
+ add_invoice(xml, options)
189
+ add_amount(xml, money)
190
+ add_credit_card(xml, credit_card)
191
+ end
192
+
193
+ commit(:credit, request)
194
+ end
195
+
196
+ def add_credentials(xml)
197
+ xml.tag! "strSiteId", @options[:login]
198
+ xml.tag! "strKey", @options[:password]
199
+ xml.tag! "strName", @options[:name]
200
+ end
201
+
202
+ def add_invoice(xml, options)
203
+ xml.tag! "strOrderNumber", options[:order_id].to_s.gsub(/[^\w]/, '').slice(0, 25)
204
+ end
205
+
206
+ def add_amount(xml, money, tag = "strAmount")
207
+ xml.tag! tag, amount(money)
208
+ end
209
+
210
+ def add_reference(xml, reference)
211
+ xml.tag! "strReferenceCode", reference
212
+ end
213
+
214
+ def add_reference_token(xml, reference)
215
+ xml.tag! "token", reference
216
+ end
217
+
218
+ def add_address(xml, options)
219
+ if address = options[:billing_address] || options[:address]
220
+ xml.tag! "strAVSStreetAddress", address[:address1]
221
+ xml.tag! "strAVSZipCode", address[:zip]
222
+ end
223
+ end
224
+
225
+ def add_credit_card(xml, credit_card)
226
+ if credit_card.respond_to?(:track_data) && credit_card.track_data.present?
227
+ xml.tag! "trackData", credit_card.track_data
228
+ else
229
+ xml.tag! "strPAN", credit_card.number
230
+ xml.tag! "strExpDate", expdate(credit_card)
231
+ xml.tag! "strCardHolder", credit_card.name
232
+ xml.tag! "strCVCode", credit_card.verification_value if credit_card.verification_value?
233
+ end
234
+ end
235
+
236
+ def split_reference(reference)
237
+ reference.to_s.split(";")
238
+ end
239
+
240
+ def parse(action, data)
241
+ response = {}
242
+ xml = REXML::Document.new(data)
243
+
244
+ root = REXML::XPath.first(xml, "//#{ACTIONS[action]}Response/#{ACTIONS[action]}Result")
245
+
246
+ root.elements.each do |element|
247
+ response[element.name] = element.text
248
+ end
249
+
250
+ status, code, message = response["ApprovalStatus"].split(";")
251
+ response[:status] = status
252
+
253
+ if response[:success] = status == "APPROVED"
254
+ response[:message] = status
255
+ else
256
+ response[:message] = message
257
+ response[:failure_code] = code
258
+ end
259
+
260
+ response
261
+ end
262
+
263
+ def parse_error(http_response)
264
+ response = {}
265
+ response[:http_code] = http_response.code
266
+ response[:http_message] = http_response.message
267
+ response[:success] = false
268
+
269
+ document = REXML::Document.new(http_response.body)
270
+
271
+ node = REXML::XPath.first(document, "//soap:Fault")
272
+
273
+ node.elements.each do |element|
274
+ response[element.name] = element.text
275
+ end
276
+
277
+ response[:message] = response["faultstring"].to_s.gsub("\n", " ")
278
+ response
279
+ rescue REXML::ParseException
280
+ response[:http_body] = http_response.body
281
+ response[:message] = "Failed to parse the failed response"
282
+ response
283
+ end
284
+
285
+ def soap_action(action, v4 = false)
286
+ v4 ? "#{TX_NAMESPACE_V4}#{ACTIONS[action]}" : "#{TX_NAMESPACE}/#{ACTIONS[action]}"
287
+ end
288
+
289
+ def url(v4 = false)
290
+ v4 ? v4_live_url : live_url
291
+ end
292
+
293
+ def commit(action, request, v4 = false)
294
+ begin
295
+ data = ssl_post(url(v4), request,
296
+ "Content-Type" => 'text/xml; charset=utf-8',
297
+ "SOAPAction" => soap_action(action, v4)
298
+ )
299
+ response = parse(action, data)
300
+ rescue ActiveMerchant::ResponseError => e
301
+ response = parse_error(e.response)
302
+ end
303
+
304
+ Response.new(response[:success], response[:message], response,
305
+ :test => test?,
306
+ :authorization => authorization_from(response),
307
+ :avs_result => { :code => response["AVSResponse"] },
308
+ :cvv_result => response["CVResponse"]
309
+ )
310
+ end
311
+
312
+ def authorization_from(response)
313
+ if response[:success]
314
+ [ response["ReferenceID"], response["OrderNumber"] ].join(";")
315
+ end
316
+ end
317
+ end
318
+ end
319
+ end