supercharged 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Supercharged
2
2
 
3
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)
4
+ [![Code Climate](https://codeclimate.com/github/divineforest/supercharged.png)](https://codeclimate.com/github/divineforest/supercharged)
5
5
 
6
6
  Complete MVC solution to accept charges from users on your Ruby on Rails site
7
7
 
@@ -25,6 +25,13 @@ In your application.js manifest:
25
25
  //= require supercharged
26
26
  ```
27
27
 
28
+ And then in some assets file:
29
+
30
+ ```
31
+ $ ->
32
+ new SuperchargedForm("[role='gateway-charge-form']")
33
+ ```
34
+
28
35
  Create config/initializers/supercharged.rb
29
36
 
30
37
  ```ruby
@@ -84,9 +91,27 @@ class Charge < Supercharged::Charge::Base
84
91
  super
85
92
  end
86
93
  end
94
+
95
+ def min_amount
96
+ # specify min value for amount field here
97
+ # default is 1
98
+ 42
99
+ end
87
100
  end
88
101
  ```
89
102
 
103
+ ## Form
104
+
105
+ To display validation, supercharged form class has `onValidationError` callback:
106
+
107
+ ```
108
+ $ ->
109
+ new SuperchargedForm("[role='gateway-charge-form']", {
110
+ onValidationError: (errors)->
111
+ console.log "supercharged validation errors: ", errors
112
+ })
113
+ ```
114
+
90
115
  # Contributing
91
116
 
92
117
  The example app is at https://github.com/divineforest/supercharged-example-app
@@ -1,43 +1,57 @@
1
- class ChargeForm
2
- constructor: (selector, options = {}) ->
1
+ class @SuperchargedForm
2
+ constructor: (selector, @options = {}) ->
3
3
  @form = $(selector)
4
4
  return if @form.length == 0
5
5
 
6
6
  @amount_input = @form.find("[role='charge-amount']")
7
- @id_input = @form.find("[value='<%= Supercharged::ChargesHelper::FAKE_ORDER_ID %>']")
7
+ @gateway_name_input = @form.find("[role='charge-gateway-name']")
8
+ @id_input = if @form.find("[role='charge-id']").length then @form.find("[role='charge-id']") else @form.find("[value='<%= Supercharged::ChargesHelper::FAKE_ORDER_ID %>']")
8
9
 
9
10
  @form.submit =>
10
- @start_payment()
11
+ valid = @startPayment()
12
+
13
+ unless valid
14
+ return false
11
15
 
12
16
  unless parseInt(@id_input.val())
13
17
  alert("Error: undefined charge id")
14
18
  return false
15
19
 
16
- start_payment: ->
17
- @create_internal_transaction(
18
- success: (charge) =>
19
- @prepare_gateway_form(charge)
20
+ startPayment: ->
21
+ valid = true
22
+ @createInternalTransaction(
23
+ success: (charge)=>
24
+ @prepareGatewayForm(charge)
25
+ validationError: (errors)=>
26
+ valid = false
27
+
28
+ handler = @options.onValidationError
29
+ handler.call(this, errors) if handler?
20
30
  )
21
31
 
22
- create_internal_transaction: (options) ->
23
- charge_attributes = @get_charge_attributes()
32
+ valid
33
+
34
+ createInternalTransaction: (options) ->
35
+ charge_attributes = @getChargeAttributes()
24
36
  $.ajax(
25
37
  url: "/charges.json",
26
38
  type: "POST",
27
39
  async: false,
28
- data: { charge: charge_attributes},
29
- success: (response, a) ->
40
+ data: {charge: charge_attributes},
41
+ success: (response) ->
30
42
  options.success(response)
43
+ error: (jqXHR, status, errorThrown)=>
44
+ return unless jqXHR.status == 422
45
+
46
+ response = $.parseJSON(jqXHR.responseText)
47
+ options.validationError(response.errors)
31
48
  )
32
49
 
33
- get_charge_attributes: ->
50
+ getChargeAttributes: ->
34
51
  {
35
- amount: @amount_input.val()
52
+ amount: @amount_input.val(),
53
+ gateway_name: @gateway_name_input.val()
36
54
  }
37
55
 
38
- prepare_gateway_form: (charge) ->
56
+ prepareGatewayForm: (charge) ->
39
57
  @id_input.val(charge.id)
40
-
41
- $ ->
42
- window.widgets ||= {}
43
- window.widgets.charge_form = new ChargeForm("[role='gateway-charge-form']")
@@ -4,16 +4,47 @@ class Supercharged::ChargesController < ApplicationController
4
4
  end
5
5
 
6
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])
7
+ charge = Charge.new(charge_params)
8
+ charge.user = current_user
9
+
10
+ if charge.save
11
+ render json: charge.as_json(only: [:id])
12
+ else
13
+ render json: { errors: charge.errors }, status: :unprocessable_entity
14
+ end
15
+ end
16
+
17
+ # For example for PayPal Express, which requires getting token before purchase action.
18
+ def setup_purchase
19
+ charge = Charge.find(params[:charge_id])
20
+
21
+ token = charge.setup_purchase(
22
+ ip: request.remote_ip,
23
+ return_url: complete_charges_url,
24
+ cancel_return_url: new_charge_url
25
+ )
26
+
27
+ redirect_to charge.gateway.redirect_url_for(token)
28
+ end
29
+
30
+ def complete
31
+ params.require(:token)
32
+
33
+ @charge = Charge.with_token(params[:token])
34
+
35
+ if @charge
36
+ @charge.complete(params)
37
+
38
+ redirect_to root_url
39
+ else
40
+ head :not_found
41
+ end
11
42
  end
12
43
 
13
44
  private
14
45
 
15
46
  def charge_params
16
- params.require(:charge).permit(:amount)
47
+ params.require(:charge).permit(:amount, :gateway_name)
17
48
  end
18
49
 
19
50
  end
@@ -1,5 +1,6 @@
1
1
  class Supercharged::GatewayNotificationsController < ApplicationController
2
2
  skip_before_filter :verify_authenticity_token
3
+ before_filter :check_any_params, only: :create
3
4
 
4
5
  def create
5
6
  persistent_logger.info("Notification for #{params[:gateway]}")
@@ -50,4 +51,11 @@ class Supercharged::GatewayNotificationsController < ApplicationController
50
51
  @persistent_logger ||= Logger.new("log/supercharged/gateway_notifications.log")
51
52
  end
52
53
 
54
+ def check_any_params
55
+ if request.raw_post.blank?
56
+ head :bad_request
57
+ false
58
+ end
59
+ end
60
+
53
61
  end
@@ -3,12 +3,6 @@ module Supercharged::ChargesHelper
3
3
  # JS finds order input by this fake id because id and name will be integration specific
4
4
  FAKE_ORDER_ID = "[payment_order_id]"
5
5
 
6
- DEFAULT_AMOUNT_FIELD_OPTIONS = {
7
- role: "charge-amount",
8
- required: true,
9
- min: 0
10
- }
11
-
12
6
  def charge_form_for(service_name, options = {}, &block)
13
7
  raise ArgumentError, "Missing block" unless block_given?
14
8
 
@@ -27,9 +21,9 @@ module Supercharged::ChargesHelper
27
21
  end
28
22
 
29
23
  def charge_form_amount_field(service, options = {})
30
- amount_field_name = service.mappings[:amount] || raise("Undefined amount field mapping")
24
+ amount_field_name = service.mappings[:amount] || raise(ArgumentError, "Undefined amount field mapping")
31
25
 
32
- options = options.merge(DEFAULT_AMOUNT_FIELD_OPTIONS)
26
+ options = default_amount_field_options.merge(options)
33
27
 
34
28
  number_field_tag amount_field_name, nil, options
35
29
  end
@@ -42,4 +36,14 @@ module Supercharged::ChargesHelper
42
36
  options
43
37
  end
44
38
 
39
+ def default_amount_field_options
40
+ {
41
+ role: "charge-amount",
42
+ required: true,
43
+ data: {
44
+ min_value: Charge.min_amount
45
+ }
46
+ }
47
+ end
48
+
45
49
  end
@@ -0,0 +1,17 @@
1
+ class GatewayResponse < ActiveRecord::Base
2
+ belongs_to :charge
3
+
4
+ serialize :params
5
+
6
+ def response=(response)
7
+ self.success = response.success?
8
+ self.authorization = response.authorization
9
+ self.message = response.message
10
+ self.params = response.params
11
+ rescue ActiveMerchant::ActiveMerchantError => e
12
+ self.success = false
13
+ self.authorization = nil
14
+ self.message = e.message
15
+ self.params = {}
16
+ end
17
+ end
@@ -8,10 +8,16 @@ module Supercharged
8
8
 
9
9
  belongs_to :user
10
10
  has_many :gateway_input_notifications
11
+ has_many :gateway_responses
11
12
 
12
- validates :amount, presence: true
13
+ validates :amount, presence: true, numericality: {
14
+ greater_than_or_equal_to: ->(model) {
15
+ model.class.min_amount
16
+ }
17
+ }
13
18
 
14
19
  scope :latest, order("created_at DESC")
20
+ scope :by_gateway, ->(gateway_name) { where(gateway_name: gateway_name.to_s) }
15
21
 
16
22
  state_machine :state, initial: :new do
17
23
  # store_audit_trail
@@ -34,12 +40,77 @@ module Supercharged
34
40
  end
35
41
  end
36
42
 
43
+ def self.with_token(token)
44
+ where(gateway_token: token).first
45
+ end
46
+
37
47
  # require implicit amount from gateway, not from user
38
48
  def approve(real_amount)
39
49
  self.real_amount = real_amount
40
50
  set_ok!
41
51
  end
42
52
 
53
+ def self.min_amount
54
+ 1
55
+ end
56
+
57
+ def setup_purchase(options)
58
+ response = gateway.setup_purchase(amount_in_cents,
59
+ ip: options[:id],
60
+ return_url: options[:return_url],
61
+ cancel_return_url: options[:cancel_return_url]
62
+ )
63
+
64
+ if response.success?
65
+ update_attributes!(
66
+ gateway_token: response.token,
67
+ ip_address: options[:id]
68
+ )
69
+ end
70
+
71
+ response.token
72
+ end
73
+
74
+ def complete(options = {})
75
+ get_purchase_details
76
+
77
+ response = process_purchase
78
+
79
+ approve(amount) if response.success?
80
+
81
+ response.success?
82
+ end
83
+
84
+ def gateway
85
+ Supercharged::Helpers.gateway(gateway_name)
86
+ end
87
+
88
+ private
89
+
90
+ def amount_in_cents
91
+ amount * 100
92
+ end
93
+
94
+ def get_purchase_details
95
+ details = gateway.details_for(gateway_token)
96
+ self.gateway_payer_id = details.payer_id
97
+ end
98
+
99
+ def process_purchase
100
+ response = gateway.purchase(amount_in_cents,
101
+ ip: ip_address,
102
+ token: gateway_token,
103
+ payer_id: gateway_payer_id
104
+ )
105
+
106
+ save_gateway_response(response)
107
+
108
+ response
109
+ end
110
+
111
+ def save_gateway_response(response)
112
+ GatewayResponse.create!(charge: self, action: "purchase", amount: amount, response: response)
113
+ end
43
114
  end
44
115
  end
45
116
  end
data/config/routes.rb CHANGED
@@ -8,7 +8,12 @@ module ActionDispatch::Routing
8
8
  }
9
9
  controllers.merge!(options[:controllers]) if options[:controllers]
10
10
 
11
- resources :charges, only: [:new, :create], controller: controllers[:charges]
11
+ resources :charges, only: [:new, :create], controller: controllers[:charges] do
12
+ collection do
13
+ post :setup_purchase
14
+ get :complete
15
+ end
16
+ end
12
17
 
13
18
  match "gateways/:gateway/result" => "#{controllers[:gateway_notifications]}#create", as: :gateways_result
14
19
  end
@@ -0,0 +1,27 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/active_record'
4
+
5
+ module Supercharged
6
+ module Generators
7
+ class MigrationsGenerator < Rails::Generators::Base
8
+ include Rails::Generators::Migration
9
+
10
+ source_root File.expand_path("../templates", __FILE__)
11
+
12
+ desc "Generates migration for Supercharged"
13
+
14
+ def self.next_migration_number(dirname)
15
+ ActiveRecord::Generators::Base.next_migration_number(dirname)
16
+ end
17
+
18
+ def copy_migration
19
+ migration_template 'install_migration.rb', 'db/migrate/install_supercharged.rb'
20
+ end
21
+
22
+ def mount_engine
23
+ route "supercharged"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,64 @@
1
+ class InstallSupercharged < ActiveRecord::Migration
2
+ def change
3
+ create_table "gateway_notifications", :force => true do |t|
4
+ t.text "params"
5
+ t.string "status"
6
+ t.string "external_transaction_id"
7
+ t.integer "charge_id"
8
+ t.datetime "created_at", :null => false
9
+ t.datetime "updated_at", :null => false
10
+ t.string "gateway"
11
+ end
12
+
13
+ add_index "gateway_notifications", ["charge_id"], :name => "index_gateway_input_notifications_on_charge_id"
14
+
15
+ create_table "gateway_responses", :force => true do |t|
16
+ t.integer "charge_id", :null => false
17
+ t.string "action", :null => false
18
+ t.decimal "amount"
19
+ t.boolean "success", :null => false
20
+ t.string "authorization"
21
+ t.string "message"
22
+ t.text "params"
23
+ t.datetime "created_at", :null => false
24
+ t.datetime "updated_at", :null => false
25
+ end
26
+
27
+ add_index "gateway_responses", ["charge_id"], :name => "index_gateway_responses_on_charge_id"
28
+
29
+ create_table "charges_state_transitions", :force => true do |t|
30
+ t.integer "charges_id"
31
+ t.string "charges_type"
32
+ t.string "event"
33
+ t.string "from"
34
+ t.string "to"
35
+ t.datetime "created_at"
36
+ end
37
+
38
+ add_index "charges_state_transitions", ["charges_id"], :name => "index_charges_state_transitions_on_charges_id"
39
+
40
+ create_table "charges", :force => true do |t|
41
+ t.integer "amount", :null => false
42
+ t.integer "user_id", :null => false
43
+ t.string "external_transaction_id"
44
+ t.text "params"
45
+ t.string "state", :default => "new", :null => false
46
+ t.datetime "created_at", :null => false
47
+ t.datetime "updated_at", :null => false
48
+ t.string "error"
49
+ t.integer "approved_by"
50
+ t.text "reject_reason"
51
+ t.decimal "real_amount"
52
+ t.string "gateway_name"
53
+ t.string "gateway_token"
54
+ t.string "gateway_payer_id"
55
+ t.string "ip_address"
56
+ end
57
+
58
+ add_index "charges", ["approved_by"], :name => "index_charges_on_approved_by"
59
+ add_index "charges", ["gateway_name"], :name => "index_charges_on_gateway_name"
60
+ add_index "charges", ["gateway_token"], :name => "index_charges_on_gateway_token"
61
+ add_index "charges", ["state"], :name => "index_charges_on_state"
62
+ add_index "charges", ["user_id"], :name => "index_charges_on_user_id"
63
+ end
64
+ end
@@ -0,0 +1,26 @@
1
+ module Supercharged::Helpers
2
+
3
+ @gateways = {}
4
+
5
+ def self.gateway(name)
6
+ @gateways[name.to_sym] || raise("Gateway not registered")
7
+ end
8
+
9
+ def self.init_gateway(name, options)
10
+ klass = gateway_class_by_name(name)
11
+ gateway = klass.new(options)
12
+ add_gateway(name, gateway)
13
+ end
14
+
15
+ private
16
+
17
+ def self.gateway_class_by_name(name)
18
+ "ActiveMerchant::Billing::#{name.to_s.camelcase}Gateway".classify.constantize
19
+ rescue NameError
20
+ raise "Unknown gateway '#{name}'"
21
+ end
22
+
23
+ def self.add_gateway(name, gateway)
24
+ @gateways[name.to_sym] = gateway
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Supercharged
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/supercharged.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config/routes'))
2
2
  require 'supercharged/activemerchant'
3
+ require 'supercharged/helpers'
3
4
 
4
5
  require 'state_machine'
5
6
 
data/test/fake_app.rb CHANGED
@@ -2,11 +2,7 @@ require 'active_record'
2
2
  require 'action_controller/railtie'
3
3
 
4
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
5
+ ActiveRecord::Base.configurations = {'test' => {adapter: 'sqlite3', database: ':memory:'}}
10
6
  ActiveRecord::Base.establish_connection('test')
11
7
 
12
8
  # config
@@ -39,6 +35,20 @@ ActiveRecord::Base.silence do
39
35
 
40
36
  add_index "gateway_notifications", ["charge_id"], :name => "index_gateway_input_notifications_on_charge_id"
41
37
 
38
+ create_table "gateway_responses", :force => true do |t|
39
+ t.integer "charge_id", :null => false
40
+ t.string "action", :null => false
41
+ t.decimal "amount"
42
+ t.boolean "success", :null => false
43
+ t.string "authorization"
44
+ t.string "message"
45
+ t.text "params"
46
+ t.datetime "created_at", :null => false
47
+ t.datetime "updated_at", :null => false
48
+ end
49
+
50
+ add_index "gateway_responses", ["charge_id"], :name => "index_gateway_responses_on_charge_id"
51
+
42
52
  create_table "charges_state_transitions", :force => true do |t|
43
53
  t.integer "charges_id"
44
54
  t.string "charges_type"
@@ -48,6 +58,11 @@ ActiveRecord::Base.silence do
48
58
  t.datetime "created_at"
49
59
  end
50
60
 
61
+ create_table "users", :force => true do |t|
62
+ t.datetime "created_at", :null => false
63
+ t.datetime "updated_at", :null => false
64
+ end
65
+
51
66
  add_index "charges_state_transitions", ["charges_id"], :name => "index_charges_state_transitions_on_charges_id"
52
67
 
53
68
  create_table "charges", :force => true do |t|
@@ -58,14 +73,19 @@ ActiveRecord::Base.silence do
58
73
  t.string "state", :default => "new", :null => false
59
74
  t.datetime "created_at", :null => false
60
75
  t.datetime "updated_at", :null => false
61
- t.integer "user_transaction_id"
62
76
  t.string "error"
63
77
  t.integer "approved_by"
64
78
  t.text "reject_reason"
65
79
  t.decimal "real_amount"
80
+ t.string "gateway_name"
81
+ t.string "gateway_token"
82
+ t.string "gateway_payer_id"
83
+ t.string "ip_address"
66
84
  end
67
85
 
68
86
  add_index "charges", ["approved_by"], :name => "index_charges_on_approved_by"
87
+ add_index "charges", ["gateway_name"], :name => "index_charges_on_gateway_name"
88
+ add_index "charges", ["gateway_token"], :name => "index_charges_on_gateway_token"
69
89
  add_index "charges", ["state"], :name => "index_charges_on_state"
70
90
  add_index "charges", ["user_id"], :name => "index_charges_on_user_id"
71
91
 
@@ -92,3 +112,6 @@ end
92
112
 
93
113
  # helpers
94
114
  Object.const_set(:ApplicationHelper, Module.new)
115
+
116
+ class User < ActiveRecord::Base
117
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ describe Supercharged::ChargesController do
4
+ describe "create action" do
5
+ context "authorized" do
6
+ let(:fake_user) { User.create! }
7
+
8
+ before do
9
+ Supercharged::ChargesController.any_instance.stubs(:current_user).returns(fake_user)
10
+ end
11
+
12
+ context "correct conditions" do
13
+ it "response contains id in json" do
14
+ post :create, charge: { amount: 100 }
15
+
16
+ assert_response :success
17
+
18
+ expected = {"charge"=>{"id"=>1}}
19
+ JSON.parse(@response.body).must_equal(expected)
20
+ end
21
+ end
22
+
23
+ context "bad conditions" do
24
+ it "response contains errors in json" do
25
+ post :create, charge: { amount: 0 }
26
+
27
+ assert_response 422
28
+
29
+ expected = {"errors"=>{"amount"=>["must be greater than or equal to 1"]}}
30
+ JSON.parse(@response.body).must_equal(expected)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -17,7 +17,7 @@ describe Supercharged::GatewayNotificationsController do
17
17
 
18
18
  GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
19
19
 
20
- post :create, gateway: "webmoney"
20
+ post :create, gateway: "webmoney", amount: 100
21
21
 
22
22
  charge.reload
23
23
  charge.state_name.must_equal :ok
@@ -33,7 +33,7 @@ describe Supercharged::GatewayNotificationsController do
33
33
 
34
34
  GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
35
35
 
36
- post :create, gateway: "webmoney"
36
+ post :create, gateway: "webmoney", amount: 100
37
37
 
38
38
  charge.reload
39
39
  charge.state_name.must_equal :error
@@ -47,7 +47,7 @@ describe Supercharged::GatewayNotificationsController do
47
47
 
48
48
  GatewayNotification.any_instance.stubs(:adapter).returns(adapter)
49
49
 
50
- post :create, gateway: "webmoney"
50
+ post :create, gateway: "webmoney", amount: 100
51
51
 
52
52
  charge.reload
53
53
  charge.state_name.must_equal :error
@@ -58,5 +58,14 @@ describe Supercharged::GatewayNotificationsController do
58
58
 
59
59
  end
60
60
  end
61
+
62
+ context "without any payload params" do
63
+ it "returns bad_request" do
64
+ # head :bad_request
65
+ post :create, gateway: "paypal"
66
+
67
+ assert_response :bad_request
68
+ end
69
+ end
61
70
  end
62
71
  end
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ class Supercharged::ChargesHelperTest < ActionView::TestCase
4
+ def test_min_value
5
+ field = charge_form_amount_field(sample_service, { min: 500 })
6
+ field.must_include 'min="500"'
7
+ end
8
+
9
+ def sample_service
10
+ stub(mappings: { amount: "amount" })
11
+ end
12
+ end
@@ -8,11 +8,27 @@ describe Charge do
8
8
 
9
9
  subject.errors[:amount][0].must_equal "can't be blank"
10
10
  end
11
+
12
+ it "min amount is required" do
13
+ subject.amount = 0
14
+ subject.valid?
15
+
16
+ subject.errors[:amount][0].must_equal "must be greater than or equal to 1"
17
+
18
+ subject.amount = 100
19
+ subject.valid?.must_equal true
20
+ end
11
21
  end
12
22
 
13
23
  describe "states" do
14
24
  subject { Charge.create!({user_id: 1, amount: 10}, without_protection: true) }
15
25
 
26
+ describe "initial state" do
27
+ it "initial state is new" do
28
+ Charge.new.state_name.must_equal :new
29
+ end
30
+ end
31
+
16
32
  describe "#approve" do
17
33
  it "changes state and real_amount" do
18
34
  subject.approve(5)
@@ -7,5 +7,15 @@ describe GatewayNotification do
7
7
  GatewayNotification.create!(gateway: "webmoney")
8
8
  }.must_raise GatewayNotification::EmptyChargeIdError
9
9
  end
10
+
11
+ it "charge id is inherited from adapter" do
12
+ gateway_notification = GatewayNotification.new
13
+
14
+ adapter = stub(item_id: 42)
15
+ gateway_notification.stubs(:adapter).returns(adapter)
16
+
17
+ gateway_notification.save!
18
+ gateway_notification.charge_id.must_equal 42
19
+ end
10
20
  end
11
21
  end
data/test/test_helper.rb CHANGED
@@ -9,7 +9,6 @@ require "mocha/setup"
9
9
  require 'rails'
10
10
  require 'active_record'
11
11
  require 'action_view'
12
- # require 'action_controller'
13
12
 
14
13
  require "rails/test_help"
15
14
  require "minitest/rails"
metadata CHANGED
@@ -1,153 +1,182 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
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
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - divineforest
13
9
  autorequire:
14
10
  bindir: bin
15
11
  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"
12
+ date: 2013-06-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
30
15
  name: rails
31
- requirement: *id001
32
- prerelease: false
33
- - !ruby/object:Gem::Dependency
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '3.1'
34
22
  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
23
  prerelease: false
45
- - !ruby/object:Gem::Dependency
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '3.1'
30
+ - !ruby/object:Gem::Dependency
31
+ name: state_machine
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
46
38
  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
39
  prerelease: false
57
- - !ruby/object:Gem::Dependency
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: state_machine-audit_trail
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
58
54
  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
55
  prerelease: false
69
- - !ruby/object:Gem::Dependency
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: activemerchant
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
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"
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
78
79
  name: strong_parameters
79
- requirement: *id005
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
80
87
  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"
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
90
95
  name: sqlite3
91
- requirement: *id006
92
- prerelease: false
93
- - !ruby/object:Gem::Dependency
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
94
102
  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
103
  prerelease: false
106
- - !ruby/object:Gem::Dependency
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: minitest
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '3.0'
107
118
  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
119
  prerelease: false
118
- - !ruby/object:Gem::Dependency
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '3.0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: minitest-spec-context
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
119
134
  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
135
  prerelease: false
130
- - !ruby/object:Gem::Dependency
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: minitest-rails
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
131
150
  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"
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
139
159
  name: mocha
140
- requirement: *id010
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
141
167
  prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
142
174
  description:
143
175
  email:
144
176
  executables: []
145
-
146
177
  extensions: []
147
-
148
178
  extra_rdoc_files: []
149
-
150
- files:
179
+ files:
151
180
  - app/assets/javascripts/charge_form.js.coffee.erb
152
181
  - app/assets/javascripts/supercharged.js
153
182
  - app/controllers/supercharged/charges_controller.rb
@@ -155,49 +184,61 @@ files:
155
184
  - app/helpers/supercharged/charges_helper.rb
156
185
  - app/models/charge.rb
157
186
  - app/models/gateway_notification.rb
187
+ - app/models/gateway_response.rb
158
188
  - app/models/payment_state_transition.rb
159
189
  - app/models/supercharged/charge/base.rb
160
190
  - config/routes.rb
191
+ - lib/generators/supercharged/migrations_generator.rb
192
+ - lib/generators/supercharged/templates/install_migration.rb
161
193
  - lib/supercharged/activemerchant.rb
194
+ - lib/supercharged/helpers.rb
162
195
  - lib/supercharged/version.rb
163
196
  - lib/supercharged.rb
164
- - lib/tasks/supercharged_tasks.rake
165
197
  - MIT-LICENSE
166
198
  - Rakefile
167
199
  - README.md
168
- has_rdoc: true
200
+ - test/fake_app.rb
201
+ - test/supercharged/controllers/charges_controller_test.rb
202
+ - test/supercharged/controllers/gateway_notifications_controller_test.rb
203
+ - test/supercharged/helpers/charges_helper_test.rb
204
+ - test/supercharged/models/charge_test.rb
205
+ - test/supercharged/models/geneway_notification_test.rb
206
+ - test/test_helper.rb
169
207
  homepage:
170
208
  licenses: []
171
-
172
209
  post_install_message:
173
210
  rdoc_options: []
174
-
175
- require_paths:
211
+ require_paths:
176
212
  - lib
177
- required_ruby_version: !ruby/object:Gem::Requirement
178
- requirements:
179
- - - ">="
180
- - !ruby/object:Gem::Version
181
- segments:
213
+ required_ruby_version: !ruby/object:Gem::Requirement
214
+ none: false
215
+ requirements:
216
+ - - ! '>='
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ segments:
182
220
  - 0
183
- version: "0"
184
- required_rubygems_version: !ruby/object:Gem::Requirement
185
- requirements:
186
- - - ">="
187
- - !ruby/object:Gem::Version
188
- segments:
221
+ hash: -708610607516919495
222
+ required_rubygems_version: !ruby/object:Gem::Requirement
223
+ none: false
224
+ requirements:
225
+ - - ! '>='
226
+ - !ruby/object:Gem::Version
227
+ version: '0'
228
+ segments:
189
229
  - 0
190
- version: "0"
230
+ hash: -708610607516919495
191
231
  requirements: []
192
-
193
232
  rubyforge_project:
194
- rubygems_version: 1.3.6
233
+ rubygems_version: 1.8.23
195
234
  signing_key:
196
235
  specification_version: 3
197
236
  summary: MVC solution for charges in rails
198
- test_files:
237
+ test_files:
199
238
  - test/fake_app.rb
239
+ - test/supercharged/controllers/charges_controller_test.rb
200
240
  - test/supercharged/controllers/gateway_notifications_controller_test.rb
241
+ - test/supercharged/helpers/charges_helper_test.rb
201
242
  - test/supercharged/models/charge_test.rb
202
243
  - test/supercharged/models/geneway_notification_test.rb
203
244
  - test/test_helper.rb
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :supercharged do
3
- # # Task goes here
4
- # end