activemerchant 1.16.0 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,6 +1,20 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
- == Version 1.16.0 (May 12, 2011)
3
+ == Version 1.17.0 (August 23, 2011)
4
+
5
+ * Add Payflow Link integration [jduff]
6
+ * Add CardSave gateway [MrJaba/jduff]]
7
+ * Quickpay: Support protocal version 4 and fraud parameters [anderslemke/jduff]
8
+ * Authorize.net: Add status_recurring [mm1/jduff]
9
+ * Paypal Express: Support specifying :items with purchase [sivabudh/jduff]
10
+ * ePay: Add Sweden and Norway to supported countries [ePay/jduff]
11
+ * Brainreee: Support passing merchant_account_id parameter [braintreeps/jduff]
12
+ * Paypal Express: Remove deprecated Address field in favor of ShipToAddress[jduff]
13
+ * Add Optimal Payments gateway [jamie/jduff]
14
+ * Documentation improvements [dasch/nhemsley/jstorimer/jduff]
15
+ * Authorize.Net: Pass through first name, last name, and zip for refunds. [ntalbott]
16
+
17
+ == Version 1.16.0 (July 18, 2011)
4
18
 
5
19
  * Bogus: Support referenced transactions for #authorize, #purchase, #recurring and
6
20
  #credit [dasch/jduff]
@@ -243,3 +243,11 @@ Paystation (July, 2011)
243
243
  ePaymentPlans offsite gatway (June, 2011)
244
244
 
245
245
  * Roberto Miranda (robertomiranda)
246
+
247
+ Optimal Payments (August, 2011)
248
+
249
+ * Jamie Macey (jamie)
250
+
251
+ CardSave (August 2011,)
252
+
253
+ * Tom Crinson (MrJaba)
@@ -4,22 +4,34 @@ require 'active_merchant/billing/expiry_date'
4
4
 
5
5
  module ActiveMerchant #:nodoc:
6
6
  module Billing #:nodoc:
7
- # == Description
8
- # This credit card object can be used as a stand alone object. It acts just like an ActiveRecord object
9
- # but doesn't support the .save method as its not backed by a database.
7
+ # A +CreditCard+ object represents a physical credit card, and is capable of validating the various
8
+ # data associated with these.
10
9
  #
11
- # For testing purposes, use the 'bogus' credit card type. This card skips the vast majority of
12
- # validations. This allows you to focus on your core concerns until you're ready to be more concerned
13
- # with the details of particular creditcards or your gateway.
10
+ # At the moment, the following credit card types are supported:
11
+ #
12
+ # * Visa
13
+ # * MasterCard
14
+ # * Discover
15
+ # * American Express
16
+ # * Diner's Club
17
+ # * JCB
18
+ # * Switch
19
+ # * Solo
20
+ # * Dankort
21
+ # * Maestro
22
+ # * Forbrugsforeningen
23
+ # * Laser
24
+ #
25
+ # For testing purposes, use the 'bogus' credit card type. This skips the vast majority of
26
+ # validations, allowing you to focus on your core concerns until you're ready to be more concerned
27
+ # with the details of particular credit cards or your gateway.
14
28
  #
15
29
  # == Testing With CreditCard
16
30
  # Often when testing we don't care about the particulars of a given card type. When using the 'test'
17
- # mode in your Gateway, there are six different valid card numbers: 1, 2, 3, 'success', 'fail',
31
+ # mode in your {Gateway}, there are six different valid card numbers: 1, 2, 3, 'success', 'fail',
18
32
  # and 'error'.
19
33
  #
20
- #--
21
- # For details, see CreditCardMethods#valid_number?
22
- #++
34
+ # For details, see {CreditCardMethods::ClassMethods#valid_number?}
23
35
  #
24
36
  # == Example Usage
25
37
  # cc = CreditCard.new(
@@ -38,44 +50,102 @@ module ActiveMerchant #:nodoc:
38
50
  include CreditCardMethods
