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 +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
|