activemerchant 1.60.0 → 1.61.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +64 -0
  3. data/lib/active_merchant/billing/gateways/authorize_net.rb +1 -1
  4. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +12 -1
  5. data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
  6. data/lib/active_merchant/billing/gateways/blue_snap.rb +1 -1
  7. data/lib/active_merchant/billing/gateways/braintree_blue.rb +8 -0
  8. data/lib/active_merchant/billing/gateways/card_stream.rb +2 -0
  9. data/lib/active_merchant/billing/gateways/citrus_pay.rb +24 -0
  10. data/lib/active_merchant/billing/gateways/clearhaus.rb +12 -4
  11. data/lib/active_merchant/billing/gateways/conekta.rb +6 -1
  12. data/lib/active_merchant/billing/gateways/credorax.rb +234 -0
  13. data/lib/active_merchant/billing/gateways/cyber_source.rb +39 -52
  14. data/lib/active_merchant/billing/gateways/element.rb +13 -2
  15. data/lib/active_merchant/billing/gateways/fat_zebra.rb +12 -3
  16. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +5 -0
  17. data/lib/active_merchant/billing/gateways/global_collect.rb +3 -1
  18. data/lib/active_merchant/billing/gateways/jetpay.rb +11 -3
  19. data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -0
  20. data/lib/active_merchant/billing/gateways/litle.rb +28 -12
  21. data/lib/active_merchant/billing/gateways/mastercard.rb +261 -0
  22. data/lib/active_merchant/billing/gateways/migs.rb +23 -1
  23. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/moneris.rb +13 -0
  25. data/lib/active_merchant/billing/gateways/netbanx.rb +245 -0
  26. data/lib/active_merchant/billing/gateways/nmi.rb +5 -0
  27. data/lib/active_merchant/billing/gateways/openpay.rb +7 -0
  28. data/lib/active_merchant/billing/gateways/opp.rb +362 -0
  29. data/lib/active_merchant/billing/gateways/orbital.rb +13 -0
  30. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +190 -0
  31. data/lib/active_merchant/billing/gateways/payflow.rb +6 -0
  32. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  33. data/lib/active_merchant/billing/gateways/paymill.rb +10 -0
  34. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  35. data/lib/active_merchant/billing/gateways/payu_latam.rb +386 -0
  36. data/lib/active_merchant/billing/gateways/pin.rb +1 -3
  37. data/lib/active_merchant/billing/gateways/redsys.rb +2 -0
  38. data/lib/active_merchant/billing/gateways/sage.rb +22 -0
  39. data/lib/active_merchant/billing/gateways/sage_pay.rb +12 -0
  40. data/lib/active_merchant/billing/gateways/securion_pay.rb +2 -2
  41. data/lib/active_merchant/billing/gateways/stripe.rb +29 -8
  42. data/lib/active_merchant/billing/gateways/telr.rb +275 -0
  43. data/lib/active_merchant/billing/gateways/tns.rb +12 -230
  44. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
  45. data/lib/active_merchant/billing/gateways/vanco.rb +12 -8
  46. data/lib/active_merchant/billing/gateways/worldpay.rb +18 -0
  47. data/lib/active_merchant/country.rb +6 -2
  48. data/lib/active_merchant/version.rb +1 -1
  49. metadata +11 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d43ab38ffa5badee3266ac1da82758f7f5a928d
4
- data.tar.gz: 044674b27950c204a881c24ef8556e4d01841f22
3
+ metadata.gz: 1fe35e2a54670d5e8b4a1b03b60e0fbdb63b862e
4
+ data.tar.gz: 776d6fcde383b0ca43232791f8816ea573a21b3a
5
5
  SHA512:
