activemerchant 1.42.2 → 1.42.3

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 (59) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG +32 -0
  5. data/CONTRIBUTORS +12 -0
  6. data/README.md +3 -0
  7. data/lib/active_merchant/billing/base.rb +9 -2
  8. data/lib/active_merchant/billing/credit_card_methods.rb +1 -1
  9. data/lib/active_merchant/billing/gateway.rb +1 -1
  10. data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
  11. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +8 -8
  12. data/lib/active_merchant/billing/gateways/balanced.rb +7 -2
  13. data/lib/active_merchant/billing/gateways/beanstream.rb +1 -1
  14. data/lib/active_merchant/billing/gateways/bogus.rb +32 -22
  15. data/lib/active_merchant/billing/gateways/braintree_blue.rb +124 -39
  16. data/lib/active_merchant/billing/gateways/cyber_source.rb +2 -2
  17. data/lib/active_merchant/billing/gateways/litle.rb +1 -1
  18. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
  19. data/lib/active_merchant/billing/gateways/moneris.rb +1 -1
  20. data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
  21. data/lib/active_merchant/billing/gateways/nab_transact.rb +3 -1
  22. data/lib/active_merchant/billing/gateways/netpay.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/pay_junction.rb +7 -7
  24. data/lib/active_merchant/billing/gateways/payex.rb +402 -0
  25. data/lib/active_merchant/billing/gateways/payflow.rb +41 -11
  26. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/paymill.rb +55 -3
  28. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  29. data/lib/active_merchant/billing/gateways/payscout.rb +171 -0
  30. data/lib/active_merchant/billing/gateways/pin.rb +1 -1
  31. data/lib/active_merchant/billing/gateways/realex.rb +1 -1
  32. data/lib/active_merchant/billing/gateways/redsys.rb +1 -1
  33. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  34. data/lib/active_merchant/billing/gateways/stripe.rb +23 -25
  35. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +26 -15
  36. data/lib/active_merchant/billing/gateways/webpay.rb +27 -11
  37. data/lib/active_merchant/billing/gateways/wirecard.rb +1 -1
  38. data/lib/active_merchant/billing/integrations/bit_pay/helper.rb +1 -1
  39. data/lib/active_merchant/billing/integrations/ipay88.rb +4 -0
  40. data/lib/active_merchant/billing/integrations/ipay88/helper.rb +1 -1
  41. data/lib/active_merchant/billing/integrations/ipay88/notification.rb +103 -0
  42. data/lib/active_merchant/billing/integrations/ipay88/return.rb +8 -74
  43. data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +1 -1
  44. data/lib/active_merchant/billing/integrations/paypal/helper.rb +1 -1
  45. data/lib/active_merchant/billing/integrations/payu_in.rb +2 -9
  46. data/lib/active_merchant/billing/integrations/payu_in/helper.rb +15 -13
  47. data/lib/active_merchant/billing/integrations/payu_in/notification.rb +9 -20
  48. data/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb +1 -1
  49. data/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb +0 -10
  50. data/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb +1 -1
  51. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +1 -1
  52. data/lib/active_merchant/billing/integrations/valitor/helper.rb +3 -3
  53. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +2 -2
  54. data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +1 -1
  55. data/lib/active_merchant/billing/integrations/wirecard_checkout_page.rb +1 -1
  56. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +2 -2
  57. data/lib/active_merchant/version.rb +1 -1
  58. metadata +7 -3
  59. metadata.gz.sig +0 -0
@@ -24,7 +24,7 @@ module ActiveMerchant #:nodoc:
24
24
  # CyberSource what kind of item you are selling. It is used when
25
25
  # calculating tax/VAT.
26
26
  # * All transactions use dollar values.
27
- # * To process pinless debit cards throught the pinless debit card
27
+ # * To process pinless debit cards through the pinless debit card
28
28
  # network, your Cybersource merchant account must accept pinless
29
29
  # debit card payments.
30
30
  class CyberSourceGateway < Gateway
@@ -102,7 +102,7 @@ module ActiveMerchant #:nodoc:
102
102
  # :vat_reg_number => your VAT registration number
103
103
  #
104
104
  # :nexus => "WI CA QC" sets the states/provinces where you have a physical
105
- # presense for tax purposes
105
+ # presence for tax purposes
106
106
  #
107
107
  # :ignore_avs => true don't want to use AVS so continue processing even
