activemerchant 1.5.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/CHANGELOG +14 -0
  2. data/CONTRIBUTORS +4 -0
  3. data/lib/active_merchant.rb +1 -9
  4. data/lib/active_merchant/billing/credit_card_methods.rb +2 -2
  5. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +2 -2
  6. data/lib/active_merchant/billing/gateways/bogus.rb +12 -8
  7. data/lib/active_merchant/billing/gateways/garanti.rb +222 -0
  8. data/lib/active_merchant/billing/gateways/linkpoint.rb +1 -1
  9. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +1 -1
  10. data/lib/active_merchant/billing/gateways/paypal_express.rb +5 -0
  11. data/lib/active_merchant/billing/gateways/sage.rb +2 -2
  12. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +3 -3
  13. data/lib/active_merchant/common.rb +14 -0
  14. data/lib/active_merchant/{lib → common}/connection.rb +2 -0
  15. data/lib/active_merchant/{lib → common}/country.rb +1 -1
  16. data/lib/active_merchant/common/error.rb +26 -0
  17. data/lib/active_merchant/common/post_data.rb +24 -0
  18. data/lib/active_merchant/{lib → common}/posts_data.rb +0 -0
  19. data/lib/active_merchant/{lib → common}/requires_parameters.rb +0 -0
  20. data/lib/active_merchant/{lib → common}/utils.rb +0 -0
  21. data/lib/active_merchant/{lib → common}/validateable.rb +0 -0
  22. data/lib/activemerchant.rb +1 -0
  23. data/lib/support/outbound_hosts.rb +25 -0
  24. metadata +50 -44
  25. data.tar.gz.sig +0 -0
  26. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb.orig +0 -736
  27. data/lib/active_merchant/lib/error.rb +0 -4
  28. data/lib/active_merchant/lib/post_data.rb +0 -22
  29. metadata.gz.sig +0 -3
data/CHANGELOG CHANGED
@@ -1,5 +1,19 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
+ * Add a task rake gateways:hosts to get a list of all outbound hosts and ports [cody]
4
+ * Fix test failure in chronopay helper in Ruby 1.9.1 [cody]
5
+ * Fix timezone issue in credit card test. [cody]
6
+ * Fix failing unit test for Garanti gateway [cody]
7
+ * Fix failing CyberSource remote test [Patrick Joyce]
8
+ * Support for Garanti Sanal Pos: Turkish bank and billing gateway [Selem Delul]
9
+ * Add deprecation note for Money objects to Bogus gateway [Soleone]
10
+ * Updated test URL for Merchant eSolutions and added valid remote test credentials [Soleone]
11
+ * Add new error class for SSL certificate problems in connection class [Soleone]
12
+ * Update valid_month and valid_expiry_year to coerce string arguments to integers [cody]
13
+ * Add support for displaying credit cards with PayPal Express. Use the :allow_guest_checkout => true option when setting up the transaction [Edward Ocampo-Gooding]
14
+ * Use card_brand method for checking for checks in Sage and Beanstream [cody]
15
+ * Add JCB and Diners Club to LinkPoint [Soleone]
16
+
3
17
  == Version 1.5.1 (February 14, 2010)
4
18
 
5
19
  * Cleanup Rakefile, add gemspec and prepare for 1.5.1 release [cody]
@@ -132,3 +132,7 @@ JetPay (September 29, 2009)
132
132
  SallieMae (October 2, 2009)
133
133
 
134
134
  * iamjwc
135
+
136
+ Garanti (May 05, 2010)
137
+
138
+ * Selem Delul (moon@mac.home)
@@ -28,15 +28,7 @@ require 'builder'
28
28
  require 'cgi'
29
29
  require 'rexml/document'
30
30
 
31
- require 'active_merchant/lib/utils'
32
- require 'active_merchant/lib/error'
33
- require 'active_merchant/lib/validateable'
34
- require 'active_merchant/lib/connection'
35
- require 'active_merchant/lib/posts_data'
36
- require 'active_merchant/lib/post_data'
37
- require 'active_merchant/lib/requires_parameters'
38
- require 'active_merchant/lib/country'
39
-
31
+ require 'active_merchant/common'
40
32
  require 'active_merchant/billing'