6
- metadata.gz: 304da6ed75b96dbfa07fb1546f318a224a021c46d2d528b29db4d821858838c28ea4b3ecc9b7319d739281224a6e42c7a5880bd7f06483165f92d8b99f544d80
7
- data.tar.gz: 889d972567c2b9cb383b29f8c472e27047b6e5b229e512b85478d9b60759014968c23963c1b48fe3b2aa1db7c36c9323e5fe5011cc00e4e3173db0c397e13f5f
6
+ metadata.gz: 1c4e2de0b7a0302afbbab9c6a486db123ac8228f83d3f7ea844ccd2108d80a79234627f2a9ce5824a9782c5eff560ef644aefea40d729564e97afb30d476946b
7
+ data.tar.gz: 2d259ac6111733da3f2d093f8638a5f2adcd8eb47a3adcce29197e37c4605daca606a2214ed274629872bdd5d6ba931acec991abfa1c398758941542d1b03963
data/CHANGELOG CHANGED
@@ -1,5 +1,69 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
+ == Version 1.61.0 (November 7, 2016)
4
+ * Add codes AQ, BQ, SX, and SS to list of countries and update SD numeric code [zxlin]
5
+ * AuthorizeNet: Update supported countries list [shasum]
6
+ * Barclay SmartPay: Add support for credit [shasum]
7
+ * Barclaycard SmartPay: Update supported countries [shasum]
8
+ * BluePay: Add Canada to supported countries list [shasum]
9
+ * BlueSnap: Update countries list [shasum]
10
+ * Braintree Blue: Add Android Pay support [mrezentes]
11
+ * Braintree Blue: Add remote test to verify card token [shasum]
12
+ * Braintree Blue: Get Android Pay tx id from payment method, not options [mrezentes]
13
+ * CardStream: Add MXN currency code [curiousepic]
14
+ * CardStream: Set captureDelay to zero on purchase [davidsantoso]
15
+ * CitrusPay: Add gateway [duff]
16
+ * CitrusPay: Update URL to current API version [davidsantoso]
17
+ * Clearhaus: Fix refund of captures [duff]
18
+ * Clearhaus: Update list of non fractal currencies [curiousepic]
19
+ * Clearhaus: Use localized amount [curiouspic]
20
+ * Conekta: Add void action [MauricioMurga]
21
+ * Credorax: Add gateway support [davidsantoso]
22
+ * CyberSource, Paymill, Payflow: Add verify_credentials [duff]
23
+ * CyberSource: Combine auth_reversal with Void [curiousepic]
24
+ * CyberSource: Increase merchant defined data fields [davidsantoso]
25
+ * CyberSource: Look up alpha2 country code [curiousepic]
26
+ * CyberSource: Use localized_amount [curiousepic]
27
+ * Element: Pass order_id and shipping address [curiousepic]
28
+ * Fat Zebra: Add cavv, xid, and sli fields [curiousepic]
29
+ * Fat Zebra: Fix improper descriptor nesting [curiousepic]
30
+ * Find countries if they are differently cased [curiousepic]
31
+ * GlobalCollect: Update credit card brand list [curiousepic]
32
+ * Jetpay: Support endpoint for Canada [shasum]
33
+ * Linkpoint: Clean whitespace from PEM [curiousepic]
34
+ * Litle: Retain amount to send in auth reversals [curiousepic]
35
+ * Litle: add scrubbing support [bruno]
36
+ * MONEI: Update supported countries list [davidgf]
37
+ * MiGS: Handle IDR currency [curiousepic]
38
+ * Migs: Add support for void [mohsenottello]
39
+ * Migs: Support some additional fields [duff]
40
+ * Moneris: Fix unit test stubs [shasum]
41
+ * Moneris: add scrubbing support [bruno]
42
+ * NMI, FirstData: Support verify_credentials [curiousepic]
43
+ * Openpay: Add support for verify [duff]
44
+ * PayJunctionV2: Add gateway support [shasum]
45
+ * PayU Latam: Add new gateway [shasum]
46
+ * PayU Latam: Update supported countries list [shasum]
47
+ * Payflow: Update supported countries list [shasum]
48
+ * PaypalExpress: Add SoftDescriptor field [talyssonoc]
49
+ * Redsys: Added DOP and CRC currency [davidsantoso]
50
+ * Sage: Add support for scrubbing [bruno]
51
+ * SagePay: Fix truncation [duff]
52
+ * SecurionPay: Update supported countries list [shasum]
53
+ * Stripe: Increase authorize amount during verify [davidsantoso]
54
+ * Stripe: Set minimum authorize amount depending on currency [davidsantoso]
55
+ * Stripe: Support new network tokenization API params [methodmissing]
56
+ * Stripe: Update supported countries list [shasum]
57
+ * TNS and CitrusPay: Support scrub and verify_credentials [duff]
58
+ * TNS and CitrusPay: Update to version 36 of the API [duff]
59
+ * TNS: Try TLS v1 [duff]
60
+ * Telr: Add gateway support [curiousepic]
61
+ * TransFirsTransactionExpress: Remove blank cvv element [davidsantoso]
62
+ * TransFirsTransactionExpress: Take into account blank string CVV [davidsantoso]
63
+ * Vanco: Improve handling of success determination [duff]
64
+ * Worldpay: Add hcgAdditionalData element [davidsantoso]
65
+ * Worldpay: Report error code [curiousepic]
66
+
3
67
  == Version 1.60.0 (July 4, 2016)
