activemerchant 1.47.0 → 1.48.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 (42) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG +34 -0
  5. data/CONTRIBUTORS +16 -0
  6. data/README.md +8 -2
  7. data/lib/active_merchant/billing/credit_card.rb +16 -4
  8. data/lib/active_merchant/billing/gateway.rb +0 -1
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +48 -1
  10. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
  11. data/lib/active_merchant/billing/gateways/braintree_blue.rb +16 -6
  12. data/lib/active_merchant/billing/gateways/cenpos.rb +272 -0
  13. data/lib/active_merchant/billing/gateways/epay.rb +8 -9
  14. data/lib/active_merchant/billing/gateways/exact.rb +9 -0
  15. data/lib/active_merchant/billing/gateways/fat_zebra.rb +33 -0
  16. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +49 -3
  17. data/lib/active_merchant/billing/gateways/inspire.rb +7 -1
  18. data/lib/active_merchant/billing/gateways/iridium.rb +1 -1
  19. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
  20. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  21. data/lib/active_merchant/billing/gateways/nab_transact.rb +47 -37
  22. data/lib/active_merchant/billing/gateways/netbilling.rb +40 -7
  23. data/lib/active_merchant/billing/gateways/orbital.rb +45 -21
  24. data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
  25. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  26. data/lib/active_merchant/billing/gateways/paymill.rb +3 -2
  27. data/lib/active_merchant/billing/gateways/pin.rb +2 -2
  28. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -4
  29. data/lib/active_merchant/billing/gateways/qvalent.rb +179 -0
  30. data/lib/active_merchant/billing/gateways/redsys.rb +29 -15
  31. data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
  32. data/lib/active_merchant/billing/gateways/stripe.rb +12 -3
  33. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -3
  34. data/lib/active_merchant/billing/gateways/worldpay.rb +2 -2
  35. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +205 -0
  36. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +12 -4
  37. data/lib/active_merchant/billing/response.rb +1 -1
  38. data/lib/active_merchant/posts_data.rb +6 -0
  39. data/lib/active_merchant/version.rb +1 -1
  40. data/lib/support/outbound_hosts.rb +13 -10
  41. metadata +9 -2
  42. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dbec33f0dbb45aa949b164bf0bc376b5aeee2f51
4
- data.tar.gz: 6bb77b71ff18e0cdaf18ff62b2fb28e1cace2588
3
+ metadata.gz: 5ff9f55a9e47319466b22c9d9826ffb0d9c2d8a7
4
+ data.tar.gz: cfe3110700b68bb12392232759ed730376435e3b
5
5
  SHA512:
6
- metadata.gz: 9e34c4f81edd376e109de5d0e2ef50463763c7ea2be6884d401417044336982cb048235c029771ba8b7e99c7a985b91e214d63ee248a25d0d9e6038999fe1fe1
7
- data.tar.gz: a9a128c91e69846177d0e3d9f9b51c1295c741423d9780db449a284902f443255f0f54660e2bfc23d89bad67d26d7956a56e19d17a28ed0a5410bfc8fa9e51a5
6
+ metadata.gz: 7bce2c57e79a9683a0c2d6557290efef7e2315b317158a4eb302b081d9c5e56f28a5a6102b30d39bfdbfd15acb88134094b0a11b6ea5e79b6d66a6cc1373e4d0
7
+ data.tar.gz: 22b1046d34bdbd344a06a9b6bd3917216b738da94ce79ed64b586c5f9a1c0ac9314bf6650f57dc2dfd30a03e34c272d0e83180444612a617cb84bef81412e458
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,5 +1,39 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
+ == Version 1.48.0 (April 8, 2015)
4
+
5
+ * Clean up `rake gateways:hosts` output [ntalbott]
6
+ * Add Axcess MS gateway [timtait]
7
+ * Add PayHub gateway [grepruby]
8
+ * Orbital: Improve data formatting [boone]
9
+ * [POSSIBLE BREAKAGE] USAePay Transaction: Make "void release" the default [dppcode]
10
+ * Redsys: Add rudimentary vaulting [varyonic]
11
+ * Exact: Handle 401 failures better [jefflaporte]
12
+ * SagePay: make `VPSProtocol` user-configurable [boxofrad]
13
+ * Netbilling: Add store support [cshepherd]
14
+ * Add Qvalent gateway [markabe]
15
+ * Expose proxy address and port to gateways [arkes]
16
+ * Remove Ruby 1.9 [j-mutter]
17
+ * Qvalent: Do not sent order.ipAddress when storing [markabe]
18
+ * Qvalent: Fix argument name [bruno]
19
+ * Qvalent: map card storage reference to authorization [markabe]
20
+ * Qvalent: Fix scrub replacement, it was too greedy [markabe]
21
+ * PayConex: Add gateway [duff]
22
+ * AuthorizeNet: Add credit support [duff]
23
+ * CenPOS: Add gateway [markabe]
24
+ * Stripe: Update country list [markabe]
25
+ * Add Monei.net gateway [leolara]
26
+ * MerchantWarrior: Fix refund and capture signatures [duff]
27
+ * CenPOS: Add support for capture and refund [markabe]
28
+ * Authorize.net: Add support for network tokenization credit cards [jnormore]
29
+ * Stripe: Add support for passing in metadata for auths and purchases [kitt]
30
+ * Pin: Pass amount param for captures [ab9]
31
+ * NAB Transact: Improve store functionality [duff]
32
+ * Add Worldpay Online Payments [ao]
33
+ * Fat Zebra: Add multi-currency support [nagash]
34
+ * Fat Zebra: Add auth/capture capability [nagash]
35
+ * Fat Zebra: Add soft descriptor support [nagash]
36
+
3
37
  == Version 1.47.0 (February 25, 2015)
4
38
 
5
39
  * Authorize.Net: Properly send name in shipping address line, when shipping address is provided [girasquid]
data/CONTRIBUTORS CHANGED
@@ -518,3 +518,19 @@ QuickBooks Payments (January 2015)
518
518
 
519
519
  * Arbab Ahmed (bizla)
520
520
  * Ivan Sanchez (ivanfer)
