supercharged 1.0.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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Alexander Balashov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # Supercharged
2
+
3
+ [![Build Status](https://travis-ci.org/divineforest/supercharged.png?branch=master)](https://travis-ci.org/divineforest/supercharged)
4
+ [![CodeClimate](https://codeclimate.com/github/divineforest/supercharged.png)](https://codeclimate.com/github/divineforest/supercharged)
5
+
6
+ Complete MVC solution to accept charges from users on your Ruby on Rails site
7
+
8
+ ## Installation
9
+
10
+ Add to Gemfile:
11
+
12
+ ```ruby
13
+ gem 'supercharged'
14
+ ```
15
+
16
+ run
17
+
18
+ rails g supercharged:migrations
19
+ rails db:migrate
20
+ rails g supercharged:views
21
+
22
+ In your application.js manifest:
23
+
24
+ ```
25
+ //= require supercharged
26
+ ```
27
+
28
+ Create config/initializers/supercharged.rb
29
+
30
+ ```ruby
31
+ ActiveMerchant::Billing::Base.integration_mode = Rails.env.production? ? :production : :test
32
+ ```
33
+
34
+ Add
35
+
36
+ ```ruby
37
+ supercharged
38
+ ```
39
+
40
+ to your routes.rb somewhere in draw block.
41
+
42
+ # Using
43
+
44
+ Create view in app/views/supercharged/charges/new.html.haml
45
+
46
+ ```haml
47
+ = charge_form_for(:paypal, account: 'yourpaypalaccountid', html: {}) do |service|
48
+ - service.description 'Write here description that will be shown in paymennt form'
49
+ = charge_form_amount_field(service)
50
+ = submit_tag 'Pay now'
51
+ ```
52
+
53
+ # Customization
54
+
55
+ ## Controller
56
+
57
+ Create controller in app/controllers/charges_controller.rb and inherit from Supercharged::ChargesController.
58
+ Then add what you need or change existing methods with 'super'.
59
+
60
+ ```ruby
61
+ class ChargesController < Supercharged::ChargesController
62
+ before_filter :authenticate_user! # this is Devise's authenticate method
63
+ end
64
+ ```
65
+
66
+ If you create your own controllers then you need to customize routing method:
67
+
68
+ ```
69
+ supercharged controllers: {charges: :charges, gateway_notifications: :gateway_notifications}
70
+ ```
71
+
72
+ ## Model
73
+
74
+ Create model in app/models/charge.rb and inherit from Supercharged::Charge::Base
75
+
76
+ ```ruby
77
+ class Charge < Supercharged::Charge::Base
78
+ # your custom code here
79
+
80
+ def approve(real_amount)
81
+ transaction do
82
+ # update user balance with your own update_balance method or other things you want to do after charged approved
83
+ user.update_balance(real_amount)
84
+ super
85
+ end
86
+ end
87
+ end
88
+ ```
89
+
90
+ # Contributing
91
+
92
+ The example app is at https://github.com/divineforest/supercharged-example-app
93
+
94
+ # License
95
+
96
+ Supercharged is released under the MIT License
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ task :default => :test
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.libs << "lib"
10
+ t.libs << "test"
11
+ t.test_files = FileList["test/**/*_test.rb"]
12
+ t.verbose = true
13
+ end
@@ -0,0 +1,43 @@
1
+ class ChargeForm
2
+ constructor: (selector, options = {}) ->
3
+ @form = $(selector)
4
+ return if @form.length == 0
5
+
6
+ @amount_input = @form.find("[role='charge-amount']")
7
+ @id_input = @form.find("[value='<%= Supercharged::ChargesHelper::FAKE_ORDER_ID %>']")
8
+
9
+ @form.submit =>
10
+ @start_payment()
11
+
12
+ unless parseInt(@id_input.val())
13
+ alert("Error: undefined charge id")
14
+ return false
15
+
16
+ start_payment: ->
17
+ @create_internal_transaction(
18
+ success: (charge) =>
19
+ @prepare_gateway_form(charge)
20
+ )
21
+
22
+ create_internal_transaction: (options) ->
23
+ charge_attributes = @get_charge_attributes()
24
+ $.ajax(
25
+ url: "/charges.json",
26
+ type: "POST",
27
+ async: false,
28
+ data: { charge: charge_attributes},
29
+ success: (response, a) ->
30
+ options.success(response)
31
+ )
32
+
33
+ get_charge_attributes: ->
34
+ {
35
+ amount: @amount_input.val()
36
+ }
37
+
38
+ prepare_gateway_form: (charge) ->
39
+ @id_input.val(charge.id)
40
+
41
+ $ ->
42
+ window.widgets ||= {}
43
+ window.widgets.charge_form = new ChargeForm("[role='gateway-charge-form']")
@@ -0,0 +1 @@
1
+ //= require_directory .
@@ -0,0 +1,19 @@
1
+ class Supercharged::ChargesController < ApplicationController
2
+
3
+ def new
4
+ end
5
+
6
+ def create
7
+ @charge = Charge.new(charge_params)
8
+ @charge.user = current_user
9
+ @charge.save!
10
+ render json: @charge.as_json(only: [:id])
11
+ end
12
+
13
+ private
14
+
15
+ def charge_params
16
+ params.require(:charge).permit(:amount)
17
+ end
18
+
19
+ end
@@ -0,0 +1,53 @@
1
+ class Supercharged::GatewayNotificationsController < ApplicationController
2
+ skip_before_filter :verify_authenticity_token
3
+
4
+ def create
5
+ persistent_logger.info("Notification for #{params[:gateway]}")
6
+ persistent_logger.info("params = #{params.inspect}")
7
+
8
+ @notification = GatewayNotification.create!(params: params, gateway: params[:gateway], raw_post: request.raw_post)
9
+ @notification.logger = persistent_logger
10
+
11
+ error = if !@notification.complete?
12
+ "not_completed"
13
+ elsif !@notification.acknowledge
14
+ "acknowledge_failed"
15
+ elsif !@notification.charge
16
+ "charge not found"
17
+ end
18
+
19
+ if error
20
+ persistent_logger.error("Error: #{error.inspect}")
21
+ if @notification.charge
22
+ @notification.charge.failed!
23
+ @notification.charge.update_attribute(:error, error)
24
+ end
25
+ head :bad_request
26
+ else
27
+ persistent_logger.info("Success")
28
+ @notification.approve
29
+ if @notification.need_response?
30
+ persistent_logger.info("Need need_response: #{@notification.success_response.inspect}")
31
+ render text: @notification.success_response
32
+ else
33
+ persistent_logger.info("Redirecting")
34
+ redirect_to root_url
35
+ end
36
+ end
37
+ end
38
+
39
+ def success
40
+ redirect_to root_url, notice: "Success"
41
+ end
42
+
43
+ def fail
44
+ redirect_to root_url, error: "Fail"
45
+ end
46
+
47
+ private
48
+
49
+ def persistent_logger
50
+ @persistent_logger ||= Logger.new("log/supercharged/gateway_notifications.log")
51
+ end
52
+
53
+ end
@@ -0,0 +1,45 @@
1
+ module Supercharged::ChargesHelper
2
+ # No order id while generating form. It will be added later via JS
3
+ # JS finds order input by this fake id because id and name will be integration specific
4
+ FAKE_ORDER_ID = "[payment_order_id]"
5
+
6
+ DEFAULT_AMOUNT_FIELD_OPTIONS = {
7
+ role: "charge-amount",
8
+ required: true,
9
+ min: 0
10
+ }
11
+
12
+ def charge_form_for(service_name, options = {}, &block)
13
+ raise ArgumentError, "Missing block" unless block_given?
14
+
15
+ default_options = {service: service_name}
16
+ options.merge!(default_options)
17
+
18
+ options = with_default_html_options(options)
19
+
20
+ account = options.delete(:account)
21
+ notify_url = gateways_result_url(service_name)
22
+
23
+ payment_service_for(FAKE_ORDER_ID, account, options) do |service|
24
+ service.notify_url notify_url
25
+ block.call(service)
26
+ end
27
+ end
28
+
29
+ def charge_form_amount_field(service, options = {})
30
+ amount_field_name = service.mappings[:amount] || raise("Undefined amount field mapping")
31
+
32
+ options = options.merge(DEFAULT_AMOUNT_FIELD_OPTIONS)
33
+
34
+ number_field_tag amount_field_name, nil, options
35
+ end
36
+
37
+ private
38
+
39
+ def with_default_html_options(options)
40
+ options[:html] ||= {}
41
+ options[:html].merge!(role: "gateway-charge-form")
42
+ options
43
+ end
44
+
45
+ end
@@ -0,0 +1,2 @@
1
+ class Charge < Supercharged::Charge::Base
2
+ end
@@ -0,0 +1,55 @@
1
+ require 'active_merchant'
2
+
3
+ class GatewayNotification < ActiveRecord::Base
4
+ class EmptyChargeIdError < ArgumentError;end
5
+
6
+ belongs_to :charge
7
+
8
+ serialize :params
9
+
10
+ before_create :set_charge_id
11
+
12
+ attr_accessor :raw_post, :logger
13
+
14
+ def acknowledge
15
+ adapter.acknowledge
16
+ end
17
+
18
+ def complete?
19
+ adapter.complete?
20
+ end
21
+
22
+ def need_response?
23
+ adapter.respond_to?(:success_response)
24
+ end
25
+
26
+ def success_response
27
+ adapter.respond_to?(:success_response) ? adapter.success_response : "OK"
28
+ end
29
+
30
+ def approve
31
+ logger.info "real amount = #{real_amount}"
32
+ charge.approve(real_amount) unless charge.ok?
33
+ end
34
+
35
+ def real_amount
36
+ params[service.mappings[:amount]]
37
+ end
38
+
39
+ private
40
+
41
+ def adapter
42
+ @adapter ||= "ActiveMerchant::Billing::Integrations::#{gateway.classify}::Notification".classify.constantize.new(raw_post)
43
+ rescue NameError
44
+ raise "Unknown integration '#{gateway}'"
45
+ end
46
+
47
+ def service
48
+ "ActiveMerchant::Billing::Integrations::#{gateway.classify}::Helper".classify.constantize
49
+ end
50
+
51
+ def set_charge_id
52
+ self.charge_id = adapter.item_id || raise(EmptyChargeIdError)
53
+ end
54
+
55
+ end
@@ -0,0 +1,3 @@
1
+ class PaymentStateTransition < ActiveRecord::Base
2
+ belongs_to :payment
3
+ end
@@ -0,0 +1,45 @@
1
+ module Supercharged
2
+ module Charge
3
+ class Base < ActiveRecord::Base
4
+ include ActiveModel::ForbiddenAttributesProtection
5
+
6
+ self.table_name = "charges"
7
+ self.abstract_class = true
8
+
9
+ belongs_to :user
10
+ has_many :gateway_input_notifications
11
+
12
+ validates :amount, presence: true
13
+
14
+ scope :latest, order("created_at DESC")
15
+
16
+ state_machine :state, initial: :new do
17
+ # store_audit_trail
18
+
19
+ state :new
20
+ state :rejected
21
+ state :ok
22
+ state :error
23
+
24
+ event :set_ok do
25
+ transition [:new, :error] => :ok
26
+ end
27
+
28
+ event :failed do
29
+ transition [:new] => :error
30
+ end
31
+
32
+ event :reject do
33
+ transition [:new, :error] => :rejected
34
+ end
35
+ end
36
+
37
+ # require implicit amount from gateway, not from user
38
+ def approve(real_amount)
39
+ self.real_amount = real_amount
40
+ set_ok!
41
+ end
42
+
43
+ end
44
+ end
45
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,17 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+
4
+ def supercharged(options = {})
5
+ controllers = {
6
+ charges: "supercharged/charges",
7
+ gateway_notifications: "supercharged/gateway_notifications"
8
+ }
9
+ controllers.merge!(options[:controllers]) if options[:controllers]
10
+
11
+ resources :charges, only: [:new, :create], controller: controllers[:charges]
12
+
13
+ match "gateways/:gateway/result" => "#{controllers[:gateway_notifications]}#create", as: :gateways_result
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,4 @@
1
+ require 'active_merchant'
2
+ require 'active_merchant/billing/integrations/action_view_helper'
3
+
4
+ ActionView::Base.send(:include, ActiveMerchant::Billing::Integrations::ActionViewHelper)
@@ -0,0 +1,3 @@
1
+ module Supercharged
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config/routes'))
2
+ require 'supercharged/activemerchant'
3
+
4
+ require 'state_machine'
5
+
6
+ module Supercharged
7
+ class Engine < Rails::Engine
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :supercharged do
3
+ # # Task goes here
4
+ # end
data/test/fake_app.rb ADDED
@@ -0,0 +1,94 @@
1
+ require 'active_record'
2
+ require 'action_controller/railtie'
3
+
4
+ # database
5
+ if ENV['TRAVIS'].present?
6
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'postgresql', :database => 'supercharged_test', :username => "postgres"}}
7
+ else
8
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
9
+ end
10
+ ActiveRecord::Base.establish_connection('test')
11
+
12
+ # config
13
+ app = Class.new(Rails::Application)
14
+ app.config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
15
+ app.config.session_store :cookie_store, :key => "_fakeapp_session"
16
+ app.config.active_support.deprecation = :log
17
+ app.initialize!
18
+
19
+ Rails.application.routes.draw do
20
+ supercharged
21
+
22
+ root to: "empty#index"
23
+ end
24
+
25
+ # migrations
26
+ ActiveRecord::Base.silence do
27
+ ActiveRecord::Migration.verbose = false
28
+ ActiveRecord::Schema.define :version => 0 do
29
+
30
+ create_table "gateway_notifications", :force => true do |t|
31
+ t.text "params"
32
+ t.string "status"
33
+ t.string "external_transaction_id"
34
+ t.integer "charge_id"
35
+ t.datetime "created_at", :null => false
36
+ t.datetime "updated_at", :null => false
37
+ t.string "gateway"
38
+ end
39
+
40
+ add_index "gateway_notifications", ["charge_id"], :name => "index_gateway_input_notifications_on_charge_id"
41
+
42
+ create_table "charges_state_transitions", :force => true do |t|
43
+ t.integer "charges_id"
44
+ t.string "charges_type"
45
+ t.string "event"
46
+ t.string "from"
47
+ t.string "to"
48
+ t.datetime "created_at"
49
+ end
50
+
51
+ add_index "charges_state_transitions", ["charges_id"], :name => "index_charges_state_transitions_on_charges_id"
52
+
53
+ create_table "charges", :force => true do |t|
54
+ t.integer "amount", :null => false
55
+ t.integer "user_id", :null => false
56
+ t.string "external_transaction_id"
57
+ t.text "params"
58
+ t.string "state", :default => "new", :null => false
59
+ t.datetime "created_at", :null => false
60
+ t.datetime "updated_at", :null => false
61
+ t.integer "user_transaction_id"
62
+ t.string "error"
63
+ t.integer "approved_by"
64
+ t.text "reject_reason"
65
+ t.decimal "real_amount"
66
+ end
67
+
68
+ add_index "charges", ["approved_by"], :name => "index_charges_on_approved_by"
69
+ add_index "charges", ["state"], :name => "index_charges_on_state"
70
+ add_index "charges", ["user_id"], :name => "index_charges_on_user_id"
71
+
72
+ end
73
+ end
74
+
75
+ class ApplicationController < ActionController::Base
76
+ protect_from_forgery
77
+
78
+ helper_method :current_user
79
+
80
+ private
81
+
82
+ def current_user
83
+ raise "stub me"
84
+ end
85
+ end
86
+
87
+ class EmptyController < ApplicationController
88
+ def index
89
+ render empty: true
90
+ end
91
+ end
92
+
93
+ # helpers
94
+ Object.const_set(:ApplicationHelper, Module.new)
@@ -0,0 +1,62 @@
1
+ require 'test_helper'
2
+
3
+ describe Supercharged::GatewayNotificationsController do
4
+ describe "create action" do
5
+ let(:charge) { Charge.create!({user_id: 1, amount: 10}, without_protection: true) }
6
+
7
+ context "authorized" do
8
+ let(:fake_user) { stub(id: 1) }
9
+
10
+ before do
11
+ GatewayNotification.any_instance.stubs(:current_user).returns(fake_user)
12
+ end
13
+
14
+ context "correct conditions" do
15
+ it "works with good notification" do
16
+ adapter = stub(item_id: 1, "complete?" => true, acknowledge: true, charge: charge)
17
+
18
+ GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
19
+
20
+ post :create, gateway: "webmoney"
21
+
22
+ charge.reload
23
+ charge.state_name.must_equal :ok
24
+
25
+ assert_response :redirect, "/"
26
+ end
27
+ end
28
+
29
+ context "bad conditions" do
30
+
31
+ it "completed = false" do
32
+ adapter = stub(item_id: 1, "complete?" => false, acknowledge: true, charge: charge)
33
+
34
+ GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
35
+
36
+ post :create, gateway: "webmoney"
37
+
38
+ charge.reload
39
+ charge.state_name.must_equal :error
40
+ charge.error.must_equal "not_completed"
41
+
42
+ assert_response :bad_request
43
+ end
44
+
45
+ it "acknowledge = false" do
46
+ adapter = stub(item_id: 1, "complete?" => true, acknowledge: false, charge: charge)
47
+
48
+ GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
49
+
50
+ post :create, gateway: "webmoney"
51
+
52
+ charge.reload
53
+ charge.state_name.must_equal :error
54
+ charge.error.must_equal "acknowledge_failed"
55
+
56
+ assert_response :bad_request
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ describe Charge do
4
+ describe "validations" do
5
+ subject { Charge.new }
6
+ it "amount is required" do
7
+ subject.valid?
8
+
9
+ subject.errors[:amount][0].must_equal "can't be blank"
10
+ end
11
+ end
12
+
13
+ describe "states" do
14
+ subject { Charge.create!({user_id: 1, amount: 10}, without_protection: true) }
15
+
16
+ describe "#approve" do
17
+ it "changes state and real_amount" do
18
+ subject.approve(5)
19
+
20
+ subject.real_amount.must_equal 5
21
+ subject.state_name.must_equal :ok
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+
3
+ describe GatewayNotification do
4
+ describe "create" do
5
+ it "raise EmptyChargeId if charge_id = nil" do
6
+ ->{
7
+ GatewayNotification.create!(gateway: "webmoney")
8
+ }.must_raise GatewayNotification::EmptyChargeIdError
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+
3
+ require "minitest/autorun"
4
+ require "minitest/spec"
5
+ require "minitest/pride"
6
+ require "minitest-spec-context"
7
+ require "mocha/setup"
8
+
9
+ require 'rails'
10
+ require 'active_record'
11
+ require 'action_view'
12
+ # require 'action_controller'
13
+
14
+ require "rails/test_help"
15
+ require "minitest/rails"
16
+
17
+ require 'state_machine'
18
+ require 'state_machine-audit_trail'
19
+ require 'strong_parameters'
20
+
21
+ require "supercharged"
22
+ require "fake_app"
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: supercharged
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - divineforest
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-05-07 00:00:00 +04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ type: :runtime
22
+ version_requirements: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 3
28
+ - 1
29
+ version: "3.1"
30
+ name: rails
31
+ requirement: *id001
32
+ prerelease: false
33
+ - !ruby/object:Gem::Dependency
34
+ type: :runtime
35
+ version_requirements: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ name: state_machine
43
+ requirement: *id002
44
+ prerelease: false
45
+ - !ruby/object:Gem::Dependency
46
+ type: :runtime
47
+ version_requirements: &id003 !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 0
53
+ version: "0"
54
+ name: state_machine-audit_trail
55
+ requirement: *id003
56
+ prerelease: false
57
+ - !ruby/object:Gem::Dependency
58
+ type: :runtime
59
+ version_requirements: &id004 !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ name: activemerchant
67
+ requirement: *id004
68
+ prerelease: false
69
+ - !ruby/object:Gem::Dependency
70
+ type: :runtime
71
+ version_requirements: &id005 !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ name: strong_parameters
79
+ requirement: *id005
80
+ prerelease: false
81
+ - !ruby/object:Gem::Dependency
82
+ type: :development
83
+ version_requirements: &id006 !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ name: sqlite3
91
+ requirement: *id006
92
+ prerelease: false
93
+ - !ruby/object:Gem::Dependency
94
+ type: :development
95
+ version_requirements: &id007 !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ~>
98
+ - !ruby/object:Gem::Version
99
+ segments:
100
+ - 3
101
+ - 0
102
+ version: "3.0"
103
+ name: minitest
104
+ requirement: *id007
105
+ prerelease: false
106
+ - !ruby/object:Gem::Dependency
107
+ type: :development
108
+ version_requirements: &id008 !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ name: minitest-spec-context
116
+ requirement: *id008
117
+ prerelease: false
118
+ - !ruby/object:Gem::Dependency
119
+ type: :development
120
+ version_requirements: &id009 !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ segments:
125
+ - 0
126
+ version: "0"
127
+ name: minitest-rails
128
+ requirement: *id009
129
+ prerelease: false
130
+ - !ruby/object:Gem::Dependency
131
+ type: :development
132
+ version_requirements: &id010 !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ segments:
137
+ - 0
138
+ version: "0"
139
+ name: mocha
140
+ requirement: *id010
141
+ prerelease: false
142
+ description:
143
+ email:
144
+ executables: []
145
+
146
+ extensions: []
147
+
148
+ extra_rdoc_files: []
149
+
150
+ files:
151
+ - app/assets/javascripts/charge_form.js.coffee.erb
152
+ - app/assets/javascripts/supercharged.js
153
+ - app/controllers/supercharged/charges_controller.rb
154
+ - app/controllers/supercharged/gateway_notifications_controller.rb
155
+ - app/helpers/supercharged/charges_helper.rb
156
+ - app/models/charge.rb
157
+ - app/models/gateway_notification.rb
158
+ - app/models/payment_state_transition.rb
159
+ - app/models/supercharged/charge/base.rb
160
+ - config/routes.rb
161
+ - lib/supercharged/activemerchant.rb
162
+ - lib/supercharged/version.rb
163
+ - lib/supercharged.rb
164
+ - lib/tasks/supercharged_tasks.rake
165
+ - MIT-LICENSE
166
+ - Rakefile
167
+ - README.md
168
+ has_rdoc: true
169
+ homepage:
170
+ licenses: []
171
+
172
+ post_install_message:
173
+ rdoc_options: []
174
+
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ segments:
182
+ - 0
183
+ version: "0"
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ segments:
189
+ - 0
190
+ version: "0"
191
+ requirements: []
192
+
193
+ rubyforge_project:
194
+ rubygems_version: 1.3.6
195
+ signing_key:
196
+ specification_version: 3
197
+ summary: MVC solution for charges in rails
198
+ test_files:
199
+ - test/fake_app.rb
200
+ - test/supercharged/controllers/gateway_notifications_controller_test.rb
201
+ - test/supercharged/models/charge_test.rb
202
+ - test/supercharged/models/geneway_notification_test.rb
203
+ - test/test_helper.rb