activemerchant 1.42.2 → 1.42.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG +32 -0
  5. data/CONTRIBUTORS +12 -0
  6. data/README.md +3 -0
  7. data/lib/active_merchant/billing/base.rb +9 -2
  8. data/lib/active_merchant/billing/credit_card_methods.rb +1 -1
  9. data/lib/active_merchant/billing/gateway.rb +1 -1
  10. data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
  11. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +8 -8
  12. data/lib/active_merchant/billing/gateways/balanced.rb +7 -2
  13. data/lib/active_merchant/billing/gateways/beanstream.rb +1 -1
  14. data/lib/active_merchant/billing/gateways/bogus.rb +32 -22
  15. data/lib/active_merchant/billing/gateways/braintree_blue.rb +124 -39
  16. data/lib/active_merchant/billing/gateways/cyber_source.rb +2 -2
  17. data/lib/active_merchant/billing/gateways/litle.rb +1 -1
  18. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
  19. data/lib/active_merchant/billing/gateways/moneris.rb +1 -1
  20. data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
  21. data/lib/active_merchant/billing/gateways/nab_transact.rb +3 -1
  22. data/lib/active_merchant/billing/gateways/netpay.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/pay_junction.rb +7 -7
  24. data/lib/active_merchant/billing/gateways/payex.rb +402 -0
  25. data/lib/active_merchant/billing/gateways/payflow.rb +41 -11
  26. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/paymill.rb +55 -3
  28. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  29. data/lib/active_merchant/billing/gateways/payscout.rb +171 -0
  30. data/lib/active_merchant/billing/gateways/pin.rb +1 -1
  31. data/lib/active_merchant/billing/gateways/realex.rb +1 -1
  32. data/lib/active_merchant/billing/gateways/redsys.rb +1 -1
  33. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  34. data/lib/active_merchant/billing/gateways/stripe.rb +23 -25
  35. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +26 -15
  36. data/lib/active_merchant/billing/gateways/webpay.rb +27 -11
  37. data/lib/active_merchant/billing/gateways/wirecard.rb +1 -1
  38. data/lib/active_merchant/billing/integrations/bit_pay/helper.rb +1 -1
  39. data/lib/active_merchant/billing/integrations/ipay88.rb +4 -0
  40. data/lib/active_merchant/billing/integrations/ipay88/helper.rb +1 -1
  41. data/lib/active_merchant/billing/integrations/ipay88/notification.rb +103 -0
  42. data/lib/active_merchant/billing/integrations/ipay88/return.rb +8 -74
  43. data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +1 -1
  44. data/lib/active_merchant/billing/integrations/paypal/helper.rb +1 -1
  45. data/lib/active_merchant/billing/integrations/payu_in.rb +2 -9
  46. data/lib/active_merchant/billing/integrations/payu_in/helper.rb +15 -13
  47. data/lib/active_merchant/billing/integrations/payu_in/notification.rb +9 -20
  48. data/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb +1 -1
  49. data/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb +0 -10
  50. data/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb +1 -1
  51. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +1 -1
  52. data/lib/active_merchant/billing/integrations/valitor/helper.rb +3 -3
  53. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +2 -2
  54. data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +1 -1
  55. data/lib/active_merchant/billing/integrations/wirecard_checkout_page.rb +1 -1
  56. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +2 -2
  57. data/lib/active_merchant/version.rb +1 -1
  58. metadata +7 -3
  59. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MjQ2OTAyZDUwMzYxMTA1ZDkwODdiNWI4NjY1NzcyNTkyOWNhMjdmMw==
4
+ NjhkNTg2ZGQxMmYxMTJjMGVhNTZhOWJhMmM4NWE5OTEzMDRiZGY0Ng==
5
5
  data.tar.gz: !binary |-
6
- Y2RjZGZhZjJhNGY1MTlmMTcxM2VmZWM0Y2NkZjY0NWViNzU1YjY3Yg==
6
+ ZGI2ZmRkZWVjN2Y5NTYyNDQ2MmQ3NWRiNzg3MWQ2Y2FjMjk4NjY1ZQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OWZjNTExODRmNGZhYTZmNjUxM2NmMjg0YjYzN2Y0MTE5ZWZjZTAyNjM2YWQ0
10
- ZTk1NGRlMzFjZTYwYTg3MWU1N2QxMjllOGM5YTQxODhjODk2NDJlZDM5MzA0
11
- N2QwOTJkYjRlMTc4NTIyZjc5YTFlNTZmMzQ2YjViZDQzMjA5NzQ=
9
+ OGJhMjg0N2JjNDI5ZDk3Y2MyM2ExNzY2NDQ4MmU1MjUwNWNhYTg3NTEyNmQx
10
+ NjE1MDMxMjcxZjBhNGY1OTQ0NzMwNDkzYTQwMjQzZTY1N2U1ZjhkMzFkNzYy
11
+ OTQ1YmEwOWVlYjdmNjI4ZmMyYWI4MGIwOGJkNWM1Njk1N2UxMDM=
12
12
  data.tar.gz: !binary |-