108
108
  # if AVS would have failed
@@ -335,7 +335,7 @@ module ActiveMerchant #:nodoc:
335
335
  end
336
336
 
337
337
  if options[:description]
338
- enhanced_data['customerReference'] = options[:description]
338
+ enhanced_data['customerReference'] = options[:description][0..16]
339
339
  end
340
340
 
341
341
  if options[:billing_address]
@@ -75,7 +75,7 @@ module ActiveMerchant #:nodoc:
75
75
  end
76
76
 
77
77
  def add_address(post, options)
78
- return unless(address = options[:address])
78
+ return unless(address = (options[:billing_address] || options[:address]))
79
79
 
80
80
  post['customerName'] = address[:name]
81
81
  post['customerCountry'] = address[:country]
@@ -86,7 +86,7 @@ module ActiveMerchant #:nodoc:
86
86
  end
87
87
 
88
88
  def add_product(post, options)
89
- post['transactionProduct'] = options[:transaction_product]
89
+ post['transactionProduct'] = options[:description]
90
90
  end
91
91
 
92
92
  def add_payment_method(post, payment_method)
@@ -167,7 +167,7 @@ module ActiveMerchant #:nodoc:
167
167
  }.merge(options)
168
168
  end
169
169
 
170
- # Splits an +authorization+ param and retrives the order id and
170
+ # Splits an +authorization+ param and retrieves the order id and
171
171
  # transaction number in that order.
172
172
  def split_authorization(authorization)
173
173
  if authorization.nil? || authorization.empty? || authorization !~ /;/
@@ -111,7 +111,7 @@ module ActiveMerchant #:nodoc:
111
111
  }.merge(options)
112
112
  end
113
113
 
114
- # Splits an +authorization+ param and retrives the order id and
114
+ # Splits an +authorization+ param and retrieves the order id and
115
115
  # transaction number in that order.
116
116
  def split_authorization(authorization)
117
117
  if authorization.nil? || authorization.empty? || authorization !~ /;/
@@ -127,11 +127,13 @@ module ActiveMerchant #:nodoc:
127
127
  xml.tag! 'purchaseOrderNo', order_id
128
128
  xml.tag! 'preauthID', preauth_id
129
129
 
130
+ add_metadata(xml, options)
131
+
130
132
  xml.target!
131
133
  end
132
134
 
133
135
  #Generate payment request XML
134
- # - API is set to allow multiple Txn's but currentlu only allows one
136
+ # - API is set to allow multiple Txn's but currently only allows one
135
137
  # - txnSource = 23 - (XML)
136
138
  def build_request(action, body)
137
139
  xml = Builder::XmlMarkup.new
@@ -18,7 +18,7 @@ module ActiveMerchant #:nodoc:
18
18
  # transaction. After this, a refund should be performed instead.
19
19
  #
20
20
  # In addition to the regular ActiveMerchant transaction options, NETPAY
21
- # also supports a `:mode` parameter. This allows testing to be peformed
21
+ # also supports a `:mode` parameter. This allows testing to be performed
22
22
  # in production and force specific results.
23
23
  #
24
24
  # * 'P' - Production
@@ -73,16 +73,16 @@ module ActiveMerchant #:nodoc:
73
73
  #
74
74
  # PayJunction Field ActiveMerchant Use
75
75
  #
76
- # dc_logon provide as :login value to gateway instantation
76
+ # dc_logon provide as :login value to gateway instantiation
77
77
  # dc_password provide as :password value to gateway instantiation
78
78
  #
79
79
  # dc_name will be retrieved from credit_card.name
80
- # dc_first_name :first_name on CreditCard object instantation
81
- # dc_last_name :last_name on CreditCard object instantation
82
- # dc_number :number on CreditCard object instantation
83
- # dc_expiration_month :month on CreditCard object instantation
84
- # dc_expiration_year :year on CreditCard object instantation
85
- # dc_verification_number :verification_value on CC object instantation
80
+ # dc_first_name :first_name on CreditCard object instantiation
81
+ # dc_last_name :last_name on CreditCard object instantiation
82
+ # dc_number :number on CreditCard object instantiation
83
+ # dc_expiration_month :month on CreditCard object instantiation
84
+ # dc_expiration_year :year on CreditCard object instantiation
85
+ # dc_verification_number :verification_value on CC object instantiation
86
86
  #
87
87
  # dc_transaction_amount include as argument to method for your transaction type
