spree_core 0.40.4 → 0.50.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +6 -1
- data/app/controllers/admin/base_controller.rb +0 -57
- data/app/controllers/admin/configurations_controller.rb +1 -1
- data/app/controllers/admin/general_settings_controller.rb +1 -1
- data/app/controllers/admin/images_controller.rb +18 -8
- data/app/controllers/admin/inventory_settings_controller.rb +1 -1
- data/app/controllers/admin/mail_settings_controller.rb +1 -1
- data/app/controllers/admin/option_types_controller.rb +11 -0
- data/app/controllers/admin/orders_controller.rb +16 -20
- data/app/controllers/admin/overview_controller.rb +1 -1
- data/app/controllers/admin/payment_methods_controller.rb +6 -6
- data/app/controllers/admin/product_groups_controller.rb +10 -11
- data/app/controllers/admin/product_properties_controller.rb +5 -5
- data/app/controllers/admin/product_scopes_controller.rb +12 -4
- data/app/controllers/admin/products_controller.rb +17 -12
- data/app/controllers/admin/properties_controller.rb +7 -7
- data/app/controllers/admin/prototypes_controller.rb +15 -15
- data/app/controllers/admin/reports_controller.rb +12 -11
- data/app/controllers/admin/shipments_controller.rb +0 -5
- data/app/controllers/admin/shipping_categories_controller.rb +6 -6
- data/app/controllers/admin/shipping_methods_controller.rb +1 -2
- data/app/controllers/admin/states_controller.rb +12 -12
- data/app/controllers/admin/tax_categories_controller.rb +2 -2
- data/app/controllers/admin/tax_rates_controller.rb +8 -8
- data/app/controllers/admin/tax_settings_controller.rb +1 -1
- data/app/controllers/admin/taxonomies_controller.rb +3 -3
- data/app/controllers/admin/taxons_controller.rb +1 -8
- data/app/controllers/admin/trackers_controller.rb +1 -1
- data/app/controllers/admin/users_controller.rb +6 -9
- data/app/controllers/admin/variants_controller.rb +13 -2
- data/app/controllers/admin/zones_controller.rb +9 -9
- data/app/controllers/checkout_controller.rb +5 -5
- data/app/controllers/products_controller.rb +1 -1
- data/app/controllers/taxons_controller.rb +3 -1
- data/app/helpers/admin/navigation_helper.rb +36 -19
- data/app/helpers/admin/payments_helper.rb +1 -1
- data/app/helpers/admin/product_groups_helper.rb +1 -1
- data/app/helpers/admin/product_properties_helper.rb +5 -5
- data/app/helpers/admin/products_helper.rb +2 -2
- data/app/helpers/admin/users_helper.rb +5 -2
- data/app/helpers/hook_helper.rb +3 -3
- data/app/helpers/products_helper.rb +0 -19
- data/app/helpers/spree/base_helper.rb +33 -2
- data/app/helpers/taxons_helper.rb +3 -3
- data/app/mailers/order_mailer.rb +2 -2
- data/app/mailers/shipment_mailer.rb +2 -2
- data/app/models/address.rb +42 -9
- data/app/models/adjustment.rb +8 -8
- data/app/models/app_configuration.rb +0 -6
- data/app/models/billing_integration.rb +1 -1
- data/app/models/calculator/sales_tax.rb +3 -3
- data/app/models/configuration.rb +1 -1
- data/app/models/country.rb +4 -5
- data/app/models/creditcard.rb +38 -31
- data/app/models/gateway.rb +14 -14
- data/app/models/gateway/beanstream.rb +4 -4
- data/app/models/gateway/bogus.rb +6 -6
- data/app/models/gateway/braintree.rb +88 -0
- data/app/models/gateway/eway.rb +3 -3
- data/app/models/image.rb +5 -4
- data/app/models/option_type.rb +1 -0
- data/app/models/order.rb +60 -21
- data/app/models/payment.rb +5 -32
- data/app/models/preference.rb +7 -7
- data/app/models/product.rb +22 -7
- data/app/models/product_group.rb +22 -26
- data/app/models/product_property.rb +5 -5
- data/app/models/product_scope.rb +26 -6
- data/app/models/property.rb +1 -1
- data/app/models/state.rb +2 -3
- data/app/models/tax_category.rb +1 -0
- data/app/models/tax_rate.rb +1 -2
- data/app/models/taxon.rb +12 -10
- data/app/models/taxonomy.rb +7 -4
- data/app/models/tracker.rb +1 -1
- data/app/models/user.rb +4 -0
- data/app/models/variant.rb +1 -1
- data/app/models/zone.rb +1 -1
- data/app/models/zone_member.rb +3 -3
- data/app/views/admin/{shared → adjustments}/_adjustments_table.html.erb +7 -4
- data/app/views/admin/adjustments/edit.html.erb +1 -1
- data/app/views/admin/adjustments/index.html.erb +2 -2
- data/app/views/admin/adjustments/new.html.erb +2 -1
- data/app/views/admin/general_settings/edit.html.erb +4 -12
- data/app/views/admin/general_settings/show.html.erb +0 -5
- data/app/views/admin/images/index.html.erb +8 -5
- data/app/views/admin/inventory_settings/show.html.erb +1 -1
- data/app/views/admin/mail_methods/index.html.erb +4 -4
- data/app/views/admin/option_types/_form.html.erb +4 -4
- data/app/views/admin/option_types/_option_value_fields.html.erb +2 -2
- data/app/views/admin/option_types/edit.html.erb +4 -2
- data/app/views/admin/option_types/index.html.erb +5 -5
- data/app/views/admin/orders/_line_item.html.erb +2 -1
- data/app/views/admin/orders/history.html.erb +6 -2
- data/app/views/admin/orders/index.html.erb +22 -19
- data/app/views/admin/orders/show.html.erb +1 -1
- data/app/views/admin/orders/user.html.erb +1 -1
- data/app/views/admin/payment_methods/index.html.erb +7 -5
- data/app/views/admin/payments/_list.html.erb +3 -3
- data/app/views/admin/payments/index.html.erb +1 -1
- data/app/views/admin/payments/show.html.erb +2 -2
- data/app/views/admin/product_groups/edit.html.erb +7 -7
- data/app/views/admin/product_groups/index.html.erb +5 -3
- data/app/views/admin/product_groups/update.js.erb +4 -3
- data/app/views/admin/product_properties/_product_property_fields.html.erb +3 -3
- data/app/views/admin/product_properties/index.html.erb +10 -5
- data/app/views/admin/product_scopes/destroy.js.erb +1 -0
- data/app/views/admin/products/index.html.erb +32 -33
- data/app/views/admin/properties/_form.html.erb +2 -2
- data/app/views/admin/properties/index.html.erb +4 -4
- data/app/views/admin/prototypes/index.html.erb +4 -4
- data/app/views/admin/shared/_address_form.html.erb +1 -1
- data/app/views/admin/shared/_calculator_fields.html.erb +1 -1
- data/app/views/admin/shared/_destroy.js.erb +15 -2
- data/app/views/admin/shared/_order_tabs.html.erb +1 -1
- data/app/views/admin/shared/_report_criteria.html.erb +1 -1
- data/app/views/admin/shipments/_form.html.erb +6 -2
- data/app/views/admin/shipments/edit.html.erb +1 -1
- data/app/views/admin/shipments/index.html.erb +4 -2
- data/app/views/admin/shipping_methods/_form.html.erb +2 -0
- data/app/views/admin/shipping_methods/index.html.erb +3 -2
- data/app/views/admin/states/_state_list.html.erb +11 -5
- data/app/views/admin/tax_categories/index.html.erb +9 -4
- data/app/views/admin/tax_settings/show.html.erb +2 -2
- data/app/views/admin/taxonomies/_list.html.erb +4 -2
- data/app/views/admin/taxonomies/index.html.erb +2 -2
- data/app/views/admin/taxons/_form.html.erb +1 -1
- data/app/views/admin/trackers/index.html.erb +5 -5
- data/app/views/admin/users/_form.html.erb +3 -4
- data/app/views/admin/users/index.html.erb +7 -6
- data/app/views/admin/users/show.html.erb +3 -3
- data/app/views/admin/variants/index.html.erb +21 -6
- data/app/views/admin/zones/_form.html.erb +9 -9
- data/app/views/admin/zones/_member_type.html.erb +5 -5
- data/app/views/admin/zones/index.html.erb +7 -5
- data/app/views/checkout/_address.html.erb +2 -2
- data/app/views/checkout/_payment.html.erb +3 -6
- data/app/views/layouts/admin.html.erb +3 -9
- data/app/views/layouts/spree_application.html.erb +2 -1
- data/app/views/orders/_line_item.html.erb +1 -1
- data/app/views/orders/edit.html.erb +17 -16
- data/app/views/orders/show.html.erb +1 -1
- data/app/views/shared/_admin_head.html.erb +1 -1
- data/app/views/shared/_error_messages.html.erb +2 -2
- data/app/views/shared/_filters.html.erb +4 -4
- data/app/views/shared/_head.html.erb +2 -2
- data/app/views/shared/_nav_bar.html.erb +2 -2
- data/app/views/shared/_products.html.erb +4 -2
- data/app/views/shared/_taxonomies.html.erb +15 -8
- data/app/views/shipment_mailer/shipped_email.text.erb +2 -2
- data/config/cucumber.yml +10 -0
- data/config/initializers/form_builder.rb +1 -5
- data/config/initializers/workarounds_for_ruby19.rb +5 -5
- data/config/locales/en.yml +33 -6
- data/config/routes.rb +18 -13
- data/db/migrate/20090923100315_add_count_on_hand_to_variants_and_products.rb +5 -5
- data/db/migrate/20091213222815_creditcard_last_four_digits.rb +5 -5
- data/db/migrate/20100105132138_shipment_id_for_inventory_units.rb +2 -2
- data/db/migrate/20100209025806_create_payment_methods.rb +3 -3
- data/db/migrate/20100209144531_polymorphic_payments.rb +1 -1
- data/db/migrate/20100214212536_assign_creditcard_txns_to_payment.rb +2 -2
- data/db/migrate/20100224153127_deleted_at_for_payment_methods.rb +1 -1
- data/db/migrate/20100506185838_add_description_to_taxons.rb +1 -1
- data/db/migrate/20100816212146_shipping_method_id_for_orders.rb +1 -1
- data/db/migrate/20101026184808_migrate_checkout_to_orders.rb +2 -2
- data/db/migrate/20101223215658_add_position_to_variants.rb +9 -0
- data/db/migrate/20110110130847_add_next_state_to_state_events.rb +9 -0
- data/db/migrate/20110111122537_add_position_to_option_types.rb +9 -0
- data/db/migrate/20110314192118_remove_trailing_slashes_in_taxon_permalinks.rb +17 -0
- data/lib/custom_fixtures.rb +1 -1
- data/lib/{seo_assist.rb → middleware/seo_assist.rb} +14 -8
- data/lib/product_filters.rb +49 -43
- data/lib/redirect_legacy_product_url.rb +5 -5
- data/lib/scopes.rb +2 -2
- data/lib/scopes/dynamic.rb +9 -16
- data/lib/scopes/product.rb +33 -16
- data/lib/scopes/variant.rb +4 -3
- data/lib/spree/calculated_adjustments.rb +5 -2
- data/lib/spree/config.rb +2 -0
- data/lib/spree/current_order.rb +4 -4
- data/lib/spree/mail_settings.rb +3 -2
- data/lib/spree/search/base.rb +9 -10
- data/lib/spree_base.rb +22 -23
- data/lib/spree_core.rb +10 -69
- data/lib/spree_core/authorize_net_cim_hack.rb +1 -1
- data/lib/spree_core/delegate_belongs_to.rb +18 -24
- data/lib/spree_core/enumerable_constants.rb +38 -38
- data/lib/spree_core/find_by_param.rb +8 -6
- data/lib/spree_core/preferences/preference_definition.rb +7 -7
- data/lib/spree_core/railtie.rb +58 -0
- data/lib/spree_core/ssl_requirement.rb +4 -3
- data/lib/spree_core/testing_support/factories.rb +13 -0
- data/lib/spree_core/testing_support/factories/address_factory.rb +20 -0
- data/lib/spree_core/testing_support/factories/adjustment_factory.rb +6 -0
- data/lib/spree_core/testing_support/factories/calculator_factory.rb +5 -0
- data/lib/spree_core/testing_support/factories/configuraion_factory.rb +4 -0
- data/lib/spree_core/testing_support/factories/country_factory.rb +7 -0
- data/lib/spree_core/testing_support/factories/creditcard_factory.rb +11 -0
- data/lib/spree_core/testing_support/factories/inventory_unit_factory.rb +7 -0
- data/lib/spree_core/testing_support/factories/line_item_factory.rb +8 -0
- data/lib/spree_core/testing_support/factories/mail_method_factory.rb +4 -0
- data/lib/spree_core/testing_support/factories/options_factory.rb +10 -0
- data/lib/spree_core/testing_support/factories/order_factory.rb +18 -0
- data/lib/spree_core/testing_support/factories/payment_factory.rb +26 -0
- data/lib/spree_core/testing_support/factories/payment_method_factory.rb +17 -0
- data/lib/spree_core/testing_support/factories/product_factory.rb +16 -0
- data/lib/spree_core/testing_support/factories/product_group_factory.rb +3 -0
- data/lib/spree_core/testing_support/factories/product_option_type_factory.rb +4 -0
- data/lib/spree_core/testing_support/factories/product_property_factory.rb +4 -0
- data/lib/spree_core/testing_support/factories/product_scope_factory.rb +6 -0
- data/lib/spree_core/testing_support/factories/property_factory.rb +4 -0
- data/lib/spree_core/testing_support/factories/prototype_factory.rb +4 -0
- data/lib/spree_core/testing_support/factories/return_authorization_factory.rb +8 -0
- data/lib/spree_core/testing_support/factories/role_factory.rb +9 -0
- data/lib/spree_core/testing_support/factories/shipment_factory.rb +9 -0
- data/lib/spree_core/testing_support/factories/shipping_category_factory.rb +5 -0
- data/lib/spree_core/testing_support/factories/shipping_method_factory.rb +7 -0
- data/lib/spree_core/testing_support/factories/state_factory.rb +11 -0
- data/lib/spree_core/testing_support/factories/tax_category_factory.rb +8 -0
- data/lib/spree_core/testing_support/factories/tax_rate_factory.rb +5 -0
- data/lib/spree_core/testing_support/factories/taxon_factory.rb +5 -0
- data/lib/spree_core/testing_support/factories/taxonomy_factory.rb +3 -0
- data/lib/spree_core/testing_support/factories/tracker_factory.rb +5 -0
- data/lib/spree_core/testing_support/factories/user_factory.rb +15 -0
- data/lib/spree_core/testing_support/factories/variant_factory.rb +14 -0
- data/lib/spree_core/testing_support/factories/zone_factory.rb +18 -0
- data/lib/spree_core/theme_support/hook.rb +1 -1
- data/lib/spree_core/theme_support/more_patches.rb +20 -20
- data/lib/spree_core/version.rb +5 -0
- data/lib/tasks/common.rb +30 -0
- data/lib/tasks/install.rake +1 -1
- data/lib/tasks/rake_util.rb +19 -0
- data/lib/tasks/taxon.rake +14 -0
- data/public/images/reorder.jpg +0 -0
- data/public/javascripts/admin.js +0 -6
- data/public/javascripts/admin/unobtrusive_handlers.js +28 -0
- data/public/javascripts/checkout.js +3 -3
- data/public/stylesheets/admin/admin-forms.css +1 -6
- data/public/stylesheets/admin/admin.css +0 -28
- data/public/stylesheets/screen.css +0 -280
- metadata +81 -43
- data/app/controllers/countries_controller.rb +0 -11
- data/app/models/spree/alert.rb +0 -13
- data/app/models/state_monitor.rb +0 -25
- data/app/views/admin/shared/_alert.html.erb +0 -6
- data/app/views/countries/index.js.erb +0 -1
- data/app/views/shared/_doc_and_xmlns.html.erb +0 -2
- data/app/views/users/edit.html.erb +0 -9
- data/app/views/users/show.html.erb +0 -46
- data/lib/spree_core/validation_group.rb +0 -143
- data/public/stylesheets/scaffold.css +0 -54
@@ -2,8 +2,6 @@ class AppConfiguration < Configuration
|
|
2
2
|
|
3
3
|
preference :site_name, :string, :default => 'Spree Demo Site'
|
4
4
|
preference :site_url, :string, :default => 'demo.spreecommerce.com'
|
5
|
-
preference :store_cc, :boolean, :default => false
|
6
|
-
preference :store_cvv, :boolean, :default => false
|
7
5
|
preference :default_locale, :string, :default => 'en'
|
8
6
|
preference :allow_locale_switching, :boolean, :default => true
|
9
7
|
preference :default_country_id, :integer, :default => 214
|
@@ -23,7 +21,6 @@ class AppConfiguration < Configuration
|
|
23
21
|
preference :allow_ssl_in_production, :boolean, :default => true
|
24
22
|
preference :allow_ssl_in_development_and_test, :boolean, :default => false
|
25
23
|
preference :allow_guest_checkout, :boolean, :default => true
|
26
|
-
preference :allow_anonymous_checkout, :boolean, :default => false
|
27
24
|
preference :alternative_billing_phone, :boolean, :default => false # Request extra phone for bill addr
|
28
25
|
preference :alternative_shipping_phone, :boolean, :default => false # Request extra phone for ship addr
|
29
26
|
preference :shipping_instructions, :boolean, :default => false # Request instructions/info for shipping
|
@@ -35,9 +32,6 @@ class AppConfiguration < Configuration
|
|
35
32
|
preference :cache_static_content, :boolean, :default => true
|
36
33
|
preference :use_content_controller, :boolean, :default => true
|
37
34
|
preference :allow_checkout_on_gateway_error, :boolean, :default => false
|
38
|
-
preference :check_for_spree_alerts, :boolean, :default => true
|
39
|
-
preference :dismissed_spree_alerts, :string, :default => ''
|
40
|
-
preference :last_check_for_spree_alerts, :string, :default => nil
|
41
35
|
|
42
36
|
validates :name, :presence => true, :uniqueness => true
|
43
37
|
|
@@ -7,7 +7,7 @@ class BillingIntegration < PaymentMethod
|
|
7
7
|
|
8
8
|
def provider
|
9
9
|
integration_options = options
|
10
|
-
ActiveMerchant::Billing::Base.integration_mode = integration_options[:server]
|
10
|
+
ActiveMerchant::Billing::Base.integration_mode = integration_options[:server].to_sym
|
11
11
|
integration_options = options
|
12
12
|
integration_options[:test] = true if integration_options[:test_mode]
|
13
13
|
@provider ||= provider_class.new(integration_options)
|
@@ -3,12 +3,12 @@ class Calculator::SalesTax < Calculator
|
|
3
3
|
def self.description
|
4
4
|
I18n.t("sales_tax")
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def self.register
|
8
8
|
super
|
9
9
|
TaxRate.register_calculator(self)
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def self.calculate_tax(order, rates)
|
13
13
|
ActiveSupport::Deprecation.warn("please use Calculator::SalesTax#compute instead", caller)
|
14
14
|
|
@@ -16,7 +16,7 @@ class Calculator::SalesTax < Calculator
|
|
16
16
|
# note: there is a bug with associations in rails 2.1 model caching so we're using this hack
|
17
17
|
# (see http://rails.lighthouseapp.com/projects/8994/tickets/785-caching-models-fails-in-development)
|
18
18
|
cache_hack = rates.first.respond_to?(:tax_category_id)
|
19
|
-
|
19
|
+
|
20
20
|
taxable_totals = {}
|
21
21
|
order.line_items.each do |line_item|
|
22
22
|
next unless tax_category = line_item.variant.product.tax_category
|
data/app/models/configuration.rb
CHANGED
data/app/models/country.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
class Country < ActiveRecord::Base
|
2
2
|
has_many :states
|
3
|
-
|
4
|
-
has_one :zone_member, :as => :zoneable
|
5
|
-
has_one :zone, :through => :zone_member
|
6
3
|
|
7
|
-
|
4
|
+
has_one :zone_member, :as => :zoneable
|
5
|
+
has_one :zone, :through => :zone_member
|
6
|
+
|
8
7
|
validates :name, :iso_name, :presence => true
|
9
|
-
|
8
|
+
|
10
9
|
def <=>(other)
|
11
10
|
name <=> other.name
|
12
11
|
end
|
data/app/models/creditcard.rb
CHANGED
@@ -10,12 +10,10 @@ class Creditcard < ActiveRecord::Base
|
|
10
10
|
validates :verification_value, :presence => true, :unless => :has_payment_profile?, :on => :create
|
11
11
|
|
12
12
|
def process!(payment)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
authorize(payment.amount.to_f, payment)
|
18
|
-
end
|
13
|
+
if Spree::Config[:auto_capture]
|
14
|
+
purchase(payment.amount.to_f, payment)
|
15
|
+
else
|
16
|
+
authorize(payment.amount.to_f, payment)
|
19
17
|
end
|
20
18
|
end
|
21
19
|
|
@@ -30,19 +28,19 @@ class Creditcard < ActiveRecord::Base
|
|
30
28
|
end
|
31
29
|
|
32
30
|
def first_name?
|
33
|
-
|
31
|
+
first_name.present?
|
34
32
|
end
|
35
33
|
|
36
34
|
def last_name?
|
37
|
-
|
35
|
+
last_name.present?
|
38
36
|
end
|
39
37
|
|
40
38
|
def name
|
41
|
-
"#{
|
39
|
+
"#{first_name} #{last_name}"
|
42
40
|
end
|
43
41
|
|
44
42
|
def verification_value?
|
45
|
-
|
43
|
+
verification_value.present?
|
46
44
|
end
|
47
45
|
|
48
46
|
# Show the card number, with all but last 4 numbers replace with "X". (XXXX-XXXX-XXXX-4338)
|
@@ -63,6 +61,9 @@ class Creditcard < ActiveRecord::Base
|
|
63
61
|
|
64
62
|
def authorize(amount, payment)
|
65
63
|
# ActiveMerchant is configured to use cents so we need to multiply order total by 100
|
64
|
+
payment_gateway = payment.payment_method
|
65
|
+
check_environment(payment_gateway)
|
66
|
+
|
66
67
|
response = payment_gateway.authorize((amount * 100).round, self, gateway_options(payment))
|
67
68
|
record_log payment, response
|
68
69
|
|
@@ -74,12 +75,15 @@ class Creditcard < ActiveRecord::Base
|
|
74
75
|
payment.fail
|
75
76
|
gateway_error(response)
|
76
77
|
end
|
77
|
-
rescue ActiveMerchant::ConnectionError
|
78
|
+
rescue ActiveMerchant::ConnectionError
|
78
79
|
gateway_error I18n.t(:unable_to_connect_to_gateway)
|
79
80
|
end
|
80
81
|
|
81
82
|
def purchase(amount, payment)
|
82
83
|
#combined Authorize and Capture that gets processed by the ActiveMerchant gateway as one single transaction.
|
84
|
+
payment_gateway = payment.payment_method
|
85
|
+
check_environment(payment_gateway)
|
86
|
+
|
83
87
|
response = payment_gateway.purchase((amount * 100).round, self, gateway_options(payment))
|
84
88
|
record_log payment, response
|
85
89
|
|
@@ -91,12 +95,15 @@ class Creditcard < ActiveRecord::Base
|
|
91
95
|
payment.fail
|
92
96
|
gateway_error(response) unless response.success?
|
93
97
|
end
|
94
|
-
rescue ActiveMerchant::ConnectionError
|
98
|
+
rescue ActiveMerchant::ConnectionError
|
95
99
|
gateway_error t(:unable_to_connect_to_gateway)
|
96
100
|
end
|
97
101
|
|
98
102
|
def capture(payment)
|
99
103
|
return unless payment.pending?
|
104
|
+
payment_gateway = payment.payment_method
|
105
|
+
check_environment(payment_gateway)
|
106
|
+
|
100
107
|
if payment_gateway.payment_profiles_supported?
|
101
108
|
# Gateways supporting payment profiles will need access to creditcard object because this stores the payment profile information
|
102
109
|
# so supply the authorization itself as well as the creditcard, rather than just the authorization code
|
@@ -115,11 +122,14 @@ class Creditcard < ActiveRecord::Base
|
|
115
122
|
payment.fail
|
116
123
|
gateway_error(response)
|
117
124
|
end
|
118
|
-
rescue ActiveMerchant::ConnectionError
|
125
|
+
rescue ActiveMerchant::ConnectionError
|
119
126
|
gateway_error I18n.t(:unable_to_connect_to_gateway)
|
120
127
|
end
|
121
128
|
|
122
129
|
def void(payment)
|
130
|
+
payment_gateway = payment.payment_method
|
131
|
+
check_environment(payment_gateway)
|
132
|
+
|
123
133
|
response = payment_gateway.void(payment.response_code, minimal_gateway_options(payment))
|
124
134
|
record_log payment, response
|
125
135
|
|
@@ -129,11 +139,14 @@ class Creditcard < ActiveRecord::Base
|
|
129
139
|
else
|
130
140
|
gateway_error(response)
|
131
141
|
end
|
132
|
-
rescue ActiveMerchant::ConnectionError
|
142
|
+
rescue ActiveMerchant::ConnectionError
|
133
143
|
gateway_error I18n.t(:unable_to_connect_to_gateway)
|
134
144
|
end
|
135
145
|
|
136
146
|
def credit(payment)
|
147
|
+
payment_gateway = payment.payment_method
|
148
|
+
check_environment(payment_gateway)
|
149
|
+
|
137
150
|
amount = payment.credit_allowed >= payment.order.outstanding_balance.abs ? payment.order.outstanding_balance.abs : payment.credit_allowed.abs
|
138
151
|
|
139
152
|
if payment_gateway.payment_profiles_supported?
|
@@ -154,13 +167,10 @@ class Creditcard < ActiveRecord::Base
|
|
154
167
|
else
|
155
168
|
gateway_error(response)
|
156
169
|
end
|
157
|
-
rescue ActiveMerchant::ConnectionError
|
170
|
+
rescue ActiveMerchant::ConnectionError
|
158
171
|
gateway_error I18n.t(:unable_to_connect_to_gateway)
|
159
172
|
end
|
160
173
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
174
|
def actions
|
165
175
|
%w{capture void credit}
|
166
176
|
end
|
@@ -170,20 +180,14 @@ class Creditcard < ActiveRecord::Base
|
|
170
180
|
payment.state == "pending"
|
171
181
|
end
|
172
182
|
|
173
|
-
# Indicates whether its possible to void the payment.
|
174
|
-
# settled yet when performing a void (which generally happens within 12-24 hours of the transaction.) For
|
175
|
-
# this reason, the default behavior of Spree is to only allow void operations within the first 12 hours of
|
176
|
-
# the payment creation time.
|
183
|
+
# Indicates whether its possible to void the payment.
|
177
184
|
def can_void?(payment)
|
178
|
-
|
179
|
-
%w{completed pending}.include? payment.state
|
185
|
+
payment.state == "void" ? false : true
|
180
186
|
end
|
181
187
|
|
182
|
-
# Indicates whether its possible to credit the payment.
|
183
|
-
# first which generally happens within 12-24 hours of the transaction.
|
184
|
-
# behavior of Spree is to disallow credit operations until the payment is at least 12 hours old.
|
188
|
+
# Indicates whether its possible to credit the payment. Note that most gateways require that the
|
189
|
+
# payment be settled first which generally happens within 12-24 hours of the transaction.
|
185
190
|
def can_credit?(payment)
|
186
|
-
return false unless (Time.now - 12.hours) > payment.created_at
|
187
191
|
return false unless payment.state == "completed"
|
188
192
|
return false unless payment.order.payment_state == "credit_owed"
|
189
193
|
payment.credit_allowed > 0
|
@@ -239,8 +243,11 @@ class Creditcard < ActiveRecord::Base
|
|
239
243
|
self.class.type?(number)
|
240
244
|
end
|
241
245
|
|
242
|
-
|
243
|
-
|
246
|
+
# Saftey check to make sure we're not accidentally performing operations on a live gateway.
|
247
|
+
# Ex. When testing in staging environment with a copy of production data.
|
248
|
+
def check_environment(gateway)
|
249
|
+
return if gateway.environment == Rails.env
|
250
|
+
message = I18n.t(:gateway_config_unavailable) + " - #{Rails.env}"
|
251
|
+
raise Spree::GatewayError.new(message)
|
244
252
|
end
|
245
|
-
|
246
253
|
end
|
data/app/models/gateway.rb
CHANGED
@@ -1,48 +1,48 @@
|
|
1
1
|
class Gateway < PaymentMethod
|
2
2
|
delegate_belongs_to :provider, :authorize, :purchase, :capture, :void, :credit
|
3
|
-
|
3
|
+
|
4
4
|
validates :name, :type, :presence => true
|
5
|
-
|
5
|
+
|
6
6
|
preference :server, :string, :default => 'test'
|
7
7
|
preference :test_mode, :boolean, :default => true
|
8
8
|
|
9
9
|
def payment_source_class
|
10
10
|
Creditcard
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
# instantiates the selected gateway and configures with the options stored in the database
|
14
14
|
def self.current
|
15
15
|
super
|
16
|
-
end
|
17
|
-
|
16
|
+
end
|
17
|
+
|
18
18
|
def provider
|
19
19
|
gateway_options = options
|
20
20
|
ActiveMerchant::Billing::Base.gateway_mode = gateway_options[:server].to_sym
|
21
21
|
@provider ||= provider_class.new(gateway_options)
|
22
|
-
end
|
23
|
-
|
22
|
+
end
|
23
|
+
|
24
24
|
def options
|
25
25
|
options_hash = {}
|
26
|
-
self.preferences.each do |key,value|
|
26
|
+
self.preferences.each do |key,value|
|
27
27
|
options_hash[key.to_sym] = value
|
28
28
|
end
|
29
29
|
options_hash
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def method_missing(method, *args)
|
33
|
-
if @provider.nil?
|
33
|
+
if @provider.nil? || !@provider.respond_to?(method)
|
34
34
|
super
|
35
35
|
else
|
36
|
-
|
36
|
+
provider.send(method)
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
def payment_profiles_supported?
|
41
41
|
false
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def method_type
|
45
45
|
"gateway"
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
end
|
@@ -26,11 +26,11 @@ class Gateway::Beanstream < Gateway
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def capture(transaction, creditcard, gateway_options)
|
31
31
|
beanstream_gateway.capture((transaction.amount*100).round, transaction.response_code, gateway_options)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def void(transaction_response, creditcard, gateway_options)
|
35
35
|
beanstream_gateway.void(transaction_response, gateway_options)
|
36
36
|
end
|
@@ -41,13 +41,13 @@ class Gateway::Beanstream < Gateway
|
|
41
41
|
end
|
42
42
|
|
43
43
|
private
|
44
|
-
|
44
|
+
|
45
45
|
def beanstream_gateway
|
46
46
|
ActiveMerchant::Billing::Base.gateway_mode = preferred_server.to_sym
|
47
47
|
gateway_options = options
|
48
48
|
ActiveMerchant::Billing::BeanstreamGateway.new(gateway_options)
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
def verify_creditcard_name!(creditcard)
|
52
52
|
bill_address = creditcard.payments.first.order.bill_address
|
53
53
|
creditcard.first_name = bill_address.firstname unless creditcard.first_name?
|
data/app/models/gateway/bogus.rb
CHANGED
@@ -15,7 +15,7 @@ class Gateway::Bogus < Gateway
|
|
15
15
|
def preferences
|
16
16
|
{}
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def create_profile(payment)
|
20
20
|
# simulate the storage of credit card profile using remote service
|
21
21
|
success = VALID_CCS.include? payment.source.number
|
@@ -24,7 +24,7 @@ class Gateway::Bogus < Gateway
|
|
24
24
|
|
25
25
|
def authorize(money, creditcard, options = {})
|
26
26
|
profile_id = creditcard.gateway_customer_profile_id
|
27
|
-
if VALID_CCS.include? creditcard.number or (profile_id and profile_id.starts_with? "BGS-")
|
27
|
+
if VALID_CCS.include? creditcard.number or (profile_id and profile_id.starts_with? "BGS-")
|
28
28
|
ActiveMerchant::Billing::Response.new(true, "Bogus Gateway: Forced success", {}, :test => true, :authorization => '12345', :avs_result => {:code => 'A'})
|
29
29
|
else
|
30
30
|
ActiveMerchant::Billing::Response.new(false, "Bogus Gateway: Forced failure", {:message => 'Bogus Gateway: Forced failure'}, :test => true)
|
@@ -61,11 +61,11 @@ class Gateway::Bogus < Gateway
|
|
61
61
|
# Test mode is not really relevant with bogus gateway (no such thing as live server)
|
62
62
|
true
|
63
63
|
end
|
64
|
-
|
65
|
-
def payment_profiles_supported?
|
64
|
+
|
65
|
+
def payment_profiles_supported?
|
66
66
|
true
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
private
|
70
70
|
def generate_profile_id(success)
|
71
71
|
record = true
|
@@ -75,6 +75,6 @@ class Gateway::Bogus < Gateway
|
|
75
75
|
record = Creditcard.find(:first, :conditions => ["gateway_customer_profile_id = ?", random])
|
76
76
|
end
|
77
77
|
random
|
78
|
-
end
|
78
|
+
end
|
79
79
|
|
80
80
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class Gateway::Braintree < Gateway
|
2
|
+
preference :merchant_id, :string
|
3
|
+
preference :public_key, :string
|
4
|
+
preference :private_key, :string
|
5
|
+
|
6
|
+
def provider_class
|
7
|
+
ActiveMerchant::Billing::BraintreeGateway
|
8
|
+
end
|
9
|
+
|
10
|
+
def authorize(money, creditcard, options = {})
|
11
|
+
adjust_options_for_braintree(creditcard, options)
|
12
|
+
payment_method = creditcard.gateway_customer_profile_id || creditcard
|
13
|
+
provider.authorize(money, payment_method, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def capture(authorization, ignored_creditcard, ignored_options)
|
17
|
+
amount = (authorization.amount * 100).to_i
|
18
|
+
provider.capture(amount, authorization.response_code)
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_profile(payment)
|
22
|
+
if payment.source.gateway_customer_profile_id.nil?
|
23
|
+
response = provider.store(payment.source)
|
24
|
+
if response.success?
|
25
|
+
payment.source.update_attributes!(:gateway_customer_profile_id => response.params["customer_vault_id"])
|
26
|
+
else
|
27
|
+
payment.source.gateway_error response.message
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def credit(*args)
|
33
|
+
if args.size == 4
|
34
|
+
credit_with_payment_profiles(*args)
|
35
|
+
elsif args.size == 3
|
36
|
+
credit_without_payment_profiles(*args)
|
37
|
+
else
|
38
|
+
raise ArgumentError, "Expected 3 or 4 arguments, received #{args.size}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def credit_with_payment_profiles(amount, payment, response_code, option)
|
43
|
+
provider.credit(amount, payment)
|
44
|
+
end
|
45
|
+
|
46
|
+
def credit_without_payment_profiles(amount, response_code, options)
|
47
|
+
transaction = ::Braintree::Transaction.find(response_code)
|
48
|
+
if BigDecimal.new(amount.to_s) == (transaction.amount * 100)
|
49
|
+
provider.refund(response_code)
|
50
|
+
else
|
51
|
+
raise NotImplementedError
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def payment_profiles_supported?
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
def purchase(money, creditcard, options = {})
|
60
|
+
authorize(money, creditcard, options.merge(:submit_for_settlement => true))
|
61
|
+
end
|
62
|
+
|
63
|
+
def void(response_code, ignored_options)
|
64
|
+
provider.void(response_code)
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
def adjust_country_name(options)
|
70
|
+
[:billing_address, :shipping_address].each do |address|
|
71
|
+
if options[address] && options[address][:country] == "US"
|
72
|
+
options[address][:country] = "United States of America"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def adjust_billing_address(creditcard, options)
|
78
|
+
if creditcard.gateway_customer_profile_id
|
79
|
+
options.delete(:billing_address)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def adjust_options_for_braintree(creditcard, options)
|
84
|
+
adjust_country_name(options)
|
85
|
+
adjust_billing_address(creditcard, options)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|