13
- NmQ5YjFlNThjMDA4ZDE1NDZjMTI3MWY2OTI3NzdjMmU1YjhmZmZkN2JiN2Ni
14
- YTExODQ5NjE0MTU3YmZhNTFmYjc0ZDJiMjRkMmFiOTc3ZjBiOGJlNDI2ZTJi
15
- MDNmOGE4OWQyYmExNzg0MDg4OWYyMDc2MzIzNTI3Y2E2NDFmNjQ=
13
+ NTlkYjg4NGY2OGE5ZmZhN2ZiZGY3MDhlM2E3NjFlZmNlNzdmMDQxZTgyZWQx
14
+ NDk5MDQ0OTU2MTYzNDU1YjNlMjIxNzE3NzY3ZGVkNDVkOTVmZDQ3OTA3MDE4
15
+ NDYzMWIzNWNkOTVjZGFlYzExODcxYTliYzYxYWVhMTY4ZGFkOGY=
Binary file
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,5 +1,37 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
+ == Version 1.42.3 (December 18th, 2013)
4
+
5
+ * Balanced: Add support for appears_on_statement_as [duff]
6
+ * Authorize.Net: Make already actioned responses failures [odorcicd]
7
+ * Add Payex gateway [atomgiant]
8
+ * Paymill: Fix authorizations [duff]
9
+ * Braintree Blue: Allow specifying the credit card token [ntalbott]
10
+ * Braintree Blue: Allow specifying the customer id [ntalbott]
11
+ * Braintree Blue: Scrub invalid emails and zips [ntalbott]
12
+ * Braintree Blue: Return :credit_card_token as a top level param [ntalbott]
13
+ * Braintree Blue: Allow unstoring just a credit card [ntalbott]
14
+ * Braintree Blue: #store adds cards to existing customers [ntalbott]
15
+ * USA ePay Advanced: Fix check handling [nearapogee]
16
+ * USA ePay Advanced: Fix credit card expiration handling [nearapogee]
17
+ * USA ePay Advanced: Fix handling of custom transaction responses for single items [nearapogee]
18
+ * USA ePay Advanced: Fix capture amount [nearapogee]
19
+ * NAB Transact: Fix merchant descriptor with capture/refund requests [nagash]
20
+ * Braintree Blue: Add custom_fields & device_data parameters [parallel588]
21
+ * Webpay: Add authorize & capture [keikubo]
22
+ * MerchantWarrior: Pass description [duff]
23
+ * Stripe: Separate email from description [duff]
24
+ * Add Payscout gateway [llopez]
25
+ * Merchant Warrior: Use billing_address [duff]
26
+ * Add SoEasyPay gateway [ir-soeasycorp]
27
+ * Bogus: Add check support [npverni]
28
+ * Payflow: Add Check support [crazyivan]
29
+ * Stripe: Allow expanding objects inline [odorcicd]
30
+
31
+ == Version 1.42.2 (November 13th, 2013)
32
+
33
+ * Renew public certificate
34
+
3
35
  == Version 1.42.1 (November 13th, 2013)
4
36
 
5
37
  * Signed version of 1.42.0
@@ -436,3 +436,15 @@ Swipe Checkout (November 2013)
436
436
  Raven PacNet (November 2013)
437
437
 
438
438
  * Luis Lopez (llopez)
