stripe-rails 0.0.1 → 0.1.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/Changelog.md ADDED
@@ -0,0 +1,11 @@
1
+ ## 0.1.0 (2012-11-14)
2
+
3
+ * add config/stripe/plans.rb to define and create plans
4
+ * use `STRIPE_API_KEY` as default value of `config.stripe.api_key`
5
+ * require stripe.js from asset pipeline
6
+ * autoconfigure stripe.js with config.stripe.publishable_key.
7
+ * add rake stripe:verify to ensure stripe.com authentication is configured properly
8
+
9
+ ## 0.0.1 (2012-10-12)
10
+
11
+ * basic railtie
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Stripe::Rails
1
+ # Stripe::Rails: A Full-Featured Rails Engine for Use with stripe.com
2
2
 
3
- TODO: Write a gem description
3
+ [stripe.com](http://stripe.com) integration for your rails application
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,22 +8,82 @@ Add this line to your application's Gemfile:
8
8
 
9
9
  gem 'stripe-rails'
10
10
 
11
- And then execute:
11
+ If you are going to be using [stripe.js][1] to securely collect credit card information
12
+ on the client, then add the following to app/assets/javascripts/application.js
12
13
 
13
- $ bundle
14
+ //= require stripe
14
15
 
15
- Or install it yourself as:
16
+ ### Setup your API keys.
16
17
 
17
- $ gem install stripe-rails
18
+ You will need to configure your application to authenticate with stripe.com
19
+ using [your api key][1]. There are two methods to do this, you can either set the environment
20
+ variable `STRIPE_API_KEY`, or use the rails configuration setting `config.stripe.api_key`.
21
+ In either case, it is recommended that you *not* check in this value into source control.
18
22
 
19
- ## Usage
23
+ Once you can verify that your api is set up and functioning properly by running the following command:
24
+
25
+ rake stripe:verify
26
+
27
+ If you are going to be using stripe.js, then you will also need to set the value of your
28
+ publishiable key. A nice way to do it is to set your test publishable for all environments:
29
+
30
+ # config/application.rb
31
+ # ...
32
+ config.stripe.publishable_key = 'pk_test_XXXYYYZZZ'
33
+
34
+ And then override it to use your live key in production only
35
+
36
+ # config/environments/production.rb
37
+ # ...
38
+ config.stripe.publishable_key = 'pk_live_XXXYYYZZZ'
39
+
40
+ This key will be publicly visible on the internet, so it is ok to put in your source.
41
+
42
+ ### Setup your payment configuration
43
+
44
+ If you're using subscriptions, then you'll need to set up your application's payment plans
45
+ and discounts. `Stripe::Rails` lets you automate the management of these definitions from
46
+ within the application itself. To get started:
47
+
48
+ rails generate stripe:install
49
+
50
+ this will generate the configuration files containing your plan and coupon definitions:
20
51
 
21
- TODO: Write usage instructions here
52
+ create config/stripe/plans.rb
53
+ create config/stripe/coupons.rb
22
54
 
23
- ## Contributing
55
+ ### Configuring your plans
56
+
57
+ Use the plan builder to define as many plans as you want in `config/stripe/plans.rb`
58
+
59
+ Stripe.plan :silver do |plan|
60
+ plan.name = 'ACME Silver'
61
+ plan.amount = 699 # $6.99
62
+ plan.interval = 'month'
63
+ end
64
+
65
+ Stripe.plan :gold do |plan|
66
+ plan.name = 'ACME Gold'
67
+ plan.amount = 999 # $9.99
68
+ plan.interval = 'month'
69
+ end
70
+
71
+ This will define constants for these plans in the Stripe::Plans module so that you
72
+ can refer to them by reference as opposed to an id string.
73
+
74
+ Stripe::Plans::SILVER # => 'silver: ACME Silver'
75
+ Stripe::Plans::GOLD # => 'gold: ACME Gold'
76
+
77
+ To upload these plans onto stripe.com, run:
78
+
79
+ rake stripe:prepare
80
+
81
+ This will create any plans that do not currently exist, and treat as a NOOP any
82
+ plans that do, so you can run this command safely as many times as you wish.
83
+
84
+ NOTE: You must destroy plans manually from your stripe dashboard.
85
+
86
+ ## Usage
24
87
 
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Added some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
88
+ [1]: https://stripe.com/docs/stripe.js
89
+ [2]: https://manage.stripe.com/#account/apikeys
data/Rakefile CHANGED
@@ -1,2 +1,9 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+
4
+ desc "run minitests"
5
+ task :spec do
6
+ sh "bundle exec ruby -Itest test/*_spec.rb"
7
+ end
8
+
9
+ task :default => :spec
@@ -0,0 +1,10 @@
1
+ module Stripe
2
+ class InstallGenerator < ::Rails::Generators::Base
3
+ source_root File.expand_path("../../templates", __FILE__)
4
+
5
+ desc "copy plans.rb"
6
+ def copy_plans_file
7
+ copy_file "plans.rb", "config/stripe/plans.rb"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ # This file contains descriptions of all your stripe plans
2
+
3
+ # Example
4
+ # Stripe::Plans::PRIMO #=> 'primo'
5
+
6
+ # Stripe.plan :primo do |plan|
7
+ #
8
+ # # plan name as it will appear on credit card statements
9
+ # plan.name = 'Acme as a service PRIMO'
10
+ #
11
+ # # amount in cents. This is 6.99
12
+ # plan.amount = 699
13
+ #
14
+ # # interval must be either 'month' or 'year'
15
+ # plan.interval = 'month'
16
+ #
17
+ # # only bill once every three months (default 1)
18
+ # plan.interval_count = 3
19
+ #
20
+ # # number of days before charging customer's card (default 0)
21
+ # plan.trial_period_days = 30
22
+ # end
23
+
24
+ # Once you have your plans defined, you can run
25
+ #
26
+ # rake stripe:prepare
27
+ #
28
+ # This will export any new plans to stripe.com so that you can
29
+ # begin using them in your API calls.
@@ -0,0 +1,38 @@
1
+ require 'stripe'
2
+
3
+ module Stripe::Rails
4
+ class << self
5
+ attr_accessor :testing
6
+ end
7
+
8
+ class Engine < ::Rails::Engine
9
+
10
+ config.stripe = Struct.new(:api_base, :api_key, :verify_ssl_certs, :publishable_key).new
11
+
12
+ initializer 'stripe.configure.api_key', :before => 'stripe.configure' do |app|
13
+ app.config.stripe.api_key ||= ENV['STRIPE_API_KEY']
14
+ end
15
+
16
+ initializer 'stripe.configure' do |app|
17
+ [:api_base, :api_key, :verify_ssl_certs].each do |key|
18
+ value = app.config.stripe.send(key)
19
+ Stripe.send("#{key}=", value) unless value.nil?
20
+ end
21
+ $stderr.puts <<-MSG unless Stripe.api_key
22
+ No stripe.com API key was configured for environment #{::Rails.env}! this application will be
23
+ unable to interact with stripe.com. You can set your API key with either the environment
24
+ variable `STRIPE_API_KEY` (recommended) or by setting `config.stripe.api_key` in your
25
+ environment file directly.
26
+ MSG
27
+ end
28
+
29
+ initializer 'stripe.plans' do |app|
30
+ path = app.root.join('config/stripe/plans.rb')
31
+ load path if path.exist?
32
+ end
33
+
34
+ rake_tasks do
35
+ load 'stripe-rails/tasks.rake'
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,98 @@
1
+ module Stripe
2
+ module Plans
3
+ @plans = {}
4
+
5
+ def self.all
6
+ @plans.values
7
+ end
8
+
9
+ def self.[](key)
10
+ @plans[key.to_s]
11
+ end
12
+
13
+ def self.[]=(key, value)
14
+ @plans[key.to_s] = value
15
+ end
16
+
17
+ def self.put!
18
+ all.each do |plan|
19
+ plan.put!
20
+ end
21
+ end
22
+
23
+ def plan(id)
24
+ config = Configuration.new(id)
25
+ yield config
26
+ config.finalize!
27
+ end
28
+
29
+ class Configuration
30
+ include ActiveModel::Validations
31
+ attr_reader :id, :currency
32
+ attr_accessor :name, :amount, :interval, :interval_count, :trial_period_days
33
+
34
+ validates_presence_of :id, :name, :amount
35
+ validates_inclusion_of :interval, :in => %w(month year), :message => "'%{value}' is not one of 'month' or 'year'"
36
+
37
+ def initialize(id)
38
+ @id = id
39
+ @currency = 'usd'
40
+ @interval_count = 1
41
+ @trial_period_days = 0
42
+ end
43
+
44
+ def finalize!
45
+ validate!
46
+ globalize!
47
+ end
48
+
49
+ def validate!
50
+ fail InvalidPlanError, errors if invalid?
51
+ end
52
+
53
+ def globalize!
54
+ Stripe::Plans[@id.to_s] = self
55
+ Stripe::Plans.const_set(@id.to_s.upcase, self)
56
+ end
57
+
58
+ def put!
59
+ if exists?
60
+ puts "[EXISTS] - #{@id}" unless Stripe::Rails.testing
61
+ else
62
+ plan = Stripe::Plan.create(
63
+ :id => @id,
64
+ :currency => @currency,
65
+ :name => @name,
66
+ :amount => @amount,
67
+ :interval => @interval,
68
+ :interval_count => @interval_count,
69
+ :trial_period_days => @trial_period_days
70
+ )
71
+ puts "[CREATE] - #{plan}" unless Stripe::Rails.testing
72
+ end
73
+ end
74
+
75
+ def to_s
76
+ @id.to_s
77
+ end
78
+
79
+ def exists?
80
+ !!Stripe::Plan.retrieve("#{@id}")
81
+ rescue Stripe::InvalidRequestError
82
+ false
83
+ end
84
+ end
85
+
86
+ class InvalidPlanError < StandardError
87
+ attr_reader :errors
88
+
89
+ def initialize(errors)
90
+ super errors.messages
91
+ @errors = errors
92
+ end
93
+
94
+ end
95
+
96
+ end
97
+ extend Plans
98
+ end
@@ -0,0 +1,20 @@
1
+
2
+ namespace :stripe do
3
+
4
+ desc 'verify your stripe.com authentication configuration'
5
+ task 'verify' => :environment do
6
+ begin
7
+ Stripe::Plan.all
8
+ puts "[OK] - connection to stripe.com is functioning properly"
9
+ rescue Stripe::AuthenticationError => e
10
+ puts "[FAIL] - authentication failed"
11
+ end
12
+ end
13
+
14
+ task 'plans:prepare' => :environment do
15
+ Stripe::Plans.put!
16
+ end
17
+
18
+ desc "create all plans defined in config/stripe/plans.rb"
19
+ task 'prepare' => 'plans:prepare'
20
+ end
@@ -1,5 +1,5 @@
1
1
  module Stripe
2
2
  module Rails
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
data/lib/stripe-rails.rb CHANGED
@@ -1,7 +1,4 @@
1
1
  require "stripe-rails/version"
2
+ require 'stripe-rails/engine'
3
+ require 'stripe-rails/plans'
2
4
 
3
- module Stripe
4
- module Rails
5
- # Your code goes here...
6
- end
7
- end
data/stripe-rails.gemspec CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
5
5
  gem.authors = ["rubygeek"]
6
6
  gem.email = ["nola@rubygeek.com"]
7
7
  gem.description = "A gem to integrate stripe into your rails app"
8
- gem.summary = "A gem to integrate stripe into your rails app"
8
+ gem.summary = "A gem to integrate stripe into your rails app"
9
9
  gem.homepage = ""
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.version = Stripe::Rails::VERSION
17
17
  gem.add_dependency 'railties', '~> 3.0'
18
18
  gem.add_dependency 'stripe'
19
-
20
- gem.add_development_dependency 'tzinfo'
21
19
 
20
+ gem.add_development_dependency 'tzinfo'
21
+ gem.add_development_dependency 'mocha'
22
22
  end
@@ -1,4 +1,8 @@
1
1
  Dummy::Application.configure do
2
+
3
+ config.stripe.api_base = 'http://localhost:5000'
4
+ config.stripe.verify_ssl_certs = false
5
+
2
6
  # Settings specified here will take precedence over those in config/application.rb
3
7
 
4
8
  # The test environment is used exclusively to run your application's
@@ -0,0 +1,5 @@
1
+ Stripe.plan :gold do |plan|
2
+ plan.name = 'Solid Gold'
3
+ plan.amount = 699
4
+ plan.interval = 'month'
5
+ end
@@ -0,0 +1,71 @@
1
+ require 'minitest/autorun'
2
+ require 'spec_helper'
3
+
4
+ describe 'building plans' do
5
+ describe 'simply' do
6
+ before do
7
+ Stripe.plan :primo do |plan|
8
+ plan.name = 'Acme as a service PRIMO'
9
+ plan.amount = 699
10
+ plan.interval = 'month'
11
+ plan.interval_count = 3
12
+ plan.trial_period_days = 30
13
+ end
14
+ end
15
+ after do
16
+ Stripe::Plans.send(:remove_const, :PRIMO)
17
+ end
18
+
19
+ it 'is accessible via id' do
20
+ Stripe::Plans::PRIMO.wont_be_nil
21
+ end
22
+
23
+ it 'is accessible via collection' do
24
+ Stripe::Plans.all.must_include Stripe::Plans::PRIMO
25
+ end
26
+
27
+ it 'is accessible via hash lookup (symbol/string agnostic)' do
28
+ Stripe::Plans[:primo].must_equal Stripe::Plans::PRIMO
29
+ Stripe::Plans['primo'].must_equal Stripe::Plans::PRIMO
30
+ end
31
+
32
+ describe 'uploading' do
33
+ describe 'when none exists on stripe.com' do
34
+ before do
35
+ Stripe::Plan.stubs(:retrieve).raises(Stripe::InvalidRequestError.new("not found", "id"))
36
+ end
37
+ it 'creates the plan online' do
38
+ Stripe::Plan.expects(:create).with(
39
+ :id => :gold,
40
+ :currency => 'usd',
41
+ :name => 'Solid Gold',
42
+ :amount => 699,
43
+ :interval => 'month',
44
+ :interval_count => 1,
45
+ :trial_period_days => 0
46
+ )
47
+ Stripe::Plans::GOLD.put!
48
+ end
49
+
50
+ end
51
+ describe 'when it is already present on stripe.com' do
52
+ before do
53
+ Stripe::Plan.stubs(:retrieve).returns(Stripe::Plan.construct_from({
54
+ :id => :gold,
55
+ :name => 'Solid Gold'
56
+ }))
57
+ end
58
+ it 'is a no-op' do
59
+ Stripe::Plan.expects(:create).never
60
+ Stripe::Plans::GOLD.put!
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ describe 'with missing mandatory values' do
67
+ it 'raises an exception after configuring it' do
68
+ proc {Stripe.plan(:bad) {}}.must_raise Stripe::Plans::InvalidPlanError
69
+ end
70
+ end
71
+ end
data/test/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # Configure Rails Environment
2
2
  ENV["RAILS_ENV"] = "test"
3
+ ENV['STRIPE_API_KEY'] = 'XYZ'
3
4
 
4
5
  require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
6
  require "rails/test_help"
@@ -13,3 +14,6 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
13
14
  if ActiveSupport::TestCase.method_defined?(:fixture_path=)
14
15
  ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
15
16
  end
17
+
18
+ Stripe::Rails.testing = true
19
+ require 'mocha/setup'
@@ -1,15 +1,19 @@
1
1
  require 'minitest/autorun'
2
2
  require 'spec_helper'
3
3
 
4
- # Expectations: http://bfts.rubyforge.org/minitest/MiniTest/Expectations.html
5
-
6
- describe "Configuring the stripe" do
7
- it "true should be true" do
8
- @boolean = true
9
- @boolean.must_equal true
4
+ describe "Configuring the stripe engine" do
5
+ it "reads the api key that is set in the environment" do
6
+ Stripe.api_base.must_equal 'http://localhost:5000'
7
+ Stripe.api_key.must_equal 'XYZ'
8
+ Stripe.verify_ssl_certs.must_equal false
10
9
  end
11
-
12
- it "should be a module" do
13
- assert_kind_of Module, Stripe::Rails
10
+ end
11
+
12
+ describe 'initializing plans' do
13
+ require 'rake'
14
+ load 'stripe-rails/tasks.rake'
15
+ it 'creates any plans that do not exist on stripe.com' do
16
+ Stripe::Plans.expects(:put!)
17
+ Rake::Task['stripe:plans:prepare'].invoke
14
18
  end
15
19
  end
@@ -0,0 +1,279 @@
1
+ (function() {
2
+ var _this = this;
3
+
4
+ this.Stripe = (function() {
5
+
6
+ function Stripe() {}
7
+
8
+ Stripe.version = 2;
9
+
10
+ Stripe.endpoint = 'https://api.stripe.com/v1';
11
+
12
+ Stripe.validateCardNumber = function(num) {
13
+ num = (num + '').replace(/\s+|-/g, '');
14
+ return num.length >= 10 && num.length <= 16 && Stripe.luhnCheck(num);
15
+ };
16
+
17
+ Stripe.validateCVC = function(num) {
18
+ num = Stripe.trim(num);
19
+ return /^\d+$/.test(num) && num.length >= 3 && num.length <= 4;
20
+ };
21
+
22
+ Stripe.validateExpiry = function(month, year) {
23
+ var currentTime, expiry;
24
+ month = Stripe.trim(month);
25
+ year = Stripe.trim(year);
26
+ if (!/^\d+$/.test(month)) {
27
+ return false;
28
+ }
29
+ if (!/^\d+$/.test(year)) {
30
+ return false;
31
+ }
32
+ if (!(parseInt(month, 10) <= 12)) {
33
+ return false;
34
+ }
35
+ expiry = new Date(year, month);
36
+ currentTime = new Date;
37
+ expiry.setMonth(expiry.getMonth() - 1);
38
+ expiry.setMonth(expiry.getMonth() + 1, 1);
39
+ return expiry > currentTime;
40
+ };
41
+
42
+ Stripe.cardType = function(num) {
43
+ return Stripe.cardTypes[num.slice(0, 2)] || 'Unknown';
44
+ };
45
+
46
+ Stripe.setPublishableKey = function(key) {
47
+ Stripe.key = key;
48
+ };
49
+
50
+ Stripe.createToken = function(card, params, callback) {
51
+ var amount, key, value;
52
+ if (params == null) {
53
+ params = {};
54
+ }
55
+ if (!card) {
56
+ throw 'card required';
57
+ }
58
+ if (typeof card !== 'object') {
59
+ throw 'card invalid';
60
+ }
61
+ if (typeof params === 'function') {
62
+ callback = params;
63
+ params = {};
64
+ } else if (typeof params !== 'object') {
65
+ amount = parseInt(params, 10);
66
+ params = {};
67
+ if (amount > 0) {
68
+ params.amount = amount;
69
+ }
70
+ }
71
+ for (key in card) {
72
+ value = card[key];
73
+ delete card[key];
74
+ card[Stripe.underscore(key)] = value;
75
+ }
76
+ params.card = card;
77
+ params.key || (params.key = Stripe.key || Stripe.publishableKey);
78
+ Stripe.validateKey(params.key);
79
+ return Stripe.ajaxJSONP({
80
+ url: "" + Stripe.endpoint + "/tokens",
81
+ data: params,
82
+ method: 'POST',
83
+ success: function(body, status) {
84
+ return typeof callback === "function" ? callback(status, body) : void 0;
85
+ },
86
+ complete: Stripe.complete(callback),
87
+ timeout: 40000
88
+ });
89
+ };
90
+
91
+ Stripe.getToken = function(token, callback) {
92
+ if (!token) {
93
+ throw 'token required';
94
+ }
95
+ Stripe.validateKey(Stripe.key);
96
+ return Stripe.ajaxJSONP({
97
+ url: "" + Stripe.endpoint + "/tokens/" + token,
98
+ data: {
99
+ key: Stripe.key
100
+ },
101
+ success: function(body, status) {
102
+ return typeof callback === "function" ? callback(status, body) : void 0;
103
+ },
104
+ complete: Stripe.complete(callback),
105
+ timeout: 40000
106
+ });
107
+ };
108
+
109
+ Stripe.complete = function(callback) {
110
+ return function(type, xhr, options) {
111
+ if (type !== 'success') {
112
+ return typeof callback === "function" ? callback(500, {
113
+ error: {
114
+ code: type,
115
+ type: type,
116
+ message: 'An unexpected error has occured.\nWe have been notified of the problem.'
117
+ }
118
+ }) : void 0;
119
+ }
120
+ };
121
+ };
122
+
123
+ Stripe.validateKey = function(key) {
124
+ if (!key || typeof key !== 'string') {
125
+ throw new Error('You did not set a valid publishable key.\nCall Stripe.setPublishableKey() with your publishable key.\nFor more info, see https://stripe.com/docs/stripe.js');
126
+ }
127
+ if (/^sk_/.test(key)) {
128
+ throw new Error('You are using a secret key with Stripe.js, instead of the publishable one.\nFor more info, see https://stripe.com/docs/stripe.js');
129
+ }
130
+ };
131
+
132
+ return Stripe;
133
+
134
+ }).call(this);
135
+
136
+ if (typeof module !== "undefined" && module !== null) {
137
+ module.exports = this.Stripe;
138
+ }
139
+
140
+ if (typeof define === "function") {
141
+ define('stripe', [], function() {
142
+ return _this.Stripe;
143
+ });
144
+ }
145
+
146
+ }).call(this);
147
+ (function() {
148
+ var e, requestID, serialize,
149
+ __slice = [].slice;
150
+
151
+ e = encodeURIComponent;
152
+
153
+ requestID = new Date().getTime();
154
+
155
+ serialize = function(object, result, scope) {
156
+ var key, value;
157
+ if (result == null) {
158
+ result = [];
159
+ }
160
+ for (key in object) {
161
+ value = object[key];
162
+ if (scope) {
163
+ key = "" + scope + "[" + key + "]";
164
+ }
165
+ if (typeof value === 'object') {
166
+ serialize(value, result, key);
167
+ } else {
168
+ result.push("" + key + "=" + (e(value)));
169
+ }
170
+ }
171
+ return result.join('&').replace(/%20/g, '+');
172
+ };
173
+
174
+ this.Stripe.ajaxJSONP = function(options) {
175
+ var abort, abortTimeout, callbackName, head, script, xhr;
176
+ if (options == null) {
177
+ options = {};
178
+ }
179
+ callbackName = 'sjsonp' + (++requestID);
180
+ script = document.createElement('script');
181
+ abortTimeout = null;
182
+ abort = function() {
183
+ var _ref;
184
+ if ((_ref = script.parentNode) != null) {
185
+ _ref.removeChild(script);
186
+ }
187
+ if (callbackName in window) {
188
+ window[callbackName] = (function() {});
189
+ }
190
+ return typeof options.complete === "function" ? options.complete('abort', xhr, options) : void 0;
191
+ };
192
+ xhr = {
193
+ abort: abort
194
+ };
195
+ script.onerror = function() {
196
+ xhr.abort();
197
+ return typeof options.error === "function" ? options.error(xhr, options) : void 0;
198
+ };
199
+ window[callbackName] = function() {
200
+ var args;
201
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
202
+ clearTimeout(abortTimeout);
203
+ script.parentNode.removeChild(script);
204
+ try {
205
+ delete window[callbackName];
206
+ } catch (e) {
207
+ window[callbackName] = void 0;
208
+ }
209
+ if (typeof options.success === "function") {
210
+ options.success.apply(options, args);
211
+ }
212
+ return typeof options.complete === "function" ? options.complete('success', xhr, options) : void 0;
213
+ };
214
+ options.data || (options.data = {});
215
+ options.data.callback = callbackName;
216
+ if (options.method) {
217
+ options.data._method = options.method;
218
+ }
219
+ script.src = options.url + '?' + serialize(options.data);
220
+ head = document.getElementsByTagName('head')[0];
221
+ head.appendChild(script);
222
+ if (options.timeout > 0) {
223
+ abortTimeout = setTimeout(function() {
224
+ xhr.abort();
225
+ return typeof options.complete === "function" ? options.complete('timeout', xhr, options) : void 0;
226
+ }, options.timeout);
227
+ }
228
+ return xhr;
229
+ };
230
+
231
+ }).call(this);
232
+ (function() {
233
+
234
+ this.Stripe.trim = function(str) {
235
+ return (str + '').replace(/^\s+|\s+$/g, '');
236
+ };
237
+
238
+ this.Stripe.underscore = function(str) {
239
+ return (str + '').replace(/([A-Z])/g, function($1) {
240
+ return "_" + ($1.toLowerCase());
241
+ });
242
+ };
243
+
244
+ this.Stripe.luhnCheck = function(num) {
245
+ var digit, digits, odd, sum, _i, _len;
246
+ odd = true;
247
+ sum = 0;
248
+ digits = (num + '').split('').reverse();
249
+ for (_i = 0, _len = digits.length; _i < _len; _i++) {
250
+ digit = digits[_i];
251
+ digit = parseInt(digit, 10);
252
+ if ((odd = !odd)) {
253
+ digit *= 2;
254
+ }
255
+ if (digit > 9) {
256
+ digit -= 9;
257
+ }
258
+ sum += digit;
259
+ }
260
+ return sum % 10 === 0;
261
+ };
262
+
263
+ this.Stripe.cardTypes = (function() {
264
+ var num, types, _i, _j;
265
+ types = {};
266
+ for (num = _i = 40; _i <= 49; num = ++_i) {
267
+ types[num] = 'Visa';
268
+ }
269
+ for (num = _j = 50; _j <= 59; num = ++_j) {
270
+ types[num] = 'MasterCard';
271
+ }
272
+ types[34] = types[37] = 'American Express';
273
+ types[60] = types[62] = types[64] = types[65] = 'Discover';
274
+ types[35] = 'JCB';
275
+ types[30] = types[36] = types[38] = types[39] = 'Diners Club';
276
+ return types;
277
+ })();
278
+
279
+ }).call(this);
@@ -0,0 +1,3 @@
1
+ //= require stripe-debug
2
+
3
+ Stripe.publishableKey = "<%= Rails.application.config.stripe.publishable_key or fail 'No stripe.com publishable key found. Please set config.stripe.publishable_key in config/application.rb to one of your publishable keys, which can be found here: https://manage.stripe.com/#account/apikeys' %>"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stripe-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-27 00:00:00.000000000 Z
12
+ date: 2012-11-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: mocha
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  description: A gem to integrate stripe into your rails app
63
79
  email:
64
80
  - nola@rubygeek.com
@@ -67,11 +83,17 @@ extensions: []
67
83
  extra_rdoc_files: []
68
84
  files:
69
85
  - .gitignore
86
+ - Changelog.md
70
87
  - Gemfile
71
88
  - LICENSE
72
89
  - README.md
73
90
  - Rakefile
91
+ - lib/generators/stripe/install_generator.rb
92
+ - lib/generators/templates/plans.rb
74
93
  - lib/stripe-rails.rb
94
+ - lib/stripe-rails/engine.rb
95
+ - lib/stripe-rails/plans.rb
96
+ - lib/stripe-rails/tasks.rake
75
97
  - lib/stripe-rails/version.rb
76
98
  - stripe-rails.gemspec
77
99
  - test/.DS_Store
@@ -100,6 +122,7 @@ files:
100
122
  - test/dummy/config/initializers/wrap_parameters.rb
101
123
  - test/dummy/config/locales/en.yml
102
124
  - test/dummy/config/routes.rb
125
+ - test/dummy/config/stripe/plans.rb
103
126
  - test/dummy/lib/assets/.gitkeep
104
127
  - test/dummy/log/.gitkeep
105
128
  - test/dummy/log/test.log
@@ -108,8 +131,11 @@ files:
108
131
  - test/dummy/public/500.html
109
132
  - test/dummy/public/favicon.ico
110
133
  - test/dummy/script/rails
134
+ - test/plan_builder_spec.rb
111
135
  - test/spec_helper.rb
112
136
  - test/stripe_rails_spec.rb
137
+ - vendor/assets/javascripts/stripe-debug.js
138
+ - vendor/assets/javascripts/stripe.js.erb
113
139
  homepage: ''
114
140
  licenses: []
115
141
  post_install_message:
@@ -122,18 +148,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
148
  - - ! '>='
123
149
  - !ruby/object:Gem::Version
124
150
  version: '0'
125
- segments:
126
- - 0
127
- hash: -3770056635503761163
128
151
  required_rubygems_version: !ruby/object:Gem::Requirement
129
152
  none: false
130
153
  requirements:
131
154
  - - ! '>='
132
155
  - !ruby/object:Gem::Version
133
156
  version: '0'
134
- segments:
135
- - 0
136
- hash: -3770056635503761163
137
157
  requirements: []
138
158
  rubyforge_project:
139
159
  rubygems_version: 1.8.24
@@ -167,6 +187,7 @@ test_files:
167
187
  - test/dummy/config/initializers/wrap_parameters.rb
168
188
  - test/dummy/config/locales/en.yml
169
189
  - test/dummy/config/routes.rb
190
+ - test/dummy/config/stripe/plans.rb
170
191
  - test/dummy/lib/assets/.gitkeep
171
192
  - test/dummy/log/.gitkeep
172
193
  - test/dummy/log/test.log
@@ -175,5 +196,6 @@ test_files:
175
196
  - test/dummy/public/500.html
176
197
  - test/dummy/public/favicon.ico
177
198
  - test/dummy/script/rails
199
+ - test/plan_builder_spec.rb
178
200
  - test/spec_helper.rb
179
201
  - test/stripe_rails_spec.rb