41
33
 
42
34
  module ActiveMerchant #:nodoc:
@@ -22,11 +22,11 @@ module ActiveMerchant #:nodoc:
22
22
  end
23
23
 
24
24
  def valid_month?(month)
25
- (1..12).include?(month)
25
+ (1..12).include?(month.to_i)
26
26
  end
27
27
 
28
28
  def valid_expiry_year?(year)
29
- (Time.now.year..Time.now.year + 20).include?(year)
29
+ (Time.now.year..Time.now.year + 20).include?(year.to_i)
30
30
  end
31
31
 
32
32
  def valid_start_year?(year)
@@ -78,7 +78,7 @@ module ActiveMerchant #:nodoc:
78
78
 
79
79
  private
80
80
  def purchase_action(source)
81
- source.type.to_s == "check" ? :check_purchase : :purchase
81
+ card_brand(source) == "check" ? :check_purchase : :purchase
82
82
  end
83
83
 
84
84
  def void_action(original_transaction_type)
@@ -221,7 +221,7 @@ module ActiveMerchant #:nodoc:
221
221
  end
222
222
 
223
223
  def add_source(post, source)
224
- source.type == "check" ? add_check(post, source) : add_credit_card(post, source)
224
+ card_brand(source) == "check" ? add_check(post, source) : add_credit_card(post, source)
225
225
  end
226
226
 
227
227
  def add_transaction_type(post, action)
@@ -18,46 +18,50 @@ module ActiveMerchant #:nodoc:
18
18
  self.display_name = 'Bogus'
19
19
 
20
20
  def authorize(money, creditcard, options = {})
21
+ money = amount(money)
21
22
  case creditcard.number
22
23
  when '1'
23
- Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money.to_s}, :test => true, :authorization => AUTHORIZATION )
24
+ Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money}, :test => true, :authorization => AUTHORIZATION )
24
25
  when '2'
25
- Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money.to_s, :error => FAILURE_MESSAGE }, :test => true)
26
+ Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money, :error => FAILURE_MESSAGE }, :test => true)
26
27
  else
27
28
  raise Error, ERROR_MESSAGE
28
29
  end
29
30
  end
30
31
 
31
32
  def purchase(money, creditcard, options = {})
33
+ money = amount(money)
32
34
  case creditcard.number
33
35
  when '1'
34
- Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money.to_s}, :test => true)
36
+ Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
35
37
  when '2'
36
- Response.new(false, FAILURE_MESSAGE, {:paid_amount => money.to_s, :error => FAILURE_MESSAGE },:test => true)
38
+ Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
37
39
  else
38
40
  raise Error, ERROR_MESSAGE
39
41
  end
40
42
  end
41
43
 
42
44
  def credit(money, ident, options = {})
45
+ money = amount(money)
43
46
  case ident
44
47
  when '1'
45
48
  raise Error, CREDIT_ERROR_MESSAGE
46
49
  when '2'
47
- Response.new(false, FAILURE_MESSAGE, {:paid_amount => money.to_s, :error => FAILURE_MESSAGE }, :test => true)
50
+ Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
48
51
  else
49
- Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money.to_s}, :test => true)
52
+ Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
50
53
  end
51
54
  end
52
55
 
53
56
  def capture(money, ident, options = {})
57
+ money = amount(money)
54
58
  case ident
55
59
  when '1'
56
60
  raise Error, CAPTURE_ERROR_MESSAGE
57
61
  when '2'
58
- Response.new(false, FAILURE_MESSAGE, {:paid_amount => money.to_s, :error => FAILURE_MESSAGE }, :test => true)
62
+ Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
59
63
  else
60
- Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money.to_s}, :test => true)
64
+ Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
61
65
  end
62
66
  end
63
67
 
