spree_core 0.40.4 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|
+
|