88
88
  # dc_transaction_type do nothing, set by your transaction type
@@ -0,0 +1,402 @@
1
+ require "nokogiri"
2
+ module ActiveMerchant #:nodoc:
3
+ module Billing #:nodoc:
4
+ class PayexGateway < Gateway
5
+ self.live_url = 'https://external.payex.com/'
6
+ self.test_url = 'https://test-external.payex.com/'
7
+
8
+ self.money_format = :cents
9
+ self.supported_countries = ['SE', 'NO', 'DK']
10
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
11
+ self.homepage_url = 'http://payex.com/'
12
+ self.display_name = 'Payex'
13
+ self.default_currency = "EUR"
14
+
15
+ # NOTE: the PurchaseCC uses a different url for test transactions
16
+ TEST_CONFINED_URL = 'https://test-confined.payex.com/'
17
+
18
+ TRANSACTION_STATUS = {
19
+ sale: '0',
20
+ initialize: '1',
21
+ credit: '2',
22
+ authorize: '3',
23
+ cancel: '4',
24
+ failure: '5',
25
+ capture: '6',
26
+ }
27
+
28
+ SOAP_ACTIONS = {
29
+ initialize: { name: 'Initialize8', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
30
+ purchasecc: { name: 'PurchaseCC', url: 'pxconfined/pxorder.asmx', xmlns: 'http://confined.payex.com/PxOrder/', confined: true},
31
+ cancel: { name: 'Cancel2', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
32
+ capture: { name: 'Capture5', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
33
+ credit: { name: 'Credit5', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
34
+ create_agreement: { name: 'CreateAgreement3', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
35
+ delete_agreement: { name: 'DeleteAgreement', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
36
+ autopay: { name: 'AutoPay3', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
37
+ }
38
+
39
+ def initialize(options = {})
40
+ requires!(options, :account, :encryption_key)
41
+ super
42
+ end
43
+
44
+ # Public: Send an authorize Payex request
45
+ #
46
+ # amount - The monetary amount of the transaction in cents.
47
+ # payment_method - The Active Merchant payment method or the +store+ authorization for stored transactions.
48
+ # options - A standard ActiveMerchant options hash:
49
+ # :currency - Three letter currency code for the transaction (default: "EUR")
50
+ # :order_id - The unique order ID for this transaction (required).
51
+ # :product_number - The merchant product number (default: '1').
52
+ # :description - The merchant description for this product (default: The :order_id).
53
+ # :ip - The client IP address (default: '127.0.0.1').
54
+ # :vat - The vat amount (optional).
55
+ #
56
+ # Returns an ActiveMerchant::Billing::Response object
57
+ def authorize(amount, payment_method, options = {})
58
+ requires!(options, :order_id)
59
+ amount = amount(amount)
60
+ if payment_method.respond_to?(:number)
61
+ # credit card authorization
62
+ MultiResponse.new.tap do |r|
63
+ r.process {send_initialize(amount, true, options)}
64
+ r.process {send_purchasecc(payment_method, r.params['orderref'])}
65
+ end
66
+ else
67
+ # stored authorization
68
+ send_autopay(amount, payment_method, true, options)
69
+ end
70
+
71
+ end
72
+
73
+ # Public: Send a purchase Payex request
74
+ #
75
+ # amount - The monetary amount of the transaction in cents.
76
+ # payment_method - The Active Merchant payment method or the +store+ authorization for stored transactions.
77
+ # options - A standard ActiveMerchant options hash:
78
+ # :currency - Three letter currency code for the transaction (default: "EUR")
79
+ # :order_id - The unique order ID for this transaction (required).
80
+ # :product_number - The merchant product number (default: '1').
81
+ # :description - The merchant description for this product (default: The :order_id).
82
+ # :ip - The client IP address (default: '127.0.0.1').
83
+ # :vat - The vat amount (optional).
84
+ #
85
+ # Returns an ActiveMerchant::Billing::Response object
86
+ def purchase(amount, payment_method, options = {})
87
+ requires!(options, :order_id)
88
+ amount = amount(amount)
89
+ if payment_method.respond_to?(:number)
90
+ # credit card purchase
91
+ MultiResponse.new.tap do |r|
92
+ r.process {send_initialize(amount, false, options)}
93
+ r.process {send_purchasecc(payment_method, r.params['orderref'])}
94
+ end
95
+ else
96
+ # stored purchase
97
+ send_autopay(amount, payment_method, false, options)
98
+ end
99
+ end
100
+
101
+ # Public: Capture money from a previously authorized transaction
102
+ #
103
+ # money - The amount to capture
104
+ # authorization - The authorization token from the authorization request
105
+ #
106
+ # Returns an ActiveMerchant::Billing::Response object
107
+ def capture(money, authorization, options = {})
108
+ amount = amount(money)
109
+ send_capture(amount, authorization)
110
+ end
111
+
112
+ # Public: Voids an authorize transaction
113
+ #
114
+ # authorization - The authorization returned from the successful authorize transaction.
115
+ # options - A standard ActiveMerchant options hash
116
+ #
117
+ # Returns an ActiveMerchant::Billing::Response object
118
+ def void(authorization, options={})
119
+ send_cancel(authorization)
120
+ end
121
+
122
+ # Public: Refunds a purchase transaction
123
+ #
124
+ # money - The amount to refund
125
+ # authorization - The authorization token from the purchase request.
126
+ # options - A standard ActiveMerchant options hash:
127
+ # :order_id - The unique order ID for this transaction (required).
128
+ # :vat_amount - The vat amount (optional).
129
+ #
130
+ # Returns an ActiveMerchant::Billing::Response object
131
+ def refund(money, authorization, options = {})
132
+ requires!(options, :order_id)
133
+ amount = amount(money)
134
+ send_credit(authorization, amount, options)
135
+ end
136
+
137
+ # Public: Stores a credit card and creates a Payex agreement with a customer
138
+ #
139
+ # creditcard - The credit card to store.
140
+ # options - A standard ActiveMerchant options hash:
141
+ # :order_id - The unique order ID for this transaction (required).
142
+ # :merchant_ref - A reference that links this agreement to something the merchant takes money for (default: '1')
143
+ # :currency - Three letter currency code for the transaction (default: "EUR")
144
+ # :product_number - The merchant product number (default: '1').
145
+ # :description - The merchant description for this product (default: The :order_id).
146
+ # :ip - The client IP address (default: '127.0.0.1').
147
+ # :max_amount - The maximum amount to allow to be charged (default: 100000).
148
+ # :vat - The vat amount (optional).
149
+ #
150
+ # Returns an ActiveMerchant::Billing::Response object where the authorization is set to the agreement_ref which is used for stored payments.
151
+ def store(creditcard, options = {})
152
+ requires!(options, :order_id)
153
+ amount = amount(1) # 1 cent for authorization
154
+ MultiResponse.run(:first) do |r|
155
+ r.process {send_create_agreement(options)}
156
+ r.process {send_initialize(amount, true, options.merge({agreement_ref: r.authorization}))}
157
+ order_ref = r.params['orderref']
158
+ r.process {send_purchasecc(creditcard, order_ref)}
159
+ end
160
+ end
161
+
162
+ # Public: Unstores a customer's credit card and deletes their Payex agreement.
163
+ #
164
+ # authorization - The authorization token from the store request.
165
+ #
166
+ # Returns an ActiveMerchant::Billing::Response object
167
+ def unstore(authorization, options = {})
168
+ send_delete_agreement(authorization)
169
+ end
170
+
171
+ private
172
+
173
+ def send_initialize(amount, is_auth, options = {})
174
+ properties = {
175
+ accountNumber: @options[:account],
176
+ purchaseOperation: is_auth ? 'AUTHORIZATION' : 'SALE',
177
+ price: amount,
178
+ priceArgList: nil,
179
+ currency: (options[:currency] || default_currency),
180
+ vat: options[:vat] || 0,
181
+ orderID: options[:order_id],
182
+ productNumber: options[:product_number] || '1',
183
+ description: options[:description] || options[:order_id],
184
+ clientIPAddress: options[:client_ip_address] || '127.0.0.1',
185
+ clientIdentifier: nil,
186
+ additionalValues: nil,
187
+ externalID: nil,
188
+ returnUrl: 'http://example.net', # set to dummy value since this is not used but is required
189
+ view: 'CREDITCARD',
190
+ agreementRef: options[:agreement_ref], # this is used to attach a stored agreement to a transaction as part of the store card
191
+ cancelUrl: nil,
192
+ clientLanguage: nil
193
+ }
194
+ hash_fields = [:accountNumber, :purchaseOperation, :price, :priceArgList, :currency, :vat, :orderID,
195
+ :productNumber, :description, :clientIPAddress, :clientIdentifier, :additionalValues,
196
+ :externalID, :returnUrl, :view, :agreementRef, :cancelUrl, :clientLanguage]
197
+ add_request_hash(properties, hash_fields)
198
+ soap_action = SOAP_ACTIONS[:initialize]
199
+ request = build_xml_request(soap_action, properties)
200
+ commit(soap_action, request)
201
+ end
202
+
203
+ def send_purchasecc(payment_method, order_ref)
204
+ properties = {
205
+ accountNumber: @options[:account],
206
+ orderRef: order_ref,
207
+ transactionType: 1, # online payment
208
+ cardNumber: payment_method.number,
209
+ cardNumberExpireMonth: "%02d" % payment_method.month,
210
+ cardNumberExpireYear: "%02d" % payment_method.year,
211
+ cardHolderName: payment_method.name,
212
+ cardNumberCVC: payment_method.verification_value
213
+ }
214
+ hash_fields = [:accountNumber, :orderRef, :transactionType, :cardNumber, :cardNumberExpireMonth,
215
+ :cardNumberExpireYear, :cardNumberCVC, :cardHolderName]
216
+ add_request_hash(properties, hash_fields)
217
+
218
+ soap_action = SOAP_ACTIONS[:purchasecc]
219
+ request = build_xml_request(soap_action, properties)
220
+ commit(soap_action, request)
221
+ end
222
+
223
+ def send_autopay(amount, authorization, is_auth, options = {})
224
+ properties = {
225
+ accountNumber: @options[:account],
226
+ agreementRef: authorization,
227
+ price: amount,
228
+ productNumber: options[:product_number] || '1',
229
+ description: options[:description] || options[:order_id],
230
+ orderId: options[:order_id],
231
+ purchaseOperation: is_auth ? 'AUTHORIZATION' : 'SALE',
232
+ currency: (options[:currency] || default_currency),
233
+ }
234
+ hash_fields = [:accountNumber, :agreementRef, :price, :productNumber, :description, :orderId, :purchaseOperation, :currency]
235
+ add_request_hash(properties, hash_fields)
236
+
237
+ soap_action = SOAP_ACTIONS[:autopay]
238
+ request = build_xml_request(soap_action, properties)
239
+ commit(soap_action, request)
240
+ end
241
+
242
+ def send_capture(amount, transaction_number, options = {})
243
+ properties = {
244
+ accountNumber: @options[:account],
245
+ transactionNumber: transaction_number,
246
+ amount: amount,
247
+ orderId: options[:order_id] || '',
248
+ vatAmount: options[:vat_amount] || 0,
249
+ additionalValues: ''
250
+ }
251
+ hash_fields = [:accountNumber, :transactionNumber, :amount, :orderId, :vatAmount, :additionalValues]
252
+ add_request_hash(properties, hash_fields)
253
+
254
+ soap_action = SOAP_ACTIONS[:capture]
255
+ request = build_xml_request(soap_action, properties)
256
+ commit(soap_action, request)
257
+ end
258
+
259
+ def send_credit(transaction_number, amount, options = {})
260
+ properties = {
261
+ accountNumber: @options[:account],
262
+ transactionNumber: transaction_number,
263
+ amount: amount,
264
+ orderId: options[:order_id],
265
+ vatAmount: options[:vat_amount] || 0,
266
+ additionalValues: ''
267
+ }
268
+ hash_fields = [:accountNumber, :transactionNumber, :amount, :orderId, :vatAmount, :additionalValues]
269
+ add_request_hash(properties, hash_fields)
270
+
271
+ soap_action = SOAP_ACTIONS[:credit]
272
+ request = build_xml_request(soap_action, properties)
273
+ commit(soap_action, request)
274
+ end
275
+
276
+ def send_cancel(transaction_number)
277
+ properties = {
278
+ accountNumber: @options[:account],
279
+ transactionNumber: transaction_number,
280
+ }
281
+ hash_fields = [:accountNumber, :transactionNumber]
282
+ add_request_hash(properties, hash_fields)
283
+
284
+ soap_action = SOAP_ACTIONS[:cancel]
285
+ request = build_xml_request(soap_action, properties)
286
+ commit(soap_action, request)
287
+ end
288
+
289
+ def send_create_agreement(options)
290
+ properties = {
291
+ accountNumber: @options[:account],
292
+ merchantRef: options[:merchant_ref] || '1',
293
+ description: options[:description] || options[:order_id],
294
+ purchaseOperation: 'SALE',
295
+ maxAmount: options[:max_amount] || 100000, # default to 1,000
296
+ notifyUrl: '',
297
+ startDate: options[:startDate] || '',
298
+ stopDate: options[:stopDate] || ''
299
+ }
300
+ hash_fields = [:accountNumber, :merchantRef, :description, :purchaseOperation, :maxAmount, :notifyUrl, :startDate, :stopDate]
301
+ add_request_hash(properties, hash_fields)
302
+
303
+ soap_action = SOAP_ACTIONS[:create_agreement]
304
+ request = build_xml_request(soap_action, properties)
305
+ commit(soap_action, request)
306
+ end
307
+
308
+ def send_delete_agreement(authorization)
309
+ properties = {
310
+ accountNumber: @options[:account],
311
+ agreementRef: authorization,
312
+ }
313
+ hash_fields = [:accountNumber, :agreementRef]
314
+ add_request_hash(properties, hash_fields)
315
+
316
+ soap_action = SOAP_ACTIONS[:delete_agreement]
317
+ request = build_xml_request(soap_action, properties)
318
+ commit(soap_action, request)
319
+ end
320
+
321
+ def url_for(soap_action)
322
+ base_url = test? ? (soap_action[:confined] ? TEST_CONFINED_URL : test_url) : live_url
323
+ File.join(base_url, soap_action[:url])
324
+ end
325
+
326
+ # this will add a hash to the passed in properties as required by Payex requests
327
+ def add_request_hash(properties, fields)
328
+ data = fields.map { |e| properties[e] }
329
+ data << @options[:encryption_key]
330
+ properties['hash_'] = Digest::MD5.hexdigest(data.join(''))
331
+ end
332
+
333
+ def build_xml_request(soap_action, properties)
334
+ builder = Nokogiri::XML::Builder.new
335
+ builder.__send__('soap12:Envelope', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
336
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
337
+ 'xmlns:soap12' => 'http://www.w3.org/2003/05/soap-envelope'}) do |root|
338
+ root.__send__('soap12:Body') do |body|
339
+ body.__send__(soap_action[:name], xmlns: soap_action[:xmlns]) do |doc|
340
+ properties.each do |key, val|
341
+ doc.send(key, val)
342
+ end
343
+ end
344
+ end
345
+ end
346
+ builder.to_xml
347
+ end
348
+
349
+ def parse(xml)
350
+ response = {}
351
+
352
+ xmldoc = Nokogiri::XML(xml)
353
+ body = xmldoc.xpath("//soap:Body/*[1]")[0].inner_text
354
+
355
+ doc = Nokogiri::XML(body)
356
+
357
+ doc.root.xpath("*").each do |node|
358
+ if (node.elements.size == 0)
359
+ response[node.name.downcase.to_sym] = node.text
360
+ else
361
+ node.elements.each do |childnode|
362
+ name = "#{node.name.downcase}_#{childnode.name.downcase}"
363
+ response[name.to_sym] = childnode.text
364
+ end
365
+ end
366
+ end unless doc.root.nil?
367
+
368
+ response
369
+ end
370
+
371
+ # Commits all requests to the Payex soap endpoint
372
+ def commit(soap_action, request)
373
+ url = url_for(soap_action)
374
+ headers = {
375
+ 'Content-Type' => 'application/soap+xml; charset=utf-8',
376
+ 'Content-Length' => request.size.to_s
377
+ }
378
+ response = parse(ssl_post(url, request, headers))
379
+ Response.new(success?(response),
380
+ message_from(response),
381
+ response,
382
+ test: test?,
383
+ authorization: build_authorization(response)
384
+ )
385
+ end
386
+
387
+ def build_authorization(response)
388
+ # agreementref is for the store transaction, everything else gets transactionnumber
389
+ response[:transactionnumber] || response[:agreementref]
390
+ end
391
+
392
+ def success?(response)
393
+ response[:status_errorcode] == 'OK' && response[:transactionstatus] != TRANSACTION_STATUS[:failure]
394
+ end
395
+
396
+ def message_from(response)
397
+ response[:status_description]
398
+ end
399
+ end
400
+ end
401
+ end
402
+