@@ -0,0 +1,222 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class GarantiGateway < Gateway
4
+ URL = 'https://ccpos.garanti.com.tr/servlet/cc5ApiServer'
5
+
6
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
7
+ self.supported_countries = ['US','TR']
8
+
9
+ # The card types supported by the payment gateway
10
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
11
+
12
+ # The homepage URL of the gateway
13
+ self.homepage_url = 'https://ccpos.garanti.com.tr/ccRaporlar/garanti/ccReports'
14
+
15
+ # The name of the gateway
16
+ self.display_name = 'Garanti Sanal POS'
17
+
18
+ self.default_currency = 'TRL'
19
+
20
+ CURRENCY_CODES = {
21
+ 'YTL' => 949,
22
+ 'TRL' => 949,
23
+ 'USD' => 840,
24
+ 'EUR' => 978
25
+ }
26
+
27
+
28
+ def initialize(options = {})
29
+ requires!(options, :login, :password, :client_id)
30
+ @options = options
31
+ super
32
+ end
33
+
34
+ def purchase(money, credit_card, options = {})
35
+ commit(money, build_sale_request(money, credit_card, options))
36
+ end
37
+
38
+ def authorize(money, credit_card, options = {})
39
+ commit(money, build_authorize_request(money, credit_card, options))
40
+ end
41
+
42
+ def capture(money, reference, options = {})
43
+ commit(money, build_capture_request(money,reference,options))
44
+ end
45
+
46
+ private
47
+
48
+ def build_xml_request(transaction_type,&block)
49
+ xml = Builder::XmlMarkup.new
50
+ xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
51
+
52
+ xml.tag! 'CC5Request' do
53
+ xml.tag! 'Name', @options[:login]
54
+ xml.tag! 'Password', @options[:password]
55
+ xml.tag! 'ClientId', @options[:client_id]
56
+ xml.tag! 'Mode', if test? then 'R' else 'P' end
57
+ xml.tag! 'Type', transaction_type
58
+
59
+ if block_given?
60
+ yield xml
61
+ else
62
+ xml.target!
63
+ end
64
+ end
65
+ end
66
+
67
+ def build_sale_request(money, credit_card, options)
68
+ build_xml_request('Auth') do |xml|
69
+ add_customer_data(xml,options)
70
+ add_order_data(xml,options)
71
+ add_credit_card(xml, credit_card)
72
+ add_addresses(xml, options)
73
+
74
+ xml.tag! 'Total', amount(money)
75
+ xml.tag! 'Currency', currency_code(options[:currency])
76
+
77
+ xml.target!
78
+ end
79
+ end
80
+
81
+ def build_authorize_request(money, credit_card, options)
82
+ build_xml_request('PreAuth') do |xml|
83
+ add_customer_data(xml,options)
84
+ add_order_data(xml,options)
85
+ add_credit_card(xml, credit_card)
86
+ add_addresses(xml, options)
87
+
88
+ xml.tag! 'Total', amount(money)
89
+ xml.tag! 'Currency', currency_code(options[:currency])
90
+
91
+ xml.target!
92
+
93
+ end
94
+ end
95
+
96
+ def build_capture_request(money, reference, options = {})
97
+ build_xml_request('PostAuth') do |xml|
98
+ add_customer_data(xml,options)
99
+ xml.tag! 'OrderId', reference
100
+ xml.tag! 'Total', amount(money)
101
+ xml.tag! 'Currency', currency_code(options[:currency])
102
+
103
+ xml.target!
104
+ end
105
+ end
106
+
107
+ def build_void_request(reference, options = {})
108
+ build_xml_request('Void') do |xml|
109
+ add_customer_data(xml,options)
110
+ xml.tag! 'OrderId', reference
111
+ xml.tag! 'Total', amount(money)
112
+ xml.tag! 'Currency', currency_code(options[:currency])
113
+
114
+ xml.target!
115
+ end
116
+ end
117
+
118
+ def build_credit_request(money, reference, options = {})
119
+ build_xml_request('Credit') do |xml|
120
+ add_customer_data(xml,options)
121
+ xml.tag! 'OrderId', reference
122
+ xml.tag! 'Total', amount(money)
123
+ xml.tag! 'Currency', currency_code(options[:currency])
124
+
125
+ xml.target!
126
+ end
127
+ end
128
+
129
+ def add_customer_data(xml, options)
130
+ xml.tag! 'IPAddress', options[:ip_]
131
+ xml.tag! 'Email', options[:email]
132
+ end
133
+
134
+ def add_order_data(xml,options)
135
+ xml.tag! 'OrderId', options[:order_id]
136
+ xml.tag! 'GroupId', nil
137
+ xml.tag! 'TransId', nil
138
+ end
139
+
140
+ def add_credit_card(xml, credit_card)
141
+ xml.tag! 'Number', credit_card.number
142
+ xml.tag! 'Expires', [format_exp(credit_card.month),format_exp(credit_card.year)].join('/')
143
+ xml.tag! 'Cvv2Val', credit_card.verification_value
144
+ end
145
+
146
+ def format_exp(value)
147
+ format(value, :two_digits)
148
+ end
149
+
150
+ def add_addresses(xml,options)
151
+ if billing_address = options[:billing_address] || options[:address]
152
+ xml.tag! 'BillTo' do
153
+ xml.tag! 'Name', billing_address[:name]
154
+ xml.tag! 'Street1', billing_address[:address1]
155
+ xml.tag! 'Street2', billing_address[:address2]
156
+ xml.tag! 'City', billing_address[:city]
157
+ xml.tag! 'StateProv', billing_address[:state]
158
+ xml.tag! 'PostalCode', billing_address[:zip]
159
+ xml.tag! 'Country', billing_address[:country]
160
+ xml.tag! 'Company', billing_address[:company]
161
+ xml.tag! 'TelVoice', billing_address[:phone]
162
+ end
163
+ end
164
+
165
+ if shipping_address = options[:shipping_address]
166
+ xml.tag! 'ShipTo' do
167
+ xml.tag! 'Name', shipping_address[:name]
168
+ xml.tag! 'Street1', shipping_address[:address1]
169
+ xml.tag! 'Street2', shipping_address[:address2]
170
+ xml.tag! 'City', shipping_address[:city]
171
+ xml.tag! 'StateProv',shipping_address[:state]
172
+ xml.tag! 'PostalCode',shipping_address[:zip]
173
+ xml.tag! 'Country', shipping_address[:country]
174
+ xml.tag! 'Company', shipping_address[:company]
175
+ xml.tag! 'TelVoice', shipping_address[:phone]
176
+ end
177
+ end
178
+ end
179
+
180
+ def currency_code(currency)
181
+ CURRENCY_CODES[currency] || CURRENCY_CODES[default_currency]
182
+ end
183
+
184
+ def commit(money,request)
185
+ raw_response = ssl_post(URL,"DATA=" + request)
186
+ response = parse(raw_response)
187
+
188
+ success = success?(response)
189
+
190
+ Response.new(success,
191
+ success ? 'Approved' : 'Declined',
192
+ response,
193
+ :test => test?,
194
+ :authorization => response[:order_id])
195
+ end
196
+
197
+ def parse(body)
198
+ xml = REXML::Document.new(body)
199
+
200
+ response = {}
201
+ xml.root.elements.to_a.each do |node|
202
+ parse_element(response, node)
203
+ end
204
+ response
205
+ end
206
+
207
+ def parse_element(response, node)
208
+ if node.has_elements?
209
+ node.elements.each{|element| parse_element(response, element) }
210
+ else
211
+ response[node.name.underscore.to_sym] = node.text
212
+ end
213
+ end
214
+
215
+ def success?(response)
216
+ response[:response] == "Approved"
217
+ end
218
+
219
+ end
220
+ end
221
+ end
222
+
@@ -134,7 +134,7 @@ module ActiveMerchant #:nodoc:
134
134
  self.ssl_strict = false
