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,188 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PayboxDirectGateway < Gateway
4
+ class_attribute :live_url_backup
5
+
6
+ self.test_url = 'https://preprod-ppps.paybox.com/PPPS.php'
7
+ self.live_url = 'https://ppps.paybox.com/PPPS.php'
8
+ self.live_url_backup = 'https://ppps1.paybox.com/PPPS.php'
9
+
10
+ # Payment API Version
11
+ API_VERSION = '00103'
12
+
13
+ # Transactions hash
14
+ TRANSACTIONS = {
15
+ :authorization => '00001',
16
+ :capture => '00002',
17
+ :purchase => '00003',
18
+ :unreferenced_credit => '00004',
19
+ :void => '00005',
20
+ :refund => '00014'
21
+ }
22
+
23
+ CURRENCY_CODES = {
24
+ "AUD"=> '036',
25
+ "CAD"=> '124',
26
+ "CZK"=> '203',
27
+ "DKK"=> '208',
28
+ "HKD"=> '344',
29
+ "ICK"=> '352',
30
+ "JPY"=> '392',
31
+ "NOK"=> '578',
32
+ "SGD"=> '702',
33
+ "SEK"=> '752',
34
+ "CHF"=> '756',
35
+ "GBP"=> '826',
36
+ "USD"=> '840',
37
+ "EUR"=> '978'
38
+ }
39
+
40
+ SUCCESS_CODES = ['00000']
41
+ UNAVAILABILITY_CODES = ['00001', '00097', '00098']
42
+ SUCCESS_MESSAGE = 'The transaction was approved'
43
+ FAILURE_MESSAGE = 'The transaction failed'
44
+
45
+ # Money is referenced in cents
46
+ self.money_format = :cents
47
+ self.default_currency = 'EUR'
48
+
49
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
50
+ self.supported_countries = ['FR']
51
+
52
+ # The card types supported by the payment gateway
53
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
54
+
55
+ # The homepage URL of the gateway
56
+ self.homepage_url = 'http://www.paybox.com/'
57
+
58
+ # The name of the gateway
59
+ self.display_name = 'Paybox Direct'
60
+
61
+ def initialize(options = {})
62
+ requires!(options, :login, :password)
63
+ super
64
+ end
65
+
66
+ def authorize(money, creditcard, options = {})
67
+ post = {}
68
+ add_invoice(post, options)
69
+ add_creditcard(post, creditcard)
70
+ commit('authorization', money, post)
71
+ end
72
+
73
+ def purchase(money, creditcard, options = {})
74
+ post = {}
75
+ add_invoice(post, options)
76
+ add_creditcard(post, creditcard)
77
+ commit('purchase', money, post)
78
+ end
79
+
80
+ def capture(money, authorization, options = {})
81
+ requires!(options, :order_id)
82
+ post = {}
83
+ add_invoice(post, options)
84
+ post[:numappel] = authorization[0,10]
85
+ post[:numtrans] = authorization[10,10]
86
+ commit('capture', money, post)
87
+ end
88
+
89
+ def void(identification, options = {})
90
+ requires!(options, :order_id, :amount)
91
+ post ={}
92
+ add_invoice(post, options)
93
+ add_reference(post, identification)
94
+ post[:porteur] = '000000000000000'
95
+ post[:dateval] = '0000'
96
+ commit('void', options[:amount], post)
97
+ end
98
+
99
+ def credit(money, identification, options = {})
100
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
101
+ refund(money, identification, options)
102
+ end
103
+
104
+ def refund(money, identification, options = {})
105
+ post = {}
106
+ add_invoice(post, options)
107
+ add_reference(post, identification)
108
+ commit('refund', money, post)
109
+ end
110
+
111
+ private
112
+
113
+ def add_invoice(post, options)
114
+ post[:reference] = options[:order_id]
115
+ end
116
+
117
+ def add_creditcard(post, creditcard)
118
+ post[:porteur] = creditcard.number
119
+ post[:dateval] = expdate(creditcard)
120
+ post[:cvv] = creditcard.verification_value if creditcard.verification_value?
121
+ end
122
+
123
+ def add_reference(post, identification)
124
+ post[:numappel] = identification[0,10]
125
+ post[:numtrans] = identification[10,10]
126
+ end
127
+
128
+ def parse(body)
129
+ results = {}
130
+ body.split(/&/).each do |pair|
131
+ key,val = pair.split(/\=/)
132
+ results[key.downcase.to_sym] = CGI.unescape(val) if val
133
+ end
134
+ results
135
+ end
136
+
137
+ def commit(action, money = nil, parameters = nil)
138
+ parameters[:montant] = ('0000000000' + (money ? amount(money) : ''))[-10..-1]
139
+ parameters[:devise] = CURRENCY_CODES[options[:currency] || currency(money)]
140
+ request_data = post_data(action,parameters)
141
+ response = parse(ssl_post(test? ? self.test_url : self.live_url, request_data))
142
+ response = parse(ssl_post(self.live_url_backup, request_data)) if service_unavailable?(response) && !test?
143
+ Response.new(success?(response), message_from(response), response.merge(
144
+ :timestamp => parameters[:dateq]),
145
+ :test => test?,
146
+ :authorization => response[:numappel].to_s + response[:numtrans].to_s,
147
+ :fraud_review => false,
148
+ :sent_params => parameters.delete_if{|key,value| ['porteur','dateval','cvv'].include?(key.to_s)}
149
+ )
150
+ end
151
+
152
+ def success?(response)
153
+ SUCCESS_CODES.include?(response[:codereponse])
154
+ end
155
+
156
+ def service_unavailable?(response)
157
+ UNAVAILABILITY_CODES.include?(response[:codereponse])
158
+ end
159
+
160
+ def message_from(response)
161
+ success?(response) ? SUCCESS_MESSAGE : (response[:commentaire] || FAILURE_MESSAGE)
162
+ end
163
+
164
+ def post_data(action, parameters = {})
165
+
166
+ parameters.update(
167
+ :version => API_VERSION,
168
+ :type => TRANSACTIONS[action.to_sym],
169
+ :dateq => Time.now.strftime('%d%m%Y%H%M%S'),
170
+ :numquestion => unique_id(parameters[:order_id]),
171
+ :site => @options[:login].to_s[0,7],
172
+ :rang => @options[:login].to_s[7..-1],
173
+ :cle => @options[:password],
174
+ :pays => '',
175
+ :archivage => parameters[:order_id]
176
+ )
177
+
178
+ parameters.collect { |key, value| "#{key.to_s.upcase}=#{CGI.escape(value.to_s)}" }.join("&")
179
+ end
180
+
181
+ def unique_id(seed = 0)
182
+ randkey = "#{seed}#{Time.now.usec}".to_i % 2147483647 # Max paybox value for the question number
183
+
184
+ "0000000000#{randkey}"[-10..-1]
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,412 @@
1
+ require "nokogiri"
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class PayexGateway < Gateway
6
+ class_attribute :live_external_url, :test_external_url, :live_confined_url, :test_confined_url
7
+
8
+ self.live_external_url = 'https://external.payex.com/'
9
+ self.test_external_url = 'https://test-external.payex.com/'
10
+
11
+ self.live_confined_url = 'https://confined.payex.com/'
12
+ self.test_confined_url = 'https://test-confined.payex.com/'
13
+
14
+ self.money_format = :cents
15
+ self.supported_countries = ['DK', 'FI', 'NO', 'SE']
16
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
17
+ self.homepage_url = 'http://payex.com/'
18
+ self.display_name = 'Payex'
19
+ self.default_currency = "EUR"
20
+
21
+ TRANSACTION_STATUS = {
22
+ sale: '0',
23
+ initialize: '1',
24
+ credit: '2',
25
+ authorize: '3',
26
+ cancel: '4',
27
+ failure: '5',
28
+ capture: '6',
29
+ }
30
+
31
+ SOAP_ACTIONS = {
32
+ initialize: { name: 'Initialize8', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
33
+ purchasecc: { name: 'PurchaseCC', url: 'pxconfined/pxorder.asmx', xmlns: 'http://confined.payex.com/PxOrder/', confined: true},
34
+ cancel: { name: 'Cancel2', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
35
+ capture: { name: 'Capture5', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
36
+ credit: { name: 'Credit5', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
37
+ create_agreement: { name: 'CreateAgreement3', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
38
+ delete_agreement: { name: 'DeleteAgreement', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
39
+ autopay: { name: 'AutoPay3', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
40
+ }
41
+
42
+ def initialize(options = {})
43
+ requires!(options, :account, :encryption_key)
44
+ super
45
+ end
46
+
47
+ # Public: Send an authorize Payex request
48
+ #
49
+ # amount - The monetary amount of the transaction in cents.
50
+ # payment_method - The Active Merchant payment method or the +store+ authorization for stored transactions.
51
+ # options - A standard ActiveMerchant options hash:
52
+ # :currency - Three letter currency code for the transaction (default: "EUR")
53
+ # :order_id - The unique order ID for this transaction (required).
54
+ # :product_number - The merchant product number (default: '1').
55
+ # :description - The merchant description for this product (default: The :order_id).
56
+ # :ip - The client IP address (default: '127.0.0.1').
57
+ # :vat - The vat amount (optional).
58
+ #
59
+ # Returns an ActiveMerchant::Billing::Response object
60
+ def authorize(amount, payment_method, options = {})
61
+ requires!(options, :order_id)
62
+ amount = amount(amount)
63
+ if payment_method.respond_to?(:number)
64
+ # credit card authorization
65
+ MultiResponse.new.tap do |r|
66
+ r.process {send_initialize(amount, true, options)}
67
+ r.process {send_purchasecc(payment_method, r.params['orderref'])}
68
+ end
69
+ else
70
+ # stored authorization
71
+ send_autopay(amount, payment_method, true, options)
72
+ end
73
+
74
+ end
75
+
76
+ # Public: Send a purchase Payex request
77
+ #
78
+ # amount - The monetary amount of the transaction in cents.
79
+ # payment_method - The Active Merchant payment method or the +store+ authorization for stored transactions.
80
+ # options - A standard ActiveMerchant options hash:
81
+ # :currency - Three letter currency code for the transaction (default: "EUR")
82
+ # :order_id - The unique order ID for this transaction (required).
83
+ # :product_number - The merchant product number (default: '1').
84
+ # :description - The merchant description for this product (default: The :order_id).
85
+ # :ip - The client IP address (default: '127.0.0.1').
86
+ # :vat - The vat amount (optional).
87
+ #
88
+ # Returns an ActiveMerchant::Billing::Response object
89
+ def purchase(amount, payment_method, options = {})
90
+ requires!(options, :order_id)
91
+ amount = amount(amount)
92
+ if payment_method.respond_to?(:number)
93
+ # credit card purchase
94
+ MultiResponse.new.tap do |r|
95
+ r.process {send_initialize(amount, false, options)}
96
+ r.process {send_purchasecc(payment_method, r.params['orderref'])}
97
+ end
98
+ else
99
+ # stored purchase
100
+ send_autopay(amount, payment_method, false, options)
101
+ end
102
+ end
103
+
104
+ # Public: Capture money from a previously authorized transaction
105
+ #
106
+ # money - The amount to capture
107
+ # authorization - The authorization token from the authorization request
108
+ #
109
+ # Returns an ActiveMerchant::Billing::Response object
110
+ def capture(money, authorization, options = {})
111
+ amount = amount(money)
112
+ send_capture(amount, authorization)
113
+ end
114
+
115
+ # Public: Voids an authorize transaction
116
+ #
117
+ # authorization - The authorization returned from the successful authorize transaction.
118
+ # options - A standard ActiveMerchant options hash
119
+ #
120
+ # Returns an ActiveMerchant::Billing::Response object
121
+ def void(authorization, options={})
122
+ send_cancel(authorization)
123
+ end
124
+
125
+ # Public: Refunds a purchase transaction
126
+ #
127
+ # money - The amount to refund
128
+ # authorization - The authorization token from the purchase request.
129
+ # options - A standard ActiveMerchant options hash:
130
+ # :order_id - The unique order ID for this transaction (required).
131
+ # :vat_amount - The vat amount (optional).
132
+ #
133
+ # Returns an ActiveMerchant::Billing::Response object
134
+ def refund(money, authorization, options = {})
135
+ requires!(options, :order_id)
136
+ amount = amount(money)
137
+ send_credit(authorization, amount, options)
138
+ end
139
+
140
+ # Public: Stores a credit card and creates a Payex agreement with a customer
141
+ #
142
+ # creditcard - The credit card to store.
143
+ # options - A standard ActiveMerchant options hash:
144
+ # :order_id - The unique order ID for this transaction (required).
145
+ # :merchant_ref - A reference that links this agreement to something the merchant takes money for (default: '1')
146
+ # :currency - Three letter currency code for the transaction (default: "EUR")
147
+ # :product_number - The merchant product number (default: '1').
148
+ # :description - The merchant description for this product (default: The :order_id).
149
+ # :ip - The client IP address (default: '127.0.0.1').
150
+ # :max_amount - The maximum amount to allow to be charged (default: 100000).
151
+ # :vat - The vat amount (optional).
152
+ #
153
+ # Returns an ActiveMerchant::Billing::Response object where the authorization is set to the agreement_ref which is used for stored payments.
154
+ def store(creditcard, options = {})
155
+ requires!(options, :order_id)
156
+ amount = amount(1) # 1 cent for authorization
157
+ MultiResponse.run(:first) do |r|
158
+ r.process {send_create_agreement(options)}
159
+ r.process {send_initialize(amount, true, options.merge({agreement_ref: r.authorization}))}
160
+ order_ref = r.params['orderref']
161
+ r.process {send_purchasecc(creditcard, order_ref)}
162
+ end
163
+ end
164
+
165
+ # Public: Unstores a customer's credit card and deletes their Payex agreement.
166
+ #
167
+ # authorization - The authorization token from the store request.
168
+ #
169
+ # Returns an ActiveMerchant::Billing::Response object
170
+ def unstore(authorization, options = {})
171
+ send_delete_agreement(authorization)
172
+ end
173
+
174
+ private
175
+
176
+ def send_initialize(amount, is_auth, options = {})
177
+ properties = {
178
+ accountNumber: @options[:account],
179
+ purchaseOperation: is_auth ? 'AUTHORIZATION' : 'SALE',
180
+ price: amount,
181
+ priceArgList: nil,
182
+ currency: (options[:currency] || default_currency),
183
+ vat: options[:vat] || 0,
184
+ orderID: options[:order_id],
185
+ productNumber: options[:product_number] || '1',
186
+ description: options[:description] || options[:order_id],
187
+ clientIPAddress: options[:client_ip_address] || '127.0.0.1',
188
+ clientIdentifier: nil,
189
+ additionalValues: nil,
190
+ externalID: nil,
191
+ returnUrl: 'http://example.net', # set to dummy value since this is not used but is required
192
+ view: 'CREDITCARD',
193
+ agreementRef: options[:agreement_ref], # this is used to attach a stored agreement to a transaction as part of the store card
194
+ cancelUrl: nil,
195
+ clientLanguage: nil
196
+ }
197
+ hash_fields = [:accountNumber, :purchaseOperation, :price, :priceArgList, :currency, :vat, :orderID,
198
+ :productNumber, :description, :clientIPAddress, :clientIdentifier, :additionalValues,
199
+ :externalID, :returnUrl, :view, :agreementRef, :cancelUrl, :clientLanguage]
200
+ add_request_hash(properties, hash_fields)
201
+ soap_action = SOAP_ACTIONS[:initialize]
202
+ request = build_xml_request(soap_action, properties)
203
+ commit(soap_action, request)
204
+ end
205
+
206
+ def send_purchasecc(payment_method, order_ref)
207
+ properties = {
208
+ accountNumber: @options[:account],
209
+ orderRef: order_ref,
210
+ transactionType: 1, # online payment
211
+ cardNumber: payment_method.number,
212
+ cardNumberExpireMonth: format(payment_method.month, :two_digits),
213
+ cardNumberExpireYear: format(payment_method.year, :two_digits),
214
+ cardHolderName: payment_method.name,
215
+ cardNumberCVC: payment_method.verification_value
216
+ }
217
+ hash_fields = [:accountNumber, :orderRef, :transactionType, :cardNumber, :cardNumberExpireMonth,
218
+ :cardNumberExpireYear, :cardNumberCVC, :cardHolderName]
219
+ add_request_hash(properties, hash_fields)
220
+
221
+ soap_action = SOAP_ACTIONS[:purchasecc]
222
+ request = build_xml_request(soap_action, properties)
223
+ commit(soap_action, request)
224
+ end
225
+
226
+ def send_autopay(amount, authorization, is_auth, options = {})
227
+ properties = {
228
+ accountNumber: @options[:account],
229
+ agreementRef: authorization,
230
+ price: amount,
231
+ productNumber: options[:product_number] || '1',
232
+ description: options[:description] || options[:order_id],
233
+ orderId: options[:order_id],
234
+ purchaseOperation: is_auth ? 'AUTHORIZATION' : 'SALE',
235
+ currency: (options[:currency] || default_currency),
236
+ }
237
+ hash_fields = [:accountNumber, :agreementRef, :price, :productNumber, :description, :orderId, :purchaseOperation, :currency]
238
+ add_request_hash(properties, hash_fields)
239
+
240
+ soap_action = SOAP_ACTIONS[:autopay]
241
+ request = build_xml_request(soap_action, properties)
242
+ commit(soap_action, request)
243
+ end
244
+
245
+ def send_capture(amount, transaction_number, options = {})
246
+ properties = {
247
+ accountNumber: @options[:account],
248
+ transactionNumber: transaction_number,
249
+ amount: amount,
250
+ orderId: options[:order_id] || '',
251
+ vatAmount: options[:vat_amount] || 0,
252
+ additionalValues: ''
253
+ }
254
+ hash_fields = [:accountNumber, :transactionNumber, :amount, :orderId, :vatAmount, :additionalValues]
255
+ add_request_hash(properties, hash_fields)
256
+
257
+ soap_action = SOAP_ACTIONS[:capture]
258
+ request = build_xml_request(soap_action, properties)
259
+ commit(soap_action, request)
260
+ end
261
+
262
+ def send_credit(transaction_number, amount, options = {})
263
+ properties = {
264
+ accountNumber: @options[:account],
265
+ transactionNumber: transaction_number,
266
+ amount: amount,
267
+ orderId: options[:order_id],
268
+ vatAmount: options[:vat_amount] || 0,
269
+ additionalValues: ''
270
+ }
271
+ hash_fields = [:accountNumber, :transactionNumber, :amount, :orderId, :vatAmount, :additionalValues]
272
+ add_request_hash(properties, hash_fields)
273
+
274
+ soap_action = SOAP_ACTIONS[:credit]
275
+ request = build_xml_request(soap_action, properties)
276
+ commit(soap_action, request)
277
+ end
278
+
279
+ def send_cancel(transaction_number)
280
+ properties = {
281
+ accountNumber: @options[:account],
282
+ transactionNumber: transaction_number,
283
+ }
284
+ hash_fields = [:accountNumber, :transactionNumber]
285
+ add_request_hash(properties, hash_fields)
286
+
287
+ soap_action = SOAP_ACTIONS[:cancel]
288
+ request = build_xml_request(soap_action, properties)
289
+ commit(soap_action, request)
290
+ end
291
+
292
+ def send_create_agreement(options)
293
+ properties = {
294
+ accountNumber: @options[:account],
295
+ merchantRef: options[:merchant_ref] || '1',
296
+ description: options[:description] || options[:order_id],
297
+ purchaseOperation: 'SALE',
298
+ maxAmount: options[:max_amount] || 100000, # default to 1,000
299
+ notifyUrl: '',
300
+ startDate: options[:startDate] || '',
301
+ stopDate: options[:stopDate] || ''
302
+ }
303
+ hash_fields = [:accountNumber, :merchantRef, :description, :purchaseOperation, :maxAmount, :notifyUrl, :startDate, :stopDate]
304
+ add_request_hash(properties, hash_fields)
305
+
306
+ soap_action = SOAP_ACTIONS[:create_agreement]
307
+ request = build_xml_request(soap_action, properties)
308
+ commit(soap_action, request)
309
+ end
310
+
311
+ def send_delete_agreement(authorization)
312
+ properties = {
313
+ accountNumber: @options[:account],
314
+ agreementRef: authorization,
315
+ }
316
+ hash_fields = [:accountNumber, :agreementRef]
317
+ add_request_hash(properties, hash_fields)
318
+
319
+ soap_action = SOAP_ACTIONS[:delete_agreement]
320
+ request = build_xml_request(soap_action, properties)
321
+ commit(soap_action, request)
322
+ end
323
+
324
+ def url_for(soap_action)
325
+ File.join(base_url(soap_action), soap_action[:url])
326
+ end
327
+
328
+ def base_url(soap_action)
329
+ if soap_action[:confined]
330
+ test? ? test_confined_url : live_confined_url
331
+ else
332
+ test? ? test_external_url : live_external_url
333
+ end
334
+ end
335
+
336
+ # this will add a hash to the passed in properties as required by Payex requests
337
+ def add_request_hash(properties, fields)
338
+ data = fields.map { |e| properties[e] }
339
+ data << @options[:encryption_key]
340
+ properties['hash_'] = Digest::MD5.hexdigest(data.join(''))
341
+ end
342
+
343
+ def build_xml_request(soap_action, properties)
344
+ builder = Nokogiri::XML::Builder.new
345
+ builder.__send__('soap12:Envelope', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
346
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
347
+ 'xmlns:soap12' => 'http://www.w3.org/2003/05/soap-envelope'}) do |root|
348
+ root.__send__('soap12:Body') do |body|
349
+ body.__send__(soap_action[:name], xmlns: soap_action[:xmlns]) do |doc|
350
+ properties.each do |key, val|
351
+ doc.send(key, val)
352
+ end
353
+ end
354
+ end
355
+ end
356
+ builder.to_xml
357
+ end
358
+
359
+ def parse(xml)
360
+ response = {}
361
+
362
+ xmldoc = Nokogiri::XML(xml)
363
+ body = xmldoc.xpath("//soap:Body/*[1]")[0].inner_text
364
+
365
+ doc = Nokogiri::XML(body)
366
+
367
+ doc.root.xpath("*").each do |node|
368
+ if (node.elements.size == 0)
369
+ response[node.name.downcase.to_sym] = node.text
370
+ else
371
+ node.elements.each do |childnode|
372
+ name = "#{node.name.downcase}_#{childnode.name.downcase}"
373
+ response[name.to_sym] = childnode.text
374
+ end
375
+ end
376
+ end unless doc.root.nil?
377
+
378
+ response
379
+ end
380
+
381
+ # Commits all requests to the Payex soap endpoint
382
+ def commit(soap_action, request)
383
+ url = url_for(soap_action)
384
+ headers = {
385
+ 'Content-Type' => 'application/soap+xml; charset=utf-8',
386
+ 'Content-Length' => request.size.to_s
387
+ }
388
+ response = parse(ssl_post(url, request, headers))
389
+ Response.new(success?(response),
390
+ message_from(response),
391
+ response,
392
+ test: test?,
393
+ authorization: build_authorization(response)
394
+ )
395
+ end
396
+
397
+ def build_authorization(response)
398
+ # agreementref is for the store transaction, everything else gets transactionnumber
399
+ response[:transactionnumber] || response[:agreementref]
400
+ end
401
+
402
+ def success?(response)
403
+ response[:status_errorcode] == 'OK' && response[:transactionstatus] != TRANSACTION_STATUS[:failure]
404
+ end
405
+
406
+ def message_from(response)
407
+ response[:status_description]
408
+ end
409
+ end
410
+ end
411
+ end
412
+