4
68
  * Orbital: Fix CC num leak on profile calls [drewblas]
5
69
  * VisaNetPeru: Add ability to refund [duff]
@@ -8,7 +8,7 @@ module ActiveMerchant
8
8
  self.test_url = 'https://apitest.authorize.net/xml/v1/request.api'
9
9
  self.live_url = 'https://api2.authorize.net/xml/v1/request.api'
10
10
 
11
- self.supported_countries = %w(AD AT AU BE BG CA CH CY CZ DE DK EE ES FI FR GB GB GI GR HU IE IS IT LI LT LU LV MC MT NL NO PL PT RO SE SI SK SM TR US VA)
11
+ self.supported_countries = %w(AD AT AU BE BG CA CH CY CZ DE DK EE ES FI FR GB GB GI GR HU IE IL IS IT LI LT LU LV MC MT NL NO PL PT RO SE SI SK SM TR US VA)
12
12
  self.default_currency = 'USD'
13
13
  self.money_format = :dollars
14
14
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro]
@@ -4,7 +4,7 @@ module ActiveMerchant #:nodoc:
4
4
  self.test_url = 'https://pal-test.barclaycardsmartpay.com/pal/servlet'
5
5
  self.live_url = 'https://pal-live.barclaycardsmartpay.com/pal/servlet'
6
6
 
7
- self.supported_countries = ['AR', 'AT', 'BE', 'BR', 'CA', 'CH', 'CL', 'CN', 'CO', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'HK', 'ID', 'IE', 'IL', 'IN', 'IT', 'JP', 'KR', 'LU', 'MX', 'MY', 'NL', 'NO', 'PA', 'PE', 'PH', 'PL', 'PT', 'RU', 'SE', 'SG', 'TH', 'TR', 'TW', 'US', 'VN', 'ZA']
7
+ self.supported_countries = ['AL', 'AD', 'AM', 'AT', 'AZ', 'BY', 'BE', 'BA', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'GE', 'DE', 'GR', 'HU', 'IS', 'IE', 'IT', 'KZ', 'LV', 'LI', 'LT', 'LU', 'MK', 'MT', 'MD', 'MC', 'ME', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SM', 'RS', 'SK', 'SI', 'ES', 'SE', 'CH', 'TR', 'UA', 'GB', 'VA']
8
8
  self.default_currency = 'EUR'
9
9
  self.money_format = :cents
10
10
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro]
@@ -62,6 +62,14 @@ module ActiveMerchant #:nodoc:
62
62
  commit('refund', post)
63
63
  end
64
64
 
65
+ def credit(money, creditcard, options = {})
66
+ post = payment_request(money, options)
67
+ post[:amount] = amount_hash(money, options[:currency])
68
+ post[:card] = credit_card_hash(creditcard)
69
+
70
+ commit('refundWithData', post)
71
+ end
72
+
65
73
  def void(identification, options = {})