135
135
 
136
136
  self.supported_countries = ['US']
137
- self.supported_cardtypes = [:visa, :master, :american_express, :discover]
137
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
138
138
  self.homepage_url = 'http://www.linkpoint.com/'
139
139
  self.display_name = 'LinkPoint'
140
140
 
@@ -2,7 +2,7 @@ module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class MerchantESolutionsGateway < Gateway
4
4
 
5
- TEST_URL = 'https://test.merchante-solutions.com/mes-api/tridentApi'
5
+ TEST_URL = 'https://cert.merchante-solutions.com/mes-api/tridentApi'
6
6
  LIVE_URL = 'https://api.merchante-solutions.com/mes-api/tridentApi'
7
7
 
8
8
  # The countries the gateway supports merchants from as 2 digit ISO country codes
@@ -114,6 +114,11 @@ module ActiveMerchant #:nodoc:
114
114
  xml.tag! 'n2:cpp-header-border-color', options[:header_border_color] unless options[:header_border_color].blank?
115
115
  xml.tag! 'n2:cpp-payflow-color', options[:background_color] unless options[:background_color].blank?
116
116
 
117
+ if options[:allow_guest_checkout]
118
+ xml.tag! 'n2:SolutionType', 'Sole'
119
+ xml.tag! 'n2:LandingPage', 'Billing'
120
+ end
121
+
117
122
  xml.tag! 'n2:LocaleCode', options[:locale] unless options[:locale].blank?
