activemerchant 1.21.0 → 1.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +63 -0
  3. data/CONTRIBUTORS +29 -0
  4. data/README.md +195 -0
  5. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +2 -0
  6. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +2 -2
  7. data/lib/active_merchant/billing/gateways/blue_pay.rb +492 -11
  8. data/lib/active_merchant/billing/gateways/braintree_blue.rb +46 -19
  9. data/lib/active_merchant/billing/gateways/certo_direct.rb +1 -1
  10. data/lib/active_merchant/billing/gateways/cyber_source.rb +342 -106
  11. data/lib/active_merchant/billing/gateways/elavon.rb +2 -0
  12. data/lib/active_merchant/billing/gateways/epay.rb +3 -1
  13. data/lib/active_merchant/billing/gateways/itransact.rb +450 -0
  14. data/lib/active_merchant/billing/gateways/migs.rb +259 -0
  15. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  16. data/lib/active_merchant/billing/gateways/moneris_us.rb +211 -0
  17. data/lib/active_merchant/billing/gateways/ogone.rb +104 -12
  18. data/lib/active_merchant/billing/gateways/orbital.rb +15 -6
  19. data/lib/active_merchant/billing/gateways/paybox_direct.rb +1 -4
  20. data/lib/active_merchant/billing/gateways/payflow.rb +8 -3
  21. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +4 -1
  22. data/lib/active_merchant/billing/gateways/payflow_express.rb +4 -2
  23. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/paypal.rb +3 -18
  25. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +287 -1
  26. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +245 -0
  27. data/lib/active_merchant/billing/gateways/paypal_express.rb +14 -66
  28. data/lib/active_merchant/billing/gateways/realex.rb +5 -7
  29. data/lib/active_merchant/billing/gateways/stripe.rb +1 -9
  30. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +2 -2
  31. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -5
  32. data/lib/active_merchant/billing/gateways/viaklix.rb +7 -2
  33. data/lib/active_merchant/billing/gateways/vindicia.rb +359 -0
  34. data/lib/active_merchant/billing/integrations/dotpay.rb +22 -0
  35. data/lib/active_merchant/billing/integrations/dotpay/helper.rb +77 -0
  36. data/lib/active_merchant/billing/integrations/dotpay/notification.rb +86 -0
  37. data/lib/active_merchant/billing/integrations/dotpay/return.rb +11 -0
  38. data/lib/active_merchant/billing/integrations/epay.rb +21 -0
  39. data/lib/active_merchant/billing/integrations/epay/helper.rb +55 -0
  40. data/lib/active_merchant/billing/integrations/epay/notification.rb +110 -0
  41. data/lib/active_merchant/billing/integrations/paypal/notification.rb +2 -1
  42. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +2 -3
  43. data/lib/active_merchant/billing/integrations/robokassa.rb +49 -0
  44. data/lib/active_merchant/billing/integrations/robokassa/common.rb +19 -0
  45. data/lib/active_merchant/billing/integrations/robokassa/helper.rb +50 -0
  46. data/lib/active_merchant/billing/integrations/robokassa/notification.rb +55 -0
  47. data/lib/active_merchant/billing/integrations/robokassa/return.rb +17 -0
  48. data/lib/active_merchant/billing/integrations/two_checkout.rb +25 -3
  49. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +15 -0
  50. data/lib/active_merchant/billing/integrations/verkkomaksut.rb +20 -0
  51. data/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb +87 -0
  52. data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +59 -0
  53. data/lib/active_merchant/version.rb +1 -1
  54. metadata +59 -26
  55. metadata.gz.sig +0 -0
@@ -59,6 +59,7 @@ module ActiveMerchant #:nodoc:
59
59
  add_creditcard(form, creditcard)
60
60
  add_address(form, options)
61
61
  add_customer_data(form, options)
62
+ add_test_mode(form, options)
62
63
  commit(:authorize, money, form)
63
64
  end
