spree_fastspring 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in spree_fastspring.gemspec
4
+ gemspec
data/INSTALL ADDED
@@ -0,0 +1,19 @@
1
+ ############################################
2
+ ## ##
3
+ ## INSTALLATION ##
4
+ ## ##
5
+ ############################################
6
+
7
+
8
+ The PaymentMethod::Fastspring configurable should be directly available in spree admin payment methods.
9
+
10
+ Be sure to set up your gateway.
11
+
12
+ In your user model (where current_user reads from), add an "should_checkout_with_fastspring?" method like follows:
13
+
14
+ def should_checkout_with_fastspring?
15
+ return true
16
+ end
17
+
18
+ In order for FastSpring to actually work, you''ll need to create spree products, and assign the SKU of those products to
19
+ be identical to the product_ref from FastSpring.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Kevin Hopkins
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # SpreeFastspring
2
+
3
+ Allows for Fastspring integration into Spree for international purchases
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'spree_fastspring'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install spree_fastspring
18
+
19
+ ## Usage
20
+
21
+ the PaymentMethod::Fastspring configurable should be directly available in spree admin payment methods. Be sure to set up your gateway.
22
+
23
+ Also, be sure in your user model (where current_user reads from) to add an "should_checkout_with_fastspring?" logic block like follows:
24
+
25
+ def should_checkout_with_fastspring?
26
+ return true
27
+ end
28
+
29
+ In order for fastspring to actually work, youll need to create spree products, and assign the SKU of those products to
30
+ be identical to the product_ref from FastSpring
31
+
32
+ ## Contributing
33
+
34
+ 1. Fork it
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,63 @@
1
+ module Spree
2
+ OrdersController.class_eval do
3
+ before_filter :allow_fastspring, only: :edit
4
+
5
+ def allow_fastspring
6
+ @use_fastspring = true if current_user && current_user.should_checkout_with_fastspring?
7
+ end
8
+
9
+ def fastspring_complete
10
+ return false if !params[:OrderID]
11
+ return false if !params[:OrderReferrer]
12
+ order = Spree::Order.find(params[:OrderReferrer])
13
+ user = User.find_by_email(params[:CustomerEmail])
14
+ resp = ::PaymentMethod::Fastspring.get_order(params[:OrderID])
15
+ if resp.status == "accepted" || resp.status == "completed"
16
+ order.update_attributes({
17
+ special_instructions: resp.reference,
18
+ user_id: (user.id rescue nil)
19
+ })
20
+ EcommerceApi.process_purchase(order)
21
+ order.line_items.each do |li|
22
+ Spree::Adjustment.create({
23
+ source_id: li.id,
24
+ amount: (li.price * -1),
25
+ label: "Paid via FastSpring: #{resp.reference}",
26
+ adjustable_id: li.id,
27
+ adjustable_type: "Spree::LineItem",
28
+ payment_state: "completed"
29
+ })
30
+
31
+ order.state_changes.create({
32
+ :previous_state => 'cart',
33
+ :next_state => 'complete',
34
+ :name => 'order' ,
35
+ :user_id => order.user_id
36
+ }, :without_protection => true)
37
+ end
38
+
39
+ render :text => "Done" and return
40
+ else
41
+ render :text => "Bad" and return
42
+ end
43
+ end
44
+
45
+ def test_fastspring
46
+ uri = URI.parse("http://localhost:3000/fastspring/fastspring_complete")
47
+ http = Net::HTTP.new(uri.host, uri.port)
48
+ post_params = {"AddressStreet1"=>"373 Neff Avenue", "CustomerCompany"=>"", "CustomerLastName"=>"Hopkins", "OrderProductNames"=>"TestProduct", "OrderDiscountTotalUSD"=>"0.0", "OrderShippingTotalUSD"=>"0.0", "OrderIsTest"=>"true", "CustomerFirstName"=>"Kevin", "CustomerEmail"=>"sa.phx@scitent.com", "AddressRegion"=>"VA", "AddressPostalCode"=>"22801", "AddressStreet2"=>"", "AddressCity"=>"Harrisonburg", "OrderReferrer"=>"1", "OrderID"=>"SCI130208-9320-17125", "AddressCountry"=>"US", "CustomerPhone"=>"5403311772", "OrderSubTotalUSD"=>"10.0", "security_data"=>"1360359443021SCI130208-9320-17125sa.phx@scitent.com1360359443008", "security_hash"=>"e47e74ea2d6bce428588f039ac9756c3"}
49
+
50
+ req = Net::HTTP::Post.new(uri.path)
51
+ req.body = JSON.generate(post_params)
52
+ req["Content-Type"] = "application/json"
53
+
54
+ response = http.start {|htt| htt.request(req)}
55
+
56
+ render text: response.inspect and return
57
+ end
58
+
59
+ def test_form
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,145 @@
1
+ require 'httparty' unless defined?(HTTParty)
2
+ require 'active_support/builder' unless defined?(Builder)
3
+ class FsprgOrder
4
+ attr_accessor :status, :status_changed, :status_reason, :cancelable, :reference, :test
5
+ attr_accessor :customer, :customer_url, :next_period_date, :end_date, :line_items
6
+ end
7
+
8
+ class FsprgException < RuntimeError
9
+ def initialize(http_status_code, error_code)
10
+ @http_status_code = http_status_code
11
+ @error_code = error_code
12
+ end
13
+
14
+ def http_status_code
15
+ @http_status_code
16
+ end
17
+
18
+ def error_code
19
+ @error_code
20
+ end
21
+ end
22
+
23
+ class FsprgCustomer
24
+ attr_accessor :first_name, :last_name, :company, :email, :phone_number
25
+ end
26
+
27
+ class PaymentMethod::Fastspring < Spree::PaymentMethod
28
+ attr_accessible :preferred_company, :preferred_password, :preferred_username
29
+
30
+ preference :company, :string
31
+ preference :username, :string
32
+ preference :password, :string
33
+
34
+ def self.set_auth
35
+ m = Spree::PaymentMethod.find_by_type("PaymentMethod::FastSpring")
36
+ @auth = {
37
+ username: m.preferences[:username],
38
+ password: m.preferences[:password],
39
+ store_id: m.preferences[:company]
40
+ }
41
+ end
42
+
43
+ @test_mode = false
44
+
45
+ def self.test_mode?
46
+ @test_mode
47
+ end
48
+
49
+ def self.test_mode=(mode)
50
+ @test_mode = true
51
+ end
52
+
53
+ def self.add_test_mode(url)
54
+ if @test_mode
55
+ if url.include? "?"
56
+ url = url << "&mode=test"
57
+ else
58
+ url = url << "?mode=test"
59
+ end
60
+ end
61
+ url
62
+ end
63
+
64
+ def self.get_order(order_ref)
65
+ set_auth
66
+ url = orders_url(order_ref)
67
+ options = { :basic_auth => @auth }
68
+ response = HTTParty.get(url, options)
69
+ if response.code == 200
70
+ order = parse_order(response.parsed_response.fetch('order'))
71
+ else
72
+ exception = FsprgException.new(response.code, nil)
73
+ raise exception, "An error occurred calling the FastSpring order service", caller
74
+ end
75
+
76
+ order
77
+ end
78
+
79
+ def self.orders_url(reference, *options)
80
+ url = "https://api.fastspring.com/company/#{@auth[:store_id]}/order/#{reference}"
81
+
82
+ unless options.nil? || options.length == 0
83
+ opt = options[0]
84
+ if opt.has_key?(:postfix)
85
+ url = url << opt[:postfix]
86
+ end
87
+ if opt.has_key?(:params)
88
+ params = opt[:params]
89
+ if params.length > 0
90
+ url = url << "?"
91
+ end
92
+ params.each do |param|
93
+ url = url << param
94
+ end
95
+ end
96
+ end
97
+
98
+ url = add_test_mode(url)
99
+ end
100
+
101
+ def self.product_add_url
102
+ set_auth
103
+ url = "https://sites.fastspring.com/#{@auth[:store_id]}/api/order"
104
+ end
105
+
106
+ def self.parse_order(response)
107
+ order = FsprgOrder.new
108
+
109
+ order.status = response.fetch('status', 'error')
110
+ status_changed = response.fetch("statusChanged", nil)
111
+
112
+ if not status_changed.nil?
113
+ order.status_changed = Date.parse(status_changed)
114
+ end
115
+
116
+ order.status_reason = response.fetch("statusReason", nil)
117
+ order.cancelable = response.fetch("cancelable", nil)
118
+ order.reference = response.fetch("reference", nil)
119
+ order.test = response.fetch("test", nil)
120
+ order.line_items = response.fetch("orderItems", nil).fetch("orderItem", nil)
121
+
122
+ customer = FsprgCustomer.new;
123
+ custResponse = response.fetch("customer")
124
+
125
+ customer.first_name = custResponse.fetch("firstName", nil)
126
+ customer.last_name = custResponse.fetch("lastName", nil)
127
+ customer.company = custResponse.fetch("company", nil)
128
+ customer.email = custResponse.fetch("email", nil)
129
+ customer.phone_number = custResponse.fetch("phoneNumber", nil)
130
+
131
+ order.customer = customer;
132
+
133
+ order.customer_url = response.fetch("customerUrl", nil)
134
+ next_period_date = response.fetch("nextPeriodDate", nil)
135
+ if not next_period_date.nil?
136
+ order.next_period_date = Date.parse(next_period_date)
137
+ end
138
+ end_date = response.fetch("end", nil)
139
+ if not end_date.nil?
140
+ order.end_date = Date.parse(end_date)
141
+ end
142
+
143
+ order
144
+ end
145
+ end
@@ -0,0 +1,3 @@
1
+ Spree::Adjustment.class_eval do
2
+ attr_accessible :source_id, :adjustable_id, :adjustable_type
3
+ end
@@ -0,0 +1,3 @@
1
+ Spree::Order.class_eval do
2
+ attr_accessible :state, :completed_at, :payment_state, :user_id
3
+ end
@@ -0,0 +1,63 @@
1
+ <% @body_id = 'cart' %>
2
+ <h1><%= t(:shopping_cart) %></h1>
3
+
4
+ <% if @order.line_items.empty? %>
5
+
6
+ <div data-hook="empty_cart">
7
+ <p><%= t(:your_cart_is_empty) %></p>
8
+ <p><%= link_to t(:continue_shopping), products_path, :class => 'button continue' %></p>
9
+ </div>
10
+
11
+ <% else %>
12
+ <div data-hook="outside_cart_form">
13
+ <%= form_for @order, :url => (@use_fastspring ? PaymentMethod::Fastspring.product_add_url : update_cart_path), :html => {:id => 'update-cart'} do |order_form| %>
14
+ <div data-hook="inside_cart_form">
15
+
16
+ <div data-hook="cart_items">
17
+ <%= render :partial => 'form', :locals => { :order_form => order_form } %>
18
+ </div>
19
+
20
+ <div id="subtotal" data-hook class="columns sixteen alpha omega">
21
+ <h5><%= t(:subtotal) %>: <span class="order-total"><%= @order.display_total %></span></h5>
22
+ </div>
23
+
24
+ <div class="links columns sixteen alpha omega" data-hook="cart_buttons">
25
+ <%= button_tag :class => 'primary', :id => 'update-button' do %>
26
+ <%= t(:update) %>
27
+ <% end %>
28
+ <% if @use_fastspring %>
29
+ <input type="hidden" name="operation" value="create"/>
30
+ <input type="hidden" name="destination" value="contents"/>
31
+ <input type="hidden" name="mode" value="test" />
32
+ <input type="hidden" name="contact_fname" />
33
+ <input type="hidden" name="contact_lname" />
34
+ <input type="hidden" name="contact_company" />
35
+ <input type="hidden" name="contact_email" value="<%= current_user.email %>" />
36
+ <input type="hidden" name="contact_phone" />
37
+ <input type="hidden" name="referrer" value="<%= @order.id %>" />
38
+ <% i = 0 %>
39
+ <% @order.line_items.each do |li| %>
40
+ <% i += 1 %>
41
+ <input type="hidden" name="product_<%= i %>_path" value="/<%= li.variant.sku %>" />
42
+ <input type="hidden" name="product_<%= i %>_quantity" value="<%= li.quantity %>" />
43
+ <% end %>
44
+ <% end %>
45
+ <%= button_tag :class => 'button checkout primary', :id => 'checkout-link', :name => 'checkout' do %>
46
+ <%= t(:checkout) %>
47
+ <% end %>
48
+ </div>
49
+ </div>
50
+ <% end %>
51
+ </div>
52
+
53
+ <div id="empty-cart" data-hook>
54
+ <%= form_tag empty_cart_path, :method => :put do %>
55
+ <p id="clear_cart_link" data-hook>
56
+ <%= submit_tag t(:empty_cart), :class => 'button gray' %>
57
+ <%= t(:or) %>
58
+ <%= link_to t(:continue_shopping), products_path, :class => 'continue button gray' %>
59
+ </p>
60
+ <% end %>
61
+ </div>
62
+
63
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <form action="http://localhost:3000/fastspring/fastspring_complete" type="POST">
2
+ <input type="textbox" name="CustomerEmail" value="kevin@wearefound.com"></input><br />
3
+ <input type="textbox" name="OrderReferrer" value="2"></input><br />
4
+ <input type="textbox" name="OrderID" value="SCI130208-9320-17125"></input><br />
5
+ <input type="submit"></input><br />
6
+ </form>
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Rails.application.routes.draw do
2
+ match '/fastspring/fastspring_complete', controller: "Spree::Orders", action: :fastspring_complete
3
+ match "/fastspring/test_fastspring", controller: "Spree::Orders", action: :test_fastspring
4
+ match '/fastspring/test_form', controller: "Spree::Orders", action: :test_form
5
+ end
@@ -0,0 +1,24 @@
1
+ module SpreeFastspring
2
+ class Engine < Rails::Engine
3
+ require 'spree/core'
4
+ isolate_namespace Spree
5
+ engine_name 'spree_fastspring'
6
+
7
+ config.autoload_paths += %W(#{config.root}/lib)
8
+
9
+ # use rspec for tests
10
+ config.generators do |g|
11
+ g.test_framework :rspec
12
+ end
13
+
14
+ def self.activate
15
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
16
+ Rails.configuration.cache_classes ? require(c) : load(c)
17
+ end
18
+
19
+ Rails.application.config.spree.payment_methods.push(PaymentMethod::Fastspring)
20
+ end
21
+
22
+ config.to_prepare &method(:activate).to_proc
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module SpreeFastspring
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,2 @@
1
+ require "spree_core"
2
+ require "spree_fastspring/engine"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/spree_fastspring/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Kevin Hopkins"]
6
+ gem.email = ["khopkins218@gmail.com"]
7
+ gem.description = %q{Fastspring integration for Spree}
8
+ gem.summary = %q{Allows for fastspring integration into Spree for international purchases}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "spree_fastspring"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = SpreeFastspring::VERSION
17
+
18
+ if File.exists?('INSTALL')
19
+ gem.post_install_message = File.read("INSTALL")
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_fastspring
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kevin Hopkins
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-15 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Fastspring integration for Spree
15
+ email:
16
+ - khopkins218@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - INSTALL
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - app/controllers/spree/orders_controller_decorator.rb
28
+ - app/models/payment_method/fastspring.rb
29
+ - app/models/spree/adjustments_decorator.rb
30
+ - app/models/spree/order_decorator.rb
31
+ - app/views/spree/orders/edit.html.erb
32
+ - app/views/spree/orders/test_form.html.erb
33
+ - config/routes.rb
34
+ - lib/spree_fastspring.rb
35
+ - lib/spree_fastspring/engine.rb
36
+ - lib/spree_fastspring/version.rb
37
+ - spree_fastspring.gemspec
38
+ homepage: ''
39
+ licenses: []
40
+ post_install_message: ! "############################################\n##\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t##\n##\t\t\t\t\t\t\tINSTALLATION
41
+ \ ##\n##\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t##\n############################################\n\n\nThe
42
+ PaymentMethod::Fastspring configurable should be directly available in spree admin
43
+ payment methods. \n\nBe sure to set up your gateway.\n\nIn your user model (where
44
+ current_user reads from), add an \"should_checkout_with_fastspring?\" method like
45
+ follows:\n\ndef should_checkout_with_fastspring?\n\treturn true\nend\n\nIn order
46
+ for FastSpring to actually work, you''ll need to create spree products, and assign
47
+ the SKU of those products to\nbe identical to the product_ref from FastSpring."
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Allows for fastspring integration into Spree for international purchases
69
+ test_files: []