spree_paypal_website_standard 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +23 -0
- data/README.md +79 -0
- data/app/controllers/checkout_controller_decorator.rb +22 -0
- data/app/controllers/payment_notifications_controller.rb +71 -0
- data/app/controllers/paypal_controller.rb +24 -0
- data/app/models/order_decorator.rb +15 -0
- data/app/models/payment_notification.rb +14 -0
- data/app/views/admin/orders/_pp_standard_txns.html.erb +23 -0
- data/app/views/checkout/_paypal_checkout.html.erb +49 -0
- data/app/views/checkout/edit.html.erb +28 -0
- data/app/views/orders/_paypal_checkout.html.erb +65 -0
- data/app/views/paypal_payments/successful.html.erb +1 -0
- data/lib/paypal_configuration.rb +17 -0
- data/lib/pp_website_standard.rb +30 -0
- data/lib/pp_website_standard_hooks.rb +4 -0
- data/lib/spree/paypal/config.rb +22 -0
- data/lib/tasks/install.rake +26 -0
- data/lib/tasks/pp_website_standard.rake +1 -0
- metadata +101 -0
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Redistribution and use in source and binary forms, with or without modification,
|
2
|
+
are permitted provided that the following conditions are met:
|
3
|
+
|
4
|
+
* Redistributions of source code must retain the above copyright notice,
|
5
|
+
this list of conditions and the following disclaimer.
|
6
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
7
|
+
this list of conditions and the following disclaimer in the documentation
|
8
|
+
and/or other materials provided with the distribution.
|
9
|
+
* Neither the name of the Rails Dog LLC nor the names of its
|
10
|
+
contributors may be used to endorse or promote products derived from this
|
11
|
+
software without specific prior written permission.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
14
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
15
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
16
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
17
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
18
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
19
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
20
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
21
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
22
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
23
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Spree PayPal Website Standard
|
2
|
+
|
3
|
+
A [Spree](http://spreecommerce.com) extension to allow payments using PayPal Website Standard.
|
4
|
+
|
5
|
+
## Before you read further
|
6
|
+
|
7
|
+
This README is in the process of thorough rework to describe the current codebase, design decisions and how to use it. But at the moment some parts are out-of-date. Please read the code of the extension, it's pretty well commented and structured.
|
8
|
+
|
9
|
+
## Old Introduction (outdated!)
|
10
|
+
|
11
|
+
Overrides the default Spree checkout process and uses offsite payment processing via PayPal's Website Payment Standard (WPS).
|
12
|
+
|
13
|
+
You'll want to test this using a paypal sandbox account first. Once you have a business account, you'll want to turn on Instant Payment Notification (IPN). This is how your application will be notified when a transaction is complete. Certain transactions aren't completed immediately. Because of this we use IPN for your application to get notified when the transaction is complete. IPN means that our application gets an incoming request from Paypal when the transaction goes through.
|
14
|
+
|
15
|
+
You may want to implement your own custom logic by adding 'state_machine' hooks. Just add these hooks in your site extension (don't change the 'pp_website_standard' extension.) Here's an example of how to add the hooks to your site extension.
|
16
|
+
|
17
|
+
|
18
|
+
fsm = Order.state_machines['state']
|
19
|
+
fsm.after_transition :to => 'paid', :do => :after_payment
|
20
|
+
fsm.after_transition :to => 'pending_payment', :do => :after_pending
|
21
|
+
|
22
|
+
Order.class_eval do
|
23
|
+
def after_payment
|
24
|
+
# email user and tell them we received their payment
|
25
|
+
end
|
26
|
+
|
27
|
+
def after_pending
|
28
|
+
# email user and thell them that we are processing their order, etc.
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
## Installation
|
34
|
+
|
35
|
+
Add to your Spree application Gemfile.
|
36
|
+
|
37
|
+
gem "pp_website_standard", :git => "git://github.com/tomash/spree-pp-website-standard.git"
|
38
|
+
|
39
|
+
Run the install rake task to copiy migrations (create payment_notifications table)
|
40
|
+
|
41
|
+
rake pp_website_standard:install
|
42
|
+
|
43
|
+
Configure, run, test.
|
44
|
+
|
45
|
+
|
46
|
+
## Configuration
|
47
|
+
|
48
|
+
Be sure to configure the following configuration parameters. Preferably put it in initializer like config/initializers/pp_website_standard.rb.
|
49
|
+
|
50
|
+
Example:
|
51
|
+
|
52
|
+
Spree::Paypal::Config.set(:account => "foo@example.com")
|
53
|
+
Spree::Paypal::Config.set(:ipn_notify_host => "http://example.com:3000")
|
54
|
+
Spree::Paypal::Config.set(:success_url => "http://localhost:3000/paypal/confirm")
|
55
|
+
|
56
|
+
|
57
|
+
The following configuration options (keys) can be set:
|
58
|
+
|
59
|
+
:account # email account of store
|
60
|
+
:ipn_notify_host # host prepared to receive IPN notifications
|
61
|
+
:success_url # url the customer is redirected to after successfully completing payment
|
62
|
+
:currency_code # default EUR
|
63
|
+
:sandbox_url # paypal url in sandbox mode, default https://www.sandbox.paypal.com/cgi-bin/webscr
|
64
|
+
:paypal_url # paypal url in production, default https://www.paypal.com/cgi-bin/webscr
|
65
|
+
:populate_address (true/false) # pre-populate fields of billing address based on spree order data
|
66
|
+
|
67
|
+
Only the first three ones need to be set up in order to get running.
|
68
|
+
|
69
|
+
|
70
|
+
## IPN Notes (outdated!)
|
71
|
+
|
72
|
+
Real world testing indicates that IPN can be very slow. If you want to test the IPN piece Paypal now has an IPN tool on their developer site. Just use the correct URL from the hidden field on your Spree checkout screen. In the IPN tool, change the transaction type to `cart checkout` and change the `mc_gross` variable to match your order total.
|
73
|
+
|
74
|
+
|
75
|
+
## TODO
|
76
|
+
|
77
|
+
* README with complete documentation
|
78
|
+
* Test suite
|
79
|
+
* Refunds
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# commented-out as this is too invasive at the moment
|
2
|
+
# (assumes paypal is the only payment method available in your store)
|
3
|
+
|
4
|
+
=begin
|
5
|
+
CheckoutController.class_eval do
|
6
|
+
|
7
|
+
def edit
|
8
|
+
if ((@order.state == "payment") && @order.valid?)
|
9
|
+
puts "valid, processing"
|
10
|
+
if @order.payable_via_paypal?
|
11
|
+
puts "payable via paypal, adding payment"
|
12
|
+
payment = Payment.new
|
13
|
+
payment.amount = @order.total
|
14
|
+
payment.payment_method = Order.paypal_payment_method
|
15
|
+
@order.payments << payment
|
16
|
+
payment.started_processing
|
17
|
+
render(:partial => 'checkout/paypal_checkout')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
=end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class PaymentNotificationsController < ApplicationController
|
2
|
+
protect_from_forgery :except => [:create]
|
3
|
+
skip_before_filter :restriction_access
|
4
|
+
|
5
|
+
def create
|
6
|
+
@order = Order.find_by_number(params[:invoice])
|
7
|
+
PaymentNotification.create!(:params => params,
|
8
|
+
:order_id => @order.id,
|
9
|
+
:status => params[:payment_status],
|
10
|
+
:transaction_id => params[:txn_id])
|
11
|
+
|
12
|
+
# this logging stuff won't live here for long...
|
13
|
+
|
14
|
+
Order.transaction do
|
15
|
+
# main part of hacks
|
16
|
+
order = @order
|
17
|
+
|
18
|
+
#create payment for this order
|
19
|
+
payment = Payment.new
|
20
|
+
payment.amount = order.total
|
21
|
+
payment.payment_method = Order.paypal_payment_method
|
22
|
+
order.payments << payment
|
23
|
+
payment.started_processing
|
24
|
+
|
25
|
+
order.payment.complete
|
26
|
+
logger.info("order #{order.number} (#{order.id}) -- completed payment")
|
27
|
+
while order.state != "complete"
|
28
|
+
order.next
|
29
|
+
logger.info("advanced state of Order #{order.number} (#{order.id}). current state #{order.state}. thread #{Thread.current.to_s}. issuing callback")
|
30
|
+
state_callback(:after) # that line will run all _not run before_ callbacks
|
31
|
+
end
|
32
|
+
order.update_totals
|
33
|
+
order.update!
|
34
|
+
logger.info("Order #{order.number} (#{order.id}) updated successfully, IPN complete")
|
35
|
+
end
|
36
|
+
|
37
|
+
render :nothing => true
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# those methods are copy-pasted from CheckoutController
|
43
|
+
# we cannot inherit from that class unless we want to skip_before_filter
|
44
|
+
# half of calls in SpreeBase module
|
45
|
+
def state_callback(before_or_after = :before)
|
46
|
+
method_name = :"#{before_or_after}_#{@order.state}"
|
47
|
+
send(method_name) if respond_to?(method_name, true)
|
48
|
+
end
|
49
|
+
|
50
|
+
def before_address
|
51
|
+
@order.bill_address ||= Address.new(:country => default_country)
|
52
|
+
@order.ship_address ||= Address.new(:country => default_country)
|
53
|
+
end
|
54
|
+
|
55
|
+
def before_delivery
|
56
|
+
@order.shipping_method ||= (@order.rate_hash.first && @order.rate_hash.first[:shipping_method])
|
57
|
+
end
|
58
|
+
|
59
|
+
def before_payment
|
60
|
+
current_order.payments.destroy_all if request.put?
|
61
|
+
end
|
62
|
+
|
63
|
+
def after_complete
|
64
|
+
session[:order_id] = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_country
|
68
|
+
Country.find Spree::Config[:default_country_id]
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class PaypalController < CheckoutController
|
2
|
+
protect_from_forgery :except => [:confirm]
|
3
|
+
skip_before_filter :persist_gender
|
4
|
+
|
5
|
+
def confirm
|
6
|
+
# XXX It works!
|
7
|
+
#redirect_to checkout_state_path("confirm")
|
8
|
+
# but we want this:
|
9
|
+
unless current_order
|
10
|
+
redirect_to root_path
|
11
|
+
else
|
12
|
+
order = current_order
|
13
|
+
while order.state != "complete"
|
14
|
+
order.next
|
15
|
+
state_callback(:after)
|
16
|
+
end
|
17
|
+
#order.finalize!
|
18
|
+
flash[:notice] = I18n.t(:order_processed_successfully)
|
19
|
+
flash[:commerce_tracking] = "nothing special"
|
20
|
+
redirect_to order_path(current_order)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Order.class_eval do
|
2
|
+
has_many :payment_notifications
|
3
|
+
|
4
|
+
def shipment_cost
|
5
|
+
adjustment_total - credit_total
|
6
|
+
end
|
7
|
+
|
8
|
+
def payable_via_paypal?
|
9
|
+
!!self.class.paypal_payment_method
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.paypal_payment_method
|
13
|
+
PaymentMethod.select{ |pm| pm.name.downcase =~ /paypal/}.first
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class PaymentNotification < ActiveRecord::Base
|
2
|
+
belongs_to :order
|
3
|
+
serialize :params
|
4
|
+
after_create :mark_order_as_paid
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def mark_order_as_paid
|
9
|
+
if(status == "Completed")
|
10
|
+
logger.info "Order #{order.number} should be marked as paid now -- IPN status 'Completed'"
|
11
|
+
#order.update_attributes({:paid_on => Date.today, :status_id => Status.PAID.id})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<% if @order.paypal_payment %>
|
2
|
+
|
3
|
+
<b><%= t("Paypal Transaction") %></b>
|
4
|
+
|
5
|
+
<table class="basic-table">
|
6
|
+
<tr>
|
7
|
+
<th><%= t("Amount") %></th>
|
8
|
+
<th><%= t("Fee") %></th>
|
9
|
+
<th><%= t("Status") %></th>
|
10
|
+
<th><%= t("Transaction Id") %></th>
|
11
|
+
<th><%= t("Received At") %></th>
|
12
|
+
</tr>
|
13
|
+
<% @order.paypal_payment.txns.each do |t| %>
|
14
|
+
<tr>
|
15
|
+
<td><%=number_to_currency t.amount %></td>
|
16
|
+
<td><%=number_to_currency t.fee %></td>
|
17
|
+
<td><%=t.status %></td>
|
18
|
+
<td><%=t.transaction_id %></td>
|
19
|
+
<td><%=t.received_at %></td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
</table>
|
23
|
+
<% end %>
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<%- if(RAILS_ENV == 'development')
|
2
|
+
submit_url = Spree::Paypal::Config[:sandbox_url]
|
3
|
+
else
|
4
|
+
submit_url = Spree::Paypal::Config[:paypal_url]
|
5
|
+
end
|
6
|
+
%>
|
7
|
+
<%= form_tag submit_url do %>
|
8
|
+
|
9
|
+
<input id="business" name="business" type="hidden" value="<%= Spree::Paypal::Config[:account] %>" />
|
10
|
+
<input id="invoice" name="invoice" type="hidden" value="<%= @order.number %>" />
|
11
|
+
|
12
|
+
<% @order.line_items.each_with_index do |item, index| %>
|
13
|
+
<%- if item.variant.respond_to?(:paypal_name) %>
|
14
|
+
<input id="item_name_<%= index + 1 %>" name="item_name_<%= index + 1 %>" type="hidden" value="<%= item.variant.paypal_name %>" />
|
15
|
+
<% else %>
|
16
|
+
<input id="item_name_<%= index + 1 %>" name="item_name_<%= index + 1 %>" type="hidden" value="<%= item.variant.product.name %>" />
|
17
|
+
<% end %>
|
18
|
+
<input id="amount_<%= index + 1 %>" name="amount_<%= index + 1 %>" type="hidden" value="<%= item.price %>" />
|
19
|
+
<input id="quantity_<%= index + 1 %>" name="quantity_<%= index + 1 %>" type="hidden" value="<%= item.quantity %>" />
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<input id="currency_code" name="currency_code" type="hidden" value="<%= Spree::Paypal::Config[:currency_code] %>" />
|
23
|
+
<input id="handling_cart" name="handling_cart" type="hidden" value="<%= @order.ship_total %>" />
|
24
|
+
<input id="tax_cart" name="tax_cart" type="hidden" value="<%= @order.tax_total %>" />
|
25
|
+
|
26
|
+
|
27
|
+
<input id="cmd" name="cmd" type="hidden" value="_cart" />
|
28
|
+
<input type="hidden" name="upload" value="1" />
|
29
|
+
<input id="notify_url" name="notify_url" type="hidden" value="<%= payment_notifications_url %>" />
|
30
|
+
<input type="hidden" name="rm" value ="2" />
|
31
|
+
<input id="return" name="return" type="hidden" value="<%= Spree::Paypal::Config[:success_url] %>" />
|
32
|
+
|
33
|
+
<input id="charset" name="charset" type="hidden" value="utf-8" />
|
34
|
+
|
35
|
+
<% if(Spree::Paypal::Config[:populate_address] && @order.bill_address) %>
|
36
|
+
<input type="hidden" name="address1" id="address1" value="<%= @order.bill_address.address1 %>" />
|
37
|
+
<input type="hidden" name="address2" id="address2" value="<%= @order.bill_address.address2 %>" />
|
38
|
+
<input type="hidden" name="city" id="city" value="<%= @order.bill_address.city %>" />
|
39
|
+
<input type="hidden" name="country" id="country" value="<%= @order.bill_address.country.iso %>" />
|
40
|
+
<input type="hidden" name="email" id="email" value="<%= @order.email %>" />
|
41
|
+
<input type="hidden" name="first_name" id="first_name" value="<%= @order.bill_address.firstname %>" />
|
42
|
+
<input type="hidden" name="last_name" id="last_name" value="<%= @order.bill_address.lastname %>" />
|
43
|
+
<input type="hidden" name="zip" id="zip" value="<%= @order.bill_address.zipcode %>" />
|
44
|
+
<input type="hidden" name="night_phone_b" id="night_phone_b" value="<%= @order.bill_address.phone %>" />
|
45
|
+
<% end %>
|
46
|
+
|
47
|
+
<%= image_submit_tag "pp_checkout.gif" %>
|
48
|
+
|
49
|
+
<% end -%>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<% content_for :head do %>
|
2
|
+
<%= javascript_include_tag 'checkout', '/states' %>
|
3
|
+
<% end %>
|
4
|
+
<div id="checkout">
|
5
|
+
<h1><%= t("checkout")%></h1>
|
6
|
+
<%= checkout_progress %>
|
7
|
+
<br clear="left" />
|
8
|
+
<%= render "shared/error_messages", :target => @order %>
|
9
|
+
<%= hook :checkout_summary_box do %>
|
10
|
+
<div id="checkout-summary">
|
11
|
+
<%= render 'summary', :order => @order %>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
|
16
|
+
<% if(@order.state == "payment") %>
|
17
|
+
<%= render('checkout/paypal_checkout') if @order.payable_via_paypal? %>
|
18
|
+
<% else %>
|
19
|
+
<%= form_for @order, :url => update_checkout_path(@order.state), :html => { :id => "checkout_form_#{@order.state}" } do |form| %>
|
20
|
+
<%= render @order.state, :form => form %>
|
21
|
+
<input id="post-final" type="submit" style="display:none"/>
|
22
|
+
<% end %>
|
23
|
+
<% end %>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
<div id="payment_step">
|
27
|
+
|
28
|
+
</div>
|
@@ -0,0 +1,65 @@
|
|
1
|
+
<% if RAILS_ENV == 'development' %>
|
2
|
+
<form action="<%= Spree::Paypal::Config[:sandbox_url] %>" method="post" onsubmit="return check_zipcode();">
|
3
|
+
<% else %>
|
4
|
+
<form action="<%= Spree::Paypal::Config[:paypal_url] %>" method="post" onsubmit="return check_zipcode();">
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<!-- display payment summary here -->
|
8
|
+
<input id="business" name="business" type="hidden" value="<%= Spree::Paypal::Config[:account] %>" />
|
9
|
+
<input id="invoice" name="invoice" type="hidden" value="<%= @order.number %>" />
|
10
|
+
|
11
|
+
<% @order.line_items.each_with_index do |item, index| %>
|
12
|
+
<input id="item_name_<%= index + 1 %>" name="item_name_<%= index + 1 %>" type="hidden" value="<%= item.variant.product.name %>" />
|
13
|
+
<input id="amount_<%= index + 1 %>" name="amount_<%= index + 1 %>" type="hidden" value="<%= item.price %>" />
|
14
|
+
<input id="quantity_<%= index + 1 %>" name="quantity_<%= index + 1 %>" type="hidden" value="<%= item.quantity %>" />
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<!-- input id="amount" name="amount" type="hidden" value="58.97" /-->
|
18
|
+
|
19
|
+
<input name="no_shipping" type="hidden" value="1" />
|
20
|
+
<input id="cmd" name="cmd" type="hidden" value="_cart" />
|
21
|
+
<input type="hidden" name="upload" value="1" />
|
22
|
+
|
23
|
+
<p> <%= t('please_select_your_country') %>
|
24
|
+
<select name="country" id="country">
|
25
|
+
<%= options_from_collection_for_select(Country.all, :id, :name, 214) %>
|
26
|
+
</select>
|
27
|
+
</p>
|
28
|
+
<span style="color:red; font-weight:bold; display:none;" id="needZipcode">
|
29
|
+
<%= t("please_enter_valid_zip") %>
|
30
|
+
</span>
|
31
|
+
<p>
|
32
|
+
<%= t('zip_code_if_you_have_one')%>: <input id="zip" name="zip" type="text" value="" />
|
33
|
+
</p>
|
34
|
+
|
35
|
+
<input id="notify_url" name="notify_url" type="hidden" value="<%= Spree::Paypal::Config[:ipn_notify_host] + order_paypal_payments_path(@order) %>" />
|
36
|
+
<input type="hidden" name="rm" value ="2"> <!-- tells paypal that the return should be POST instead of GET -->
|
37
|
+
<input id="return" name="return" type="hidden" value="<%= successful_order_paypal_payments_url(@order) %>" />
|
38
|
+
|
39
|
+
<!-- input id="address_override" name="address_override" type="hidden" value="0" />
|
40
|
+
<input id="charset" name="charset" type="hidden" value="utf-8" />
|
41
|
+
<input id="no_note" name="no_note" type="hidden" value="1" />
|
42
|
+
<input id="no_shipping" name="no_shipping" type="hidden" value="1" />
|
43
|
+
<input id="item_name" name="item_name" type="hidden" value="Store purchase" />
|
44
|
+
<input id="return" name="return" type="hidden" value="http://localhost:3000/account/show" />
|
45
|
+
<input id="currency_code" name="currency_code" type="hidden" value="USD" />
|
46
|
+
<input id="cancel_return" name="cancel_return" type="hidden" value="http://localhost:3000/account/show" />
|
47
|
+
<input id="custom" name="custom" type="hidden" value="11" />
|
48
|
+
<input id="item_number" name="item_number" type="hidden" value="11" / -->
|
49
|
+
<!-- input id="bn" name="bn" type="hidden" value="ActiveMerchant" /-->
|
50
|
+
|
51
|
+
<%= image_submit_tag "pp_checkout.gif" %>
|
52
|
+
|
53
|
+
</form>
|
54
|
+
|
55
|
+
|
56
|
+
<script type="text/javascript" charset="utf-8">
|
57
|
+
function check_zipcode () {
|
58
|
+
if ($('country').value == "United States" && ($('zip').value == null || $('zip').value.length < 5)) {
|
59
|
+
$('needZipcode').show();
|
60
|
+
return false;
|
61
|
+
} else {
|
62
|
+
return true;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
</script>
|
@@ -0,0 +1 @@
|
|
1
|
+
SUCCESS!
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class PaypalConfiguration < Configuration
|
2
|
+
|
3
|
+
# the url parameters should not need to be changed (unless paypal changes the api or something other major change)
|
4
|
+
preference :sandbox_url, :string, :default => "https://www.sandbox.paypal.com/cgi-bin/webscr"
|
5
|
+
preference :paypal_url, :string, :default => "https://www.paypal.com/cgi-bin/webscr"
|
6
|
+
|
7
|
+
# these are just default preferences of course, you'll need to change them to something meaningful
|
8
|
+
preference :account, :string, :default => "foo@example.com"
|
9
|
+
preference :ipn_notify_host, :string, :default => "http://example.com:3000"
|
10
|
+
preference :success_url, :string, :default => "http://localhost:3000/paypal/confirm"
|
11
|
+
|
12
|
+
# this stuff is really handy
|
13
|
+
preference :currency_code, :string, :default => "EUR"
|
14
|
+
|
15
|
+
validates_presence_of :name
|
16
|
+
validates_uniqueness_of :name
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spree_core'
|
2
|
+
require 'pp_website_standard_hooks'
|
3
|
+
|
4
|
+
module PpWebsiteStandard
|
5
|
+
class Engine < Rails::Engine
|
6
|
+
|
7
|
+
config.autoload_paths += %W(#{config.root}/lib)
|
8
|
+
|
9
|
+
def self.activate
|
10
|
+
Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
|
11
|
+
Rails.env.production? ? require(c) : load(c)
|
12
|
+
end
|
13
|
+
|
14
|
+
# add new events and states to the FSM
|
15
|
+
=begin
|
16
|
+
fsm = Order.state_machines[:state]
|
17
|
+
fsm.events << StateMachine::Event.new(fsm, "fail_payment")
|
18
|
+
fsm.events["fail_payment"].transition(:to => 'payment_failure', :from => ['in_progress', 'payment_pending'])
|
19
|
+
|
20
|
+
fsm.events << StateMachine::Event.new(fsm, "pend_payment")
|
21
|
+
fsm.events["pend_payment"].transition(:to => 'payment_pending', :from => 'in_progress')
|
22
|
+
fsm.after_transition(:to => 'payment_pending', :do => lambda {|order| order.update_attribute(:checkout_complete, true)})
|
23
|
+
|
24
|
+
fsm.events["pay"].transition(:to => 'paid', :from => ['payment_pending', 'in_progress'])
|
25
|
+
=end
|
26
|
+
end
|
27
|
+
|
28
|
+
config.to_prepare &method(:activate).to_proc
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Spree
|
2
|
+
module Paypal
|
3
|
+
# Singleton class to access the Paypal configuration object (PaypalConfiguration.first by default) and it's preferences.
|
4
|
+
#
|
5
|
+
# Usage:
|
6
|
+
# Spree::Paypal::Config[:foo] # Returns the foo preference
|
7
|
+
# Spree::Paypal::Config[] # Returns a Hash with all the tax preferences
|
8
|
+
# Spree::Paypal::Config.instance # Returns the configuration object (PaypalConfiguration.first)
|
9
|
+
# Spree::Paypal::Config.set(preferences_hash) # Set the tax preferences as especified in +preference_hash+
|
10
|
+
class Config
|
11
|
+
include Singleton
|
12
|
+
include PreferenceAccess
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def instance
|
16
|
+
return nil unless ActiveRecord::Base.connection.tables.include?('configurations')
|
17
|
+
PaypalConfiguration.find_or_create_by_name("Default paypal configuration")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
namespace :pp_website_standard do
|
2
|
+
desc "Copies all migrations and assets (NOTE: This will be obsolete with Rails 3.1)"
|
3
|
+
task :install do
|
4
|
+
Rake::Task['pp_website_standard:install:migrations'].invoke
|
5
|
+
Rake::Task['pp_website_standard:install:assets'].invoke
|
6
|
+
end
|
7
|
+
|
8
|
+
namespace :install do
|
9
|
+
desc "Copies all migrations (NOTE: This will be obsolete with Rails 3.1)"
|
10
|
+
task :migrations do
|
11
|
+
source = File.join(File.dirname(__FILE__), '..', '..', 'db')
|
12
|
+
destination = File.join(Rails.root, 'db')
|
13
|
+
puts "INFO: Mirroring assets from #{source} to #{destination}"
|
14
|
+
Spree::FileUtilz.mirror_files(source, destination)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Copies all assets (NOTE: This will be obsolete with Rails 3.1)"
|
18
|
+
task :assets do
|
19
|
+
source = File.join(File.dirname(__FILE__), '..', '..', 'public')
|
20
|
+
destination = File.join(Rails.root, 'public')
|
21
|
+
puts "INFO: Mirroring assets from #{source} to #{destination}"
|
22
|
+
Spree::FileUtilz.mirror_files(source, destination)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# add custom rake tasks here
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spree_paypal_website_standard
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 61
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 8
|
9
|
+
- 1
|
10
|
+
version: 0.8.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Gregg Pollack, Sean Schofield, Tomasz Stachewicz
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-04-29 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: spree_core
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 103
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 30
|
33
|
+
- 0
|
34
|
+
version: 0.30.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
description: Spree extension for integration with PayPal Website Standard payment
|
38
|
+
email: tomekrs@o2.pl
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- README.md
|
47
|
+
- LICENSE
|
48
|
+
- lib/spree/paypal/config.rb
|
49
|
+
- lib/pp_website_standard.rb
|
50
|
+
- lib/paypal_configuration.rb
|
51
|
+
- lib/pp_website_standard_hooks.rb
|
52
|
+
- lib/tasks/pp_website_standard.rake
|
53
|
+
- lib/tasks/install.rake
|
54
|
+
- app/controllers/checkout_controller_decorator.rb
|
55
|
+
- app/controllers/payment_notifications_controller.rb
|
56
|
+
- app/controllers/paypal_controller.rb
|
57
|
+
- app/views/admin/orders/_pp_standard_txns.html.erb
|
58
|
+
- app/views/orders/_paypal_checkout.html.erb
|
59
|
+
- app/views/paypal_payments/successful.html.erb
|
60
|
+
- app/views/checkout/_paypal_checkout.html.erb
|
61
|
+
- app/views/checkout/edit.html.erb
|
62
|
+
- app/models/order_decorator.rb
|
63
|
+
- app/models/payment_notification.rb
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://github.com/tomash/spree-pp-website-standard
|
66
|
+
licenses: []
|
67
|
+
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 57
|
79
|
+
segments:
|
80
|
+
- 1
|
81
|
+
- 8
|
82
|
+
- 7
|
83
|
+
version: 1.8.7
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 3
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
requirements:
|
94
|
+
- none
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.3.7
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: Spree extension for integration with PayPal Website Standard payment
|
100
|
+
test_files: []
|
101
|
+
|