activemerchant 1.42.2 → 1.42.3

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 (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