stripe-rails 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.md +11 -0
- data/README.md +74 -14
- data/Rakefile +7 -0
- data/lib/generators/stripe/install_generator.rb +10 -0
- data/lib/generators/templates/plans.rb +29 -0
- data/lib/stripe-rails/engine.rb +38 -0
- data/lib/stripe-rails/plans.rb +98 -0
- data/lib/stripe-rails/tasks.rake +20 -0
- data/lib/stripe-rails/version.rb +1 -1
- data/lib/stripe-rails.rb +2 -5
- data/stripe-rails.gemspec +3 -3
- data/test/dummy/config/environments/test.rb +4 -0
- data/test/dummy/config/stripe/plans.rb +5 -0
- data/test/plan_builder_spec.rb +71 -0
- data/test/spec_helper.rb +4 -0
- data/test/stripe_rails_spec.rb +13 -9
- data/vendor/assets/javascripts/stripe-debug.js +279 -0
- data/vendor/assets/javascripts/stripe.js.erb +3 -0
- metadata +30 -8
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
|
-
|
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
|
-
|
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
|
-
|
14
|
+
//= require stripe
|
14
15
|
|
15
|
-
|
16
|
+
### Setup your API keys.
|
16
17
|
|
17
|
-
|
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
|
-
|
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
|
-
|
52
|
+
create config/stripe/plans.rb
|
53
|
+
create config/stripe/coupons.rb
|
22
54
|
|
23
|
-
|
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.
|
26
|
-
2.
|
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
@@ -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
|
data/lib/stripe-rails/version.rb
CHANGED
data/lib/stripe-rails.rb
CHANGED
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,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'
|
data/test/stripe_rails_spec.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
13
|
-
|
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
|
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-
|
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
|