521
+
522
+ Axcess MS (February 2015)
523
+
524
+ * Tim Tait (timtait)
525
+
526
+ PayHub (February 2015)
527
+
528
+ * Grep Ruby (grepruby)
529
+
530
+ Qvalent (March 2015)
531
+
532
+ * Mark Bennett (markabe)
533
+
534
+ Worldpay Online Payments (April 2015)
535
+
536
+ * (ao)
data/README.md CHANGED
@@ -85,6 +85,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
85
85
  * [App55](https://www.app55.com/) - AU, BR, CA, CH, CL, CN, CO, CZ, DK, EU, GB, HK, HU, ID, IS, JP, KE, KR, MX, MY, NO, NZ, PH, PL, TH, TW, US, VN, ZA
86
86
  * [Authorize.Net CIM](http://www.authorize.net/) - US
87
87
  * [Authorize.Net](http://www.authorize.net/) - AD, AT, AU, BE, BG, CA, CH, CY, CZ, DE, DK, ES, FI, FR, GB, GB, GI, GR, HU, IE, IT, LI, LU, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, SM, TR, US, VA
88
+ * [Axcess MS](http://www.axcessms.com/) - AD, AT, BE, BG, BR, CA, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GI, GR, HR, HU, IE, IL, IM, IS, IT, LI, LT, LU, LV, MC, MT, MX, NL, NO, PL, PT, RO, RU, SE, SI, SK, TR, US, VA
88
89
  * [Balanced](https://www.balancedpayments.com/) - US
89
90
  * [Bank Frick](http://www.bankfrickacquiring.com/) - LI, US
90
91
  * [Banwire](http://www.banwire.com/) - MX
@@ -100,6 +101,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
100
101
  * [CardStream](http://www.cardstream.com/) - GB
101
102
  * [Cashnet](http://www.higherone.com/) - US
102
103
  * [Cecabank](http://www.ceca.es/es/) - ES
104
+ * [Cenpos](https://www.cenpos.com/) - AD, AI, AG, AR, AU, AT, BS, BB, BE, BZ, BM, BR, BN, BG, CA, HR, CY, CZ, DK, DM, EE, FI, FR, DE, GR, GD, GY, HK, HU, IS, IN, IL, IT, JP, LV, LI, LT, LU, MY, MT, MX, MC, MS, NL, PA, PL, PT, KN, LC, MF, VC, SM, SG, SK, SI, ZA, ES, SR, SE, CH, TR, GB, US, UY
103
105
  * [CertoDirect](http://www.certodirect.com/) - BE, BG, CZ, DK, DE, EE, IE, EL, ES, FR, IT, CY, LV, LT, LU, HU, MT, NL, AT, PL, PT, RO, SI, SK, FI, SE, GB
104
106
  * [Checkout.com](https://www.checkout.com/) - AT, BE, BG, CY, CZ, DE, DK, EE, ES, FI, FR, GR, HR, HU, IE, IS, IT, LI, LT, LU, LV, MT, MU, NL, NO, PL, PT, RO, SE, SI, SK, US
105
107
  * [Commercegate](http://www.commercegate.com/) - AD, AT, AX, BE, BG, CH, CY, CZ, DE, DK, ES, FI, FR, GB, GG, GI, GR, HR, HU, IE, IM, IS, IT, JE, LI, LT, LU, LV, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, VA
@@ -156,7 +158,9 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
156
158
  * [Optimal Payments](http://www.optimalpayments.com/) - CA, US, GB
157
159
  * [Orbital Paymentech](http://chasepaymentech.com/) - US, CA
158
160
  * [PagoFacil](http://www.pagofacil.net/) - MX
161
+ * [PayConex](http://www.bluefincommerce.com/) - US, CA
159
162
  * [PayGate PayXML](http://paygate.co.za/) - US, ZA
163
+ * [PayHub](http://www.payhub.com/) - US
160
164
  * [PayJunction](http://www.payjunction.com/) - US
161
165
  * [PaySecure](http://www.commsecure.com.au/paysecure.shtml) - AU
162
166
  * [Paybox Direct](http://www.paybox.com/) - FR
@@ -181,6 +185,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
181
185
  * [QuickBooks Payments](http://payments.intuit.com/) - US
182
186
  * [Quantum Gateway](http://www.quantumgateway.com) - US
183
187
  * [QuickPay](http://quickpay.net/) - DE, DK, ES, FI, FR, FO, GB, IS, NO, SE
188
+ * [Qvalent](https://www.qvalent.com/) - AU
184
189
  * [Raven PacNet](http://www.pacnetservices.com/) - US
185
190
  * [Realex](http://www.realexpayments.com/) - IE, GB, FR, BE, NL, LU, IT
186
191
  * [Redsys](http://www.redsys.es/) - ES
@@ -193,7 +198,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
193
198
  * [SkipJack](http://www.skipjack.com/) - US, CA
194
199
  * [SoEasyPay](http://www.soeasypay.com/) - US, CA, AT, BE, BG, HR, CY, CZ, DK, EE, FI, FR, DE, GR, HU, IE, IT, LV, LT, LU, MT, NL, PL, PT, RO, SK, SI, ES, SE, GB, IS, NO, CH
195
200
  * [Spreedly](https://spreedly.com) - AD, AE, AT, AU, BD, BE, BG, BN, CA, CH, CY, CZ, DE, DK, EE, EG, ES, FI, FR, GB, GI, GR, HK, HU, ID, IE, IL, IM, IN, IS, IT, JO, KW, LB, LI, LK, LT, LU, LV, MC, MT, MU, MV, MX, MY, NL, NO, NZ, OM, PH, PL, PT, QA, RO, SA, SE, SG, SI, SK, SM, TR, TT, UM, US, VA, VN, ZA
196
- * [Stripe](https://stripe.com/) - AU, BE, CA, CH, DE, ES, FI, FR, GB, IE, IT, LU, NL, US
201
+ * [Stripe](https://stripe.com/) - AT, AU, BE, CA, CH, DE, DK, ES, FI, FR, GB, IE, IT, LU, NL, NO, SE, US
197
202
  * [Swipe](https://www.swipehq.com/checkout) - CA, NZ
198
203
  * [TransFirst](http://www.transfirst.com/) - US
199
204
  * [TNS](http://www.tnsi.com/) - AR, AU, BR, FR, DE, HK, MX, NZ, SG, GB, US
@@ -206,7 +211,8 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
206
211
  * [WebPay](https://webpay.jp/) - JP
207
212
  * [WePay](https://www.wepay.com/) - US
208
213
  * [Wirecard](http://www.wirecard.com) - AD, CY, GI, IM, MT, RO, CH, AT, DK, GR, IT, MC, SM, TR, BE, EE, HU, LV, NL, SK, GB, BG, FI, IS, LI, NO, SI, VA, FR, IL, LT, PL, ES, CZ, DE, IE, LU, PT, SE
209
- * [Worldpay](http://www.worldpay.com/) - HK, US, GB, AU, AD, BE, CH, CY, CZ, DE, DK, ES, FI, FR, GI, GR, HU, IE, IL, IT, LI, LU, MC, MT, NL, NO, NZ, PL, PT, SE, SG, SI, SM, TR, UM, VA
214
+ * [Worldpay Global](http://www.worldpay.com/) - HK, GB, AU, AD, BE, CH, CY, CZ, DE, DK, ES, FI, FR, GI, GR, HU, IE, IL, IT, LI, LU, MC, MT, NL, NO, NZ, PL, PT, SE, SG, SI, SM, TR, UM, VA
215
+ * [Worlpay Online](http://www.worldpay.com/) - HK, US, GB, AU, AD, BE, CH, CY, CZ, DE, DK, ES, FI, FR, GI, GR, HU, IE, IL, IT, LI, LU, MC, MT, NL, NO, NZ, PL, PT, SE, SG, SI, SM, TR, UM, VA
210
216
  * [Worldpay US](http://www.worldpay.com/us) - US
211
217
 
212
218
  ## API stability policy
@@ -49,7 +49,13 @@ module ActiveMerchant #:nodoc:
49
49
  class CreditCard < Model
50
50
  include CreditCardMethods
51
51
 
52
- cattr_accessor :require_verification_value
52
+ class << self
53
+ # Inherited, but can be overridden w/o changing parent's value
54
+ attr_accessor :require_verification_value
55
+ attr_accessor :require_name
56
+ end
57
+
58
+ self.require_name = true
53
59
  self.require_verification_value = true
54
60
 
55
61
  # Returns or sets the credit card number.
@@ -243,13 +249,19 @@ module ActiveMerchant #:nodoc:
243
249
  require_verification_value
244
250
  end
245
251
 
252
+ def self.requires_name?
253
+ require_name
254
+ end
255
+
246
256
  private
247
257
 
248
258
  def validate_essential_attributes #:nodoc:
249
259
  errors = []
250
260
 
251
- errors << [:first_name, "cannot be empty"] if first_name.blank?
252
- errors << [:last_name, "cannot be empty"] if last_name.blank?
261
+ if self.class.requires_name?
262
+ errors << [:first_name, "cannot be empty"] if first_name.blank?
263
+ errors << [:last_name, "cannot be empty"] if last_name.blank?
264
+ end
253
265
 
254
266
  if(empty?(month) || empty?(year))
255
267
  errors << [:month, "is required"] if empty?(month)
@@ -294,7 +306,7 @@ module ActiveMerchant #:nodoc:
294
306
  unless valid_card_verification_value?(verification_value, brand)
295
307
  errors << [:verification_value, "should be #{card_verification_value_length(brand)} digits"]
296
308
  end
297
- elsif CreditCard.requires_verification_value?
309
+ elsif self.class.requires_verification_value?
298
310
  errors << [:verification_value, "is required"]
299
311
  end
300
312
  errors
@@ -250,7 +250,6 @@ module ActiveMerchant #:nodoc:
250
250
  end
251
251
  end
252
252
 
253
-
254
253
  def currency(money)
255
254
  money.respond_to?(:currency) ? money.currency : self.default_currency
256
255
  end
@@ -16,6 +16,25 @@ module ActiveMerchant #:nodoc:
16
16
  self.homepage_url = 'http://www.authorize.net/'
17
17
  self.display_name = 'Authorize.Net'
18
18
 
19
+ STANDARD_ERROR_CODE_MAPPING = {
20
+ '36' => STANDARD_ERROR_CODE[:incorrect_number],
21
+ '237' => STANDARD_ERROR_CODE[:invalid_number],
22
+ '2315' => STANDARD_ERROR_CODE[:invalid_number],
23
+ '37' => STANDARD_ERROR_CODE[:invalid_expiry_date],
24
+ '2316' => STANDARD_ERROR_CODE[:invalid_expiry_date],
25
+ '378' => STANDARD_ERROR_CODE[:invalid_cvc],
26
+ '38' => STANDARD_ERROR_CODE[:expired_card],
27
+ '2317' => STANDARD_ERROR_CODE[:expired_card],
28
+ '244' => STANDARD_ERROR_CODE[:incorrect_cvc],
29
+ '227' => STANDARD_ERROR_CODE[:incorrect_address],
30
+ '2127' => STANDARD_ERROR_CODE[:incorrect_address],
31
+ '22' => STANDARD_ERROR_CODE[:card_declined],
32
+ '23' => STANDARD_ERROR_CODE[:card_declined],
33
+ '3153' => STANDARD_ERROR_CODE[:processing_error],
34
+ '235' => STANDARD_ERROR_CODE[:processing_error],
35
+ '24' => STANDARD_ERROR_CODE[:pickup_card]
36
+ }
37
+
19
38
  class_attribute :duplicate_window
20
39
 
21
40
  APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4
@@ -116,6 +135,26 @@ module ActiveMerchant #:nodoc:
116
135
  end
117
136
  end
118
137
 
138
+ def credit(amount, payment, options={})
139
+ if payment.is_a?(String)
140
+ raise ArgumentError, "Reference credits are not supported. Please supply the original credit card or use the #refund method."
141
+ end
142
+
143
+ commit("CREDIT") do |xml|
144
+ add_order_id(xml, options)
145
+ xml.transactionRequest do
146
+ xml.transactionType('refundTransaction')
147
+ xml.amount(amount(amount))
148
+
149
+ add_payment_source(xml, payment)
150
+ add_invoice(xml, options)
151
+ add_customer_data(xml, payment, options)
152
+ add_settings(xml, payment, options)
153
+ add_user_fields(xml, amount, options)
154
+ end
155
+ end
156
+ end
157
+
119
158
  def verify(credit_card, options = {})
120
159
  MultiResponse.run(:use_first_response) do |r|
121
160
  r.process { authorize(100, credit_card, options) }
@@ -198,6 +237,9 @@ module ActiveMerchant #:nodoc:
198
237
  unless empty?(credit_card.verification_value)
199
238
  xml.cardCode(credit_card.verification_value)
200
239
  end
240
+ if credit_card.is_a?(NetworkTokenizationCreditCard)
241
+ xml.cryptogram(credit_card.payment_cryptogram)
242
+ end
201
243
  end
202
244
  end
203
245
  end
@@ -339,7 +381,8 @@ module ActiveMerchant #:nodoc:
339
381
  test: test?,
340
382
  avs_result: avs_result,
341
383
  cvv_result: cvv_result,
342
- fraud_review: fraud_review?(response)
384
+ fraud_review: fraud_review?(response),
385
+ error_code: map_error_code(response[:response_code], response[:response_reason_code])
343
386
  )
344
387
  end
345
388
  end
@@ -451,6 +494,10 @@ module ActiveMerchant #:nodoc:
451
494
  def using_live_gateway_in_test_mode?(response)
452
495
  !test? && response[:test_request] == "1"
453
496
  end
497
+
498
+ def map_error_code(response_code, response_reason_code)
499
+ STANDARD_ERROR_CODE_MAPPING[response_code.to_s << response_reason_code.to_s]
500
+ end
454
501
  end
455
502
  end
456
503
  end
@@ -0,0 +1,181 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class AxcessmsGateway < Gateway
4
+ self.test_url = "https://test.ctpe.io/payment/ctpe"
5
+ self.live_url = "https://ctpe.io/payment/ctpe"
6
+
7
+ self.supported_countries = %w(AD AT BE BG BR CA CH CY CZ DE DK EE ES FI FO FR GB
8
+ GI GR HR HU IE IL IM IS IT LI LT LU LV MC MT MX NL
9
+ NO PL PT RO RU SE SI SK TR US VA)
10
+
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :solo]
12
+
13
+ self.homepage_url = "http://www.axcessms.com/"
14
+ self.display_name = "Axcess MS"
15
+ self.money_format = :dollars
16
+ self.default_currency = "GBP"
17
+
18
+ API_VERSION = "1.0"
19
+ PAYMENT_CODE_PREAUTHORIZATION = "CC.PA"
20
+ PAYMENT_CODE_DEBIT = "CC.DB"
21
+ PAYMENT_CODE_CAPTURE = "CC.CP"
22
+ PAYMENT_CODE_REVERSAL = "CC.RV"
23
+ PAYMENT_CODE_REFUND = "CC.RF"
24
+ PAYMENT_CODE_REBILL = "CC.RB"
25
+
26
+ def initialize(options={})
27
+ requires!(options, :sender, :login, :password, :channel)
28
+ super
29
+ end
30
+
31
+ def purchase(money, payment, options={})
32
+ payment_code = payment.respond_to?(:number) ? PAYMENT_CODE_DEBIT : PAYMENT_CODE_REBILL
33
+ commit(payment_code, money, payment, options)
34
+ end
35
+
36
+ def authorize(money, authorization, options={})
37
+ commit(PAYMENT_CODE_PREAUTHORIZATION, money, authorization, options)
38
+ end
39
+
40
+ def capture(money, authorization, options={})
41
+ commit(PAYMENT_CODE_CAPTURE, money, authorization, options)
42
+ end
43
+
44
+ def refund(money, authorization, options={})
45
+ commit(PAYMENT_CODE_REFUND, money, authorization, options)
46
+ end
47
+
48
+ def void(authorization, options={})
49
+ commit(PAYMENT_CODE_REVERSAL, nil, authorization, options)
50
+ end
51
+
52
+ def verify(credit_card, options={})
53
+ MultiResponse.run(:use_first_response) do |r|
54
+ r.process { authorize(100, credit_card, options) }
55
+ r.process(:ignore_result) { void(r.authorization, options) }
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def commit(paymentcode, money, payment, options)
62
+ options[:mode] ||= (test? ? "INTEGRATOR_TEST" : "LIVE")
63
+ request = build_request(paymentcode, money, payment, options)
64
+
65
+ headers = {
66
+ "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
67
+ }
68
+
69
+ response = parse(ssl_post((test? ? test_url : live_url), "load=#{CGI.escape(request)}", headers))
70
+ success = (response[:result] == "ACK")
71
+ message = "#{response[:reason]} - #{response[:return]}"
72
+ authorization = response[:unique_id]
73
+
74
+ Response.new(success, message, response,
75
+ :authorization => authorization,
76
+ :test => (response[:mode] != "LIVE")
77
+ )
78
+ end
79
+
80
+ def parse(body)
81
+ return {} if body.blank?
82
+
83
+ xml = REXML::Document.new(body)
84
+
85
+ response = {}
86
+ xml.root.elements.to_a.each do |node|
87
+ parse_element(response, node)
88
+ end
89
+
90
+ response[:mode] = REXML::XPath.first(xml, "//Transaction").attributes["mode"]
91
+
92
+ response
93
+ end
94
+
95
+ def parse_element(response, node)
96
+ if node.has_attributes?
97
+ node.attributes.each{|name, value| response["#{node.name}_#{name}".underscore.to_sym] = value }
98
+ end
99
+
100
+ if node.has_elements?
101
+ node.elements.each{|element| parse_element(response, element) }
102
+ else
103
+ response[node.name.underscore.to_sym] = node.text
104
+ end
105
+ end
106
+
107
+ def build_request(payment_code, money, payment, options)
108
+ xml = Builder::XmlMarkup.new :indent => 2
109
+ xml.instruct!
110
+ xml.tag! "Request", "version" => API_VERSION do
111
+ xml.tag! "Header" do
112
+ xml.tag! "Security", "sender" => @options[:sender]
113
+ end
114
+ xml.tag! "Transaction", "mode" => options[:mode], "channel" => @options[:channel], "response" => "SYNC" do
115
+ xml.tag! "User", "login" => @options[:login], "pwd" => @options[:password]
116
+ xml.tag! "Identification" do
117
+ xml.tag! "TransactionID", options[:order_id] || generate_unique_id
118
+ xml.tag! "ReferenceID", payment unless payment.respond_to?(:number)
119
+ end
120
+
121
+ xml.tag! "Payment", "code" => payment_code do
122
+ xml.tag! "Memo", options[:memo] unless options[:memo].blank?
123
+ xml.tag! "Presentation" do
124
+ xml.tag! "Amount", amount(money)
125
+ xml.tag! "Currency", (options[:currency] || currency(money))
126
+ xml.tag! "Usage", options[:description]
127
+ end
128
+ end
129
+
130
+ if payment.respond_to?(:number)
131
+ add_payment(xml, payment)
132
+
133
+ xml.tag! "Customer" do
134
+ add_customer_name(xml, payment)
135
+ add_address(xml, options[:billing_address] || options[:address])
136
+ add_contact(xml, options)
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ xml.target!
143
+ end
144
+
145
+ def add_contact(xml, options)
146
+ xml.tag! "Contact" do
147
+ xml.tag! "Email", (options[:email] || "unknown@example.com")
148
+ xml.tag! "Ip", (options[:ip] || "127.0.0.1")
149
+ end
150
+ end
151
+
152
+ def add_customer_name(xml, payment)
153
+ xml.tag! "Name" do
154
+ xml.tag! "Given", payment.first_name
155
+ xml.tag! "Family", payment.last_name
156
+ end
157
+ end
158
+
159
+ def add_payment(xml, payment)
160
+ xml.tag! "Account" do
161
+ xml.tag! "Number", payment.number
162
+ xml.tag! "Holder", payment.name
163
+ xml.tag! "Brand", payment.brand
164
+ xml.tag! "Expiry", "month" => payment.month, "year" => payment.year
165
+ xml.tag! "Verification", payment.verification_value
166
+ end
167
+ end
168
+
169
+ def add_address(xml, address)
170
+ raise ArgumentError.new("Address is required") unless address
171
+ xml.tag! "Address" do
172
+ xml.tag! "Street", "#{address[:address1]} #{address[:address2]}".strip
173
+ xml.tag! "City", address[:city]
174
+ xml.tag! "State", address[:state]
175
+ xml.tag! "Zip", address[:zip]
176
+ xml.tag! "Country", address[:country]
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end