39
51
  include Validateable
40
52
 
41
- ## Attributes
42
-
43
53
  cattr_accessor :require_verification_value
44
54
  self.require_verification_value = true
45
55
 
46
- # Essential attributes for a valid, non-bogus creditcards
47
- attr_accessor :number, :month, :year, :type, :first_name, :last_name
56
+ # Returns or sets the credit card number.
57
+ #
58
+ # @return [String]
59
+ attr_accessor :number
60
+
61
+ # Returns or sets the expiry month for the card.
62
+ #
63
+ # @return [Integer]
64
+ attr_accessor :month
65
+
66
+ # Returns or sets the expiry year for the card.
67
+ #
68
+ # @return [Integer]
69
+ attr_accessor :year
70
+
71
+ # Returns or sets the credit card type.
72
+ #
73
+ # Valid card types are
74
+ #
75
+ # * +'visa'+
76
+ # * +'master'+
77
+ # * +'discover'+
78
+ # * +'american_express'+
79
+ # * +'diners_club'+
80
+ # * +'jcb'+
81
+ # * +'switch'+
82
+ # * +'solo'+
83
+ # * +'dankort'+
84
+ # * +'maestro'+
85
+ # * +'forbrugsforeningen'+
86
+ # * +'laser'+
87
+ #
88
+ # Or, if you wish to test your implementation, +'bogus'+.
89
+ #
90
+ # @return (String) the credit card type
91
+ attr_accessor :type
92
+
93
+ # Returns or sets the first name of the card holder.
94
+ #
95
+ # @return [String]
96
+ attr_accessor :first_name
97
+
98
+ # Returns or sets the last name of the card holder.
99
+ #
100
+ # @return [String]
101
+ attr_accessor :last_name
48
102
 
49
103
  # Required for Switch / Solo cards
50
104
  attr_accessor :start_month, :start_year, :issue_number
51
105
 
52
- # Optional verification_value (CVV, CVV2 etc). Gateways will try their best to
53
- # run validation on the passed in value if it is supplied
106
+ # Returns or sets the card verification value.
107
+ #
108
+ # This attribute is optional but recommended. The verification value is
109
+ # a {card security code}[http://en.wikipedia.org/wiki/Card_security_code]. If provided,
110
+ # the gateway will attempt to validate the value.
111
+ #
112
+ # @return [String] the verification value
54
113
  attr_accessor :verification_value
55
114
 
56
115
  alias_method :brand, :type
57
-
116
+
58
117
  # Provides proxy access to an expiry date object
118
+ #
119
+ # @return [ExpiryDate]
59
120
  def expiry_date
60
121
  ExpiryDate.new(@month, @year)
61
122
  end
62
123
 
124
+ # Returns whether the credit card has expired.
125
+ #
126
+ # @return +true+ if the card has expired, +false+ otherwise
63
127
  def expired?
64
128
  expiry_date.expired?
65
129
  end
66
130
 
131
+ # Returns whether either the +first_name+ or the +last_name+ attributes has been set.
67
132
  def name?
68
133
  first_name? || last_name?
69
134
  end
70
135
 
136
+ # Returns whether the +first_name+ attribute has been set.
71
137
  def first_name?
72
138
  @first_name.present?
73
139
  end
74
140
 
141
+ # Returns whether the +last_name+ attribute has been set.
75
142
  def last_name?
76
143
  @last_name.present?
77
144
  end
78
145
 
146
+ # Returns the full name of the card holder.
147
+ #
148
+ # @return [String] the full name of the card holder
79
149
  def name
80
150
  [@first_name, @last_name].compact.join(' ')
81
151
  end
@@ -90,7 +160,16 @@ module ActiveMerchant #:nodoc:
90
160
  !@verification_value.blank?
91
161
  end
92
162
 
