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,179 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class QvalentGateway < Gateway
4
+ self.display_name = "Qvalent"
5
+ self.homepage_url = "https://www.qvalent.com/"
6
+
7
+ self.test_url = "https://ccapi.client.support.qvalent.com/post/CreditCardAPIReceiver"
8
+ self.live_url = "https://ccapi.client.qvalent.com/post/CreditCardAPIReceiver"
9
+
10
+ self.supported_countries = ["AU"]
11
+ self.default_currency = "AUD"
12
+ self.money_format = :cents
13
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners]
14
+
15
+ def initialize(options={})
16
+ requires!(options, :username, :password, :merchant)
17
+ super
18
+ end
19
+
20
+ def purchase(amount, payment_method, options={})
21
+ post = {}
22
+ add_invoice(post, amount, options)
23
+ add_order_number(post, options)
24
+ add_payment_method(post, payment_method)
25
+ add_verification_value(post, payment_method)
26
+ add_customer_data(post, options)
27
+
28
+ commit("capture", post)
29
+ end
30
+
31
+ def refund(amount, authorization, options={})
32
+ post = {}
33
+ add_invoice(post, amount, options)
34
+ add_reference(post, authorization, options)
35
+ add_customer_data(post, options)
36
+
37
+ commit("refund", post)
38
+ end
39
+
40
+ def store(payment_method, options = {})
41
+ post = {}
42
+ add_payment_method(post, payment_method)
43
+ add_card_reference(post)
44
+
45
+ commit("registerAccount", post)
46
+ end
47
+
48
+ def supports_scrubbing?
49
+ true
50
+ end
51
+
52
+ def scrub(transcript)
53
+ transcript.
54
+ gsub(%r((&?customer.password=)[^&]*), '\1[FILTERED]').
55
+ gsub(%r((&?card.PAN=)[^&]*), '\1[FILTERED]').
56
+ gsub(%r((&?card.CVN=)[^&]*), '\1[FILTERED]')
57
+ end
58
+
59
+ private
60
+
61
+ CURRENCY_CODES = Hash.new{|h,k| raise ArgumentError.new("Unsupported currency: #{k}")}
62
+ CURRENCY_CODES["AUD"] = "AUD"
63
+ CURRENCY_CODES["INR"] = "INR"
64
+
65
+ def add_invoice(post, money, options)
66
+ post["order.amount"] = amount(money)
67
+ post["card.currency"] = CURRENCY_CODES[options[:currency] || currency(money)]
68
+ post["order.ECI"] = "SSL"
69
+ end
70
+
71
+ def add_payment_method(post, payment_method)
72
+ post["card.cardHolderName"] = payment_method.name
73
+ post["card.PAN"] = payment_method.number
74
+ post["card.expiryYear"] = format(payment_method.year, :two_digits)
75
+ post["card.expiryMonth"] = format(payment_method.month, :two_digits)
76
+ end
77
+
78
+ def add_verification_value(post, payment_method)
79
+ post["card.CVN"] = payment_method.verification_value
80
+ end
81
+
82
+ def add_card_reference(post)
83
+ post["customer.customerReferenceNumber"] = options[:order_id]
84
+ end
85
+
86
+ def add_reference(post, authorization, options)
87
+ post["customer.originalOrderNumber"] = authorization
88
+ add_order_number(post, options)
89
+ end
90
+
91
+ def add_order_number(post, options)
92
+ post["customer.orderNumber"] = options[:order_id] || SecureRandom.uuid
93
+ end
94
+
95
+ def add_customer_data(post, options)
96
+ post["order.ipAddress"] = options[:ip]
97
+ end
98
+
99
+ def commit(action, post)
100
+ post["customer.username"] = @options[:username]
101
+ post["customer.password"] = @options[:password]
102
+ post["customer.merchant"] = @options[:merchant]
103
+ post["order.type"] = action
104
+
105
+ data = build_request(post)
106
+ raw = parse(ssl_post(url(action), data, headers))
107
+
108
+ succeeded = success_from(raw["response.responseCode"])
109
+ Response.new(
110
+ succeeded,
111
+ message_from(succeeded, raw),
112
+ raw,
113
+ authorization: raw["response.orderNumber"] || raw["response.customerReferenceNumber"],
114
+ error_code: error_code_from(succeeded, raw),
115
+ test: test?
116
+ )
117
+ end
118
+
119
+ def headers
120
+ {
121
+ "Content-Type" => "application/x-www-form-urlencoded"
122
+ }
123
+ end
124
+
125
+ def build_request(post)
126
+ post.to_query + "&message.end"
127
+ end
128
+
129
+ def url(action)
130
+ (test? ? test_url : live_url)
131
+ end
132
+
133
+ def parse(body)
134
+ result = {}
135
+ body.to_s.each_line do |pair|
136
+ result[$1] = $2 if pair.strip =~ /\A([^=]+)=(.+)\Z/im
137
+ end
138
+ result
139
+ end
140
+
141
+ def parse_element(response, node)
142
+ if node.has_elements?
143
+ node.elements.each{|element| parse_element(response, element) }
144
+ else
145
+ response[node.name.underscore.to_sym] = node.text
146
+ end
147
+ end
148
+
149
+ SUCCESS_CODES = %w(00 08 10 11 16 QS QZ)
150
+
151
+ def success_from(response)
152
+ SUCCESS_CODES.include?(response)
153
+ end
154
+
155
+ def message_from(succeeded, response)
156
+ if succeeded
157
+ "Succeeded"
158
+ else
159
+ response["response.text"] || "Unable to read error message"
160
+ end
161
+ end
162
+
163
+ STANDARD_ERROR_CODE_MAPPING = {
164
+ "14" => STANDARD_ERROR_CODE[:invalid_number],
165
+ "QQ" => STANDARD_ERROR_CODE[:invalid_cvc],
166
+ "33" => STANDARD_ERROR_CODE[:expired_card],
167
+ "NT" => STANDARD_ERROR_CODE[:incorrect_address],
168
+ "12" => STANDARD_ERROR_CODE[:card_declined],
169
+ "06" => STANDARD_ERROR_CODE[:processing_error],
170
+ "01" => STANDARD_ERROR_CODE[:call_issuer],
171
+ "04" => STANDARD_ERROR_CODE[:pickup_card],
172
+ }
173
+
174
+ def error_code_from(succeeded, response)
175
+ succeeded ? nil : STANDARD_ERROR_CODE_MAPPING[response["response.responseCode"]]
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,298 @@
1
+ require 'nokogiri'
2
+ require 'digest/sha1'
3
+
4
+ module ActiveMerchant
5
+ module Billing
6
+ # Realex is the leading CC gateway in Ireland
7
+ # see http://www.realexpayments.com
8
+ # Contributed by John Ward (john@ward.name)
9
+ # see http://thinedgeofthewedge.blogspot.com
10
+ #
11
+ # Realex works using the following
12
+ # login - The unique id of the merchant
13
+ # password - The secret is used to digitally sign the request
14
+ # account - This is an optional third part of the authentication process
15
+ # and is used if the merchant wishes do distinguish cc traffic from the different sources
16
+ # by using a different account. This must be created in advance
17
+ #
18
+ # the Realex team decided to make the orderid unique per request,
19
+ # so if validation fails you can not correct and resend using the
20
+ # same order id
21
+ class RealexGateway < Gateway
22
+ self.live_url = self.test_url = 'https://epage.payandshop.com/epage-remote.cgi'
23
+
24
+ CARD_MAPPING = {
25
+ 'master' => 'MC',
26
+ 'visa' => 'VISA',
27
+ 'american_express' => 'AMEX',
28
+ 'diners_club' => 'DINERS',
29
+ 'switch' => 'SWITCH',
30
+ 'solo' => 'SWITCH',
31
+ 'laser' => 'LASER',
32
+ 'maestro' => 'MC'
33
+ }
34
+
35
+ self.money_format = :cents
36
+ self.default_currency = 'EUR'
37
+ self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :switch, :solo, :laser ]
38
+ self.supported_countries = %w(IE GB FR BE NL LU IT)
39
+ self.homepage_url = 'http://www.realexpayments.com/'
40
+ self.display_name = 'Realex'
41
+
42
+ SUCCESS, DECLINED = "Successful", "Declined"
43
+ BANK_ERROR = REALEX_ERROR = "Gateway is in maintenance. Please try again later."
44
+ ERROR = CLIENT_DEACTIVATED = "Gateway Error"
45
+
46
+ def initialize(options = {})
47
+ requires!(options, :login, :password)
48
+ options[:refund_hash] = Digest::SHA1.hexdigest(options[:rebate_secret]) if options.has_key?(:rebate_secret)
49
+ super
50
+ end
51
+
52
+ def purchase(money, credit_card, options = {})
53
+ requires!(options, :order_id)
54
+
55
+ request = build_purchase_or_authorization_request(:purchase, money, credit_card, options)
56
+ commit(request)
57
+ end
58
+
59
+ def authorize(money, creditcard, options = {})
60
+ requires!(options, :order_id)
61
+
62
+ request = build_purchase_or_authorization_request(:authorization, money, creditcard, options)
63
+ commit(request)
64
+ end
65
+
66
+ def capture(money, authorization, options = {})
67
+ request = build_capture_request(authorization, options)
68
+ commit(request)
69
+ end
70
+
71
+ def refund(money, authorization, options = {})
72
+ request = build_refund_request(money, authorization, options)
73
+ commit(request)
74
+ end
75
+
76
+ def credit(money, authorization, options = {})
77
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
78
+ refund(money, authorization, options)
79
+ end
80
+
81
+ def void(authorization, options = {})
82
+ request = build_void_request(authorization, options)
83
+ commit(request)
84
+ end
85
+
86
+ private
87
+ def commit(request)
88
+ response = parse(ssl_post(self.live_url, request))
89
+
90
+ Response.new(
91
+ (response[:result] == "00"),
92
+ message_from(response),
93
+ response,
94
+ :test => (response[:message] =~ %r{\[ test system \]}),
95
+ :authorization => authorization_from(response),
96
+ :cvv_result => response[:cvnresult],
97
+ :avs_result => {
98
+ :street_match => response[:avspostcoderesponse],
99
+ :postal_match => response[:avspostcoderesponse]
100
+ }
101
+ )
102
+ end
103
+
104
+ def parse(xml)
105
+ response = {}
106
+
107
+ doc = Nokogiri::XML(xml)
108
+ doc.xpath('//response/*').each do |node|
109
+ if (node.elements.size == 0)
110
+ response[node.name.downcase.to_sym] = normalize(node.text)
111
+ else
112
+ node.elements.each do |childnode|
113
+ name = "#{node.name.downcase}_#{childnode.name.downcase}"
114
+ response[name.to_sym] = normalize(childnode.text)
115
+ end
116
+ end
117
+ end unless doc.root.nil?
118
+
119
+ response
120
+ end
121
+
122
+ def authorization_from(parsed)
123
+ [parsed[:orderid], parsed[:pasref], parsed[:authcode]].join(';')
124
+ end
125
+
126
+ def build_purchase_or_authorization_request(action, money, credit_card, options)
127
+ timestamp = new_timestamp
128
+ xml = Builder::XmlMarkup.new :indent => 2
129
+ xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'auth' do
130
+ add_merchant_details(xml, options)
131
+ xml.tag! 'orderid', sanitize_order_id(options[:order_id])
132
+ add_amount(xml, money, options)
133
+ add_card(xml, credit_card)
134
+ xml.tag! 'autosettle', 'flag' => auto_settle_flag(action)
135
+ add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), amount(money), (options[:currency] || currency(money)), credit_card.number)
136
+ add_comments(xml, options)
137
+ add_address_and_customer_info(xml, options)
138
+ end
139
+ xml.target!
140
+ end
141
+
142
+ def build_capture_request(authorization, options)
143
+ timestamp = new_timestamp
144
+ xml = Builder::XmlMarkup.new :indent => 2
145
+ xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'settle' do
146
+ add_merchant_details(xml, options)
147
+ add_transaction_identifiers(xml, authorization, options)
148
+ add_comments(xml, options)
149
+ add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), nil, nil, nil)
150
+ end
151
+ xml.target!
152
+ end
153
+
154
+ def build_refund_request(money, authorization, options)
155
+ timestamp = new_timestamp
156
+ xml = Builder::XmlMarkup.new :indent => 2
157
+ xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'rebate' do
158
+ add_merchant_details(xml, options)
159
+ add_transaction_identifiers(xml, authorization, options)
160
+ xml.tag! 'amount', amount(money), 'currency' => options[:currency] || currency(money)
161
+ xml.tag! 'refundhash', @options[:refund_hash] if @options[:refund_hash]
162
+ xml.tag! 'autosettle', 'flag' => 1
163
+ add_comments(xml, options)
164
+ add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), amount(money), (options[:currency] || currency(money)), nil)
165
+ end
166
+ xml.target!
167
+ end
168
+
169
+ def build_void_request(authorization, options)
170
+ timestamp = new_timestamp
171
+ xml = Builder::XmlMarkup.new :indent => 2
172
+ xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'void' do
173
+ add_merchant_details(xml, options)
174
+ add_transaction_identifiers(xml, authorization, options)
175
+ add_comments(xml, options)
176
+ add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), nil, nil, nil)
177
+ end
178
+ xml.target!
179
+ end
180
+
181
+ def add_address_and_customer_info(xml, options)
182
+ billing_address = options[:billing_address] || options[:address]
183
+ shipping_address = options[:shipping_address]
184
+
185
+ return unless billing_address || shipping_address || options[:customer] || options[:invoice] || options[:ip]
186
+
187
+ xml.tag! 'tssinfo' do
188
+ xml.tag! 'custnum', options[:customer] if options[:customer]
189
+ xml.tag! 'prodid', options[:invoice] if options[:invoice]
190
+ xml.tag! 'custipaddress', options[:ip] if options[:ip]
191
+
192
+ if billing_address
193
+ xml.tag! 'address', 'type' => 'billing' do
194
+ xml.tag! 'code', format_address_code(billing_address)
195
+ xml.tag! 'country', billing_address[:country]
196
+ end
197
+ end
198
+
199
+ if shipping_address
200
+ xml.tag! 'address', 'type' => 'shipping' do
201
+ xml.tag! 'code', format_address_code(shipping_address)
202
+ xml.tag! 'country', shipping_address[:country]
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ def add_merchant_details(xml, options)
209
+ xml.tag! 'merchantid', @options[:login]
210
+ if options[:account] || @options[:account]
211
+ xml.tag! 'account', (options[:account] || @options[:account])
212
+ end
213
+ end
214
+
215
+ def add_transaction_identifiers(xml, authorization, options)
216
+ options[:order_id], pasref, authcode = authorization.split(';')
217
+ xml.tag! 'orderid', sanitize_order_id(options[:order_id])
218
+ xml.tag! 'pasref', pasref
219
+ xml.tag! 'authcode', authcode
220
+ end
221
+
222
+ def add_comments(xml, options)
223
+ return unless options[:description]
224
+ xml.tag! 'comments' do
225
+ xml.tag! 'comment', options[:description], 'id' => 1
226
+ end
227
+ end
228
+
229
+ def add_amount(xml, money, options)
230
+ xml.tag! 'amount', amount(money), 'currency' => options[:currency] || currency(money)
231
+ end
232
+
233
+ def add_card(xml, credit_card)
234
+ xml.tag! 'card' do
235
+ xml.tag! 'number', credit_card.number
236
+ xml.tag! 'expdate', expiry_date(credit_card)
237
+ xml.tag! 'chname', credit_card.name
238
+ xml.tag! 'type', CARD_MAPPING[card_brand(credit_card).to_s]
239
+ xml.tag! 'issueno', credit_card.issue_number
240
+ xml.tag! 'cvn' do
241
+ xml.tag! 'number', credit_card.verification_value
242
+ xml.tag! 'presind', (options['presind'] || (credit_card.verification_value? ? 1 : nil))
243
+ end
244
+ end
245
+ end
246
+
247
+ def format_address_code(address)
248
+ code = [address[:zip].to_s, address[:address1].to_s + address[:address2].to_s]
249
+ code.collect{|e| e.gsub(/\D/, "")}.reject{|e| e.empty?}.join("|")
250
+ end
251
+
252
+ def new_timestamp
253
+ Time.now.strftime('%Y%m%d%H%M%S')
254
+ end
255
+
256
+ def add_signed_digest(xml, *values)
257
+ string = Digest::SHA1.hexdigest(values.join("."))
258
+ xml.tag! 'sha1hash', Digest::SHA1.hexdigest([string, @options[:password]].join("."))
259
+ end
260
+
261
+ def auto_settle_flag(action)
262
+ action == :authorization ? '0' : '1'
263
+ end
264
+
265
+ def expiry_date(credit_card)
266
+ "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
267
+ end
268
+
269
+ def message_from(response)
270
+ message = nil
271
+ case response[:result]
272
+ when "00"
273
+ message = SUCCESS
274
+ when "101"
275
+ message = response[:message]
276
+ when "102", "103"
277
+ message = DECLINED
278
+ when /^2[0-9][0-9]/
279
+ message = BANK_ERROR
280
+ when /^3[0-9][0-9]/
281
+ message = REALEX_ERROR
282
+ when /^5[0-9][0-9]/
283
+ message = response[:message]
284
+ when "600", "601", "603"
285
+ message = ERROR
286
+ when "666"
287
+ message = CLIENT_DEACTIVATED
288
+ else
289
+ message = DECLINED
290
+ end
291
+ end
292
+
293
+ def sanitize_order_id(order_id)
294
+ order_id.to_s.gsub(/[^a-zA-Z0-9\-_]/, '')
295
+ end
296
+ end
297
+ end
298
+ end