aktivemerchant 2.0.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 (193) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1596 -0
  3. data/CONTRIBUTORS +511 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +18 -0
  6. data/lib/active_merchant.rb +108 -0
  7. data/lib/active_merchant/billing.rb +13 -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 +352 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +160 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +268 -0
  18. data/lib/active_merchant/billing/gateways.rb +17 -0
  19. data/lib/active_merchant/billing/gateways/adyen.rb +209 -0
  20. data/lib/active_merchant/billing/gateways/alfabank.rb +117 -0
  21. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net.rb +419 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  24. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -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 +188 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +393 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -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 +210 -0
  37. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  38. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  39. data/lib/active_merchant/billing/gateways/braintree_blue.rb +515 -0
  40. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  41. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  42. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  43. data/lib/active_merchant/billing/gateways/card_stream.rb +220 -0
  44. data/lib/active_merchant/billing/gateways/cashnet.rb +191 -0
  45. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  46. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  47. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  48. data/lib/active_merchant/billing/gateways/checkout.rb +213 -0
  49. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  50. data/lib/active_merchant/billing/gateways/conekta.rb +209 -0
  51. data/lib/active_merchant/billing/gateways/cyber_source.rb +709 -0
  52. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  53. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  54. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  55. data/lib/active_merchant/billing/gateways/epay.rb +275 -0
  56. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  57. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  58. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  59. data/lib/active_merchant/billing/gateways/eway_rapid.rb +524 -0
  60. data/lib/active_merchant/billing/gateways/exact.rb +218 -0
  61. data/lib/active_merchant/billing/gateways/fat_zebra.rb +173 -0
  62. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  63. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  64. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  65. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  66. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +355 -0
  67. data/lib/active_merchant/billing/gateways/garanti.rb +257 -0
  68. data/lib/active_merchant/billing/gateways/global_transport.rb +183 -0
  69. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  70. data/lib/active_merchant/billing/gateways/hps.rb +288 -0
  71. data/lib/active_merchant/billing/gateways/iats_payments.rb +251 -0
  72. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  73. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  74. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  75. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  76. data/lib/active_merchant/billing/gateways/inspire.rb +213 -0
  77. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  78. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  79. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  80. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  81. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  82. data/lib/active_merchant/billing/gateways/litle.rb +346 -0
  83. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  84. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  85. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  86. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  87. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  88. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  89. data/lib/active_merchant/billing/gateways/mercury.rb +333 -0
  90. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  91. data/lib/active_merchant/billing/gateways/migs.rb +265 -0
  92. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  93. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  94. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  95. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  96. data/lib/active_merchant/billing/gateways/moneris_us.rb +291 -0
  97. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  98. data/lib/active_merchant/billing/gateways/nab_transact.rb +280 -0
  99. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  100. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  101. data/lib/active_merchant/billing/gateways/netbilling.rb +190 -0
  102. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  103. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  104. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  105. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  106. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  107. data/lib/active_merchant/billing/gateways/optimal_payment.rb +313 -0
  108. data/lib/active_merchant/billing/gateways/orbital.rb +803 -0
  109. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  110. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  111. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  112. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +261 -0
  113. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  114. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  115. data/lib/active_merchant/billing/gateways/pay_u_latam.rb +462 -0
  116. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  117. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  118. data/lib/active_merchant/billing/gateways/payflow.rb +304 -0
  119. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +209 -0
  120. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  121. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  122. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  123. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  124. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  125. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  126. data/lib/active_merchant/billing/gateways/paymill.rb +281 -0
  127. data/lib/active_merchant/billing/gateways/paypal.rb +117 -0
  128. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +670 -0
  129. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  130. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  131. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  132. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  133. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  134. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  135. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  136. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  137. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  138. data/lib/active_merchant/billing/gateways/pin.rb +197 -0
  139. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  140. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  141. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  142. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  143. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  144. data/lib/active_merchant/billing/gateways/quickpay.rb +367 -0
  145. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  146. data/lib/active_merchant/billing/gateways/redsys.rb +391 -0
  147. data/lib/active_merchant/billing/gateways/sage.rb +175 -0
  148. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +87 -0
  149. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +114 -0
  150. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  151. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +102 -0
  152. data/lib/active_merchant/billing/gateways/sage_pay.rb +398 -0
  153. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  154. data/lib/active_merchant/billing/gateways/secure_net.rb +252 -0
  155. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  156. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  157. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  158. data/lib/active_merchant/billing/gateways/skip_jack.rb +452 -0
  159. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  160. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  161. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  162. data/lib/active_merchant/billing/gateways/stripe.rb +411 -0
  163. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  164. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  165. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  166. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  167. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  168. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  169. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  170. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  171. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +254 -0
  172. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  173. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  174. data/lib/active_merchant/billing/gateways/vindicia.rb +385 -0
  175. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  176. data/lib/active_merchant/billing/gateways/wepay.rb +189 -0
  177. data/lib/active_merchant/billing/gateways/wirecard.rb +421 -0
  178. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  179. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  180. data/lib/active_merchant/billing/model.rb +30 -0
  181. data/lib/active_merchant/billing/payment_token.rb +21 -0
  182. data/lib/active_merchant/billing/rails.rb +3 -0
  183. data/lib/active_merchant/billing/response.rb +91 -0
  184. data/lib/active_merchant/country.rb +332 -0
  185. data/lib/active_merchant/empty.rb +20 -0
  186. data/lib/active_merchant/errors.rb +29 -0
  187. data/lib/active_merchant/offsite_payments_shim.rb +19 -0
  188. data/lib/active_merchant/version.rb +3 -0
  189. data/lib/activemerchant.rb +1 -0
  190. data/lib/support/gateway_support.rb +71 -0
  191. data/lib/support/outbound_hosts.rb +25 -0
  192. data/lib/support/ssl_verify.rb +93 -0
  193. metadata +400 -0