66
74
  requires!(options, :order_id)
67
75
 
@@ -137,6 +145,8 @@ module ActiveMerchant #:nodoc:
137
145
  case e.response.code
138
146
  when '401'
139
147
  return Response.new(false, 'Invalid credentials', {}, :test => test?)
148
+ when '403'
149
+ return Response.new(false, 'Not allowed', {}, :test => test?)
140
150
  when '422'
141
151
  return Response.new(false, 'Unprocessable Entity', {}, :test => test?)
142
152
  when '500'
@@ -198,6 +208,7 @@ module ActiveMerchant #:nodoc:
198
208
  def success_from(response)
199
209
  return true if response.has_key?('authCode')
200
210
  return true if response['result'] == 'Success'
211
+ return true if response['resultCode'] == 'Received'
201
212
  successful_responses = %w([capture-received] [cancel-received] [refund-received])
202
213
  successful_responses.include?(response['response'])
203
214
  end
@@ -43,7 +43,7 @@ module ActiveMerchant #:nodoc:
43
43
  'USUAL_DATE' => :undoc_usual_date, # Not found in the bp20rebadmin API doc.
44
44
  }
45
45
 
46
- self.supported_countries = ['US']
46
+ self.supported_countries = ['US', 'CA']
47
47
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
48
48
  self.homepage_url = 'http://www.bluepay.com/'
49
49
  self.display_name = 'BluePay'
@@ -5,7 +5,7 @@ module ActiveMerchant
5
5
  class BlueSnapGateway < Gateway
6
6
  self.test_url = "https://sandbox.bluesnap.com/services/2"
7
7
  self.live_url = "https://ws.bluesnap.com/services/2"
8
- self.supported_countries = %w(US GB)
8
+ self.supported_countries = %w(US CA GB 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)
9
9
 
10
10
  self.default_currency = 'USD'
11
11
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
@@ -576,6 +576,14 @@ module ActiveMerchant #:nodoc:
576
576
  :cardholder_name => "#{credit_card_or_vault_id.first_name} #{credit_card_or_vault_id.last_name}",
577
577
  :cryptogram => credit_card_or_vault_id.payment_cryptogram
578
578
  }
579
+ elsif credit_card_or_vault_id.source == :android_pay
580
+ parameters[:android_pay_card] = {
581
+ :number => credit_card_or_vault_id.number,
582
+ :cryptogram => credit_card_or_vault_id.payment_cryptogram,
583
+ :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
584
+ :expiration_year => credit_card_or_vault_id.year.to_s,
585
+ :google_transaction_id => credit_card_or_vault_id.transaction_id
586
+ }
579
587
  end
580
588
  else
581
589
  parameters[:credit_card] = {
@@ -25,6 +25,7 @@ module ActiveMerchant #:nodoc:
25
25
  "HKD" => "344",
26
26
  "ICK" => "352",
27
27
  "JPY" => "392",
28
+ "MXN" => "484",
28
29
  "NOK" => "578",
29
30
  "NZD" => "554",
30
31
  "SEK" => "752",
@@ -87,6 +88,7 @@ module ActiveMerchant #:nodoc:
87
88
 
88
89
  def purchase(money, credit_card_or_reference, options = {})
89
90
  post = {}
91
+ add_pair(post, :captureDelay, 0)
90
92
  add_amount(post, money, options)
91
93
  add_invoice(post, credit_card_or_reference, money, options)
92
94
  add_credit_card_or_reference(post, credit_card_or_reference)
@@ -0,0 +1,24 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ class CitrusPayGateway < Gateway
4
+ include MastercardGateway
5
+
6
+ class_attribute :live_na_url, :live_ap_url, :test_na_url, :test_ap_url
7
+
8
+ self.test_na_url = 'https://test-gateway.mastercard.com/api/rest/version/39/'
9
+ self.test_ap_url = 'https://test-gateway.mastercard.com/api/rest/version/39/'
10
+
11
+ self.live_na_url = 'https://na-gateway.mastercard.com/api/rest/version/39/'
12
+ self.live_ap_url = 'https://ap-gateway.mastercard.com/api/rest/version/39/'
13
+
14
+ self.display_name = 'Citrus Pay'
15
+ self.homepage_url = 'http://www.citruspay.com/'
16
+ self.supported_countries = %w(AR AU BR FR DE HK MX NZ SG GB US)
17
+ self.default_currency = 'USD'
18
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro, :laser]
19
+ self.ssl_version = :TLSv1
20
+
21
+ end
22
+ end
23
+ end
24
+
@@ -10,6 +10,7 @@ module ActiveMerchant #:nodoc:
10
10
  'HU', 'IS', 'IE', 'IT', 'LV', 'LI', 'LT', 'LU', 'MT', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'GB']
