koudoku 0.0.2 → 0.0.3

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 CHANGED
@@ -1,80 +1,16 @@
1
1
  # Koudoku
2
2
 
3
- Robust subscription support for Ruby on Rails apps using [Stripe](https://stripe.com). Makes it easy to manage actions related to new subscriptions, upgrades, downgrades, cancelations, as well as hooking up notifications, metrics logging, coupons, etc.
3
+ Robust subscription support for Ruby on Rails apps using [Stripe](https://stripe.com). Makes it easy to manage actions related to new subscriptions, upgrades, downgrades, cancelations, payment failures, as well as hooking up notifications, metrics logging, coupons, etc.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  Include the following in your `Gemfile`:
8
8
 
9
9
  gem 'koudoku'
10
-
11
- ## Usage
12
-
13
- There are no generators at the moment, so you'll need to generate plans, subscriptions, and (optionally) coupons on your own:
14
-
15
- ### Subscriptions
16
-
17
- rails g model subscription stripe_id:string plan_id:integer last_four:string coupon_id:integer current_price:float user_id:integer
18
10
 
19
- Only include `coupon_id` if you want to support coupons. The `user_id` property should actually be the foreign key for whatever model you want your subscriptions to relate to. (User is just the default.)
20
-
21
- Then, dress up your subscription model by including the `Koudoku::Subscription` module and defining some essential relationships:
22
-
23
- class Subscription < ActiveRecord::Base
24
- include Koudoku::Subscription
25
-
26
- # Belongs to user. (This is the default.)
27
- attr_accessible :user_id
28
- belongs_to :user
29
-
30
- # Supports coupons.
31
- attr_accessible :coupon_id
32
- belongs_to :coupon
33
-
34
- end
35
-
36
- ### Plans
37
-
38
- rails g model plan name:string stripe_id:string price:float
39
-
40
- The `stripe_id` for each plan must match the ID from Stripe. The price here isn't affected by (nor does it affect) the price in Stripe.
41
-
42
- You'll need to create a few plans to start. (You don't need to create a plan to represent "free" accounts.)
43
-
44
- Plan.create(name: 'Personal', price: '10.00')
45
- Plan.create(name: 'Team', price: '30.00')
46
- Plan.create(name: 'Enterprise', price: '100.00')
47
-
48
- ### Coupons
49
-
50
- Again, this is only required if you want to support coupons:
51
-
52
- rails g model coupon code:string free_trial_length:string
53
-
54
-
55
- ## Subscriptions That Belong to Models Other than User
56
-
57
- Here's an example of a subscription that belongs to a company rather than a user:
58
-
59
- class Subscription < ActiveRecord::Base
60
- include Koudoku::Subscription
61
-
62
- # Ownership.
63
- attr_accessible :company_id
64
- belongs_to :company
65
-
66
- # Inform Koudoku::Subscription how to identify the owner of the subscription.
67
- def subscription_owner
68
- company
69
- end
70
-
71
- # Inform Koudoku::Subscription how to represent the owner in emails, etc.
72
- def subscription_owner_description
73
- "#{company.name} (#{company.primary_contact_name})"
74
- end
75
-
76
- end
11
+ After running `bundle install`, you can run a Rails generator to do the rest. Before installing, the model you'd like to have own subscriptions must already exist. (In many cases this will be "`user`".)
77
12
 
13
+ rails g koudoku:install user
78
14
 
79
15
  ## Using Coupons
80
16
 
@@ -88,7 +24,6 @@ Then assign it to a _new_ subscription before saving:
88
24
  subscription.coupon = coupon
89
25
  subscription.save
90
26
 
91
-
92
27
  ## Implementing Logging, Notifications, etc.
93
28
 
94
29
  The included module defined the following empty "template methods" which you're able to provide an implementation for:
@@ -104,8 +39,17 @@ The included module defined the following empty "template methods" which you're
104
39
  - `finalize_downgrade!`
105
40
  - `finalize_cancelation!`
106
41
  - `card_was_declined`
107
-
42
+
108
43
  Be sure to include a call to `super` in each of your implementations, especially if you're using multiple concerns to break all this logic into smaller pieces.
109
44
 
110
45
  Between `prepare_for_*` and `finalize_*`, so far I've used `finalize_*` almost exclusively. The difference is that `prepare_for_*` runs before we settle things with Stripe, and `finalize_*` runs after everything is settled in Stripe. For that reason, please be sure not to implement anything in `finalize_*` implementations that might cause issues with ActiveRecord saving the updated state of the subscription.
111
46
 
47
+ ### Stripe Webhooks
48
+
49
+ Support for Stripe Webhooks is still quite limited. To react to some of the webhooks that are currently handled, you can implement the following template methods of the `Subscription` class:
50
+
51
+ - `payment_succeeded(amount)`
52
+ - `charge_failed`
53
+ - `charge_disputed`
54
+
55
+ No additional information is currently handled from the webhook request body.
File without changes
@@ -0,0 +1,63 @@
1
+ # this generator based on rails_admin's install generator.
2
+ # https://www.github.com/sferik/rails_admin/master/lib/generators/rails_admin/install_generator.rb
3
+
4
+ require 'rails/generators'
5
+
6
+ # http://guides.rubyonrails.org/generators.html
7
+ # http://rdoc.info/github/wycats/thor/master/Thor/Actions.html
8
+
9
+ module Koudoku
10
+ class InstallGenerator < Rails::Generators::Base
11
+
12
+ # Not sure what this does.
13
+ source_root File.expand_path("../templates", __FILE__)
14
+
15
+ include Rails::Generators::Migration
16
+
17
+ argument :subscription_owner_model, :type => :string, :required => true, :desc => "Owner of the subscription"
18
+ desc "Koudoku installation generator"
19
+
20
+ def install
21
+
22
+ unless defined?(Koudoku)
23
+ gem("koudoku")
24
+ end
25
+
26
+ require "securerandom"
27
+ api_key = SecureRandom.uuid
28
+ create_file 'config/initializers/koudoku.rb' do
29
+ <<-RUBY
30
+ Koudoku.setup do |config|
31
+ config.webhooks_api_key = "#{api_key}"
32
+ end
33
+ RUBY
34
+ end
35
+
36
+ # Generate subscription.
37
+ generate("model", "subscription stripe_id:string plan_id:integer last_four:string coupon_id:integer current_price:float #{subscription_owner_model}_id:integer")
38
+ gsub_file "app/models/subscription.rb", /ActiveRecord::Base/, "ActiveRecord::Base\n include Koudoku::Subscription\n\n belongs_to :#{subscription_owner_model}\n belongs_to :coupon\n"
39
+
40
+ # Add the plans.
41
+ generate("model", "plan name:string stripe_id:string price:float")
42
+ gsub_file "app/models/plan.rb", /ActiveRecord::Base/, "ActiveRecord::Base\n belongs_to :#{subscription_owner_model}\n belongs_to :coupon\n"
43
+
44
+ # Add coupons.
45
+ generate("model coupon code:string free_trial_length:string")
46
+ gsub_file "app/models/plan.rb", /ActiveRecord::Base/, "ActiveRecord::Base\n has_many :subscriptions\n"
47
+
48
+ # Update the owner relationship.
49
+ gsub_file "app/models/#{subscription_owner_model}.rb", /ActiveRecord::Base/, "ActiveRecord::Base\n\n # Added by Koudoku.\n has_one :subscription\n\n"
50
+
51
+ # Update the owner relationship.
52
+ gsub_file "app/models/#{subscription_owner_model}.rb", /ActiveRecord::Base/, "ActiveRecord::Base\n\n # Added by Koudoku.\n has_one :subscription\n\n"
53
+
54
+ # Add webhooks to the route.
55
+ gsub_file "config/routes.rb", /Application.routes.draw do/, "Application.routes.draw do\n\n # Added by Koudoku.\n namespace :koudoku do\n match 'webhooks' => 'webhooks#process'\n end\n\n"
56
+
57
+ # Show the user the API key we generated.
58
+ say "\nTo enable support for Stripe webhooks, point it to \"/koudoku/webhooks?api_key=#{api_key}\". This API key has been randomly generated, so it's unique to your application.\n\n"
59
+
60
+ end
61
+
62
+ end
63
+ end
data/lib/koudoku.rb CHANGED
@@ -1,5 +1,18 @@
1
1
  require "koudoku/version"
2
2
  require "koudoku/subscription"
3
+ require "koudoku/webhooks_controller"
4
+ require "generators/koudoku/install_generator"
5
+
6
+ # Load all rake tasks.
7
+ Dir["tasks/**/*.rake"].each { |ext| load ext } if defined?(Rake)
3
8
 
4
9
  module Koudoku
10
+
11
+ mattr_accessor :webhooks_api_key
12
+ @@webhooks_api_key = nil
13
+
14
+ def self.setup
15
+ yield self
16
+ end
17
+
5
18
  end
@@ -182,6 +182,16 @@ module Koudoku::Subscription
182
182
 
183
183
  def card_was_declined
184
184
  end
185
+
186
+ # stripe web-hook callbacks.
187
+ def payment_succeeded(amount)
188
+ end
189
+
190
+ def charge_failed
191
+ end
192
+
193
+ def charge_disputed
194
+ end
185
195
 
186
196
  end
187
197
 
@@ -1,3 +1,3 @@
1
1
  module Koudoku
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,37 @@
1
+ class Koudoku::WebhooksController < ActionController::Base
2
+
3
+ # I have no idea why this parameter is required to be here.
4
+ # If we don't do this, we get "wrong number of arguments (1 for 0)"
5
+ def process(parameter = nil)
6
+
7
+ raise "API key not configured. For security reasons you must configure this in 'config/koudoku.rb'." unless Koudoku.webhooks_api_key.present?
8
+ raise "Invalid API key. Be sure the webhooks URL Stripe is configured with includes ?api_key= and the correct key." unless params[:api_key] == Koudoku.webhooks_api_key
9
+
10
+ data_json = JSON.parse request.body.read
11
+
12
+ if data_json['type'] == "invoice.payment_succeeded"
13
+
14
+ stripe_id = data_json['data']['object']['customer']
15
+ amount = data_json['data']['object']['total'].to_f / 100.0
16
+ subscription = Subscription.find_by_stripe_id(stripe_id)
17
+ subscription.payment_succeeded(amount)
18
+
19
+ elsif data_json['type'] == "charge.failed"
20
+
21
+ stripe_id = data_json['data']['object']['customer']
22
+ subscription = Subscription.find_by_stripe_id(stripe_id)
23
+ subscription.charge_failed
24
+
25
+ elsif data_json['type'] == "charge.dispute.created"
26
+
27
+ stripe_id = data_json['data']['object']['customer']
28
+
29
+ puts "Finding listing with Stripe ID #{stripe_id}"
30
+ subscription = Subscription.find_by_stripe_id(stripe_id)
31
+ listing = subscription.listing
32
+ subscription.charge_disputed
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,8 @@
1
+ namespace :koudoku do
2
+
3
+ desc "Install koudoku"
4
+ task :install do
5
+ system 'rails g koudoku:install'
6
+ end
7
+
8
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: koudoku
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-27 00:00:00.000000000 Z
12
+ date: 2012-12-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70303128505700 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70303128505700
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: stripe
27
- requirement: &70303128502880 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,7 +37,12 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70303128502880
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  description: Robust subscription support for Rails with Stripe. Provides package levels,
37
47
  coupons, logging, notifications, etc.
38
48
  email:
@@ -45,10 +55,15 @@ files:
45
55
  - Gemfile
46
56
  - README.md
47
57
  - Rakefile
58
+ - docs/INSTALLATION.md
48
59
  - koudoku.gemspec
60
+ - lib/generators/koudoku/install_generator.rb
61
+ - lib/generators/koudoku/templates/insert_default_plans.rb
49
62
  - lib/koudoku.rb
50
63
  - lib/koudoku/subscription.rb
51
64
  - lib/koudoku/version.rb
65
+ - lib/koudoku/webhooks_controller.rb
66
+ - lib/tasks/koudoku.rake
52
67
  homepage: http://github.com/andrewculver/koudoku
53
68
  licenses: []
54
69
  post_install_message:
@@ -69,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
84
  version: '0'
70
85
  requirements: []
71
86
  rubyforge_project: koudoku
72
- rubygems_version: 1.8.15
87
+ rubygems_version: 1.8.24
73
88
  signing_key:
74
89
  specification_version: 3
75
90
  summary: Robust subscription support for Rails with Stripe.