93
- # Show the card number, with all but last 4 numbers replace with "X". (XXXX-XXXX-XXXX-4338)
163
+ # Returns a display-friendly version of the card number.
164
+ #
165
+ # All but the last 4 numbers are replaced with an "X", and hyphens are
166
+ # inserted in order to improve legibility.
167
+ #
168
+ # @example
169
+ # credit_card = CreditCard.new(:number => "2132542376824338")
170
+ # credit_card.display_number # "XXXX-XXXX-XXXX-4338"
171
+ #
172
+ # @return [String] a display-friendly version of the card number
94
173
  def display_number
95
174
  self.class.mask(number)
96
175
  end
@@ -99,6 +178,9 @@ module ActiveMerchant #:nodoc:
99
178
  self.class.last_digits(number)
100
179
  end
101
180
 
181
+ # Validates the credit card details.
182
+ #
183
+ # Any validation errors are added to the {#errors} attribute.
102
184
  def validate
103
185
  validate_essential_attributes
104
186
 
@@ -19,7 +19,7 @@ module ActiveMerchant #:nodoc:
19
19
  #
20
20
  # Automated Recurring Billing (ARB) is an optional service for submitting and managing recurring, or subscription-based, transactions.
21
21
  #
22
- # To use recurring, update_recurring, and cancel_recurring ARB must be enabled for your account.
22
+ # To use recurring, update_recurring, cancel_recurring and status_recurring ARB must be enabled for your account.
23
23
  #
24
24
  # Information about ARB is available on the {Authorize.Net website}[http://www.authorize.net/solutions/merchantsolutions/merchantservices/automatedrecurringbilling/].
25
25
  # Information about the ARB API is available at the {Authorize.Net Integration Center}[http://developer.authorize.net/]
@@ -55,7 +55,8 @@ module ActiveMerchant #:nodoc:
55
55
  RECURRING_ACTIONS = {
56
56
  :create => 'ARBCreateSubscription',
57
57
  :update => 'ARBUpdateSubscription',
58
- :cancel => 'ARBCancelSubscription'
58
+ :cancel => 'ARBCancelSubscription',
59
+ :status => 'ARBGetSubscriptionStatus'
59
60
  }
60
61
 
61
62
  # Creates a new AuthorizeNetGateway
@@ -149,12 +150,20 @@ module ActiveMerchant #:nodoc:
149
150
  # ==== Options
150
151
  #
151
152
  # * <tt>:card_number</tt> -- The credit card number the refund is being issued to. (REQUIRED)
153
+ # * <tt>:first_name</tt> -- The first name of the account being refunded.
154
+ # * <tt>:last_name</tt> -- The last name of the account being refunded.
155
+ # * <tt>:zip</tt> -- The postal code of the account being refunded.
152
156
  def refund(money, identification, options = {})
153
157
  requires!(options, :card_number)
154
158
 
155
159
  post = { :trans_id => identification,
156
160
  :card_num => options[:card_number]
157
161
  }
162
+
163
+ post[:first_name] = options[:first_name] if options[:first_name]
164
+ post[:last_name] = options[:last_name] if options[:last_name]
165
+ post[:zip] = options[:zip] if options[:zip]
166
+
158
167
  add_invoice(post, options)
159
168
  add_duplicate_window(post)
160
169
 
@@ -234,6 +243,19 @@ module ActiveMerchant #:nodoc:
234
243
  recurring_commit(:cancel, request)
235
244
  end
236
245
 
246
+ # Get Subscription Status of a recurring payment.
247
+ #
248
+ # This transaction gets the status of an existing Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled.
249
+ #
250
+ # ==== Parameters
251
+ #
252
+ # * <tt>subscription_id</tt> -- A string containing the +subscription_id+ of the recurring payment already in place
253
+ # for a given credit card. (REQUIRED)
254
+ def status_recurring(subscription_id)
255
+ request = build_recurring_request(:status, :subscription_id => subscription_id)
256
+ recurring_commit(:status, request)
257
+ end
258
+
237
259
  private
238
260
 