439
+
440
+ Payex (November 2013)
441
+
442
+ * Tom Davies (atomgiant)
443
+
444
+ Payscout (December 2013)
445
+
446
+ * Luis Lopez (llopez)
447
+
448
+ SoEasyPay (December 2013)
449
+
450
+ * Ivan Radovanovic (ir-soeasycorp)
data/README.md CHANGED
@@ -144,6 +144,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
144
144
  * [PayJunction](http://www.payjunction.com/) - US
145
145
  * [PaySecure](http://www.commsecure.com.au/paysecure.shtml) - AU
146
146
  * [Paybox Direct](http://www.paybox.com/) - FR
147
+ * [Payex](http://payex.com/) - DK, NO, SE
147
148
  * [PaymentExpress](http://www.paymentexpress.com/) - AU, CA, DE, ES, FR, GB, HK, IE, MY, NL, NZ, SG, US, ZA
148
149
  * [PAYMILL](https://paymill.com) - AD, AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GI, GR, HU, IE, IL, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, RO, SE, SI, SK, TR, VA
149
150
  * [PayPal Express Checkout](https://www.paypal.com/webapps/mpp/express-checkout) - US, CA, SG, AU
@@ -153,6 +154,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
153
154
  * [PayPal Payments Pro (UK)](https://www.paypal.com/uk/webapps/mpp/pro) - GB
154
155
  * [PayPal Website Payments Pro (CA)](https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside) - CA
155
156
  * [PayPal Express Checkout for Digital Goods](https://www.x.com/community/ppx/xspaces/digital_goods) - AU, CA, CN, FI, GB, ID, IN, IT, MY, NO, NZ, PH, PL, SE, SG, TH, VN
157
+ * [Payscout](http://www.payscout.com/) - US
156
158
  * [Paystation](http://paystation.co.nz) - NZ
157
159
  * [Pay Way](http://www.payway.com.au) - AU
158
160
  * [Pin](http://www.pin.net.au/) - AU
@@ -173,6 +175,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
173
175
  * [SecurePay](http://www.securepay.com/) - US, CA, GB, AU
174
176
  * [SecurePayTech](http://www.securepaytech.com/) - NZ
175
177
  * [SkipJack](http://www.skipjack.com/) - US, CA
178
+ * [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
176
179
  * [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
177
180
  * [Stripe](https://stripe.com/) - US, CA, GB, AU, IE, FR, NL, BE, DE, ES
178
181
  * [Swipe](https://www.swipehq.com/checkout) - CA, NZ
@@ -31,8 +31,15 @@ module ActiveMerchant #:nodoc:
31
31
  #
32
32
  # ActiveMerchant::Billing::Base.gateway('moneris').new
33
33
  def self.gateway(name)
34
- raise NameError if (name_str = name.to_s.downcase).blank?
35
- Billing.const_get("#{name_str}_gateway".camelize)
34
+ name_str = name.to_s.strip.downcase
35
+
36
+ raise(ArgumentError, 'A gateway provider must be specified') if name_str.blank?
37
+
38
+ begin
39
+ Billing.const_get("#{name_str}_gateway".camelize)
40
+ rescue
41
+ raise ArgumentError, "The specified gateway is not valid (#{name_str})"
42
+ end
36
43
  end
37
44
 
38
45
  # Return the matching integration module
@@ -126,7 +126,7 @@ module ActiveMerchant #:nodoc:
126
126
  %w[1 2 3 success failure error].include?(number.to_s)
127
127
  end
128
128
 
129
- # Checks the validity of a card number by use of the the Luhn Algorithm.
129
+ # Checks the validity of a card number by use of the Luhn Algorithm.
130
130
  # Please see http://en.wikipedia.org/wiki/Luhn_algorithm for details.
131
131
  def valid_checksum?(number) #:nodoc:
132
132
  sum = 0
@@ -62,7 +62,7 @@ module ActiveMerchant #:nodoc:
62
62
  include Utils
63
63
 
64
64
  DEBIT_CARDS = [ :switch, :solo ]
65
- CURRENCIES_WITHOUT_FRACTIONS = [ 'JPY', 'HUF', 'TWD' ]
65
+ CURRENCIES_WITHOUT_FRACTIONS = [ 'JPY', 'HUF', 'TWD', 'ISK' ]
66
66
  CREDIT_DEPRECATION_MESSAGE = "Support for using credit to refund existing transactions is deprecated and will be removed from a future release of ActiveMerchant. Please use the refund method instead."
67
67
 
68
68
  cattr_reader :implementations
@@ -51,6 +51,7 @@ module ActiveMerchant #:nodoc:
51
51
  CARD_CODE_ERRORS = %w( N S )
52
52
  AVS_ERRORS = %w( A E N R W Z )
53
53
  AVS_REASON_CODES = %w(27 45)
54
+ TRANSACTION_ALREADY_ACTIONED = %w(310 311)
54
55
 
55
56
  AUTHORIZE_NET_ARB_NAMESPACE = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'
56
57
 
@@ -199,7 +200,7 @@ module ActiveMerchant #:nodoc:
199
200
  # For example, to charge the customer once every three months the hash would be
200
201
  # +:interval => { :unit => :months, :length => 3 }+ (REQUIRED)
201
202
  # * <tt>:duration</tt> -- A hash containing keys for the <tt>:start_date</tt> the subscription begins (also the date the
202
- # initial billing occurs) and the total number of billing <tt>:occurences</tt> or payments for the subscription. (REQUIRED)
203
+ # initial billing occurs) and the total number of billing <tt>:occurrences</tt> or payments for the subscription. (REQUIRED)
203
204
  def recurring(money, creditcard, options={})
204
205
  requires!(options, :interval, :duration, :billing_address)
205
206
  requires!(options[:interval], :length, [:unit, :days, :months])
@@ -294,7 +295,7 @@ module ActiveMerchant #:nodoc:
294
295
  end
295
296
 
296
297
  def success?(response)
297
- response[:response_code] == APPROVED
298
+ response[:response_code] == APPROVED && TRANSACTION_ALREADY_ACTIONED.exclude?(response[:response_reason_code])
298
299
  end
299
300
 
300
301
  def fraud_review?(response)
@@ -95,7 +95,7 @@ module ActiveMerchant #:nodoc:
95
95
  # * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
96
96
  # Otherwise, perform transactions against the production server.
97
97
  # * <tt>:test_requests</tt> -- +true+ or +false+. If true, perform transactions without the
98
- # test flag. This is useful when you need to generate card declines, AVS or CVV erros.
98
+ # test flag. This is useful when you need to generate card declines, AVS or CVV errors.
99
99
  # Will hold the same value as :test by default.
100
100
  # * <tt>:delimiter</tt> -- The delimiter used in the direct response. Default is ',' (comma).
101
101
  def initialize(options = {})
@@ -340,7 +340,7 @@ module ActiveMerchant #:nodoc:
340
340
  # ==== Transaction
341
341
  #
342
342
  # * <tt>:type</tt> -- The type of transaction. Can be either <tt>:auth_only</tt>, <tt>:capture_only</tt>, <tt>:auth_capture</tt>, <tt>:prior_auth_capture</tt>, <tt>:refund</tt> or <tt>:void</tt>. (REQUIRED)
343
- # * <tt>:amount</tt> -- The amount for the tranaction. Formatted with a decimal. For example "4.95" (CONDITIONAL)
343
+ # * <tt>:amount</tt> -- The amount for the transaction. Formatted with a decimal. For example "4.95" (CONDITIONAL)
344
344
  # - :type == :void (NOT USED)
345
345
  # - :type == :refund (OPTIONAL)
346
346
  # - :type == (:auth_only, :capture_only, :auth_capture, :prior_auth_capture) (REQUIRED)
@@ -369,8 +369,8 @@ module ActiveMerchant #:nodoc:
369
369
  # - :type = (:prior_auth_capture) (OPTIONAL)
370
370
  #
371
371
  # ==== For :type == :refund only
372
- # * <tt>:credit_card_number_masked</tt> -- (CONDITIONAL - requied for credit card refunds is :customer_profile_id AND :customer_payment_profile_id are missing)
373
- # * <tt>:bank_routing_number_masked && :bank_account_number_masked</tt> -- (CONDITIONAL - requied for electronic check refunds is :customer_profile_id AND :customer_payment_profile_id are missing) (NOT ABLE TO TEST - I keep getting "ACH transactions are not accepted by this merchant." when trying to make a payment and, until that's possible I can't refund (wiseleyb@gmail.com))
372
+ # * <tt>:credit_card_number_masked</tt> -- (CONDITIONAL - required for credit card refunds if :customer_profile_id AND :customer_payment_profile_id are missing)
373
+ # * <tt>:bank_routing_number_masked && :bank_account_number_masked</tt> -- (CONDITIONAL - required for electronic check refunds if :customer_profile_id AND :customer_payment_profile_id are missing) (NOT ABLE TO TEST - I keep getting "ACH transactions are not accepted by this merchant." when trying to make a payment and, until that's possible I can't refund (wiseleyb@gmail.com))
374
374
  def create_customer_profile_transaction(options)
375
375
  requires!(options, :transaction)
376
376
  requires!(options[:transaction], :type)
@@ -410,13 +410,13 @@ module ActiveMerchant #:nodoc:
410
410
  # * <tt>:customer_profile_id</tt> -- The Customer Profile ID of the customer to use in this transaction. (CONDITIONAL :customer_payment_profile_id must be included if used)
411
411
  # * <tt>:customer_payment_profile_id</tt> -- The Customer Payment Profile ID of the Customer Payment Profile to use in this transaction. (CONDITIONAL :customer_profile_id must be included if used)
412
412
  #
413
- # * <tt>:credit_card_number_masked</tt> -- Four Xs follwed by the last four digits of the credit card (CONDITIONAL - used if customer_profile_id and customer_payment_profile_id aren't given)
413
+ # * <tt>:credit_card_number_masked</tt> -- Four Xs followed by the last four digits of the credit card (CONDITIONAL - used if customer_profile_id and customer_payment_profile_id aren't given)
414
414
  #
415
- # * <tt>:bank_routing_number_masked</tt> -- The last four gidits of the routing number to be refunded (CONDITIONAL - must be used with :bank_account_number_masked)
416
- # * <tt>:bank_account_number_masked</tt> -- The last four digis of the bank account number to be refunded, Ex. XXXX1234 (CONDITIONAL - must be used with :bank_routing_number_masked)
415
+ # * <tt>:bank_routing_number_masked</tt> -- The last four digits of the routing number to be refunded (CONDITIONAL - must be used with :bank_account_number_masked)
416
+ # * <tt>:bank_account_number_masked</tt> -- The last four digits of the bank account number to be refunded, Ex. XXXX1234 (CONDITIONAL - must be used with :bank_routing_number_masked)
417
417
  #
418
418
  # * <tt>:tax</tt> - A hash containing tax information for the refund (OPTIONAL - <tt>:amount</tt>, <tt>:name</tt> (31 characters), <tt>:description</tt> (255 characters))
419
- # * <tt>:duty</tt> - A hash containting duty information for the refund (OPTIONAL - <tt>:amount</tt>, <tt>:name</tt> (31 characters), <tt>:description</tt> (255 characters))
419
+ # * <tt>:duty</tt> - A hash containing duty information for the refund (OPTIONAL - <tt>:amount</tt>, <tt>:name</tt> (31 characters), <tt>:description</tt> (255 characters))
420
420
  # * <tt>:shipping</tt> - A hash containing shipping information for the refund (OPTIONAL - <tt>:amount</tt>, <tt>:name</tt> (31 characters), <tt>:description</tt> (255 characters))
421
421
  def create_customer_profile_transaction_for_refund(options)
422
422
  requires!(options, :transaction)
@@ -131,6 +131,7 @@ module ActiveMerchant #:nodoc:
131
131
  post = {}
132
132
  post[:amount] = money
133
133
  post[:description] = options[:description]
134
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
134
135
 
135
136
  create_or_find_account(post, options)
136
137
  add_credit_card(post, credit_card, options)
@@ -168,6 +169,7 @@ module ActiveMerchant #:nodoc:
168
169
  post = {}
169
170
  post[:amount] = money
170
171
  post[:description] = options[:description]
172
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
171
173
 
172
174
  create_or_find_account(post, options)
173
175
  add_credit_card(post, credit_card, options)
@@ -197,6 +199,7 @@ module ActiveMerchant #:nodoc:
197
199
  post[:hold_uri] = authorization
198
200
  post[:amount] = money if money
199
201
  post[:description] = options[:description] if options[:description]
202
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
200
203
  post[:on_behalf_of_uri] = options[:on_behalf_of_uri] if options[:on_behalf_of_uri]
201
204
 
202
205
  create_transaction(:post, @debits_uri, post)
@@ -213,6 +216,7 @@ module ActiveMerchant #:nodoc:
213
216
  def void(authorization, options = {})
214
217
  post = {}
215
218
  post[:is_void] = true
219
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
216
220
 
217
221
  create_transaction(:put, authorization, post)
218
222
  rescue Error => ex
@@ -246,6 +250,7 @@ module ActiveMerchant #:nodoc:
246
250
  post[:debit_uri] = debit_uri
247
251
  post[:amount] = amount
248
252
  post[:description] = options[:description]
253
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
249
254
  create_transaction(:post, @refunds_uri, post)
250
255
  rescue Error => ex
251
256
  failed_response(ex.response)
@@ -265,12 +270,12 @@ module ActiveMerchant #:nodoc:
265
270
  else
266
271
  card_uri = associate_card_to_account(account_uri, credit_card)
267
272
  end
268
-
273
+
269
274
  is_test = false
270
275
  if @marketplace_uri
271
276
  is_test = (@marketplace_uri.index("TEST") ? true : false)
272
277
  end
273
-
278
+
274
279
  Response.new(true, "Card stored", {}, :test => is_test, :authorization => [card_uri, account_uri].compact.join(';'))
275
280
  rescue Error => ex
276
281
  failed_response(ex.response)
@@ -139,7 +139,7 @@ module ActiveMerchant #:nodoc:
139
139
  commit(post, true)
140
140
  end
141
141
 
142
- #can't actually delete a secure profile with the supplicaed API. This function sets the status of the profile to closed (C).
142
+ #can't actually delete a secure profile with the supplicated API. This function sets the status of the profile to closed (C).
143
143
  #Closed profiles will have to removed manually.
144
144
  def delete(vault_id)
145
145
  update(vault_id, false, {:status => "C"})
@@ -7,67 +7,67 @@ module ActiveMerchant #:nodoc:
7
7
  SUCCESS_MESSAGE = "Bogus Gateway: Forced success"
8
8
  FAILURE_MESSAGE = "Bogus Gateway: Forced failure"
9
9
  ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error"
10
- CREDIT_ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error"
11
10
  UNSTORE_ERROR_MESSAGE = "Bogus Gateway: Use trans_id ending in 1 for success, 2 for exception and anything else for error"
12
11
  CAPTURE_ERROR_MESSAGE = "Bogus Gateway: Use authorization number ending in 1 for exception, 2 for error and anything else for success"
13
12
  VOID_ERROR_MESSAGE = "Bogus Gateway: Use authorization number ending in 1 for exception, 2 for error and anything else for success"
14
13
  REFUND_ERROR_MESSAGE = "Bogus Gateway: Use trans_id number ending in 1 for exception, 2 for error and anything else for success"
14
+ CHECK_ERROR_MESSAGE = "Bogus Gateway: Use bank account number ending in 1 for success, 2 for exception and anything else for error"
15
15
 
16
16
  self.supported_countries = ['US']
17
17
  self.supported_cardtypes = [:bogus]
18
18
  self.homepage_url = 'http://example.com'
19
19
  self.display_name = 'Bogus'
20
20
 
21
- def authorize(money, credit_card_or_reference, options = {})
21
+ def authorize(money, paysource, options = {})
22
22
  money = amount(money)
23
- case normalize(credit_card_or_reference)
23
+ case normalize(paysource)
24
24
  when /1$/
25
25
  Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money}, :test => true, :authorization => AUTHORIZATION )
26
26
  when /2$/
27
27
  Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money, :error => FAILURE_MESSAGE }, :test => true)
28
28
  else
29
- raise Error, ERROR_MESSAGE
29
+ raise Error, error_message(paysource)
30
30
  end
31
31
  end
32
32
 
33
- def purchase(money, credit_card_or_reference, options = {})
33
+ def purchase(money, paysource, options = {})
34
34
  money = amount(money)
35
- case normalize(credit_card_or_reference)
35
+ case normalize(paysource)
36
36
  when /1$/, AUTHORIZATION
37
37
  Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true, :authorization => AUTHORIZATION)
38
38
  when /2$/
39
39
  Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
40
40
  else
41
- raise Error, ERROR_MESSAGE
41
+ raise Error, error_message(paysource)
42
42
  end
43
43
  end
44
44
 
45
- def recurring(money, credit_card_or_reference, options = {})
45
+ def recurring(money, paysource, options = {})
46
46
  money = amount(money)
47
- case normalize(credit_card_or_reference)
47
+ case normalize(paysource)
48
48
  when /1$/
49
49
  Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
50
50
  when /2$/
51
51
  Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
52
52
  else
53
- raise Error, ERROR_MESSAGE
53
+ raise Error, error_message(paysource)
54
54
  end
55
55
  end
56
56
 
57
- def credit(money, credit_card_or_reference, options = {})
58
- if credit_card_or_reference.is_a?(String)
57
+ def credit(money, paysource, options = {})
58
+ if paysource.is_a?(String)
59
59
  deprecated CREDIT_DEPRECATION_MESSAGE
60
- return refund(money, credit_card_or_reference, options)
60
+ return refund(money, paysource, options)
61
61
  end
62
62
 
63
63
  money = amount(money)
64
- case normalize(credit_card_or_reference)
64
+ case normalize(paysource)
65
65
  when /1$/
66
66
  Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true )
67
67
  when /2$/
68
68
  Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
69
69
  else
70
- raise Error, CREDIT_ERROR_MESSAGE
70
+ raise Error, error_message(paysource)
71
71
  end
72
72
  end
73
73
 
@@ -106,14 +106,14 @@ module ActiveMerchant #:nodoc:
106
106
  end
107
107
  end
108
108
 
109
- def store(credit_card_or_reference, options = {})
110
- case normalize(credit_card_or_reference)
109
+ def store(paysource, options = {})
110
+ case normalize(paysource)
111
111
  when /1$/
112
112
  Response.new(true, SUCCESS_MESSAGE, {:billingid => '1'}, :test => true, :authorization => AUTHORIZATION)
113
113
  when /2$/
114
114
  Response.new(false, FAILURE_MESSAGE, {:billingid => nil, :error => FAILURE_MESSAGE }, :test => true)
115
115
  else
116
- raise Error, ERROR_MESSAGE
116
+ raise Error, error_message(paysource)
117
117
  end
118
118
  end
119
119
 
@@ -130,11 +130,21 @@ module ActiveMerchant #:nodoc:
130
130
 
131
131
  private
132
132
 
133
- def normalize(credit_card_or_reference)
134
- if credit_card_or_reference.respond_to?(:number)
135
- credit_card_or_reference.number
133
+ def normalize(paysource)
134
+ if paysource.respond_to?(:account_number) && (paysource.try(:number).blank? || paysource.number.blank?)
135
+ paysource.account_number
136
+ elsif paysource.respond_to?(:number)
137
+ paysource.number
136
138
  else
137
- credit_card_or_reference.to_s
139
+ paysource.to_s
140
+ end
141
+ end
142
+
143
+ def error_message(paysource)
144
+ if paysource.respond_to?(:account_number)
145
+ CHECK_ERROR_MESSAGE
146
+ elsif paysource.respond_to?(:number)
147
+ ERROR_MESSAGE
138
148
  end
139
149
  end
140
150
  end
@@ -111,26 +111,20 @@ module ActiveMerchant #:nodoc:
111
111
  end
112
112
 
113
113
  def store(creditcard, options = {})
114
- commit do
115
- parameters = {
116
- :first_name => creditcard.first_name,
117
- :last_name => creditcard.last_name,
118
- :email => options[:email],
119
- :credit_card => {
120
- :number => creditcard.number,
121
- :cvv => creditcard.verification_value,
122
- :expiration_month => creditcard.month.to_s.rjust(2, "0"),
123
- :expiration_year => creditcard.year.to_s
124
- }
125
- }
126
- result = @braintree_gateway.customer.create(merge_credit_card_options(parameters, options))
127
- Response.new(result.success?, message_from_result(result),
128
- {
129
- :braintree_customer => (customer_hash(result.customer) if result.success?),
130
- :customer_vault_id => (result.customer.id if result.success?)
131
- },
132
- :authorization => (result.customer.id if result.success?)
133
- )
114
+ if options[:customer].present?
115
+ MultiResponse.new.tap do |r|
116
+ customer_exists_response = nil
117
+ r.process{customer_exists_response = check_customer_exists(options[:customer])}
118
+ r.process do
119
+ if customer_exists_response.params["exists"]
120
+ add_credit_card_to_customer(creditcard, options)
121
+ else
122
+ add_customer_with_credit_card(creditcard, options)
123
+ end
124
+ end
125
+ end
126
+ else
127
+ add_customer_with_credit_card(creditcard, options)
134
128
  end
135
129
  end
136
130
 
@@ -153,11 +147,11 @@ module ActiveMerchant #:nodoc:
153
147
  result = @braintree_gateway.customer.update(vault_id,
154
148
  :first_name => creditcard.first_name,
155
149
  :last_name => creditcard.last_name,
156
- :email => options[:email],
150
+ :email => scrub_email(options[:email]),
157
151
  :credit_card => credit_card_params
158
152
  )
159
153
  Response.new(result.success?, message_from_result(result),
160
- :braintree_customer => (customer_hash(@braintree_gateway.customer.find(vault_id)) if result.success?),
154
+ :braintree_customer => (customer_hash(@braintree_gateway.customer.find(vault_id), :include_credit_cards) if result.success?),
161
155
  :customer_vault_id => (result.customer.id if result.success?)
162
156
  )
163
157
  end
@@ -165,7 +159,11 @@ module ActiveMerchant #:nodoc:
165
159
 
166
160
  def unstore(customer_vault_id, options = {})
167
161
  commit do
168
- @braintree_gateway.customer.delete(customer_vault_id)
162
+ if(!customer_vault_id && options[:credit_card_token])
163
+ @braintree_gateway.credit_card.delete(options[:credit_card_token])
164
+ else
165
+ @braintree_gateway.customer.delete(customer_vault_id)
166
+ end
169
167
  Response.new(true, "OK")
170
168
  end
171
169
  end
@@ -173,6 +171,87 @@ module ActiveMerchant #:nodoc:
173
171
 
174
172
  private
175
173
 
174
+ def check_customer_exists(customer_vault_id)
175
+ commit do
176
+ begin
177
+ @braintree_gateway.customer.find(customer_vault_id)
178
+ ActiveMerchant::Billing::Response.new(true, "Customer found", {exists: true}, authorization: customer_vault_id)
179
+ rescue Braintree::NotFoundError
180
+ ActiveMerchant::Billing::Response.new(true, "Customer not found", {exists: false})
181
+ end
182
+ end
183
+ end
184
+
185
+ def add_customer_with_credit_card(creditcard, options)
186
+ commit do
187
+ parameters = {
188
+ :first_name => creditcard.first_name,
189
+ :last_name => creditcard.last_name,
190
+ :email => scrub_email(options[:email]),
191
+ :id => options[:customer],
192
+ :credit_card => {
193
+ :number => creditcard.number,
194
+ :cvv => creditcard.verification_value,
195
+ :expiration_month => creditcard.month.to_s.rjust(2, "0"),
196
+ :expiration_year => creditcard.year.to_s,
197
+ :token => options[:credit_card_token]
198
+ }
199
+ }
200
+ result = @braintree_gateway.customer.create(merge_credit_card_options(parameters, options))
201
+ Response.new(result.success?, message_from_result(result),
202
+ {
203
+ :braintree_customer => (customer_hash(result.customer, :include_credit_cards) if result.success?),
204
+ :customer_vault_id => (result.customer.id if result.success?),
205
+ :credit_card_token => (result.customer.credit_cards[0].token if result.success?)
206
+ },
207
+ :authorization => (result.customer.id if result.success?)
208
+ )
209
+ end
210
+ end
211
+
212
+ def add_credit_card_to_customer(credit_card, options)
213
+ commit do
214
+ parameters = {
215
+ customer_id: options[:customer],
216
+ token: options[:credit_card_token],
217
+ number: credit_card.number,
218
+ cvv: credit_card.verification_value,
219
+ expiration_month: credit_card.month.to_s.rjust(2, "0"),
220
+ expiration_year: credit_card.year.to_s,
221
+ }
222
+ parameters[:billing_address] = map_address(options[:billing_address]) if options[:billing_address]
223
+
224
+ result = @braintree_gateway.credit_card.create(parameters)
225
+ ActiveMerchant::Billing::Response.new(
226
+ result.success?,
227
+ message_from_result(result),
228
+ {
229
+ customer_vault_id: (result.credit_card.customer_id if result.success?),
230
+ credit_card_token: (result.credit_card.token if result.success?)
231
+ },
232
+ authorization: (result.credit_card.customer_id if result.success?)
233
+ )
234
+ end
235
+ end
236
+
237
+ def scrub_email(email)
238
+ return nil unless email.present?
239
+ return nil if (
240
+ email !~ /^.+@[^\.]+(\.[^\.]+)+[a-z]$/i ||
241
+ email =~ /\.(con|met)$/i
242
+ )
243
+ email
244
+ end
245
+
246
+ def scrub_zip(zip)
247
+ return nil unless zip.present?
248
+ return nil if(
249
+ zip.gsub(/[^a-z0-9]/i, '').length > 9 ||
250
+ zip =~ /[^a-z0-9\- ]/i
251
+ )
252
+ zip
253
+ end
254
+
176
255
  def merge_credit_card_options(parameters, options)
177
256
  valid_options = {}
178
257
  options.each do |key, value|
@@ -193,7 +272,7 @@ module ActiveMerchant #:nodoc:
193
272
  :company => address[:company],
194
273
  :locality => address[:city],
195
274
  :region => address[:state],
196
- :postal_code => address[:zip],
275
+ :postal_code => scrub_zip(address[:zip]),
197
276
  }
198
277
  if(address[:country] || address[:country_code_alpha2])
199
278
  mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2])
@@ -281,25 +360,29 @@ module ActiveMerchant #:nodoc:
281
360
  end
282
361
  end
283
362
 
284
- def customer_hash(customer)
285
- credit_cards = customer.credit_cards.map do |cc|
286
- {
287
- "bin" => cc.bin,
288
- "expiration_date" => cc.expiration_date,
289
- "token" => cc.token,
290
- "last_4" => cc.last_4,
291
- "card_type" => cc.card_type,
292
- "masked_number" => cc.masked_number
293
- }
294
- end
295
-
296
- {
363
+ def customer_hash(customer, include_credit_cards=false)
364
+ hash = {
297
365
  "email" => customer.email,
298
366
  "first_name" => customer.first_name,
299
367
  "last_name" => customer.last_name,
300
- "credit_cards" => credit_cards,
301
368
  "id" => customer.id
302
369
  }
370
+
371
+ if include_credit_cards
372
+ hash["credit_cards"] = customer.credit_cards.map do |cc|
373
+ {
374
+ "bin" => cc.bin,
375
+ "expiration_date" => cc.expiration_date,
376
+ "token" => cc.token,
377
+ "last_4" => cc.last_4,
378
+ "card_type" => cc.card_type,
379
+ "masked_number" => cc.masked_number,
380
+ "token" => cc.token
381
+ }
382
+ end
383
+ end
384
+
385
+ hash
303
386
  end
304
387
 
305
388
  def transaction_hash(transaction)
@@ -365,7 +448,7 @@ module ActiveMerchant #:nodoc:
365
448
  :order_id => options[:order_id],
366
449
  :customer => {
367
450
  :id => options[:store] == true ? "" : options[:store],
368
- :email => options[:email]
451
+ :email => scrub_email(options[:email])
369
452
  },
370
453
  :options => {
371
454
  :store_in_vault => options[:store] ? true : false,
@@ -373,6 +456,8 @@ module ActiveMerchant #:nodoc:
373
456
  }
374
457
  }
375
458
 
459
+ parameters[:custom_fields] = options[:custom_fields]
460
+ parameters[:device_data] = options[:device_data] if options[:device_data]
376
461
  if merchant_account_id = (options[:merchant_account_id] || @merchant_account_id)
377
462
  parameters[:merchant_account_id] = merchant_account_id
378
463
  end