radiant-shop-extension 0.9.3 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +9 -3
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/app/controllers/admin/shop/customers_controller.rb +35 -126
- data/app/controllers/shop/categories_controller.rb +1 -5
- data/app/controllers/shop/products_controller.rb +1 -1
- data/app/models/form_checkout.rb +198 -112
- data/app/models/shop_category.rb +3 -3
- data/app/models/shop_customer.rb +3 -12
- data/app/models/shop_order.rb +5 -3
- data/app/models/shop_payment.rb +0 -1
- data/app/models/shop_product.rb +3 -3
- data/app/views/admin/shop/customers/edit.html.haml +13 -0
- data/app/views/admin/shop/customers/edit/_fields.html.haml +33 -0
- data/app/views/admin/shop/customers/edit/_head.html.haml +2 -0
- data/app/views/admin/shop/customers/edit/_meta.html.haml +7 -0
- data/app/views/admin/shop/customers/edit/_parts.html.haml +4 -0
- data/app/views/admin/shop/customers/edit/_popups.html.haml +3 -0
- data/app/views/admin/shop/customers/edit/meta/_login.html.haml +5 -0
- data/app/views/admin/shop/customers/edit/meta/_password.html.haml +5 -0
- data/app/views/admin/shop/customers/edit/meta/_password_confirmation.html.haml +5 -0
- data/app/views/admin/shop/customers/edit/parts/_address.html.haml +7 -0
- data/app/views/admin/shop/customers/edit/parts/_addresses.html.haml +13 -0
- data/app/views/admin/shop/customers/edit/parts/_orders.html.haml +29 -0
- data/app/views/admin/shop/customers/index.html.haml +9 -35
- data/app/views/admin/shop/customers/index/_bottom.html.haml +4 -0
- data/app/views/admin/shop/customers/index/_customer.html.haml +9 -0
- data/app/views/admin/shop/customers/new.html.haml +11 -0
- data/app/views/admin/shop/customers/remove.html.haml +12 -0
- data/app/views/admin/shop/products/new.html.haml +1 -1
- data/config/locales/en.yml +37 -29
- data/config/routes.rb +2 -0
- data/db/migrate/20100927041219_remove_payment_methods.rb +16 -0
- data/db/migrate/20100927041624_change_payments_add_gateway.rb +11 -0
- data/db/migrate/20100927140446_change_payment_add_card_type_card_number.rb +11 -0
- data/db/seed.rb +1 -0
- data/db/seeds/forms.rb +179 -0
- data/db/{migrate/20100520033059_create_layouts.rb → seeds/layouts.rb} +19 -27
- data/db/seeds/snippets.rb +23 -0
- data/lib/shop/interface/customers.rb +34 -0
- data/lib/shop/tags/address.rb +1 -0
- data/lib/shop/tags/card.rb +51 -0
- data/lib/shop/tags/helpers.rb +53 -38
- data/lib/shop/tags/item.rb +1 -1
- data/lib/shop/tags/product.rb +23 -22
- data/lib/shop/tags/responses.rb +3 -3
- data/lib/tasks/shop_extension_tasks.rake +6 -0
- data/public/stylesheets/sass/admin/extensions/shop/index.sass +64 -0
- data/radiant-shop-extension.gemspec +37 -6
- data/shop_extension.rb +7 -2
- data/spec/datasets/forms.rb +112 -118
- data/spec/datasets/shop_customers.rb +30 -0
- data/spec/datasets/shop_orders.rb +7 -3
- data/spec/datasets/shop_products.rb +1 -0
- data/spec/lib/shop/tags/card_spec.rb +71 -0
- data/spec/lib/shop/tags/helpers_spec.rb +270 -283
- data/spec/lib/shop/tags/item_spec.rb +9 -0
- data/spec/lib/shop/tags/product_spec.rb +172 -158
- data/spec/lib/shop/tags/responses_spec.rb +129 -0
- data/spec/models/form_checkout_spec.rb +228 -294
- data/spec/models/shop_category_page_spec.rb +2 -2
- data/spec/models/shop_order_spec.rb +27 -20
- data/spec/models/shop_product_attachment_spec.rb +1 -0
- metadata +61 -17
- data/app/models/shop_payment_method.rb +0 -5
- data/db/migrate/20100903122123_create_forms.rb +0 -44
- data/db/migrate/20100908063639_create_snippets.rb +0 -22
data/README.md
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
# Radiant Shop
|
2
2
|
|
3
|
+
ps: [wiki](http://github.com/squaretalent/radiant-shop-extension/wiki)
|
4
|
+
|
5
|
+
pps: heavily under development means "it might not work out of the box after every commit"
|
6
|
+
|
7
|
+
ppps: I am working on the wiki as quickly as I can, but specs are more important at this point in time
|
8
|
+
|
9
|
+
pppps: love heart
|
10
|
+
|
3
11
|
## Checkout
|
4
12
|
|
5
13
|
### Form Configuration
|
6
14
|
|
7
15
|
checkout:
|
8
16
|
gateway:
|
9
|
-
name:
|
17
|
+
name: Eway
|
10
18
|
username: 123456
|
11
19
|
password: abcdef
|
12
|
-
merchant: test
|
13
|
-
pem: /var/www/certificate.pem
|
14
20
|
|
15
21
|
# Development
|
16
22
|
|
data/Rakefile
CHANGED
@@ -7,6 +7,7 @@ begin
|
|
7
7
|
gem.email = "dk@dirkkelly.com"
|
8
8
|
gem.homepage = "http://github.com/squaretalent/radiant-shop-extension"
|
9
9
|
gem.authors = ["Dirk Kelly", "John Barker"]
|
10
|
+
gem.add_dependency 'radiant', '>= 0.9.1'
|
10
11
|
gem.add_dependency 'radiant-forms-extension', '>= 3.1.0'
|
11
12
|
gem.add_dependency 'radiant-images-extension', '>= 0.2.0'
|
12
13
|
gem.add_dependency 'radiant-layouts-extension', '>= 0.9.1'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.10.0
|
@@ -1,137 +1,46 @@
|
|
1
1
|
class Admin::Shop::CustomersController < Admin::ResourceController
|
2
2
|
model_class ShopCustomer
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@shop_customers = ShopCustomer.scoped_by_access("front").all
|
11
|
-
@shop_customer = ShopCustomer.scoped_by_access("front").new
|
12
|
-
attr_hash = {}
|
13
|
-
respond_to do |format|
|
14
|
-
format.html { render }
|
15
|
-
format.js { render :partial => '/admin/shop/customers/excerpt', :collection => @shop_customers }
|
16
|
-
format.xml { render :xml => @shop_customers.to_xml(attr_hash) }
|
17
|
-
format.json { render :json => @shop_customers.to_json(attr_hash) }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# GET /admin/shop/customers/1
|
22
|
-
# GET /admin/shop/customers/1.js
|
23
|
-
# GET /admin/shop/customers/1.xml
|
24
|
-
# GET /admin/shop/customers/1.json AJAX and HTML
|
25
|
-
#----------------------------------------------------------------------------
|
26
|
-
def show
|
27
|
-
@shop_customer = ShopCustomer.scoped_by_access("front").find(params[:id])
|
28
|
-
attr_hash = {
|
29
|
-
:include => {:orders => {:only => [:id, :balance, :status, :created_at, :updated_at, :payment_id]} },
|
30
|
-
:only => [:id, :email, :reference, :created_at, :updated_at, :organization, :notes, :name, :login, :access]
|
31
|
-
}
|
32
|
-
respond_to do |format|
|
33
|
-
format.html { render }
|
34
|
-
format.js { render :partial => '/admin/shop/customers/customer', :locals => { :customer => @shop_customer } }
|
35
|
-
format.xml { render :xml => @shop_customer.to_xml(attr_hash) }
|
36
|
-
format.json { render :json => @shop_customer.to_json(attr_hash) }
|
37
|
-
end
|
38
|
-
end
|
4
|
+
before_filter :config_global
|
5
|
+
before_filter :config_new, :only => [ :new, :create ]
|
6
|
+
before_filter :config_edit, :only => [ :edit, :update ]
|
7
|
+
before_filter :assets_global
|
8
|
+
before_filter :assets_index, :only => [ :index ]
|
9
|
+
before_filter :assets_edit, :only => [ :edit, :update ]
|
39
10
|
|
40
|
-
|
41
|
-
# POST /admin/shop/customers.js
|
42
|
-
# POST /admin/shop/customers.xml
|
43
|
-
# POST /admin/shop/customers.json AJAX and HTML
|
44
|
-
#----------------------------------------------------------------------------
|
45
|
-
def create
|
46
|
-
@shop_customer = ShopCustomer.new(params[:shop_customer])
|
11
|
+
private
|
47
12
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
}
|
54
|
-
format.js { render :partial => '/admin/shop/customers/excerpt', :locals => { :excerpt => @shop_customer } }
|
55
|
-
format.xml { redirect_to "/admin/shop/customers/#{@shop_customer.id}.xml" }
|
56
|
-
format.json { redirect_to "/admin/shop/customers/#{@shop_customer.id}.json" }
|
57
|
-
end
|
58
|
-
else
|
59
|
-
respond_to do |format|
|
60
|
-
format.html {
|
61
|
-
flash[:error] = "Unable to create new customer."
|
62
|
-
render
|
63
|
-
}
|
64
|
-
format.js { render :text => @shop_customer.errors.to_json, :status => :unprocessable_entity }
|
65
|
-
format.xml { render :xml => @shop_customer.errors.to_xml, :status => :unprocessable_entity }
|
66
|
-
format.json { render :json => @shop_customer.errors.to_json, :status => :unprocessable_entity }
|
67
|
-
end
|
13
|
+
def config_global
|
14
|
+
@meta ||= []
|
15
|
+
@buttons ||= []
|
16
|
+
@parts ||= []
|
17
|
+
@popups ||= []
|
68
18
|
end
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
# PUT /admin/shop/customers/1.json AJAX and HTML
|
75
|
-
#----------------------------------------------------------------------------
|
76
|
-
def update
|
77
|
-
@shop_customer = ShopCustomer.find(params[:id])
|
78
|
-
if @shop_customer.update_attributes!(params[:shop_customer])
|
79
|
-
respond_to do |format|
|
80
|
-
format.html {
|
81
|
-
flash[:notice] = "Customer updated successfully."
|
82
|
-
redirect_to admin_shop_customers_path
|
83
|
-
}
|
84
|
-
format.js { render :partial => '/admin/shop/customers/excerpt', :locals => { :excerpt => @shop_customer } }
|
85
|
-
format.xml { redirect_to "/admin/shop/customers/#{@shop_customer.id}.xml" }
|
86
|
-
format.json { redirect_to "/admin/shop/customers/#{@shop_customer.id}.json" }
|
87
|
-
end
|
88
|
-
else
|
89
|
-
respond_to do |format|
|
90
|
-
format.html {
|
91
|
-
flash[:error] = "Unable to update customer."
|
92
|
-
render
|
93
|
-
}
|
94
|
-
format.js { render :text => @shop_customer.errors.to_s, :status => :unprocessable_entity }
|
95
|
-
format.xml { render :xml => @shop_customer.errors.to_xml, :status => :unprocessable_entity }
|
96
|
-
format.json { render :json => @shop_customer.errors.to_json, :status => :unprocessable_entity }
|
97
|
-
end
|
19
|
+
|
20
|
+
def config_new
|
21
|
+
@meta << 'login'
|
22
|
+
@meta << 'password'
|
23
|
+
@meta << 'password_confirmation'
|
98
24
|
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# DELETE /admin/shop/customers/1
|
102
|
-
# DELETE /admin/shop/customers/1.js
|
103
|
-
# DELETE /admin/shop/customers/1.xml
|
104
|
-
# DELETE /admin/shop/customers/1.json AJAX and HTML
|
105
|
-
#----------------------------------------------------------------------------
|
106
|
-
def destroy
|
107
|
-
# Need to rewrite this method to check for errors and return xml or json.
|
108
|
-
# For some reason the answer isn't obvious to me.
|
109
|
-
@shop_customer = ShopCustomer.find(params[:id])
|
110
25
|
|
111
|
-
|
112
|
-
@
|
113
|
-
@
|
26
|
+
def config_edit
|
27
|
+
@meta << 'login'
|
28
|
+
@meta << 'password'
|
29
|
+
@meta << 'password_confirmation'
|
114
30
|
|
115
|
-
|
116
|
-
|
117
|
-
flash[:notice] = @message
|
118
|
-
redirect_to admin_shop_categories_path
|
119
|
-
}
|
120
|
-
format.js { render :text => @message, :status => 200 }
|
121
|
-
format.xml { render :xml => {:message => @message}, :status => 200 }
|
122
|
-
format.json { render :json => {:message => @message}, :status => 200 }
|
123
|
-
end
|
124
|
-
else
|
125
|
-
@message = "Unable to delete category."
|
126
|
-
respond_to do |format|
|
127
|
-
format.html {
|
128
|
-
flash[:error] = @message
|
129
|
-
}
|
130
|
-
format.js { render :text => @message, :status => :unprocessable_entity }
|
131
|
-
format.xml { render :xml => {:message => @message}, :status => :unprocessable_entity }
|
132
|
-
format.json { render :json => {:message => @message}, :status => :unprocessable_entity }
|
133
|
-
end
|
31
|
+
@parts << 'orders'
|
32
|
+
@parts << 'addresses'
|
134
33
|
end
|
135
|
-
|
136
|
-
|
34
|
+
|
35
|
+
def assets_global
|
36
|
+
include_stylesheet 'admin/extensions/shop/edit'
|
37
|
+
include_stylesheet 'admin/extensions/shop/index'
|
38
|
+
end
|
39
|
+
|
40
|
+
def assets_index
|
41
|
+
end
|
42
|
+
|
43
|
+
def assets_edit
|
44
|
+
end
|
45
|
+
|
137
46
|
end
|
@@ -14,8 +14,6 @@ class Shop::CategoriesController < ApplicationController
|
|
14
14
|
# GET /shop/categories/:query.json AJAX and HTML
|
15
15
|
#----------------------------------------------------------------------------
|
16
16
|
def index
|
17
|
-
attr_hash = { :include => :products, :only => ShopCategory.params }
|
18
|
-
|
19
17
|
@shop_categories = ShopCategory.search(params[:query])
|
20
18
|
|
21
19
|
respond_to do |format|
|
@@ -30,11 +28,9 @@ class Shop::CategoriesController < ApplicationController
|
|
30
28
|
# GET /shop/:handle.json AJAX and HTML
|
31
29
|
#----------------------------------------------------------------------------
|
32
30
|
def show
|
33
|
-
attr_hash = { :include => :products, :only => ShopCategory.params }
|
34
|
-
|
35
31
|
if @shop_category = ShopCategory.find(:first, :conditions => { :handle => params[:handle] })
|
36
32
|
@title = @shop_category.name
|
37
|
-
@radiant_layout = @shop_category.layout.name
|
33
|
+
@radiant_layout = @shop_category.layout.name rescue (raise "Couldn't find Layout with id #{@shop_category.layout_id}")
|
38
34
|
|
39
35
|
respond_to do |format|
|
40
36
|
format.html { render }
|
@@ -32,7 +32,7 @@ class Shop::ProductsController < ApplicationController
|
|
32
32
|
if @shop_product = ShopProduct.find(:first, :conditions => { :sku => params[:sku] })
|
33
33
|
@shop_category = @shop_product.category unless @shop_product.nil?
|
34
34
|
|
35
|
-
@radiant_layout = @shop_product.layout.name
|
35
|
+
@radiant_layout = @shop_product.layout.name rescue (raise "Couldn't find Layout with id #{@shop_product.layout_id}")
|
36
36
|
@title = @shop_product.name
|
37
37
|
|
38
38
|
respond_to do |format|
|
data/app/models/form_checkout.rb
CHANGED
@@ -1,245 +1,331 @@
|
|
1
1
|
class FormCheckout
|
2
2
|
include Forms::Models::Extension
|
3
3
|
|
4
|
+
attr_accessor :config, :data, :result, :gateway, :card, :billing, :shipping
|
5
|
+
|
4
6
|
def create
|
5
|
-
@
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
if @config[:address].present?
|
17
|
-
# If the form was configured for address
|
18
|
-
build_addresses
|
19
|
-
end
|
20
|
-
|
21
|
-
if @config[:gateway].present? and card
|
22
|
-
# If the form was configured for gateway
|
23
|
-
build_gateway
|
24
|
-
build_card
|
7
|
+
find_current_order # locate the @order object
|
8
|
+
|
9
|
+
create_result_object # A default response object
|
10
|
+
|
11
|
+
create_order_addresses # Create @order.billing and @order.shipping
|
12
|
+
|
13
|
+
# If the form was configured for gateway and we have a billing address
|
14
|
+
if gateway.present?
|
15
|
+
prepare_gateway # Create the @gateway object
|
16
|
+
prepare_credit_card if card.present?# Create the @card object
|
25
17
|
|
26
|
-
|
27
|
-
|
18
|
+
if @result[:gateway] and @result[:card]
|
19
|
+
purchase! # Use @card to pay through @gateway
|
20
|
+
end
|
28
21
|
|
29
|
-
|
30
|
-
|
22
|
+
# We have a paid for order with a billing address
|
23
|
+
if success?
|
24
|
+
# The form was configured to send a payment email
|
25
|
+
if mail.present?
|
26
|
+
configure_invoice_mail # Create some configuration variables for mailing
|
27
|
+
end
|
28
|
+
else
|
29
|
+
@form.redirect_to = :back
|
30
|
+
end
|
31
31
|
end
|
32
|
-
|
33
32
|
@result
|
34
33
|
end
|
35
34
|
|
36
35
|
private
|
37
|
-
|
36
|
+
|
37
|
+
# Uses the page session data to find the current order
|
38
|
+
def find_current_order
|
39
|
+
@order = ShopOrder.find(@page.request.session[:shop_order])
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_result_object
|
43
|
+
@result = {
|
44
|
+
:order => @order.id, # We return the order id so the thank you screen has access to it
|
45
|
+
:billing => @order.billing.present?,
|
46
|
+
:shipping => @order.shipping.present?,
|
47
|
+
:payment => false,
|
48
|
+
:card => false,
|
49
|
+
:gateway => false,
|
50
|
+
:message => nil,
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
38
54
|
# Assigns a shipping and billing address to the @order
|
39
|
-
def
|
55
|
+
def create_order_addresses
|
40
56
|
if billing.present?
|
41
57
|
# We're going to create a billing object
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
58
|
+
create_order_billing_address
|
59
|
+
|
60
|
+
# We're going to assign shipping to billing because they didn't send shipping
|
61
|
+
if !shipping.present? and @billing.present?
|
46
62
|
@shipping = @billing
|
47
63
|
@order.update_attribute(:shipping_id, @shipping.id)
|
48
64
|
end
|
49
65
|
end
|
50
66
|
|
51
67
|
if shipping.present?
|
52
|
-
|
68
|
+
create_order_shipping_address
|
53
69
|
end
|
54
70
|
|
55
|
-
|
56
|
-
@result[:shipping] = @order.shipping.present? ? @order.shipping : false
|
57
|
-
|
58
|
-
unless @order.billing.present? and @order.shipping.present?
|
71
|
+
if @order.billing.nil?
|
59
72
|
@form.redirect_to = :back
|
60
73
|
end
|
74
|
+
|
75
|
+
@result[:billing] = @order.billing.present?
|
76
|
+
@result[:shipping] = @order.shipping.present?
|
61
77
|
end
|
62
78
|
|
63
|
-
|
79
|
+
# Attaches a billing address to the order (and current customer)
|
80
|
+
def create_order_billing_address
|
64
81
|
# Billing Address
|
65
|
-
if billing[
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
82
|
+
if billing[:id]
|
83
|
+
begin
|
84
|
+
# Use an existing Address and update its values
|
85
|
+
@billing = current_customer.billings.find(billing[:id])
|
86
|
+
@billing.update_attributes(billing)
|
87
|
+
@order.update_attribute(:billing_id, @billing.id)
|
88
|
+
rescue
|
89
|
+
# We cant find that address for that user
|
90
|
+
end
|
91
|
+
|
71
92
|
elsif @order.billing.present?
|
72
93
|
# Use the current billing and update its values
|
73
94
|
@billing = @order.billing
|
74
95
|
@billing.update_attributes(billing)
|
75
|
-
|
96
|
+
|
76
97
|
else
|
77
98
|
# Create a new address with these attributes
|
78
99
|
@billing = ShopAddress.new(billing)
|
79
100
|
if @billing.save
|
80
101
|
@order.update_attribute(:billing_id, @billing.id)
|
81
102
|
end
|
82
|
-
|
103
|
+
|
83
104
|
end
|
105
|
+
|
84
106
|
end
|
85
107
|
|
86
|
-
|
108
|
+
# Attaches a shipping address to the order (and current customer)
|
109
|
+
def create_order_shipping_address
|
87
110
|
# Shipping Address
|
88
|
-
|
111
|
+
|
112
|
+
if shipping[:id]
|
89
113
|
# Use an existing Address and update its values
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
@
|
102
|
-
|
114
|
+
begin
|
115
|
+
@shipping = current_customer.shippings.find(shipping[:id])
|
116
|
+
if @shipping == @billing and shipping == billing
|
117
|
+
# We have exactly the same shipping and billing data
|
118
|
+
@shipping = @billing
|
119
|
+
@order.update_attribute(:shipping_id, @billing.id)
|
120
|
+
|
121
|
+
elsif (shipping.reject!{|k,v| k == :id }).values.all?(&:blank?)
|
122
|
+
# We have just passed the id and not the data
|
123
|
+
@order.update_attribute(:shipping_id, @shipping.id)
|
124
|
+
|
125
|
+
elsif @shipping == @billing and shipping != billing
|
126
|
+
# We have conflicting data so create a new address
|
127
|
+
# the id is rejected so we'll get a new address
|
128
|
+
@order.update_attributes!({ :shipping_attributes => shipping })
|
129
|
+
@shipping = @order.shipping
|
130
|
+
end
|
131
|
+
rescue
|
132
|
+
# We cant find that address for that customer
|
103
133
|
end
|
104
134
|
|
105
135
|
elsif @order.shipping.present?
|
106
136
|
# Use the current shipping and update its values
|
107
137
|
@shipping = @order.shipping
|
108
138
|
@shipping.update_attributes(shipping)
|
109
|
-
|
139
|
+
|
110
140
|
elsif shipping.values.all?(&:blank?) or shipping == billing
|
111
141
|
# We haven't set a shipping, or we have copied billing, so use billing
|
112
142
|
@shipping = @billing
|
113
143
|
@order.update_attribute(:shipping_id, @billing.id)
|
114
|
-
|
144
|
+
|
115
145
|
else
|
116
146
|
# Create a new address with these attributes
|
117
147
|
@order.update_attributes!({ :shipping_attributes => shipping })
|
118
148
|
@shipping = @order.shipping
|
119
149
|
end
|
120
150
|
end
|
121
|
-
|
151
|
+
|
122
152
|
# Creates a gateway instance variable based off the form configuration
|
123
|
-
def
|
124
|
-
ActiveMerchant::Billing::Base.mode =
|
125
|
-
|
153
|
+
def prepare_gateway
|
154
|
+
ActiveMerchant::Billing::Base.mode = gateway_mode
|
126
155
|
begin
|
127
|
-
@gateway = ActiveMerchant::Billing.const_get("#{
|
156
|
+
@gateway = ActiveMerchant::Billing.const_get("#{gateway_name}Gateway").new(gateway_credentials)
|
128
157
|
@result[:gateway] = true
|
129
158
|
end
|
130
159
|
end
|
131
|
-
|
160
|
+
|
161
|
+
# Creates a payment object attached to the order
|
162
|
+
def create_payment
|
163
|
+
payment = ShopPayment.new({
|
164
|
+
:order => @order,
|
165
|
+
:gateway => gateway_name,
|
166
|
+
:amount => @order.price,
|
167
|
+
:card_type => card_type,
|
168
|
+
:card_number=> card_number_secure
|
169
|
+
})
|
170
|
+
|
171
|
+
@order.update_attribute(:status, 'paid')
|
172
|
+
|
173
|
+
@result[:payment] = payment.save
|
174
|
+
end
|
175
|
+
|
132
176
|
# Builds an ActiveMerchant card using the submitted card information
|
133
|
-
def
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
@result[:card] = {
|
146
|
-
:valid => @card.valid?
|
147
|
-
}
|
148
|
-
end
|
177
|
+
def prepare_credit_card
|
178
|
+
@card = ActiveMerchant::Billing::CreditCard.new({
|
179
|
+
:number => card_number,
|
180
|
+
:month => card_month,
|
181
|
+
:year => card_year,
|
182
|
+
:first_name => card_first_name,
|
183
|
+
:last_name => card_last_name,
|
184
|
+
:verification_value => card_verification,
|
185
|
+
:type => card_type
|
186
|
+
})
|
187
|
+
|
188
|
+
@result[:card] = @card.valid?
|
149
189
|
end
|
150
190
|
|
151
|
-
|
191
|
+
# Sets up mail to send an invoice to the billing email address
|
192
|
+
def configure_invoice_mail
|
193
|
+
@form[:extensions][:mail] ||= {}
|
194
|
+
@form[:extensions][:mail].merge!({
|
195
|
+
:recipient => @order.billing.email,
|
196
|
+
:to => @order.billing.email,
|
197
|
+
})
|
198
|
+
@form[:extensions][:mail].merge!(mail)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Uses the gateway and card objects to carry out an ActiveMerchant purchase
|
202
|
+
def purchase!
|
152
203
|
result = @gateway.purchase(amount, @card, options)
|
153
204
|
|
154
|
-
@result[:
|
155
|
-
:success => result.success?,
|
156
|
-
:message => result.message
|
157
|
-
}
|
205
|
+
@result[:message] = result.message
|
158
206
|
|
159
|
-
|
160
|
-
|
207
|
+
if result.success?
|
208
|
+
create_payment
|
161
209
|
end
|
162
210
|
end
|
163
211
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
@config[:test].present?
|
212
|
+
# Returns the current logged in ShopCustomer (if it exists)
|
213
|
+
def current_customer
|
214
|
+
return @shop_customer if @shop_customer.present?
|
215
|
+
return current_user if current_user.present?
|
216
|
+
@shop_customer = ShopCustomer.find(current_user.id)
|
170
217
|
end
|
171
218
|
|
219
|
+
# Returns an array of billing attributes
|
172
220
|
def billing
|
173
|
-
|
221
|
+
@data[:billing]
|
174
222
|
end
|
175
223
|
|
224
|
+
# Returns an array of shipping attributes
|
176
225
|
def shipping
|
177
|
-
|
226
|
+
@data[:shipping]
|
178
227
|
end
|
179
228
|
|
229
|
+
# Returns the configured gateway
|
180
230
|
def gateway
|
181
|
-
@config[:gateway]
|
231
|
+
@config[:gateway]
|
232
|
+
end
|
233
|
+
|
234
|
+
# Returns the name of the gateway (Eway)
|
235
|
+
def gateway_name
|
236
|
+
gateway[:name]
|
182
237
|
end
|
183
238
|
|
239
|
+
# Returns Gateway username and password etc
|
184
240
|
def gateway_credentials
|
185
|
-
|
241
|
+
gateway[:credentials]
|
186
242
|
end
|
187
243
|
|
244
|
+
# Returns whether the form is configured as testing or production
|
245
|
+
def gateway_mode
|
246
|
+
@config[:test].present? ? :test : :production
|
247
|
+
end
|
248
|
+
|
249
|
+
# Returns the submitted card attributes
|
188
250
|
def card
|
189
|
-
@data[
|
251
|
+
@data[:card]
|
190
252
|
end
|
191
253
|
|
254
|
+
# Returns card number (1234123412341234)
|
192
255
|
def card_number
|
193
|
-
card[
|
256
|
+
card[:number].to_s.gsub('-', '')
|
257
|
+
end
|
258
|
+
|
259
|
+
# Returns the last 4 card number digits (1234)
|
260
|
+
def card_number_secure
|
261
|
+
@card.display_number
|
194
262
|
end
|
195
263
|
|
264
|
+
# Returns card month (02)
|
196
265
|
def card_month
|
197
|
-
card[
|
266
|
+
card[:month].to_i
|
198
267
|
end
|
199
268
|
|
269
|
+
# Returns card year (2010)
|
200
270
|
def card_year
|
201
|
-
card[
|
271
|
+
card[:year].to_i
|
202
272
|
end
|
203
273
|
|
274
|
+
# Returns card type (visa)
|
204
275
|
def card_type
|
205
|
-
card[
|
276
|
+
card[:type]
|
206
277
|
end
|
207
278
|
|
279
|
+
# Returns card verification number (123)
|
208
280
|
def card_verification
|
209
|
-
card[
|
281
|
+
card[:verification].to_s
|
210
282
|
end
|
211
283
|
|
284
|
+
# Splits the card names into an array we can inspect
|
212
285
|
def card_names
|
213
286
|
return @card_names if @card_names.present?
|
214
|
-
@card_names = @data[
|
287
|
+
@card_names = @data[:card][:name].split(' ')
|
215
288
|
end
|
216
289
|
|
290
|
+
# Return all the strings bar the last on the card
|
217
291
|
def card_first_name
|
218
292
|
card_names[0, card_names.length - 1].join(' ') if card_names.present?
|
219
293
|
end
|
220
294
|
|
295
|
+
# Return the last string on the card
|
221
296
|
def card_last_name
|
222
297
|
card_names[-1] if card_names.present?
|
223
298
|
end
|
224
299
|
|
300
|
+
# Returns configured mail attributes
|
301
|
+
def mail
|
302
|
+
@config[:mail]
|
303
|
+
end
|
304
|
+
|
305
|
+
# Returns the amount to be charged, which is $10 on testing gateways
|
225
306
|
def amount
|
226
307
|
result = 0
|
227
|
-
|
228
|
-
if testing
|
308
|
+
if gateway_mode === :test
|
229
309
|
result = 1000
|
230
310
|
else
|
231
311
|
result = (@order.price * 100)
|
232
312
|
end
|
233
|
-
|
234
313
|
result
|
235
314
|
end
|
236
315
|
|
316
|
+
# Options for the gateway are created at config and runtime level
|
237
317
|
def options
|
238
318
|
@config[:options] ||= {}
|
239
319
|
|
240
320
|
@config[:options][:order_id] = @order.id
|
241
|
-
|
321
|
+
@config[:options].merge!(@data[:options]) if @data[:options].present?
|
322
|
+
|
242
323
|
@config[:options]
|
243
324
|
end
|
244
325
|
|
326
|
+
# Will return true if the order is paid for and has a billing address
|
327
|
+
def success?
|
328
|
+
@result[:payment] and @result[:billing]
|
329
|
+
end
|
330
|
+
|
245
331
|
end
|