64
65
 
@@ -77,6 +78,7 @@ module ActiveMerchant #:nodoc:
77
78
  add_invoice(form, options)
78
79
  add_creditcard(form, options[:credit_card])
79
80
  add_customer_data(form, options)
81
+ add_test_mode(form, options)
80
82
  commit(:capture, money, form)
81
83
  end
82
84
 
@@ -192,7 +192,9 @@ module ActiveMerchant #:nodoc:
192
192
  else
193
193
  return {
194
194
  'accept' => '0',
195
- 'errortext' => 'No Location header returned.'
195
+ 'errortext' => 'ePay did not respond as expected. Please try again.',
196
+ 'response_code' => response.code,
197
+ 'response_message' => response.message
196
198
  }
197
199
  end
198
200
 
@@ -0,0 +1,450 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ # iTransact, Inc. is an authorized reseller of the PaymentClearing gateway. If your merchant service provider uses PaymentClearing.com to process payments, you can use this module.
6
+ #
7
+ #
8
+ # Please note, the username and API Access Key are not what you use to log into the Merchant Control Panel.
9
+ #
10
+ # ==== How to get your GatewayID and API Access Key
11
+ #
12
+ # 1. If you don't already have a Gateway Account, go to http://www.itransact.com/merchant/test.html to sign up.
13
+ # 2. Go to http://support.paymentclearing.com and login or register, if necessary.
14
+ # 3. Click on "Submit a Ticket."
15
+ # 4. Select "Merchant Support" as the department and click "Next"
16
+ # 5. Enter *both* your company name and GatewayID. Put "API Access Key" in the subject. In the body, you can request a username, but it may already be in use.
17
+ #
18
+ # ==== Initialization
19
+ #
20
+ # Once you have the username, API Access Key, and your GatewayId, you're ready
21
+ # to begin. You initialize the Gateway like so:
22
+ #
23
+ # gateway = ActiveMerchant::Billing::ItransactGateway.new(
24
+ # :login => "#{THE_USERNAME}",
25
+ # :password => "#{THE_API_ACCESS_KEY}",
26
+ # :gateway_id => "#{THE_GATEWAY_ID}"
27
+ # )
28
+ #
29
+ # ==== Important Notes
30
+ # 1. Recurring is not implemented
31
+ # 1. CreditTransactions are not implemented (these are credits not related to a previously run transaction).
32
+ # 1. TransactionStatus is not implemented
33
+ #
34
+ class ItransactGateway < Gateway
35
+ URL = 'https://secure.paymentclearing.com/cgi-bin/rc/xmltrans2.cgi'
36
+
37
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
38
+ self.supported_countries = ['US']
39
+
40
+ # The card types supported by the payment gateway
41
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
42
+
43
+ # The homepage URL of the gateway
44
+ self.homepage_url = 'http://www.itransact.com/'
45
+
46
+ # The name of the gateway
47
+ self.display_name = 'iTransact'
48
+
49
+ #
50
+ # Creates a new instance of the iTransact Gateway.
51
+ #
52
+ # ==== Parameters
53
+ # * <tt>options</tt> - A Hash of options
54
+ #
55
+ # ==== Options Hash
56
+ # * <tt>:login</tt> - A String containing your PaymentClearing assigned API Access Username
57
+ # * <tt>:password</tt> - A String containing your PaymentClearing assigned API Access Key
58
+ # * <tt>:gateway_id</tt> - A String containing your PaymentClearing assigned GatewayID
59
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Run *all* transactions with the 'TestMode' element set to 'TRUE'.
60
+ #
61
+ def initialize(options = {})
62
+ requires!(options, :login, :password, :gateway_id)
63
+ @options = options
64
+ super
65
+ end
66
+
67
+ # Performs an authorize transaction. In PaymentClearing's documentation
68
+ # this is known as a "PreAuth" transaction.
69
+ #
70
+ # ==== Parameters
71
+ # * <tt>money</tt> - The amount to be captured. Should be an Integer amount in cents.
72
+ # * <tt>creditcard</tt> - The CreditCard details for the transaction
73
+ # * <tt>options</tt> - A Hash of options
74
+ #
75
+ # ==== Options Hash
76
+ # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as:
77
+ # * <tt>:order_items</tt> - An Array of Hash objects with the keys <tt>:description</tt>, <tt>:cost</tt> (in cents!), and <tt>:quantity</tt>. If this is provided, <tt>:description</tt> and <tt>money</tt> will be ignored.
78
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
79
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
80
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
81
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
82
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
83
+ #
84
+ # ==== Examples
85
+ # response = gateway.authorize(1000, creditcard,
86
+ # :order_id => '1212', :address => {...}, :email => 'test@test.com',
87
+ # :order_items => [
88
+ # {:description => 'Line Item 1', :cost => '8.98', :quantity => '6'},
89
+ # {:description => 'Line Item 2', :cost => '6.99', :quantity => '4'}
90
+ # ],
91
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
92
+ # :send_customer_email => true,
93
+ # :send_merchant_email => true,
94
+ # :email_text => ['line1', 'line2', 'line3'],
95
+ # :test_mode => true
96
+ # )
97
+ #
98
+ def authorize(money, payment_source, options = {})
99
+ payload = Nokogiri::XML::Builder.new do |xml|
100
+ xml.AuthTransaction {
101
+ xml.Preauth
102
+ add_customer_data(xml, payment_source, options)
103
+ add_invoice(xml, money, options)
104
+ add_payment_source(xml, payment_source)
105
+ add_transaction_control(xml, options)
106
+ add_vendor_data(xml, options)
107
+ }
108
+ end.doc
109
+
110
+ commit(payload)
111
+ end
112
+
113
+ # Performs an authorize and capture in single transaction. In PaymentClearing's
114
+ # documentation this is known as an "Auth" or a "Sale" transaction
115
+ #
116
+ # ==== Parameters
117
+ # * <tt>money</tt> - The amount to be captured. Should be <tt>nil</tt> or an Integer amount in cents.
118
+ # * <tt>creditcard</tt> - The CreditCard details for the transaction
119
+ # * <tt>options</tt> - A Hash of options
120
+ #
121
+ # ==== Options Hash
122
+ # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as:
123
+ # * <tt>:order_items</tt> - An Array of Hash objects with the keys <tt>:description</tt>, <tt>:cost</tt> (in cents!), and <tt>:quantity</tt>. If this is provided, <tt>:description</tt> and <tt>money</tt> will be ignored.
124
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
125
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
126
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
127
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
128
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
129
+ #
130
+ # ==== Examples
131
+ # response = gateway.purchase(1000, creditcard,
132
+ # :order_id => '1212', :address => {...}, :email => 'test@test.com',
133
+ # :order_items => [
134
+ # {:description => 'Line Item 1', :cost => '8.98', :quantity => '6'},
135
+ # {:description => 'Line Item 2', :cost => '6.99', :quantity => '4'}
136
+ # ],
137
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
138
+ # :send_customer_email => true,
139
+ # :send_merchant_email => true,
140
+ # :email_text => ['line1', 'line2', 'line3'],
141
+ # :test_mode => true
142
+ # )
143
+ #
144
+ def purchase(money, payment_source, options = {})
145
+ payload = Nokogiri::XML::Builder.new do |xml|
146
+ xml.AuthTransaction {
147
+ add_customer_data(xml, payment_source, options)
148
+ add_invoice(xml, money, options)
149
+ add_payment_source(xml, payment_source)
150
+ add_transaction_control(xml, options)
151
+ add_vendor_data(xml, options)
152
+ }
153
+ end.doc
154
+
155
+ commit(payload)
156
+ end
157
+
158
+ # Captures the funds from an authorize transaction. In PaymentClearing's
159
+ # documentation this is known as a "PostAuth" transaction.
160
+ #
161
+ # ==== Parameters
162
+ # * <tt>money</tt> - The amount to be captured. Should be an Integer amount in cents
163
+ # * <tt>authorization</tt> - The authorization returned from the previous capture or purchase request
164
+ # * <tt>options</tt> - A Hash of options, all are optional.
165
+ #
166
+ # ==== Options Hash
167
+ # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as:
168
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
169
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
170
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
171
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
172
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
173
+ #
174
+ # ==== Examples
175
+ # response = gateway.capture(1000, creditcard,
176
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
177
+ # :send_customer_email => true,
178
+ # :send_merchant_email => true,
179
+ # :email_text => ['line1', 'line2', 'line3'],
180
+ # :test_mode => true
181
+ # )
182
+ #
183
+ def capture(money, authorization, options = {})
184
+ payload = Nokogiri::XML::Builder.new do |xml|
185
+ xml.PostAuthTransaction {
186
+ xml.OperationXID(authorization)
187
+ add_invoice(xml, money, options)
188
+ add_transaction_control(xml, options)
189
+ add_vendor_data(xml, options)
190
+ }
191
+ end.doc
192
+
193
+ commit(payload)
194
+ end
195
+
196
+ # This will reverse a previously run transaction which *has* *not* settled.
197
+ #
198
+ # ==== Parameters
199
+ # * <tt>money</tt> - This parameter is ignored -- the PaymentClearing gateway does not allow partial voids.
200
+ # * <tt>authorization</tt> - The authorization returned from the previous capture or purchase request
201
+ # * <tt>options</tt> - A Hash of options, all are optional
202
+ #
203
+ # ==== Options Hash
204
+ # The standard options (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address) are ignored.
205
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
206
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
207
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
208
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
209
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
210
+ #
211
+ # ==== Examples
212
+ # response = gateway.void(nil, '9999999999',
213
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
214
+ # :send_customer_email => true,
215
+ # :send_merchant_email => true,
216
+ # :email_text => ['line1', 'line2', 'line3'],
217
+ # :test_mode => true
218
+ # )
219
+ #
220
+ def void(money, authorization, options = {})
221
+ payload = Nokogiri::XML::Builder.new do |xml|
222
+ xml.VoidTransaction {
223
+ xml.OperationXID(authorization)
224
+ add_transaction_control(xml, options)
225
+ add_vendor_data(xml, options)
226
+ }
227
+ end.doc
228
+
229
+ commit(payload)
230
+ end
231
+
232
+ # This will reverse a previously run transaction which *has* settled.
233
+ #
234
+ # ==== Parameters
235
+ # * <tt>money</tt> - The amount to be credited. Should be <tt>nil</tt> or an Integer amount in cents
236
+ # * <tt>authorization</tt> - The authorization returned from the previous capture or purchase request
237
+ # * <tt>options</tt> - A Hash of options, all are optional
238
+ #
239
+ # ==== Options Hash
240
+ # The standard options (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address) are ignored.
241
+ # * <tt>:vendor_data</tt> - An Array of Hash objects with the keys being the name of the VendorData element and value being the value.
242
+ # * <tt>:send_customer_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'.
243
+ # * <tt>:send_merchant_email</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'.
244
+ # * <tt>:email_text</tt> - An Array of (up to ten (10)) String objects to be included in emails
245
+ # * <tt>:test_mode</tt> - <tt>true</tt> or <tt>false</tt>. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'.
246
+ #
247
+ # ==== Examples
248
+ # response = gateway.credit(nil, '9999999999',
249
+ # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}],
250
+ # :send_customer_email => true,
251
+ # :send_merchant_email => true,
252
+ # :email_text => ['line1', 'line2', 'line3'],
253
+ # :test_mode => true
254
+ # )
255
+ #
256
+ def credit(money, authorization, options = {})
257
+ payload = Nokogiri::XML::Builder.new do |xml|
258
+ xml.TranCreditTransaction {
259
+ xml.OperationXID(authorization)
260
+ add_invoice(xml, money, options)
261
+ add_transaction_control(xml, options)
262
+ add_vendor_data(xml, options)
263
+ }
264
+ end.doc
265
+
266
+ commit(payload)
267
+ end
268
+
269
+ private
270
+
271
+ def add_customer_data(xml, payment_source, options)
272
+ billing_address = options[:billing_address] || options[:address]
273
+ shipping_address = options[:shipping_address] || options[:address]
274
+
275
+ xml.CustomerData {
276
+ xml.Email(options[:email]) unless options[:email].blank?
277
+ xml.CustId(options[:order_id]) unless options[:order_id].blank?
278
+ xml.BillingAddress {
279
+ xml.FirstName(payment_source.first_name || parse_first_name(billing_address[:name]))
280
+ xml.LastName(payment_source.last_name || parse_last_name(billing_address[:name]))
281
+ xml.Address1(billing_address[:address1])
282
+ xml.Address2(billing_address[:address2]) unless billing_address[:address2].blank?
283
+ xml.City(billing_address[:city])
284
+ xml.State(billing_address[:state])
285
+ xml.Zip(billing_address[:zip])
286
+ xml.Country(billing_address[:country])
287
+ xml.Phone(billing_address[:phone])
288
+ }
289
+ xml.ShippingAddress {
290
+ xml.FirstName(payment_source.first_name || parse_first_name(shipping_address[:name]))
291
+ xml.LastName(payment_source.last_name || parse_last_name(shipping_address[:name]))
292
+ xml.Address1(shipping_address[:address1])
293
+ xml.Address2(shipping_address[:address2]) unless shipping_address[:address2].blank?
294
+ xml.City(shipping_address[:city])
295
+ xml.State(shipping_address[:state])
296
+ xml.Zip(shipping_address[:zip])
297
+ xml.Country(shipping_address[:country])
298
+ xml.Phone(shipping_address[:phone])
299
+ } unless shipping_address.blank?
300
+ }
301
+ end
302
+
303
+ def add_invoice(xml, money, options)
304
+ xml.AuthCode options[:force] if options[:force]
305
+ if options[:order_items].blank?
306
+ xml.Total(amount(money)) unless(money.nil? || money < 0.01)
307
+ xml.Description(options[:description]) unless( options[:description].blank?)
308
+ else
309
+ xml.OrderItems {
310
+ options[:order_items].each do |item|
311
+ xml.Item {
312
+ xml.Description(item[:description])
313
+ xml.Cost(amount(item[:cost]))
314
+ xml.Qty(item[:quantity].to_s)
315
+ }
316
+ end
317
+ }
318
+ end
319
+ end
320
+
321
+ def add_payment_source(xml, source)
322
+ case determine_funding_source(source)
323
+ when :credit_card then add_creditcard(xml, source)
324
+ when :check then add_check(xml, source)
325
+ end
326
+ end
327
+
328
+ def determine_funding_source(payment_source)
329
+ case payment_source
330
+ when ActiveMerchant::Billing::CreditCard
331
+ :credit_card
332
+ when ActiveMerchant::Billing::Check
333
+ :check
334
+ end
335
+ end
336
+
337
+ def add_creditcard(xml, creditcard)
338
+ xml.AccountInfo {
339
+ xml.CardAccount {
340
+ xml.AccountNumber(creditcard.number.to_s)
341
+ xml.ExpirationMonth(creditcard.month.to_s.rjust(2,'0'))
342
+ xml.ExpirationYear(creditcard.year.to_s)
343
+ xml.CVVNumber(creditcard.verification_value.to_s) unless creditcard.verification_value.blank?
344
+ }
345
+ }
346
+ end
347
+
348
+ def add_check(xml, check)
349
+ xml.AccountInfo {
350
+ xml.ABA(check.routing_number.to_s)
351
+ xml.AccountNumber(check.account_number.to_s)
352
+ xml.AccountSource(check.account_type.to_s)
353
+ xml.AccountType(check.account_holder_type.to_s)
354
+ xml.CheckNumber(check.number.to_s)
355
+ }
356
+ end
357
+
358
+ def add_transaction_control(xml, options)
359
+ xml.TransactionControl {
360
+ # if there was a 'global' option set...
361
+ xml.TestMode(@options[:test_mode].upcase) if !@options[:test_mode].blank?
362
+ # allow the global option to be overridden...
363
+ xml.TestMode(options[:test_mode].upcase) if !options[:test_mode].blank?
364
+ xml.SendCustomerEmail(options[:send_customer_email].upcase) unless options[:send_customer_email].blank?
365
+ xml.SendMerchantEmail(options[:send_merchant_email].upcase) unless options[:send_merchant_email].blank?
366
+ xml.EmailText {
367
+ options[:email_text].each do |item|
368
+ xml.EmailTextItem(item)
369
+ end
370
+ } if options[:email_text]
371
+ }
372
+ end
373
+
374
+ def add_vendor_data(xml, options)
375
+ return if options[:vendor_data].blank?
376
+ xml.VendorData {
377
+ options[:vendor_data].each do |k,v|
378
+ xml.Element {
379
+ xml.Name(k)
380
+ xml.Key(v)
381
+ }
382
+ end
383
+ }
384
+ end
385
+
386
+ def commit(payload)
387
+ # Set the Content-Type header -- otherwise the URL decoding messes up
388
+ # the Base64 encoded payload signature!
389
+ response = parse(ssl_post(URL, post_data(payload), 'Content-Type' => 'text/xml'))
390
+
391
+ Response.new(successful?(response), response[:error_message], response,
392
+ :test => test?,
393
+ :authorization => response[:xid],
394
+ :avs_result => { :code => response[:avs_response] },
395
+ :cvv_result => response[:cvv_response])
396
+ end
397
+
398
+ def post_data(payload)
399
+ payload_xml = payload.root.to_xml(:indent => 0)
400
+
401
+ payload_signature = sign_payload(payload_xml)
402
+
403
+ request = Nokogiri::XML::Builder.new do |xml|
404
+ xml.GatewayInterface {
405
+ xml.APICredentials {
406
+ xml.Username(@options[:login])
407
+ xml.PayloadSignature(payload_signature)
408
+ xml.TargetGateway(@options[:gateway_id])
409
+ }
410
+ }
411
+ end.doc
412
+
413
+ request.root.children.first.after payload.root
414
+ request.to_xml(:indent => 0)
415
+ end
416
+
417
+ def parse(raw_xml)
418
+ doc = REXML::Document.new(raw_xml)
419
+ response = Hash.new
420
+ transaction_result = doc.root.get_elements('TransactionResponse/TransactionResult/*')
421
+ transaction_result.each do |e|
422
+ response[e.name.to_s.underscore.to_sym] = e.text unless e.text.blank?
423
+ end
424
+ response
425
+ end
426
+
427
+ def successful?(response)
428
+ # Turns out the PaymentClearing gateway is not consistent...
429
+ response[:status].downcase =='ok'
430
+ end
431
+
432
+ def test_mode?(response)
433
+ # The '1' is a legacy thing; most of the time it should be 'TRUE'...
434
+ response[:test_mode] == 'TRUE' || response[:test_mode] == '1'
435
+ end
436
+
437
+ def message_from(response)
438
+ response[:error_message]
439
+ end
440
+
441
+ def sign_payload(payload)
442
+ key = @options[:password].to_s
443
+ digest=OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new(key), key, payload)
444
+ signature = Base64.encode64(digest)
445
+ signature.chomp!
446
+ end
447
+ end
448
+ end
449
+ end
450
+