activemerchant 1.16.0 → 1.17.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.
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