239
261
  def commit(action, money, parameters)
@@ -447,6 +469,13 @@ module ActiveMerchant #:nodoc:
447
469
  xml.target!
448
470
  end
449
471
 
472
+ # Builds body for ARBGetSubscriptionStatusRequest
473
+ def build_arb_status_subscription_request(xml, options)
474
+ xml.tag!('subscriptionId', options[:subscription_id])
475
+
476
+ xml.target!
477
+ end
478
+
450
479
  # Adds subscription information
451
480
  def add_arb_subscription(xml, options)
452
481
  xml.tag!('subscription') do
@@ -158,36 +158,10 @@ module ActiveMerchant #:nodoc:
158
158
  end
159
159
 
160
160
  def create_transaction(transaction_type, money, credit_card_or_vault_id, options)
161
- parameters = {
162
- :amount => amount(money).to_s,
163
- :order_id => options[:order_id],
164
- :customer => {
165
- :id => options[:store] == true ? "" : options[:store],
166
- :email => options[:email]
167
- },
168
- :options => {
169
- :store_in_vault => options[:store] ? true : false,
170
- :submit_for_settlement => options[:submit_for_settlement]
171
- }
172
- }
173
- if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer)
174
- parameters[:customer_id] = credit_card_or_vault_id
175
- else
176
- parameters[:customer].merge!(
177
- :first_name => credit_card_or_vault_id.first_name,
178
- :last_name => credit_card_or_vault_id.last_name
179
- )
180
- parameters[:credit_card] = {
181
- :number => credit_card_or_vault_id.number,
182
- :cvv => credit_card_or_vault_id.verification_value,
183
- :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
184
- :expiration_year => credit_card_or_vault_id.year.to_s
185
- }
186
- end
187
- parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address]
188
- parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
161
+ transaction_params = create_transaction_parameters(money, credit_card_or_vault_id, options)
162
+
189
163
  commit do
190
- result = Braintree::Transaction.send(transaction_type, parameters)
164
+ result = Braintree::Transaction.send(transaction_type, transaction_params)
191
165
  response_params, response_options, avs_result, cvv_result = {}, {}, {}, {}
192
166
  if result.success?
193
167
  response_params[:braintree_transaction] = transaction_hash(result.transaction)
@@ -201,7 +175,7 @@ module ActiveMerchant #:nodoc:
201
175
  :postal_match => result.transaction.avs_postal_code_response_code
202
176
  }
203
177
  response_options[:cvv_result] = result.transaction.cvv_response_code
204
- message = result.transaction.processor_response_code + " " + result.transaction.processor_response_text
178
+ message = "#{result.transaction.processor_response_code} #{result.transaction.processor_response_text}"
205
179
  else
206
180
  message = message_from_result(result)
207
181
  end
@@ -279,13 +253,49 @@ module ActiveMerchant #:nodoc:
279
253
  }
280
254
 
281
255
  {
282
- "order_id" => transaction.order_id,
283
- "status" => transaction.status,
284
- "customer_details" => customer_details,
285
- "billing_details" => billing_details,
286
- "shipping_details" => shipping_details,
287
- "vault_customer" => vault_customer
256
+ "order_id" => transaction.order_id,
257
+ "status" => transaction.status,
258
+ "customer_details" => customer_details,
259
+ "billing_details" => billing_details,
260
+ "shipping_details" => shipping_details,
261
+ "vault_customer" => vault_customer,
262
+ "merchant_account_id" => transaction.merchant_account_id
263
+ }
264
+ end
265
+
266
+ def create_transaction_parameters(money, credit_card_or_vault_id, options)
267
+ parameters = {
268
+ :amount => amount(money).to_s,
269
+ :order_id => options[:order_id],
270
+ :customer => {
271
+ :id => options[:store] == true ? "" : options[:store],
272
+ :email => options[:email]
273
+ },
274
+ :options => {
275
+ :store_in_vault => options[:store] ? true : false,
276
+ :submit_for_settlement => options[:submit_for_settlement]
277
+ }
288
278
  }