11
11
 
12
12
  self.default_currency = 'EUR'
13
+ self.currencies_without_fractions = %w(BIF BYR DJF GNF JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
13
14
  self.supported_cardtypes = [:visa, :master]
14
15
 
15
16
  self.homepage_url = 'https://www.clearhaus.com'
@@ -121,7 +122,7 @@ module ActiveMerchant #:nodoc:
121
122
  end
122
123
 
123
124
  def add_amount(post, amount, options)
124
- post[:amount] = amount(amount)
125
+ post[:amount] = localized_amount(amount, options[:currency] || default_currency)
125
126
  post[:currency] = (options[:currency] || default_currency)
126
127
  end
127
128
 
@@ -173,7 +174,7 @@ module ActiveMerchant #:nodoc:
173
174
  success_from(response),
174
175
  message_from(response),
175
176
  response,
176
- authorization: authorization_from(response),
177
+ authorization: authorization_from(action, response),
177
178
  test: test?,
178
179
  error_code: error_code_from(response)
179
180
  )
@@ -193,8 +194,15 @@ module ActiveMerchant #:nodoc:
193
194
  end
194
195
  end
195
196
 
196
- def authorization_from(response)
197
- response['id']
197
+ def authorization_from(action, response)
198
+ id_of_auth_for_capture(action) || response['id']
199
+ end
200
+
201
+ def id_of_auth_for_capture(action)
202
+ match = action.match(/authorizations\/(.+)\/captures/)
203
+ return nil unless match
204
+
205
+ match.captures.first
198
206
  end
199
207
 
200
208
  def generate_signature(body)
@@ -12,7 +12,7 @@ module ActiveMerchant #:nodoc:
12
12
 
13
13
  def initialize(options = {})
14
14
  requires!(options, :key)
15
- options[:version] ||= '0.3.0'
15
+ options[:version] ||= '1.0.0'
16
16
  super
17
17
  end
18
18
 
@@ -55,6 +55,11 @@ module ActiveMerchant #:nodoc:
55
55
  commit(:post, "charges/#{identifier}/refund", post)
56
56
  end
57
57
 
58
+ def void(identifier, options = {})
59
+ post = {}
60
+ commit(:post, "charges/#{identifier}/void", post)
61
+ end
62
+
58
63
  def supports_scrubbing
59
64
  true
60
65
  end