@@ -0,0 +1,367 @@
1
+ require 'rexml/document'
2
+ require 'digest/md5'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ class QuickpayGateway < Gateway
7
+ self.live_url = self.test_url = 'https://secure.quickpay.dk/api'
8
+
9
+ self.default_currency = 'DKK'
10
+ self.money_format = :cents
11
+ self.supported_cardtypes = [:dankort, :forbrugsforeningen, :visa, :master, :american_express, :diners_club, :jcb, :maestro]
12
+ self.supported_countries = ['DE', 'DK', 'ES', 'FI', 'FR', 'FO', 'GB', 'IS', 'NO', 'SE']
13
+ self.homepage_url = 'http://quickpay.net/'
14
+ self.display_name = 'QuickPay'
15
+
16
+ MD5_CHECK_FIELDS = {
17
+ 3 => {
18
+ :authorize => %w(protocol msgtype merchant ordernumber amount
19
+ currency autocapture cardnumber expirationdate
20
+ cvd cardtypelock testmode),
21
+
22
+ :capture => %w(protocol msgtype merchant amount transaction),
23
+
24
+ :cancel => %w(protocol msgtype merchant transaction),
25
+
26
+ :refund => %w(protocol msgtype merchant amount transaction),
27
+
28
+ :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
29
+ expirationdate cvd cardtypelock description testmode),
30
+
31
+ :recurring => %w(protocol msgtype merchant ordernumber amount
32
+ currency autocapture transaction),
33
+
34
+ :status => %w(protocol msgtype merchant transaction),
35
+
36
+ :chstatus => %w(protocol msgtype merchant)
37
+ },
38
+
39
+ 4 => {
40
+ :authorize => %w(protocol msgtype merchant ordernumber amount
41
+ currency autocapture cardnumber expirationdate cvd
42
+ cardtypelock testmode fraud_remote_addr
43
+ fraud_http_accept fraud_http_accept_language
44
+ fraud_http_accept_encoding fraud_http_accept_charset
45
+ fraud_http_referer fraud_http_user_agent apikey),
46
+
47
+ :capture => %w(protocol msgtype merchant amount transaction apikey),
48
+
49
+ :cancel => %w(protocol msgtype merchant transaction apikey),
50
+
51
+ :refund => %w(protocol msgtype merchant amount transaction apikey),
52
+
53
+ :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
54
+ expirationdate cvd cardtypelock description testmode
55
+ fraud_remote_addr fraud_http_accept fraud_http_accept_language
56
+ fraud_http_accept_encoding fraud_http_accept_charset
57
+ fraud_http_referer fraud_http_user_agent apikey),
58
+
59
+ :recurring => %w(protocol msgtype merchant ordernumber amount currency
60
+ autocapture transaction apikey),
61
+
62
+ :status => %w(protocol msgtype merchant transaction apikey),
63
+
64
+ :chstatus => %w(protocol msgtype merchant apikey)
65
+ },
66
+
67
+ 5 => {
68
+ :authorize => %w(protocol msgtype merchant ordernumber amount
69
+ currency autocapture cardnumber expirationdate cvd
70
+ cardtypelock testmode fraud_remote_addr
71
+ fraud_http_accept fraud_http_accept_language
72
+ fraud_http_accept_encoding fraud_http_accept_charset
73
+ fraud_http_referer fraud_http_user_agent apikey),
74
+
75
+ :capture => %w(protocol msgtype merchant amount transaction apikey),
76
+
77
+ :cancel => %w(protocol msgtype merchant transaction apikey),
78
+
79
+ :refund => %w(protocol msgtype merchant amount transaction apikey),
80
+
81
+ :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
82
+ expirationdate cvd cardtypelock description testmode
83
+ fraud_remote_addr fraud_http_accept fraud_http_accept_language
84
+ fraud_http_accept_encoding fraud_http_accept_charset
85
+ fraud_http_referer fraud_http_user_agent apikey),
86
+
87
+ :recurring => %w(protocol msgtype merchant ordernumber amount currency
88
+ autocapture transaction apikey),
89
+
90
+ :status => %w(protocol msgtype merchant transaction apikey),
91
+
92
+ :chstatus => %w(protocol msgtype merchant apikey)
93
+ },
94
+
95
+ 6 => {
96
+ :authorize => %w(protocol msgtype merchant ordernumber amount
97
+ currency autocapture cardnumber expirationdate cvd
98
+ cardtypelock testmode fraud_remote_addr
99
+ fraud_http_accept fraud_http_accept_language
100
+ fraud_http_accept_encoding fraud_http_accept_charset
101
+ fraud_http_referer fraud_http_user_agent apikey),
102
+
103
+ :capture => %w(protocol msgtype merchant amount transaction
104
+ apikey),
105
+
106
+ :cancel => %w(protocol msgtype merchant transaction apikey),
107
+
108
+ :refund => %w(protocol msgtype merchant amount transaction apikey),
109
+
110
+ :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
111
+ expirationdate cvd cardtypelock description testmode
112
+ fraud_remote_addr fraud_http_accept fraud_http_accept_language
113
+ fraud_http_accept_encoding fraud_http_accept_charset
114
+ fraud_http_referer fraud_http_user_agent apikey),
115
+
116
+ :recurring => %w(protocol msgtype merchant ordernumber amount currency
117
+ autocapture transaction apikey),
118
+
119
+ :status => %w(protocol msgtype merchant transaction apikey),
120
+
121
+ :chstatus => %w(protocol msgtype merchant apikey)
122
+ },
123
+
124
+ 7 => {
125
+ :authorize => %w(protocol msgtype merchant ordernumber amount
126
+ currency autocapture cardnumber expirationdate cvd
127
+ acquirers cardtypelock testmode fraud_remote_addr
128
+ fraud_http_accept fraud_http_accept_language
129
+ fraud_http_accept_encoding fraud_http_accept_charset
130
+ fraud_http_referer fraud_http_user_agent apikey),
131
+
132
+ :capture => %w(protocol msgtype merchant amount transaction
133
+ apikey),
134
+
135
+ :cancel => %w(protocol msgtype merchant transaction apikey),
136
+
137
+ :refund => %w(protocol msgtype merchant amount transaction apikey),
138
+
139
+ :subscribe => %w(protocol msgtype merchant ordernumber amount currency
140
+ cardnumber expirationdate cvd acquirers cardtypelock
141
+ description testmode fraud_remote_addr fraud_http_accept
142
+ fraud_http_accept_language fraud_http_accept_encoding
143
+ fraud_http_accept_charset fraud_http_referer
144
+ fraud_http_user_agent apikey),
145
+
146
+ :recurring => %w(protocol msgtype merchant ordernumber amount currency
147
+ autocapture transaction apikey),
148
+
149
+ :status => %w(protocol msgtype merchant transaction apikey),
150
+
151
+ :chstatus => %w(protocol msgtype merchant apikey)
152
+ }
153
+ }
154
+
155
+ APPROVED = '000'
156
+
157
+ # The login is the QuickpayId
158
+ # The password is the md5checkword from the Quickpay manager
159
+ # To use the API-key from the Quickpay manager, specify :api-key
160
+ # Using the API-key, requires that you use version 4+. Specify :version => 4/5/6/7 in options.
161
+ def initialize(options = {})
162
+ requires!(options, :login, :password)
163
+ @protocol = options.delete(:version) || 7 # default to protocol version 7
164
+ super
165
+ end
166
+
167
+ def authorize(money, credit_card_or_reference, options = {})
168
+ post = {}
169
+
170
+ action = recurring_or_authorize(credit_card_or_reference)
171
+
172
+ add_amount(post, money, options)
173
+ add_invoice(post, options)
174
+ add_creditcard_or_reference(post, credit_card_or_reference, options)
175
+ add_autocapture(post, false)
176
+ add_fraud_parameters(post, options) if action.eql?(:authorize)
177
+ add_testmode(post)
178
+
179
+ commit(action, post)
180
+ end
181
+
182
+ def purchase(money, credit_card_or_reference, options = {})
183
+ post = {}
184
+
185
+ action = recurring_or_authorize(credit_card_or_reference)
186
+
187
+ add_amount(post, money, options)
188
+ add_creditcard_or_reference(post, credit_card_or_reference, options)
189
+ add_invoice(post, options)
190
+ add_fraud_parameters(post, options) if action.eql?(:authorize)
191
+ add_autocapture(post, true)
192
+
193
+ commit(action, post)
194
+ end
195
+
196
+ def capture(money, authorization, options = {})
197
+ post = {}
198
+
199
+ add_reference(post, authorization)
200
+ add_amount_without_currency(post, money)
201
+ commit(:capture, post)
202
+ end
203
+
204
+ def void(identification, options = {})
205
+ post = {}
206
+
207
+ add_reference(post, identification)
208
+
209
+ commit(:cancel, post)
210
+ end
211
+
212
+ def refund(money, identification, options = {})
213
+ post = {}
214
+
215
+ add_amount_without_currency(post, money)
216
+ add_reference(post, identification)
217
+
218
+ commit(:refund, post)
219
+ end
220
+
221
+ def credit(money, identification, options = {})
222
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
223
+ refund(money, identification, options)
224
+ end
225
+
226
+ def store(creditcard, options = {})
227
+ post = {}
228
+
229
+ add_creditcard(post, creditcard, options)
230
+ add_amount(post, 0, options) if @protocol >= 7
231
+ add_invoice(post, options)
232
+ add_description(post, options)
233
+ add_fraud_parameters(post, options)
234
+ add_testmode(post)
235
+
236
+ commit(:subscribe, post)
237
+ end
238
+
239
+ private
240
+
241
+ def add_amount(post, money, options = {})
242
+ post[:amount] = amount(money)
243
+ post[:currency] = options[:currency] || currency(money)
244
+ end
245
+
246
+ def add_amount_without_currency(post, money, options = {})
247
+ post[:amount] = amount(money)
248
+ end
249
+
250
+ def add_invoice(post, options)
251
+ post[:ordernumber] = format_order_number(options[:order_id])
252
+ end
253
+
254
+ def add_creditcard(post, credit_card, options)
255
+ post[:cardnumber] = credit_card.number
256
+ post[:cvd] = credit_card.verification_value
257
+ post[:expirationdate] = expdate(credit_card)
258
+ post[:cardtypelock] = options[:cardtypelock] unless options[:cardtypelock].blank?
259
+ post[:acquirers] = options[:acquirers] unless options[:acquirers].blank?
260
+ end
261
+
262
+ def add_reference(post, identification)
263
+ post[:transaction] = identification
264
+ end
265
+
266
+ def add_creditcard_or_reference(post, credit_card_or_reference, options)
267
+ if credit_card_or_reference.is_a?(String)
268
+ add_reference(post, credit_card_or_reference)
269
+ else
270
+ add_creditcard(post, credit_card_or_reference, options)
271
+ end
272
+ end
273
+
274
+ def add_autocapture(post, autocapture)
275
+ post[:autocapture] = autocapture ? 1 : 0
276
+ end
277
+
278
+ def recurring_or_authorize(credit_card_or_reference)
279
+ credit_card_or_reference.is_a?(String) ? :recurring : :authorize
280
+ end
281
+
282
+ def add_description(post, options)
283
+ post[:description] = options[:description]
284
+ end
285
+
286
+ def add_testmode(post)
287
+ return if post[:transaction].present?
288
+ post[:testmode] = test? ? '1' : '0'
289
+ end
290
+
291
+ def add_fraud_parameters(post, options)
292
+ if @protocol >= 4
293
+ post[:fraud_remote_addr] = options[:ip] if options[:ip]
294
+ post[:fraud_http_accept] = options[:fraud_http_accept] if options[:fraud_http_accept]
295
+ post[:fraud_http_accept_language] = options[:fraud_http_accept_language] if options[:fraud_http_accept_language]
296
+ post[:fraud_http_accept_encoding] = options[:fraud_http_accept_encoding] if options[:fraud_http_accept_encoding]
297
+ post[:fraud_http_accept_charset] = options[:fraud_http_accept_charset] if options[:fraud_http_accept_charset]
298
+ post[:fraud_http_referer] = options[:fraud_http_referer] if options[:fraud_http_referer]
299
+ post[:fraud_http_user_agent] = options[:fraud_http_user_agent] if options[:fraud_http_user_agent]
300
+ end
301
+ end
302
+
303
+ def commit(action, params)
304
+ response = parse(ssl_post(self.live_url, post_data(action, params)))
305
+
306
+ Response.new(successful?(response), message_from(response), response,
307
+ :test => test?,
308
+ :authorization => response[:transaction]
309
+ )
310
+ end
311
+
312
+ def successful?(response)
313
+ response[:qpstat] == APPROVED
314
+ end
315
+
316
+ def parse(data)
317
+ response = {}
318
+
319
+ doc = REXML::Document.new(data)
320
+
321
+ doc.root.elements.each do |element|
322
+ response[element.name.to_sym] = element.text
323
+ end
324
+
325
+ response
326
+ end
327
+
328
+ def message_from(response)
329
+ response[:qpstatmsg].to_s
330
+ end
331
+
332
+ def post_data(action, params = {})
333
+ params[:protocol] = @protocol
334
+ params[:msgtype] = action.to_s
335
+ params[:merchant] = @options[:login]
336
+ params[:apikey] = @options[:apikey] if @options[:apikey]
337
+ params[:md5check] = generate_check_hash(action, params)
338
+
339
+ params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
340
+ end
341
+
342
+ def generate_check_hash(action, params)
343
+ string = MD5_CHECK_FIELDS[@protocol][action].collect do |key|
344
+ params[key.to_sym]
345
+ end.join('')
346
+
347
+ # Add the md5checkword
348
+ string << @options[:password].to_s
349
+
350
+ Digest::MD5.hexdigest(string)
351
+ end
352
+
353
+ def expdate(credit_card)
354
+ year = format(credit_card.year, :two_digits)
355
+ month = format(credit_card.month, :two_digits)
356
+
357
+ "#{year}#{month}"
358
+ end
359
+
360
+ # Limited to 20 digits max
361
+ def format_order_number(number)
362
+ number.to_s.gsub(/[^\w]/, '').rjust(4, "0")[0...20]
363
+ end
364
+ end
365
+ end
366
+ end
367
+
@@ -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