279
+ if options.has_key?(:merchant_account_id)
280
+ parameters[:merchant_account_id] = options[:merchant_account_id]
281
+ end
282
+ if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer)
283
+ parameters[:customer_id] = credit_card_or_vault_id
284
+ else
285
+ parameters[:customer].merge!(
286
+ :first_name => credit_card_or_vault_id.first_name,
287
+ :last_name => credit_card_or_vault_id.last_name
288
+ )
289
+ parameters[:credit_card] = {
290
+ :number => credit_card_or_vault_id.number,
291
+ :cvv => credit_card_or_vault_id.verification_value,
292
+ :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
293
+ :expiration_year => credit_card_or_vault_id.year.to_s
294
+ }
295
+ end
296
+ parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address]
297
+ parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
298
+ parameters
289
299
  end
290
300
  end
291
301
  end
@@ -0,0 +1,23 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class CardSaveGateway < IridiumGateway
4
+ #CardSave lets you handle failovers on payments by providing 3 gateways in case one happens to be down
5
+ #URLS = ['https://gw1.cardsaveonlinepayments.com:4430/','https://gw2.cardsaveonlinepayments.com:4430/','https://gw3.cardsaveonlinepayments.com:4430/']
6
+
7
+ self.money_format = :cents
8
+ self.default_currency = 'GBP'
9
+ self.supported_cardtypes = [ :visa, :switch, :maestro, :master, :solo, :american_express, :jcb ]
10
+ self.supported_countries = [ 'GB' ]
11
+ self.homepage_url = 'http://www.cardsave.net/'
12
+ self.display_name = 'CardSave'
13
+
14
+ def initialize(options={})
15
+ super
16
+ @test_url = 'https://gw1.cardsaveonlinepayments.com:4430/'
17
+ @live_url = 'https://gw1.cardsaveonlinepayments.com:4430/'
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+
@@ -8,7 +8,7 @@ module ActiveMerchant #:nodoc:
8
8
  self.money_format = :cents
9
9
  self.supported_cardtypes = [:dankort, :forbrugsforeningen, :visa, :master,
10
10
  :american_express, :diners_club, :jcb, :maestro]
11
- self.supported_countries = ['DK']
11
+ self.supported_countries = ['DK', 'SE', 'NO']
12
12
  self.homepage_url = 'http://epay.dk/'
13
13
  self.display_name = 'ePay'
14
14
 
@@ -7,8 +7,6 @@ module ActiveMerchant #:nodoc:
7
7
  # login to the Iridium Merchant Management System. Instead, you will
8
8
  # use the API username and password you were issued separately.
9
9
  class IridiumGateway < Gateway
10
- TEST_URL = 'https://gw1.iridiumcorp.net/'
11
- LIVE_URL = 'https://gw1.iridiumcorp.net/'
12
10
 
13
11
  # The countries the gateway supports merchants from as 2 digit ISO country codes
14
12
  self.supported_countries = ['GB', 'ES']
@@ -37,6 +35,8 @@ module ActiveMerchant #:nodoc:
37
35
  def initialize(options = {})
38
36
  requires!(options, :login, :password)
39
37
  @options = options
38
+ @test_url = 'https://gw1.iridiumcorp.net/'
39
+ @live_url = 'https://gw1.iridiumcorp.net/'
40
40
  super
41
41
  end
42
42
 
@@ -172,7 +172,7 @@ module ActiveMerchant #:nodoc:
172
172
 
173
173
  def commit(request, options)
174
174
  requires!(options, :action)
175
- response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request,
175
+ response = parse(ssl_post(test? ? @test_url : @live_url, request,
176
176
  {"SOAPAction" => "https://www.thepaymentgateway.net/#{options[:action]}",
177
177
  "Content-Type" => "text/xml; charset=utf-8" }))
178
178