@@ -0,0 +1,234 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class CredoraxGateway < Gateway
4
+ class_attribute :test_url, :live_na_url, :live_eu_url
5
+
6
+ self.display_name = "Credorax Gateway"
7
+ self.homepage_url = "https://www.credorax.com/"
8
+
9
+ self.test_url = "https://intconsole.credorax.com/intenv/service/gateway"
10
+
11
+ # The live URL is assigned on a per merchant basis once certification has passed
12
+ # See the Credorax remote tests for the full certification test suite
13
+ #
14
+ # Once you have your assigned subdomain, you can override the live URL in your application via:
15
+ # ActiveMerchant::Billing::CredoraxGateway.live_url = "https://assigned-subdomain.credorax.net/crax_gate/service/gateway"
16
+ self.live_url = 'https://assigned-subdomain.credorax.net/crax_gate/service/gateway'
17
+
18
+ self.supported_countries = %w(DE GB FR IT ES PL NL BE GR CZ PT SE HU RS AT CH BG DK FI SK NO IE HR BA AL LT MK SI LV EE ME LU MT IS AD MC LI SM)
19
+ self.default_currency = "EUR"
20
+ self.money_format = :cents
21
+ self.supported_cardtypes = [:visa, :master, :maestro]
22
+
23
+ def initialize(options={})
24
+ requires!(options, :merchant_id, :cipher_key)
25
+ super
26
+ end
27
+
28
+ def purchase(amount, payment_method, options={})
29
+ post = {}
30
+ add_invoice(post, amount, options)
31
+ add_payment_method(post, payment_method)
32
+ add_customer_data(post, options)
33
+ add_email(post, options)
34
+ add_echo(post, options)
35
+
36
+ commit(:purchase, post)
37
+ end
38
+
39
+ def authorize(amount, payment_method, options={})
40
+ post = {}
41
+ add_invoice(post, amount, options)
42
+ add_payment_method(post, payment_method)
43
+ add_customer_data(post, options)
44
+ add_email(post, options)
45
+ add_echo(post, options)
46
+
47
+ commit(:authorize, post)
48
+ end
49
+
50
+ def capture(amount, authorization, options={})
51
+ post = {}
52
+ add_invoice(post, amount, options)
53
+ add_reference(post, authorization)
54
+ add_customer_data(post, options)
55
+ add_echo(post, options)
56
+
57
+ commit(:capture, post)
58
+ end
59
+
60
+ def void(authorization, options={})
61
+ post = {}
62
+ add_customer_data(post, options)
63
+ reference_action = add_reference(post, authorization)
64
+ add_echo(post, options)
65
+ post[:a1] = options[:order_id] || generate_unique_id
66
+
67
+ commit(:void, post, reference_action)
68
+ end
69
+
70
+ def refund(amount, authorization, options={})
71
+ post = {}
72
+ add_invoice(post, amount, options)
73
+ add_reference(post, authorization)
74
+ add_customer_data(post, options)
75
+ add_echo(post, options)
76
+
77
+ commit(:refund, post)
78
+ end
79
+
80
+ def credit(amount, payment_method, options={})
81
+ post = {}
82
+ add_invoice(post, amount, options)
83
+ add_payment_method(post, payment_method)
84
+ add_customer_data(post, options)
85
+ add_email(post, options)
86
+ add_echo(post, options)
87
+
88
+ commit(:credit, post)
89
+ end
90
+
91
+ def verify(credit_card, options={})
92
+ MultiResponse.run(:use_first_response) do |r|
93
+ r.process { authorize(100, credit_card, options) }
94
+ r.process(:ignore_result) { void(r.authorization, options) }
95
+ end
96
+ end
97
+
98
+ def supports_scrubbing?
99
+ true
100
+ end
101
+
102
+ def scrub(transcript)
103
+ transcript.
104
+ gsub(%r((b1=)\d+), '\1[FILTERED]').
105
+ gsub(%r((b5=)\d+), '\1[FILTERED]')
106
+ end
107
+
108
+ private
109
+
110
+ def add_invoice(post, money, options)
111
+ post[:a4] = amount(money)
112
+ post[:a1] = options[:order_id] || generate_unique_id
113
+ post[:a5] = options[:currency] || currency(money)
114
+ end
115
+
116
+ CARD_TYPES = {
117
+ "visa" => '1',
118
+ "mastercard" => '2',
119
+ "maestro" => '9'
120
+ }
121
+
122
+ def add_payment_method(post, payment_method)
123
+ post[:c1] = payment_method.name
124
+ post[:b2] = CARD_TYPES[payment_method.brand] || ''
125
+ post[:b1] = payment_method.number
126
+ post[:b5] = payment_method.verification_value
127
+ post[:b4] = format(payment_method.year, :two_digits)
128
+ post[:b3] = format(payment_method.month, :two_digits)
129
+ end
130
+
131
+ def add_customer_data(post, options)
132
+ post[:d1] = options[:ip] || '127.0.0.1'
133
+ if (billing_address = options[:billing_address])
134
+ # Credorax has separate fields for street number and street name
135
+ post[:c4] = billing_address[:address1].split.first
136
+ post[:c5] = billing_address[:address1].split.drop(1).join(" ")
137
+ post[:c7] = billing_address[:city]
138
+ post[:c10] = billing_address[:zip]
139
+ post[:c8] = billing_address[:state]
140
+ post[:c9] = billing_address[:country]
141
+ post[:c2] = billing_address[:phone]
142
+ end
143
+ end
144
+
145
+ def add_reference(post, authorization)
146
+ response_id, authorization_code, request_id, action = authorization.split(";")
147
+ post[:g2] = response_id
148
+ post[:g3] = authorization_code
149
+ post[:g4] = request_id
150
+ action || :authorize
151
+ end
152
+
153
+ def add_email(post, options)
154
+ post[:c3] = options[:email] || 'unspecified@example.com'
155
+ end
156
+
157
+ def add_echo(post, options)
158
+ # The d2 parameter is used during the certification process
159
+ # See remote tests for full certification test suite
160
+ post[:d2] = options[:echo] unless options[:echo].blank?
161
+ end
162
+
163
+ ACTIONS = {
164
+ purchase: '1',
165
+ authorize: '2',
166
+ capture: '3',
167
+ authorize_void:'4',
168
+ refund: '5',
169
+ credit: '6',
170
+ purchase_void: '7',
171
+ refund_void: '8',
172
+ capture_void: '9'
173
+ }
174
+
175
+ def commit(action, params, reference_action = nil)
176
+ raw_response = ssl_post(url, post_data(action, params, reference_action))
177
+ response = parse(raw_response)
178
+
179
+ Response.new(
180
+ success_from(response),
181
+ message_from(response),
182
+ response,
183
+ authorization: "#{response["Z1"]};#{response["Z4"]};#{response["A1"]};#{action}",
184
+ avs_result: AVSResult.new(code: response["Z9"]),
185
+ cvv_result: CVVResult.new(response["Z14"]),
186
+ test: test?
187
+ )
188
+ end
189
+
190
+ def sign_request(params)
191
+ params = params.sort
192
+ params.each { |param| param[1].gsub!(/[<>()\\]/, ' ') }
193
+ values = params.map { |param| param[1].strip }
194
+ Digest::MD5.hexdigest(values.join + @options[:cipher_key])
195
+ end
196
+
197
+ def post_data(action, params, reference_action)
198
+ params.keys.each { |key| params[key] = params[key].to_s}
199
+ params[:M] = @options[:merchant_id]
200
+ params[:O] = request_action(action, reference_action)
201
+ params[:K] = sign_request(params)
202
+ params.map {|k, v| "#{k}=#{CGI.escape(v.to_s)}"}.join('&')
203
+ end
204
+
205
+ def request_action(action, reference_action)
206
+ if reference_action
207
+ ACTIONS["#{reference_action}_#{action}".to_sym]
208
+ else
209
+ ACTIONS[action]
210
+ end
211
+ end
212
+
213
+ def url
214
+ test? ? test_url : live_url
215
+ end
216
+
217
+ def parse(body)
218
+ Hash[CGI::parse(body).map{|k,v| [k.upcase,v.first]}]
219
+ end
220
+
221
+ def success_from(response)
222
+ response["Z2"] == "0"
223
+ end
224
+
225
+ def message_from(response)
226
+ if success_from(response)
227
+ "Succeeded"
228
+ else
229
+ response["Z3"] || "Unable to read error message"
230
+ end
231
+ end
232
+ end
233
+ end
234
+ end