118
123
  end
119
124
  end
@@ -88,7 +88,7 @@ module ActiveMerchant #:nodoc:
88
88
  # * <tt>:drivers_license_number</tt> - The customer's drivers license number.
89
89
  # * <tt>:date_of_birth</tt> - The customer's date of birth as a Time or Date object or a string in the format <tt>mm/dd/yyyy</tt>.
90
90
  def purchase(money, source, options = {})
91
- if source.type == "check"
91
+ if card_brand(source) == "check"
92
92
  virtual_check.purchase(money, source, options)
93
93
  else
94
94
  bankcard.purchase(money, source, options)
@@ -125,7 +125,7 @@ module ActiveMerchant #:nodoc:
125
125
  # * <tt>money</tt> - The amount to be authorized as an integer value in cents.
126
126
  # * <tt>source</tt> - The CreditCard or Check object to be used as the target for the credit.
127
127
  def credit(money, source, options = {})
128
- if source.type == "check"
128
+ if card_brand(source) == "check"
129
129
  virtual_check.credit(money, source, options)
130
130
  else
131
131
  bankcard.credit(money, source, options)
@@ -18,9 +18,9 @@ module ActiveMerchant #:nodoc:
18
18
  'DE' => %w( DE AT CH LI ),
19
19
  'PT' => %w( AO BR CV GW MZ PT ST TL),
20
20
  'RU' => %w( BY KG KZ RU ),
21
- 'LV' => 'LV',
22
- 'CN1' => 'CN',
23
- 'NL' => 'NL'
21
+ 'LV' => %w( LV ),
22
+ 'CN1' => %w( CN ),
23
+ 'NL' => %w( NL )
24
24
  }
25
25
 
26
26
  LANG_FOR_COUNTRY = COUNTRIES_FOR_LANG.inject(Hash.new("EN")) do |memo, (lang, countries)|
@@ -0,0 +1,14 @@
1
+ module ActiveMerchant
2
+ autoload :Connection, 'active_merchant/common/connection'
3
+ autoload :Country, 'active_merchant/common/country'
4
+ autoload :ActiveMerchantError, 'active_merchant/common/error'
5
+ autoload :ConnectionError, 'active_merchant/common/error'
6
+ autoload :RetriableConnectionError, 'active_merchant/common/error'
7
+ autoload :ResponseError, 'active_merchant/common/error'
8
+ autoload :ClientCertificateError, 'active_merchant/common/error'
9
+ autoload :PostData, 'active_merchant/common/post_data'
10
+ autoload :PostsData, 'active_merchant/common/posts_data'
11
+ autoload :RequiresParameters, 'active_merchant/common/requires_parameters'
12
+ autoload :Utils, 'active_merchant/common/utils'
13
+ autoload :Validateable, 'active_merchant/common/validateable'
14
+ end
@@ -80,6 +80,8 @@ module ActiveMerchant
80
80
  raise ConnectionError, "The remote server reset the connection"
81
81
  rescue Errno::ECONNREFUSED => e
82
82
  raise RetriableConnectionError, "The remote server refused the connection"
83
+ rescue OpenSSL::X509::CertificateError => e
84
+ raise ClientCertificateError, "The remote server did not accept the provided SSL certificate"
83
85
  rescue Timeout::Error, Errno::ETIMEDOUT => e
84
86
  raise ConnectionError, "The connection to the remote server timed out"
85
87
  end